beego邮件发送需手动配置utils.email+外部smtp,关键在关闭qq邮箱“独立密码”、使用587端口+starttls、json配置字段严格匹配、to必须为字符串切片、from须与username一致,且务必检查err并记录。

Beego 的邮件发送不是开箱即用的独立服务,而是依赖 utils.EMail 模块 + 外部 SMTP 服务(如 QQ 邮箱)手动配置,且极易因授权码、端口或 TLS 设置错误导致静默失败。
QQ 邮箱 SMTP 授权码必须关闭独立密码才能生效
很多开发者卡在“账号密码正确但发不出邮件”,根本原因是 QQ 邮箱启用了「独立密码」——它会直接使授权码失效。哪怕你刚生成了 16 位授权码,只要独立密码处于开启状态,emailConn.Send() 就会返回 auth: failed to authenticate 或空错误(无明确提示)。
- 登录 QQ 邮箱网页 → 设置 → 账户 → 找到「独立密码」入口 → 点击「关闭」
- 关闭后,再重新进入「POP3/IMAP/SMTP/Exchange」设置页,点击「开启」并完成密保验证,获取新授权码
- 授权码只在首次生成时显示一次,务必立刻复制保存;修改 QQ 密码也会使其立即过期
utils.NewEMail() 的 JSON 配置必须严格匹配字段名和类型
Beego 的 utils.NewEMail() 接收一个 JSON 字符串,但不校验字段合法性,拼错字段名(比如写成 "passwd" 或 "smtp_host")会导致连接被拒绝或 panic,错误信息往往只有 connection refused 这类泛化提示。
- 必需字段只有四个:
"username"(完整邮箱)、"password"(授权码,非登录密码)、"host"(如"smtp.qq.com")、"port"(整数,不是字符串) - QQ 邮箱推荐用
port: 587+ STARTTLS,不要用 465(旧版 SSL,Beegoutils模块对 SSL 支持不稳定) - 示例正确配置:
{"username":"test@qq.com","password":"abcd1234efgh5678","host":"smtp.qq.com","port":587}
发送前必须显式设置 From 和 To,且 To 必须是切片
emailConn.To = "user@example.com" 看似合理,但会触发 panic:Beego 要求 To 是 []string 类型,单个邮箱也得写成 []string{"user@example.com"}。而 From 是字符串,不设或设错会导致邮件被拒收(尤其企业邮箱网关)。
-
emailConn.From必须与username一致,否则 QQ 邮箱会拒绝发送 -
emailConn.To可以是多个地址:[]string{"a@x.com", "b@y.com"} - 正文至少填
Text或HTML其中一个,两者都为空时Send()会返回empty body错误
日志里看不到错误?记得检查 err 并用 beego.Error() 输出
emailConn.Send() 失败时不会自动打日志,只返回 error 值。如果代码里只写 fmt.Println(err) 或漏掉判断,问题就彻底隐身了——你只会发现“邮件没收到”,却找不到线索。
- 务必检查返回值:
if err != nil { beego.Error("email send failed:", err) } - 常见错误值包括:
dial tcp: lookup smtp.qq.com: no such host(DNS 问题)、net/smtp: invalid header(From格式不对)、535 Authentication failed(授权码错或独立密码开着) - 生产环境建议加超时控制:原生
utils.EMail不支持,需自己封装net/smtp客户端或升级到logs.AdapterSMTP(仅用于日志投递,不通用)
最常被忽略的是:QQ 邮箱的 SMTP 服务开关、独立密码状态、授权码有效期这三者必须同时满足,缺一不可。调试时别只盯着代码,先去网页端确认这三项是否真正“开启且生效”。











