Iris框架本身不提供邮件发送功能,需基于Go标准库net/smtp或第三方包在service层封装实现;关键点包括使用授权码而非登录密码、正确配置smtp.PlainAuth参数顺序及SMTP服务器地址与端口。

iris 里没有内置邮件服务,得自己集成 smtp
iris 框架本身不提供邮件发送能力,它只负责 HTTP 请求处理;发邮件必须用 Go 标准库 net/smtp 或第三方包(如 gomail)。你看到的「Iris 邮件功能」都是业务层封装,不是框架能力。所以配置邮件服务器这件事,和 iris 无关,只和你的 service 层怎么调用 smtp 有关。
smtp.PlainAuth 参数顺序和授权码是关键
常见错误是把密码当 SMTP 密码填,实际绝大多数邮箱(QQ、163、Gmail)要求填「应用专用密码」或「授权码」,不是登录密码。另外 smtp.PlainAuth 四个参数不能乱序:
- 第一个参数:identity,一般留空(
"") - 第二个参数:
*mail.FormEmail(发件人邮箱全名) - 第三个参数:
*mail.Password(授权码,不是密码) - 第四个参数:
*mail.Host(如"smtp.qq.com"或"smtp.163.com")
例如 QQ 邮箱必须用 smtp.qq.com:587,且开启 TLS;163 邮箱用 smtp.163.com:465,需启用 SSL。端口配错会导致 dial tcp: i/o timeout 或 connection refused。
别在 handler 里直接写 smtp.Dial,要封装成 service
直接在 controller 或 handler 里调用 smtp.Dial 和 auth 会带来三个问题:无法复用连接、没做重试、日志和错误难追踪。正确做法是抽离为独立 service:
- 把
smtp.Auth实例缓存起来,避免每次新建 - 发信逻辑加
context.WithTimeout,防止卡死 - 错误统一返回,比如
"failed to send email: auth failed",而不是暴露底层net.Error - 收件人字段用
strings.Split(*mail.ToEmail, ",")拆分时,记得trimSpace,否则"a@b.com, c@d.com"里的空格会导致发送失败
生产环境要注意 Host 和 DNS 解析问题
如果你用 CGO_ENABLED=0 静态编译 iris 服务(推荐),那么 Go 的 DNS 解析会回退到纯 Go 实现,但某些内网 DNS 或自建 mail 服务器可能依赖 libc 的 getaddrinfo。现象是:本地测试能发,部署到 Linux 服务器后报 lookup smtp.qq.com: no such host。解决办法只有两个:
- 编译时设
CGO_ENABLED=1,并确保目标机器装了libc(如glibc) - 或者改用 IP 直连(如
"113.108.211.211:587"),但 IP 可能变更,不推荐
这个点很容易被忽略——因为错误日志看起来像网络不通,实际是 DNS 解析失败,而 Go 默认不打 DNS debug 日志。











