← 返回博客

把应用发信从 SMTP 迁到 Email API(2026):Rovela HTTP 方案

把应用里的事务发信从 Nodemailer、PHPMailer 或 smtplib 的 SMTP 迁到 Rovela 的 POST /emails,并分清这与邮箱 SMTP 不是同一条路径。

更新于 2026年11月10日
把应用发信从 SMTP 迁到 Email API(2026):Rovela HTTP 方案

把应用发信从 SMTP 迁到 HTTP Email API

如果应用还在通过 SMTP 发送事务邮件——Nodemailer 的 createTransport({ host, port, auth })、PHPMailer 的 isSMTP()、Python smtplib、Jakarta Mail——迁到 Email API 意味着这些任务改为调用 POST /emails,而不再对接中继。触发点(注册、重置、收据)不变。变的是传输、凭证,以及你观察投递的方式。

这是应用迁移。它不是Email API 与 SMTP 对比(选哪种传输),不是SMTP 端口 25、465、587(25 / 465 / 587 各自干什么),也不是把公司邮箱迁到 Rovela(搬人的邮箱)。HTTP 契约本身见HTTP 邮件 API。

可以从Email API产品页、快速开始、发送邮件 API和身份认证入手。 同时读一下SMTP 产品页,避免迁错方向。

本系列相关产品指南:

你要迁什么——以及不要迁什么

要迁的: 现在为了发验证码、收据、告警,而去打开 SMTP 会话的那些后台任务、请求处理和 cron。对端可能是 Gmail、SES、一台裸 Postfix,或「上一家供应商给的 SMTP 账号」。

不要迁到邮箱 SMTP。 Rovela 的 SMTP 面向企业邮箱:mx.rovela.dev、端口 465(隐式 TLS 1.2+),用户名是邮箱完整地址,密码是为该客户端创建的设备凭证。一个邮箱只能以自己的地址发送。SMTP 页写明的上限是每封最多 50 个收件人、同一客户端地址每分钟 30 封。同一页建议:程序化、有一定量的发信请用 HTTP API,因为这条路径带跟踪、日志和 webhook。邮件客户端(Outlook、Apple Mail、Thunderbird)应继续走邮箱 SMTP/IMAP;你的应用应迁到 HTTP。

一次可落地的切换

1. 在 SMTP 旁边把 API 先立起来

注册 Rovela,验证你已经用在 MAIL FROM 上的发信域名,并签发 sending_access Key(身份认证)。把 ROVELA_API_KEY 和 MAIL_FROM 放进原来存 SMTP 密码的、仅服务端的密钥库。不要把 Key 发到浏览器。

旧的 SMTP 路径先藏在开关后面(EMAIL_TRANSPORT=smtp|api),方便影子发送或按环境切换。

2. 替换发送函数,而不是每一个调用点

把「发送事务邮件」收拢到一个模块——这也是Email API 集成要做的事。调用方传入 to、subject、html、text,以及对该用户动作稳定的幂等键(如 password-reset:${userId}:${tokenId})。模块负责 HTTP POST:

const res = await fetch("https://api.rovela.dev/emails", {
  method: "POST",
  headers: {
    Authorization: "Bearer " + process.env.ROVELA_API_KEY,
    "Content-Type": "application/json",
    "Idempotency-Key": `signup-verify:${userId}:${codeId}`,
  },
  body: JSON.stringify({
    from: process.env.MAIL_FROM, // e.g. "Acme <no-reply@yourdomain.com>"
    to: user.email,
    subject: `Your Acme code: ${code}`,
    html: `<p>Your verification code is <b>${code}</b>. It expires in 10 minutes.</p>`,
    text: `Your verification code is ${code}. It expires in 10 minutes.`,
    tags: { kind: "signup-otp", userId },
  }),
});
if (!res.ok) {
  const err = await res.json();
  throw new Error(`Rovela ${res.status}: ${err.message}`);
}
const { id } = await res.json(); // accepted and queued — not yet delivered

把 SMTP 习惯映射到 API 字段:

以前现在
From:from(必须在已验证域名上)
To: / Cc: / Bcc:to / cc / bcc(合计上限 50,按收件人计费)
Reply-To:reply_to
MIME multipart同时给 html 和 text,或使用已存储 template
MIME 附件attachments[],content 为 base64
库的重试 / 队列 ack用同一 Idempotency-Key 重试 HTTP(邮件 API 的幂等键)
调度器把 Date 设到未来Rovela 的 scheduled_at,或调度器到点再 POST(定时发送邮件)

3. 换一种方式接收退信

SMTP 时代常常是扫退信邮箱或解析 DSN。用 API 时,200 只表示「已入队」。请订阅 email.bounced、email.complained、email.failed(事务邮件 Webhook,处理退信),并校验签名(验证 Webhook 签名)。

4. 切流量,收回中继凭证

在预发先给自己的收件箱发金丝雀,再生产只切一条链路(例如只切密码重置),再切其余。开关去掉后,撤销旧 SMTP 用户。若 Key 曾进过日志,用 create-then-revoke 轮换 Rovela Key。

常见踩坑

  • from 未验证,或换了子域。 SES/Postfix 也许允许过你从未在 Rovela 添加的域名。在完成已验证域名的 Email API之前会收到指出该域名的 400。
  • 一封信超过 50 个收件人。 这是传输上限,受理前就会检查(发送邮件 API)。拆分名单,或按场景使用批量事务邮件 API / 广播。
  • 把 200 当成已投递。 在删除 SMTP 退信处理之前,先把 webhook 接上。
  • API Key 放在 SMTP 密码曾经泄露过的地方(前端、App、CI 日志)。sending_access 就足够以你的域名发信。
  • 因为「还能走 SMTP」,就把 Rovela 邮箱凭证配进 Nodemailer。 那样只能以该邮箱身份发送,并受邮箱速率限制,也没有 API 的程序化工具。那不是这次迁移。

FAQ

应用继续用 SMTP,新功能再用 Rovela 可以吗? 短时间可以,放在开关后面。最终应只保留一种传输,避免重试、密钥和退信处理分叉。

如果某个供应商库只会 SMTP 怎么办? 在 POST /emails 前面加一个很小的内部服务,或换掉该库的 transport。几乎所有现代运行时都能发 HTTPS(简单的事务邮件 API)。

要不要重做 DKIM? 你需要发布 Rovela 为该发信域名出示的 DNS 记录(SPF、DKIM、DMARC、return-path)。即使旧中继已经有过自己的记录,这一步仍然是必须的(域名设置)。

这和迁移员工收件箱是一回事吗? 不是。邮箱、webmail 和 IMAP 见事务邮件 API + 托管邮箱。本文只谈应用发信。

去掉 SMTP 套接字,留下产品邮件

如果人需要收件箱,邮件客户端可以继续走邮箱 SMTP。把应用发送迁到 POST /emails,使用仅服务端的 sending_access,并为每个动作设置 Idempotency-Key。这才是 Rovela 所针对的 SMTP → API 迁移。