入站与出站 Email API(2026):用 Rovela 发送并接收邮件
用同一个 Rovela 账号,既通过 POST /emails 发送,又通过入站 MX 或 ingress、email.received webhook 以及 GET /inbound/:id 接收。
一个 API 里同时做出站和入站
入站 + 出站 Email API 指同一套产品既能发送事务邮件,又能在你的域名上接收邮件,并把到达的消息交给应用。Rovela 的出站是POST /emails(以及 batch)。入站则是:「为已验证域名打开入站、发布 MX(或转发到 ingress URL)、订阅 email.received,再用 GET /inbound/:id 取正文。」
这是两者合在一起的产品图。入站逐步实现(含完整 handler)已经写在入站邮件 API 与 Webhook和接收邮件示例。出站邮件的投递事件见事务邮件 Webhook。给人用的收件箱见事务邮件 API + 托管邮箱。
可以从Email API产品页、快速开始、发送邮件 API和身份认证入手。 另见Webhooks和事件目录。
本系列相关产品指南:
- 事务邮件 API
- HTTP 邮件 API
- 从 SMTP 迁到 Email API
- SaaS 应用的 Email API
- 用 curl 发送邮件
- 事务邮件 API + 托管邮箱
- 邮件发送 API
- 邮件通知 API
- Email API 集成
- 批量事务邮件 API
- 事务邮件 Webhook
- 简单的事务邮件 API
- 从应用发送事务邮件
- 已验证域名的 Email API
出站:应用发出去的
出站就是事务邮件 API和HTTP 邮件 API里的那条路:sending_access Key、已验证的 from、HTML + text(或模板),以及凡会重试的请求都带 Idempotency-Key。200 表示入队。结果以 email.sent、email.delivered、email.bounced 等事件到来——或用 full_access 调用 GET /emails/:id。
若希望对话回到你接收邮件的同一域名,请设置 reply_to(或直接用一个别人能回复的地址发送)。
入站:域名收下的
根据入站示例(需要 full_access,以及已经验证过的域名):
curl -X POST https://api.rovela.dev/domains/<domain_id>/inbound -H "Authorization: Bearer re_your_full_access_key" -H "Content-Type: application/json" -d '{"catch_all": false}'
响应里有 enabled、catch_all、ingress_url(请当作密钥;再次调用该端点会签发新的,旧的失效),以及要发布在域名上的 mx 记录。MX 生效之前,发件人仍会投递到旧的 MX。
- 若省略
catch_all,或使用文档中的默认值true,该域名下任何地址都会被接受。 catch_all: false时,只接受你列出的地址(减少随机本地部分的垃圾邮件进入应用)。用POST /domains/<domain_id>/inbound/recipients添加。未列出的地址会在门口被拒绝。地址必须属于该域名,否则是400。
订阅 email.received:
curl -X POST https://api.rovela.dev/webhooks -H "Authorization: Bearer re_your_full_access_key" -H "Content-Type: application/json" -d '{"endpoint": "https://app.acme.com/webhooks/rovela", "events": ["email.received"]}'
事件携带信封和主题,不含正文:inbound_message_id、to、from、subject。用 full_access 调用 GET /inbound/:id 获取 text 和 html(任一都可能为 null)。入站 HTML 是陌生人写的——不要未经清洗就插入自己的页面;解析时优先用 text。from 只是发件人自称,不能当作身份证明。
用 GET /inbound?limit=50&offset=0 列出到达的邮件(最新在前,每页最多 100)。若你已经在跑邮件服务器,可以不改 MX,把原始邮件 POST 到 ingress_url(超过 2 MB 会 413),必须带 X-Envelope-To,并用稳定的 X-Provider-Event-Id,避免重试再次触发 email.received。
签名校验和重试规则与其他 webhook 相同(验证 Webhook 签名,Webhook 安全)。
把两边放进同一个应用
一个偏支持场景的闭环可以是:
- 应用用
POST /emails发送「我们已收到订单」,并设置reply_to: support@mail.acme.com(或reply+ticket-381@这类地址)。 - 客户回复。入站接受(收件人名单或 catch-all)、存储,并触发
email.received。 - 你的 handler 校验签名,按事件
id去重,拉取GET /inbound/:id,把正文追加到工单。 - 坐席(或你的代码)再用同一套 API 发出下一封出站邮件,并使用新的幂等键。
不要用发信 Key 去拉入站正文——读取入站需要 full_access。把这把 Key 只放在 webhook Worker 上。
事件目录把 email.received 描述为「托管邮箱接受的入站消息」;入站示例同时展示了带收件人规则的域名级入站。按你实际采用的文档来配置。若只是需要人来读信,使用 webmail 即可(事务邮件 API + 托管邮箱)。
FAQ
这能替代入站 how-to 吗? 不能。写 handler 时请用入站邮件 API 与 Webhook。本文回答的是:为什么发送和接收会想用同一家供应商。
没有 webmail 也能用入站吗? 能——在域名上打开入站并消费 webhook。Webmail 只是给人用的可选项。
打开/点击事件适用于入站吗? 互动事件针对的是出站消息,并且只有在该发信域名开启跟踪时才会触发(事件)。
sending_access 和 full_access 怎么分工? 出站 POST /emails 和 batch:sending_access。打开入站、注册 webhook、GET /inbound/:id:full_access。
整个会话只用一个账号
用 Email API 发送,用入站 webhook 接收,必要时再在同一域名上给人提供 webmail。这就是入站 + 出站 Email API:一个供应商,两个方向,仍然只是 HTTP。