必须用html/template渲染HTML邮件,因其默认对插值自动HTML实体转义(如<→<),支持template.HTML类型插入可信HTML,而text/template无转义、无上下文感知,易致源码显示或XSS风险。

邮件模板必须用 html/template,不是 text/template —— 后者不转义、无安全防护,发 HTML 邮件会直接暴露标签源码;前者默认转义,但支持通过 template.HTML 类型插入可信片段。
为什么用 html/template 渲染 HTML 邮件?
因为 html/template 在执行时会对所有插值自动做 HTML 实体转义(比如 → <code><),防止用户输入的恶意内容被渲染为可执行脚本。而 text/template 完全不转义,也不提供 safeHTML 这类函数——它压根不是为 HTML 场景设计的。
- 用
text/template渲染 HTML 字符串,结果就是一整页<div><b>Hello</b></div>,客户端不会解析成样式 - 用
html/template但没把原始 HTML 包装成template.HTML,同样显示为源码 - SMTP 发送时必须设
Content-Type: text/html; charset=utf-8,否则 Outlook、Apple Mail 会当纯文本处理
template.HTML 怎么用才安全?
只能在数据层提前转换,不能在模板里“修复”:传入结构体字段时,该字段类型必须是 template.HTML,而不是 string。
- ✅ 正确:
Body: template.HTML(`<strong>Hi</strong>`) - ❌ 错误:
{{.Body | safeHTML}}——html/template不带这个函数,text/template有但不适用 HTML 场景 - ⚠️ 危险:把用户提交的富文本直接转
template.HTML—— 等于主动绕过 XSS 防护 - ? 替代方案:用
bluemonday或sanitizer库预处理 HTML 再包装
模板加载和复用要注意什么?
别每次发信都 ParseFiles,CPU 开销大;也别把头部/尾部硬编码进主模板,维护成本高。
立即学习“go语言免费学习笔记(深入)”;
- 启动时一次性加载:
template.Must(template.ParseGlob("templates/*.html")) - 用
{{define "header"}}...{{end}}+{{template "header" .}}拆分复用块 - 路径写错会导致
template: ...: no such template,注意相对路径基于os.Executable()目录还是工作目录 - 字段名必须首字母大写(Go 导出规则),
type EmailData { Subject string }才能在模板里写{{.Subject}}
本地预览 HTML 邮件为什么总不对?
浏览器渲染引擎和邮件客户端(Outlook、Gmail App、Apple Mail)根本不是一回事:它们不支持 Flex 布局、多数 CSS 属性会被过滤,甚至 <style> 标签都可能被丢弃。
- 别用 Chrome 直接打开
.html文件判断效果 - 用
mailcatcher或MailHog搭本地 SMTP 服务收信预览 - 优先用表格布局、内联样式、避免 JS 和外部字体
- 发送前检查换行符是否为
\r\n(尤其 Windows 环境),否则某些客户端解析 header 失败
真正麻烦的不是语法,而是 HTML 邮件的兼容性黑洞——同一份模板,在 Gmail Web 版能正常显示加粗,在 Outlook Desktop 可能连换行都错位。别指望一次写完就通用,得针对主流客户端反复测试。


















