必须用 html/template 渲染 HTML 邮件,Content-Type 设为 "text/html",数据字段首字母大写;否则模板取不到值、显示源码或触发 XSS。

必须用 html/template 渲染 HTML 邮件,Content-Type 必须设为 "text/html",且数据字段首字母必须大写;否则模板取不到值、邮件显示源码或触发 XSS 风险。
为什么发出去的邮件显示的是 HTML 源码而不是渲染结果
常见原因就两个:Content-Type 没设对,或者用了 text/template 却当成 HTML 发。
- 用
gomail时,必须调m.SetBody("text/html", ...),不能只传字符串不设类型 - 用
net/smtp手动构造 MIME 时,Content-Type: text/html; charset=utf-8这行必须存在,且不能被空行或乱序破坏 - 如果模板是用
text/template渲染的,哪怕内容全是<div><b>hi</b></div>,也会原样发出——它不转义,但也不声明自己是 HTML -
\r\n\r\n分隔符位置错会导致整个 body 被当 header 解析,直接拒收或显示异常
如何安全插入富文本或已构造好的 HTML 字符串
用户输入的富文本(比如后台编辑器内容)不能直接塞进模板,否则会被自动转义成 <div>;但也不能无条件信任并全量放开——这是 XSS 温床。
<ul>
<li>在 Go 数据层提前转换:<code>Body: template.HTML(userInput),而不是在模板里写 {{.Body | safeHTML}}(html/template 根本没这个函数)
type EmailData struct { Content template.HTML },不能是 content template.HTML
template.HTML —— 比如昵称含 <script>alert(1)</script>,一包就执行bluemonday 等库白名单过滤,再转 template.HTML
模板文件路径和执行时的常见坑
ParseFiles 和 ParseGlob 看似简单,但路径错一个字符、工作目录不对,就 panic 或静默失败。
立即学习“go语言免费学习笔记(深入)”;
- 路径用相对路径时,基准是进程启动目录,不是
main.go所在目录;建议用filepath.Join(os.Getenv("PWD"), "templates", "email.html")显式拼接 -
template.Must(template.ParseFiles("templates/email.html"))中的"templates/email.html"必须真实存在,且 Go 进程有读权限 - 执行
tmpl.Execute前,确保传入的是导出字段的结构体或 map[string]interface{},例如struct{ Title string }可以,struct{ title string }不行 - 模板里不要写 JS、
<style>或外链 CSS——Outlook、Apple Mail 大部分会干掉,表格布局仍是兼容性最稳的选择
最容易被忽略的其实是预览环节:别用浏览器直接打开 .html 文件看效果,邮件客户端的解析逻辑和浏览器完全不同。本地测试务必走真实 SMTP 流程,比如用 mailcatcher 或 smtp4dev 搭个接收端,再看它网页界面里最终渲染成什么样。



















