竹简文档
Email 邮件服务(可选)

Template 模板系统

邮件模板引擎与内置模板

Template 模板系统

Email 插件内置 Go html/template 模板引擎,提供开箱即用的邮件模板,同时支持加载外部自定义模板。

内置模板

插件通过 embed.FS 嵌入模板文件,无需额外配置即可使用:

verification — 验证码邮件

用于发送邮箱验证码,包含高亮验证码和过期时间提示。

模板数据:

字段类型说明
Codestring验证码
Expirestring过期时间描述(如 "5 分钟")

使用示例:

err := emailClient.SendTemplate(ctx, &xEmail.Message{
    To:       []string{"user@example.com"},
    Subject:  "邮箱验证码",
    Template: "verification",
    TemplateData: map[string]string{
        "Code":   "836521",
        "Expire": "5 分钟",
    },
})

welcome — 欢迎注册邮件

用户注册成功后发送的欢迎邮件。

模板数据:

字段类型说明
Usernamestring用户名

使用示例:

err := emailClient.SendTemplate(ctx, &xEmail.Message{
    To:       []string{"user@example.com"},
    Subject:  "欢迎加入",
    Template: "welcome",
    TemplateData: map[string]string{
        "Username": "筱锋",
    },
})

reset_password — 重置密码邮件

密码重置请求邮件,包含重置链接和安全提示。

模板数据:

字段类型说明
ResetURLstring密码重置链接
Expirestring链接过期时间描述(如 "30 分钟")

使用示例:

err := emailClient.SendTemplate(ctx, &xEmail.Message{
    To:       []string{"user@example.com"},
    Subject:  "重置密码",
    Template: "reset_password",
    TemplateData: map[string]string{
        "ResetURL": "https://example.com/reset?token=abc123",
        "Expire":   "30 分钟",
    },
})

模板架构

内置模板采用 基础布局 + 内容块 的架构:

_base.html              ← 基础布局(页头、页脚、样式)
  └── {{template "content" .}}
        ├── verification.html   ← {{define "verification"}} 验证码
        ├── welcome.html        ← {{define "welcome"}} 欢迎
        └── reset_password.html ← {{define "reset_password"}} 重置密码
  • _base.html 提供统一的邮件外观(品牌标题、页脚声明、背景样式)
  • 每个具体模板通过 {{define "模板名"}} 定义内容块,模板名须与文件名一致(不含 .html 后缀)
  • 渲染时通过 Lookup 查找指定模板,将内容注入 base 布局的 "content" 槽位后输出

TemplateManager API

Render — 渲染模板

渲染指定模板并返回 HTML 字符串。

func (t *TemplateManager) Render(name string, data any) (string, error)

参数:

  • name — 模板名称(不含 .html 后缀),如 "verification"
  • data — 模板数据,传入模板变量

示例:

html, err := emailClient.tmpl.Render("verification", map[string]string{
    "Code":   "123456",
    "Expire": "5 分钟",
})

Render 通常不需要直接调用,使用 SendTemplate 会自动渲染并发送。

ListTemplates — 列出模板

返回当前所有可用的模板名称。

func (t *TemplateManager) ListTemplates() []string

示例:

names := emailClient.ListTemplates()
// ["verification", "welcome", "reset_password"]

AddDir — 添加外部模板目录

加载外部目录中的 HTML 模板文件,同名模板覆盖内置模板。

func (t *TemplateManager) AddDir(dir string) error

示例:

err := emailClient.AddTemplateDir("/path/to/custom/templates")

自定义模板

方式一:环境变量指定外部模板目录

通过 EMAIL_TEMPLATE_DIR 环境变量指定外部模板目录,InitClient 时自动加载:

.env
EMAIL_TEMPLATE_DIR=/path/to/custom/templates

方式二:运行时动态添加

emailClient := xCtxUtil.MustGetEmailClient(ctx)
err := emailClient.AddTemplateDir("/path/to/custom/templates")

编写自定义模板

在外部模板目录中创建 HTML 文件,文件名即为模板名称:

custom/templates/order_confirm.html
{{define "order_confirm"}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
    <tr>
        <td style="padding-bottom: 24px;">
            <h2 style="margin: 0 0 16px; font-size: 20px; font-weight: 600; color: #1a1a1a;">
                订单确认
            </h2>
            <p style="margin: 0; font-size: 15px; color: #555555; line-height: 1.6;">
                您的订单 <strong style="color: #1a1a1a;">{{.OrderID}}</strong> 已确认。
            </p>
            <p style="margin: 16px 0 0; font-size: 15px; color: #555555; line-height: 1.6;">
                金额: <strong style="color: #4f7cff;">¥{{.Amount}}</strong>
            </p>
        </td>
    </tr>
</table>
{{end}}

使用自定义模板:

err := emailClient.SendTemplate(ctx, &xEmail.Message{
    To:       []string{"user@example.com"},
    Subject:  "订单确认",
    Template: "order_confirm",
    TemplateData: map[string]any{
        "OrderID": "ORD-20260503-001",
        "Amount":  "299.00",
    },
})

覆盖内置模板

在外部模板目录中创建与内置模板同名的文件即可覆盖:

custom/templates/
  ├── verification.html     ← 覆盖内置验证码模板
  └── order_confirm.html    ← 新增自定义模板

注意事项

  • 模板名称: 模板名称不含 .html 后缀和 template/ 前缀,直接使用如 "verification"
  • _base.html 不可覆盖: 基础布局模板名称为 _base,不会出现在 ListTemplates 结果中。
  • 文件格式: 外部模板必须是 .html 后缀的文件,且使用 {{define "模板名"}} 定义内容块。define 名称须与文件名一致(不含 .html 后缀),例如 order_confirm.html 中应为 {{define "order_confirm"}}
  • 数据传递: TemplateData 支持 map[string]any 或自定义结构体,模板中通过 {{.FieldName}} 访问字段。

下一步

On this page