根本原因是net/mail不自动解码mime头字段,需手动用mail.parseaddresslist处理from等字段并用mail.decodeheader解码subject,body需按mime结构和编码单独解码。

解析 net/mail Message 时,发件人字段为空或格式异常
根本原因不是邮件损坏,而是 net/mail 不自动解码 MIME 头字段(比如 From、Subject),遇到 =?UTF-8?B?... 这类编码会原样返回,导致解析出空字符串或乱码。
- 必须手动调用
mail.ParseAddress或mail.ParseAddressList处理From、To等头字段,它们内部会触发 MIME 解码 -
Message.Header.Get("From")返回的是原始字符串,不能直接当邮箱用;应改用msg.Header.AddressList("From") - 若返回
nil或 panic,大概率是头字段语法不规范(如缺失<...></...>),需加if len(addrs) > 0安全判断
提取主题(Subject)时中文显示为乱码或 base64 垃圾
net/mail 对 Subject 头不做任何解码,只提供原始字节。你看到的 =?UTF-8?B?... 就是它原封不动吐出来的。
- 用
mail.DecodeHeader解码:传入msg.Header.Get("Subject"),返回可读字符串 - 注意:该函数不校验编码合法性,错误编码会返回原字符串 + 错误,建议检查返回 error 是否为
nil - 某些老旧邮件用
Q编码(=?UTF-8?Q?...),DecodeHeader同样支持,无需区分
正文内容取不到 / 只拿到一部分 / 拿到的是附件二进制
net/mail 不解析 MIME body 结构,msg.Body 是一个未解码、未解包的 io.Reader,内容取决于邮件是否为 multipart 以及客户端怎么写入。
- 单部分纯文本邮件:可直接
io.ReadAll(msg.Body),但记得先调用msg.Header.Get("Content-Transfer-Encoding")判断是否为base64或quoted-printable,需要对应解码 - multipart 邮件(绝大多数现代邮件):
msg.Body是整个 multipart 流,必须用mime/multipart.NewReader拆解,按Part.Header.Get("Content-Type")匹配text/plain或text/html - 别忽略
charset参数:例如text/plain; charset=UTF-8,解码 body 字节时需按此指定编码,否则中文仍乱码
为什么 ParseAddressList 解析发件人失败却没报错?
mail.ParseAddressList 在遇到无法识别的格式时,会静默跳过非法项,只返回能 parse 的地址 —— 表现为结果 slice 长度为 0,但 error 是 nil。这不是 bug,是设计如此。
立即学习“go语言免费学习笔记(深入)”;
- 典型触发场景:发件人写成
"admin@company.com" <admin></admin>(引号+尖括号混用)、或含未转义逗号 - 调试时打印原始头:
fmt.Printf("Raw From: %q\n", msg.Header.Get("From")),比盲目重试更有效 - 生产环境建议 fallback:若
AddressList("From")为空,再尝试正则粗略提取邮箱(\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b),但仅作兜底
AddressList 的静默失败机制会让问题藏得特别深。










