iris 本身不支持邮件发送,需借助 net/smtp 或 gomail 等库;net/smtp 轻量但需手动处理 mime 和编码,易出错;gomail 更稳但须用 v2.0.0 版本;务必加超时、错误处理、外置配置,并在启动时测试 smtp 连接。

net/smtp 或第三方包(如 gomail、mailgun-go),再在 Iris 的 controller 或 service 层调用。
下面直说关键怎么做、为什么这么选、容易掉坑的地方:
用 net/smtp 发基础文本邮件最轻量,但要手动构造 MIME 头
Go 标准库够用,不用额外依赖,适合简单通知类场景(比如注册确认、密码重置)。但你要自己拼 To、From、Subject 和换行符 \r\n,漏一个就可能被当垃圾邮件或解析失败。
常见错误现象:554 Transaction failed: Mail from domain not allowed(发件域没认证)、malformed MIME header(头字段缺冒号或空格错位)。
-
auth := smtp.PlainAuth("", fromEmail, password, host)中的host必须和 SMTP 服务器域名一致(比如smtp.gmail.com),不能写成gmail.com -
Subject含中文时必须用=?UTF-8?B?...?=Base64 编码,否则 Outlook 等客户端显示乱码 - 发件人邮箱(
fromEmail)和PlainAuth第二个参数必须完全一致;Gmail 要用「应用专用密码」,不是登录密码
用 gomail 发带附件/HTML 邮件更稳,但要注意版本兼容性
gomail(v2)是社区常用选择,自动处理 MIME、编码、多部分、附件嵌入,比手写安全得多。但它已停止维护,最新稳定版是 v2.0.0(非 v3 或主干分支),用错版本会编译报错或发信静默失败。
使用场景:需要 HTML 正文、内嵌图片、多个收件人、文件附件(如 PDF 报表)。
- 初始化时用
gomail.NewDialer(host, port, username, password),注意端口——587(STARTTLS)和465(SSL)行为不同,Gmail 推荐587 - 添加附件用
m.Attach("/path/to/file.pdf"),路径必须存在且进程有读权限;内存中生成的文件建议用m.AttachFile配合bytes.NewReader - Iris controller 里别直接传
*gomail.Message,应封装为 service 方法,避免 handler 层耦合 SMTP 细节
Iris controller 中调用邮件逻辑要加错误处理和超时控制
SMTP 请求是网络 I/O,没设超时可能让整个 HTTP 请求卡住几十秒。Iris 的 context 默认无超时,得手动加。
- 在 service 层用
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)包一层再传给发信函数 - 不要忽略
err:比如auth失败、DNS 解析失败(no such host)、连接被防火墙拒绝(connection refused)都得返回明确错误,而不是只 log - 别在 handler 里直接
fmt.Println或 panic,要用ctx.StatusCode(500)+ctx.JSON返回结构化错误,方便前端或监控识别
生产环境务必避免硬编码 SMTP 凭据和配置
凭据写死在代码或 struct 里等于裸奔。IRIS 项目常配合 iris.Config().SetCharset("UTF-8") 这类全局设置,但 SMTP 配置必须外置。
- 从环境变量读取:
os.Getenv("SMTP_HOST"),启动时检查是否为空并 panic 提示 - 敏感字段(
Password)绝不进日志,log.Printf("sending to %s", to)可以,但log.Printf("auth: %v", auth)不行 - 测试阶段用
smtp.SendMail模拟函数替换真实调用,或用gomail.NewNoopSender()(需自行 patch)做单元测试隔离
TestConnection() 方法,主动连一次并 QUIT,把问题暴露在启动阶段。











