如何从Heroku发送事务型电子邮件(使用Mailer To Go)
Heroku dyno 是运行应用的好地方,但运行邮件服务器的可怕地方。文件系统是临时的,dyno IP 是共享和轮换的,出站端口 25 实际上无法使用——所以你尝试直接从 dyno 发送的任何邮件最终都会进入垃圾邮件,如果它能离开的话。解决办法是将发送交给电子邮件服务。Mailer To Go 是一个 Heroku 插件,可在几秒内配置,并自动集成到你的应用中,因此你可以通过经过身份验证、信誉管理的 587 端口连接发送。
本指南让你在 Heroku 上从零开始发送并进入收件箱的电子邮件,涵盖让人困惑的 Heroku 特定问题(配置变量、审查应用、后台任务)。
步骤 1 — 配置插件
从 CLI:
heroku addons:create mailertogo --app your-app
或从 Heroku Elements 市场添加它。无论哪种方式,配置都会自动在你的应用上设置这些配置变量——无需复制粘贴凭证:
heroku config --app your-app | grep MAILERTOGO
# MAILERTOGO_SMTP_HOST: smtp.mailertogo.com
# MAILERTOGO_SMTP_USER: ...
# MAILERTOGO_SMTP_PASSWORD: ...
# MAILERTOGO_API_KEY: ...
要将其声明为依赖项,以便每次部署和审查应用都获得它,请将其添加到 app.json:
{
"addons": ["mailertogo"]
}
步骤 2 — 验证你的发送域
在 Mailer To Go 仪表板中添加发送子域——mtg.yourdomain.com——并发布它显示的 SPF 和 DKIM 记录(加上根域处的 DMARC 策略)。子域将你应用的发送信誉与根域分离,正是这使得来自 Heroku 等临时平台的邮件可靠送达的原因。请参阅 为什么 Mailer To Go 从 mtg.yourdomain.com 发送和 SPF/DKIM/DMARC 设置指南。
步骤 3 — 指向你的应用到配置变量
你的应用已将凭证作为环境变量——只需引用它们。
Rails:
# config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: ENV["MAILERTOGO_SMTP_HOST"], # smtp.mailertogo.com
port: 587,
user_name: ENV["MAILERTOGO_SMTP_USER"],
password: ENV["MAILERTOGO_SMTP_PASSWORD"],
authentication: :plain,
enable_starttls: true
}
Node.js (Nodemailer):
const transport = require("nodemailer").createTransport({
host: process.env.MAILERTOGO_SMTP_HOST,
port: 587,
auth: { user: process.env.MAILERTOGO_SMTP_USER, pass: process.env.MAILERTOGO_SMTP_PASSWORD },
});
更喜欢 HTTP 而非 SMTP,或使用其他语言?改用 REST API——完整示例在 使用 Mailer To Go API 和 SMTP 发送电子邮件。
步骤 4 — 部署并发送测试
git push heroku main
heroku run rails runner 'ActionMailer::Base.mail(from: "hello@mtg.yourdomain.com", to: "you@example.com", subject: "Hello from Heroku", body: "It works.").deliver_now' --app your-app
heroku logs --tail --app your-app # 查看发送
在 Gmail 中打开该邮件 → 显示原文并确认 SPF、DKIM 和 DMARC 都说 PASS。
Heroku 特定问题
- 永远不要硬编码凭证。 设置配置变量会重启你的 dyno 并清洁轮换;硬编码密码在凭证轮换后仍然存在并会无声地中断。始终从
ENV读取。 - 从后台任务发送。 dyno 文件系统是临时的,web 请求有 30 秒超时,所以不要在控制器操作中内联发送。加入队列到 Sidekiq / Delayed Job / GoodJob 并从工作进程发送——更快的响应,以及临时 SMTP 错误的自动重试。
- 审查应用和管道。 在
app.json中使用mailertogo,每个审查应用都可以配置自己的实例;如果你不想从临时应用发送真实邮件,将邮件程序覆盖为:test(Rails)或在这些环境中的全局捕获。 - 端口 25 是死胡同——你不需要它。 Heroku(如同每个主要云提供商)使出站端口 25 无法使用;Mailer To Go 使用提交端口 587,它是开放的。如果你曾看到端口 25 上的连接挂起,那就是原因。
- 扩展 dyno 没关系。 SMTP 是每条消息无状态的,所以运行多个 web/worker dyno 无需特殊处理——每个 dyno 读取相同的配置变量。
为什么这个有效而从 dyno 发送不行
可递送性是由发送 IP 和域玩的信誉游戏。Heroku dyno 既没有稳定的 IP 也没有预热的信誉,无法发布收件箱提供商要求的身份验证记录。Mailer To Go 提供受管 IP、DKIM 签名和密钥轮换、SPF/DMARC 对齐以及退信/投诉处理——因此你的 dyno 做它擅长的事(运行你的应用),而你的电子邮件运行在专为送达而构建的基础设施上。
通过 Addons.io 或 Build.io 部署?设置相同——参阅 在 Heroku、Addons.io 和 Build.io 上使用 Mailer To Go。通常使用 Heroku 子域?参阅 Heroku 子域:入门指南。