Mailgun API v4 的 Go 客户端必须使用 mailgun-go v4.0.0+,需显式指定验证域名、匹配的 From 地址、分离 SetRecipients 与 SetCcs、附件路径须 ASCII 且可读、生产环境必须启用域验证并校验 Webhook 签名。

Mailgun API v4 的 Go 客户端必须用 mailgun-go 且版本 ≥ 4.0.0
旧版 mailgun-go(v3 及之前)默认调用的是已弃用的 v3 API,而 Mailgun 自 2023 年起强制要求使用 v4 API,否则会返回 401 Unauthorized 或 403 Forbidden 错误,即使 API key 正确。v4 要求显式指定 domain(不是发信域名,而是你在 Mailgun 控制台里“Sending Domains”下注册并验证的那个域名),且所有请求必须带 From 地址匹配该 domain 的 verified sender。
- 安装最新兼容版:
go get github.com/mailgun/mailgun-go/v4@latest - 初始化时必须传入 domain:
mg := mailgun.NewMailgun("your-domain.mailgun.org", "your-api-key")(注意不是api.mailgun.net) -
From必须是该 domain 下已验证的邮箱,例如"billing@your-domain.mailgun.org";未验证会直接拒信,不报错但日志显示Not Verified
账单邮件需区分 To 和 Cc,且 Cc 地址必须显式加入 SetCcs()
Mailgun 的 Go SDK 不支持在 SetRecipients() 中混写 cc: 前缀——它会把整个字符串当普通收件人处理,导致抄送人收到两封(一封 To、一封 Cc),且无法被正确归类到收件箱的“抄送”标签下。正确做法是分开设置:
- 主收件人(用户)用
msg.SetRecipients("user@example.com") - 抄送人(财务/运营邮箱)用
msg.SetCcs("finance@company.com", "ops@company.com") - 若漏掉
SetCcs()而只写进SetRecipients(),Mailgun 会当作全部是 To,触发反垃圾策略限频(尤其高频账单场景)
示例片段:
msg := mg.NewMessage(
"billing@your-domain.mailgun.org",
"您的账单已生成",
"",
"user@example.com",
)
msg.SetCcs("finance@company.com")
msg.AddContent("text/plain", plainBody)
msg.AddContent("text/html", htmlBody)
账单附件必须用 AddFile() 且路径不能含中文或空格
Mailgun 不接受 base64 内联附件,也不支持直接传入 bytes slice;必须提供可读取的本地文件路径。如果用 os.CreateTemp 生成 PDF 账单,路径中含中文或空格会导致 AddFile() 静默失败(无 error 返回,但邮件无附件)。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
立即学习“go语言免费学习笔记(深入)”;
- 临时文件路径建议用纯 ASCII:
tmpDir, _ := os.MkdirTemp("", "bill-*.pdf") - 调用前确认文件存在且可读:
os.Stat(filePath),否则AddFile()不报错但丢附件 - PDF 文件名若含特殊字符(如
invoice_2024-05-01 用户A.pdf),需用mime.BEncoding.Encode("UTF-8", filename)编码后传给AddFile()的第二个参数
生产环境必须启用 VerifyDomain() 并监听 Webhook 处理投递状态
账单邮件属于高敏感、高时效性通信,不能只依赖发送成功返回。Mailgun 的 Send() 只表示“已接收”,不代表送达。必须配置 Webhook 监听 delivered、failed、complained 事件,并关联账单 ID 做状态回写。
- 域验证不通过会导致批量退信率飙升,验证地址是
postmaster@your-domain.mailgun.org,不是你自定义的 billing 地址 - Webhook endpoint 必须校验
X-Mailgun-Signatureheader,否则易被伪造回调 - 对
failed事件,应触发重试(最多 1 次)+ 人工告警,而非静默丢弃
关键点就这些:API 版本、Cc 分离、附件路径、Webhook 校验——少一个,账单邮件就可能在某个环节失效,而且很难从日志里一眼看出问题在哪。

















