gomail是发送带附件邮件最直接方案,它封装了mime构造、base64编码、边界符生成等易错环节;需用go get gopkg.in/gomail.v2安装,调用m.attach()添加附件并注意路径可读、大小限制及中文名编码兼容性。

用 gomail 发送带附件的邮件最直接
Go 标准库没有原生支持 MIME 多部分邮件(如带附件)的高层封装,gomail 是目前最稳定、文档清晰、被广泛验证的选择。它底层仍用 net/smtp 和 mime/multipart,但帮你绕开了手动构造 Content-Type、边界符、Base64 编码、文件头字段等易错环节。
常见错误是试图用 net/smtp.SendMail 直接拼接原始邮件体——边界不一致、换行符不规范、附件内容未编码,会导致收件方看到乱码或附件无法识别。
- 安装:
go get gopkg.in/gomail.v2(注意版本号,v2 是当前主流) - 发件人邮箱必须开启 SMTP 服务(如 Gmail 需开启“应用专用密码”,QQ 邮箱需开启 SMTP 并获取授权码)
- 附件路径必须可读;相对路径以当前工作目录为准,建议用
os.ReadFile显式读取并检查错误 - 不要把大文件(>10MB)直接 attach,SMTP 服务器通常有单封邮件大小限制(Gmail 是 25MB,但含编码膨胀)
gomail.Message 添加附件的正确写法
附件不是简单“加个文件路径”,而是调用 Attach 方法,并传入原始字节和可选的 gomail.Rename 或 gomail.SetHeader 来控制文件名和 MIME 类型。
容易忽略的是:如果附件是图片或 PDF,但没显式设置 Content-Type,gomail 默认用 application/octet-stream,某些客户端可能不自动预览。
- 基础用法:
m.Attach("/path/to/report.pdf")—— 自动推断类型和文件名 - 指定文件名(如避免中文乱码):
m.Attach("/tmp/data.csv", gomail.Rename("销售数据.csv")) - 强制设置 MIME 类型:
m.Attach("/tmp/image", gomail.SetHeader(map[string][]string{"Content-Type": {"image/png"}})) - 内存中生成的附件(如动态生成的 CSV):
m.Attach("report.csv", gomail.SetCopyFunc(func(w io.Writer) error { return writeCSVTo(w) }))
认证失败或连接超时的典型原因
报错 dial tcp: i/o timeout 或 535 5.7.8 Authentication failed 不一定是代码问题,90% 出在 SMTP 配置。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- Gmail 用户必须用“应用专用密码”代替账户密码,且需已开启两步验证
- QQ 邮箱必须在网页端设置 → 账户 → “POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务”中开启 SMTP,并复制“SMTP 服务授权码”
- 端口别混淆:
smtp.gmail.com:587(STARTTLS)或:465(SSL),gomail默认走 STARTTLS,若用 465 需显式调用SetAddressPort并设UseSSL: true - 企业邮箱(如阿里云域名邮箱)可能限制非白名单 IP 的 SMTP 登录,本地开发机直连大概率被拒
附件中文名在 Outlook 里显示为乱码怎么办
这不是 Go 的 bug,是 MIME 标准对非 ASCII 文件名的支持差异。RFC 2231 规定需用 filename*=UTF-8''xxx 编码,但 gomail.v2 当前(v2.0.0)不自动处理该格式,需手动干预。
解决方式是绕过 gomail.Rename,改用 gomail.SetHeader 写入符合 RFC 的头字段:
m.Attach("/tmp/测试报告.pdf", gomail.SetHeader(map[string][]string{
"Content-Disposition": {
`attachment; filename="=?UTF-8?B?6L+Z5piv5bCP5pyf.pdf?="`,
},
}))
其中 6L+Z5piv5bCP5pyf 是“测试报告”UTF-8 字节的 Base64 编码(不含空格和换行)。更稳妥的做法是用 mime.BEncodingEncoder 动态生成,但多数场景下静态编码一次即可。
真正麻烦的是:不同客户端解析逻辑不一,iOS Mail 和 Thunderbird 支持较好,Outlook for Windows 最挑剔——所以生产环境建议附件名尽量用 ASCII 字符,避免把精力耗在编码兼容性上。










