如何使用Golang发送HTML格式邮件_Web应用通知服务实现

1次阅读

用net/smtp发html邮件必须手动构造mime头,包括mime-version、content-type(text/html; charset=utf-8)及空行分隔;漏换行、缺charset或未用multipart/alternative会导致显示异常或被拒收。

如何使用Golang发送HTML格式邮件_Web应用通知服务实现

net/smtp 发 HTML 邮件必须手动构造 MIME 头

go 标准库没有内置的 HTML 邮件封装函数,net/smtp 只负责传输,内容格式得自己拼。直接把 HTML 字符串塞进 msg 里发出去,收件方大概率看到的是纯文本源码,或者被当垃圾邮件拦截。

关键点在于:必须显式写入 MIME-VersionContent-Type 和空行分隔。常见错误是漏掉换行、类型写成 text/html 却没声明 charset,或把整个邮件体当一个字符串传给 smtp.SendMail 而没加头。

  • HTML 部分要包裹在 Content-Type: text/html; charset=utf-8 块里
  • 邮件头和正文之间必须有且仅有一个空行(rnrn
  • 如果同时发 HTML + 纯文本备用,得用 multipart/alternative 结构,不能简单拼接

gomail 库发 HTML 邮件更稳但要注意默认编码

gomail 是最常用的 Go 邮件库,它自动处理 MIME 封装,Dialer 支持 TLS/sslMessageSetBody 方法能直接设 HTML 内容。但它的默认行为容易踩坑:不显式指定 charset 时,部分邮箱(比如 outlook Web)会按 ISO-8859-1 解析 UTF-8 字符,导致中文乱码。

  • 务必调用 m.SetHeader("MIME-Version", "1.0")(虽然文档说可选,但某些 SMTP 网关会拒收无此头的邮件)
  • m.SetBody("text/html", htmlStr) 后,再补一句 m.SetHeader("Content-Transfer-Encoding", "base64") 更稳妥,尤其含中文或特殊符号时
  • 避免用 m.Attach() 传 HTML 字符串——它只处理文件路径,不是内容注入

Web 应用中发 HTML 邮件要防模板注入和链接失效

Web 服务常把用户输入动态嵌入邮件模板(比如欢迎邮件里的用户名、重置链接),这时 HTML 模板渲染不加过滤,就等于把 xss 漏洞直送收件箱;而相对路径的 CSS 或图片链接,在邮件客户端里基本全失效。

立即学习go语言免费学习笔记(深入)”;

  • 所有用户输入必须经 html.EscapeString() 处理,别信前端已过滤——邮件后端是独立上下文
  • CSS 只能用内联样式(style="..."),外部 <link>@import 基本被屏蔽
  • 图片必须用绝对 URL(如 https://yourapp.com/email-assets/logo.png),且确保该路径允许匿名访问、不带登录态校验
  • 密码重置等敏感链接,务必带一次性 Token 并设置短过期时间,别依赖前端 js 拼接

SMTP 连接失败或被拒的常见原因和验证方式

本地测试能发,上线后静默失败?多数不是代码问题,而是 SMTP 配置或网络策略卡住。Gmail、Outlook 等服务商对未验证域名、高频发送、无 SPF/DKIM 记录的邮件直接拒收或进垃圾箱。

  • 先用 telnet smtp.gmail.com 587 测试端口连通性(注意:有些云服务器禁 outbound 25/587)
  • 检查发信域名是否配置了 SPF 记录(如 v=spf1 include:_spf.google.com ~all
  • Go 日志里捕获到 535 5.7.8 Username and Password not accepted?说明密码错或需开启「应用专用密码」(Gmail 开了 2FA 后必须用)
  • go run main.go 2>&1 | grep -i "auth|535|421" 快速定位认证或限流错误

真正麻烦的从来不是怎么拼 HTML,而是让那封邮件穿过层层网关、不被当成广告、不被丢进垃圾箱——每家邮箱的过滤规则都不声不响地变,你得盯着退信日志,而不是只看 err == nil

text=ZqhQzanResources