Beego 不推荐使用已废弃的 beego.SendMail,因其不支持 TLS/SSL 1.3 和现代认证;应改用 github.com/jordan-wright/email 等第三方库,配合 App Password、正确 TLS 配置及异步发送保障可靠性。

Beego 框架本身不内置邮件发送模块,得自己集成 SMTP 客户端库,比如 net/smtp 或第三方包如 github.com/jordan-wright/email。直接用 Beego 的 beego.SendMail 已废弃且不支持 TLS/SSL 1.3、现代认证方式(如 OAuth2),生产环境会连不上 Gmail、Outlook 或企业邮箱。
为什么 beego.SendMail 不推荐用
Beego 1.x 里曾提供 beego.SendMail,但它底层调用的是过时的 net/smtp 原生实现,没有封装证书校验、STARTTLS 升级、SMTP AUTH 类型自动协商等逻辑。实际使用中常见报错:
-
dial tcp: lookup smtp.gmail.com: no such host(DNS 或代理问题,但更常因未设tls.Config导致连接被拒) -
535 5.7.8 Username and Password not accepted(Gmail 禁用“低安全性应用访问”,需开启 App Password 或 OAuth2) -
454 4.7.0 TLS not available(目标服务器要求 STARTTLS,但旧实现没触发升级)
所以别碰 beego.SendMail,哪怕文档里还留着。
用 github.com/jordan-wright/email 手动发带附件的邮件
这个包轻量、稳定、支持 HTML、纯文本、附件、自定义 From 昵称,且对 TLS 处理清晰。Beego 项目里可直接 import 使用:
先安装:
go get github.com/jordan-wright/email
在 controller 或 service 中写发送逻辑(注意替换配置):
import (
"crypto/tls"
"net/smtp"
"github.com/jordan-wright/email"
)
func sendEmail(to, subject, htmlBody, filePath string) error {
e := email.NewEmail()
e.From = "admin@yourdomain.com"
e.To = []string{to}
e.Subject = subject
e.HTML = []byte(htmlBody)
if filePath != "" {
err := e.AttachFile(filePath)
if err != nil {
return err
}
}
auth := smtp.PlainAuth("", "admin@yourdomain.com", "your-app-password", "smtp.gmail.com")
return e.SendWithTLS("smtp.gmail.com:587", auth, &tls.Config{ServerName: "smtp.gmail.com"})
}
关键点:
-
SendWithTLS必须配&tls.Config{ServerName: ...},否则 Go 1.19+ 会校验失败 - Gmail 用户必须用 App Password,不是账户密码;开启路径:Google 账户 → 安全 → 两步验证 → 应用专用密码
- 企业邮箱(如腾讯企业邮、阿里云邮件推送)端口通常是
465(SSL)或587(STARTTLS),不能混用
Beego 配置中心怎么安全存 SMTP 凭据
别把密码硬编码进代码。Beego 支持从配置文件加载,推荐用 conf/app.conf 的 ini 格式:
[prod] email.host = smtp.exmail.qq.com email.port = 465 email.from = noreply@company.com email.nickname = 公司通知系统 email.username = noreply@company.com email.password = your-secure-app-password email.is_ssl = true
读取时用:
host := beego.AppConfig.String("email.host")
port := beego.AppConfig.DefaultInt("email.port", 465)
username := beego.AppConfig.String("email.username")
password := beego.AppConfig.String("email.password")
isSSL := beego.AppConfig.DefaultBool("email.is_ssl", true)
注意:email.password 在部署时应通过环境变量覆盖(如 EMAIL_PASSWORD=xxx),避免配置文件泄露。
异步发送避免阻塞 HTTP 请求
Beego 默认是同步处理请求,如果每封邮件都走完整 SMTP 流程(平均 300–800ms),高并发下会拖垮 API。必须剥离到 goroutine 或消息队列:
- 简单场景:起 goroutine,加
recover防 panic 泄露 - 中大型项目:接入 Redis Stream 或 NSQ,由独立 worker 消费发送任务,Beego 只负责入队
- 切忌在
Controller.Post()里直接调sendEmail(...)—— 这会让用户等超时,且失败无法重试
goroutine 示例(仅限低频通知):
go func() {
defer func() {
if r := recover(); r != nil {
beego.Error("email send panic:", r)
}
}()
sendEmail(user.Email, "注册成功", "<h2>欢迎加入</h2>", "")
}()
真正要支撑日均万封以上,就得上 Redis Stream + worker 模式,这部分和 Beego 无关,而是工程架构选择 —— 别指望框架替你扛住并发。


















