跳到主要内容

邮件模板

Logto 提供了多种用于自定义邮件内容的模板,这些模板根据使用场景进行分类。

强烈建议你在不同场景下使用不同的模板。否则,用户可能会收到与当前操作不符的邮件内容,造成困惑。如果有缺失且未配置的模板,可能会导致依赖该模板的流程出错,影响业务的正常开展。

邮件模板自定义选项

Logto 提供三种不同的邮件模板管理方式:

  1. 在 Logto 内自定义模板

  2. 在服务商平台自定义模板

    • 连接器 (Connectors)
    • 功能 (Capabilities)
      • ✅ 向服务商平台传递变量
      • ✅ 向服务商平台传递 locale 参数以实现本地化
      • ✅ 在服务商控制台内完全编辑模板(使用 Logto Management API)
  3. 预设模板(不可自定义)

    • 连接器 (Connector)
    • 功能 (Capabilities)
      • ✅ 原生变量支持
      • ❌ 多语言模板 (即将支持)
      • ❌ 禁止模板 / UI 修改

邮件模板类型

usageType场景变量 (Variables)
SignIn用户使用邮箱登录,通过输入验证码而非密码进行验证。code: string
application: ApplicationInfo
organization?: OrganizationInfo
Register用户使用邮箱注册账号,并通过输入 Logto 发送到邮箱的验证码进行验证。code: string
application: ApplicationInfo
organization?: OrganizationInfo
ForgotPassword用户在登录时忘记密码,可以选择先通过邮箱验证身份以重置密码code: string
application: ApplicationInfo
organization?: OrganizationInfo
Generic此模板可作为多种场景的通用备选方案,包括测试连接器配置、登录后验证或绑定邮箱等。code: string
OrganizationInvitation使用此模板向用户发送邀请链接,邀请其加入组织 (Organization)。link: string
organization: OrganizationInfo
inviter?: UserInfo
UserPermissionValidation在应用使用过程中,某些高风险操作或风险较高的操作可能需要额外的用户验证,如银行转账、删除正在使用的资源、取消会员等。UserPermissionValidation 模板可用于定义这些场景下用户收到的邮件验证码内容。code: string
user: UserInfo
application?: ApplicationInfo
BindNewIdentifier当用户修改个人资料时,可能将邮箱地址绑定到当前账号。此时可使用 BindNewIdentifier 模板自定义验证邮件内容。code: string
user: UserInfo
application?: ApplicationInfo
MfaVerification启用邮箱 MFA 时,该模板用于在多因素认证 (MFA) 流程中向用户发送验证码。code: string
application: ApplicationInfo
organization?: OrganizationInfo
BindMfa启用邮箱 MFA 时,该模板用于设置 MFA 邮箱验证码。用户在将邮箱地址绑定或配置为账号 MFA 因子时会收到此验证码。code: string
user: UserInfo
application?: ApplicationInfo

邮件模板变量

Code

用户需要输入的验证码,用于完成验证流程。适用于 SignInRegisterForgotPasswordGenericUserPermissionValidationBindNewIdentifier 模板。

  • 验证码有效期为 10 分钟。目前暂不支持自定义验证码有效期。
  • 模板中需预留 {{code}} 占位符。发送验证码时,会用随机生成的验证码替换该占位符后再发送邮件给用户。

ApplicationInfo

用户正在交互的客户端应用的公开信息。适用于 SignInRegisterForgotPasswordUserPermissionValidationBindNewIdentifier 模板。

type ApplicationInfo = {
id: string;
name: string;
displayName?: string;
branding?: {
logoUrl?: string;
darkLogoUrl?: string;
favicon?: string;
darkFavicon?: string;
};
};
  • 所有嵌套的应用信息字段都可通过点号访问。例如,{{application.name}} 会被替换为你配置的实际应用名称。
  • 如果未提供根 application 变量,则 handlebars 占位符会被忽略且不会被替换。
  • 如果提供的 application 对象未包含所需字段或值为 undefined,则 handlebars 占位符会被替换为空字符串。例如 {{application.foo.bar}} 会被替换为 ``。

OrganizationInfo

用户正在交互的组织 (Organization) 的公开信息。

type OrganizationInfo = {
id: string;
name: string;
branding?: {
logoUrl?: string;
darkLogoUrl?: string;
favicon?: string;
darkFavicon?: string;
};
};
  • 对于 SignInRegisterForgotPassword 模板,organization 变量为可选项。仅在授权请求中存在 organization_id 参数时可用。详见组织特定品牌
  • 对于 OrganizationInvitation 模板,organization 变量为必填项。

UserInfo

邮件接收用户的公开信息。适用于 UserPermissionValidationBindNewIdentifierOrganizationInvitation 模板。

type UserInfo = {
id: string;
name?: string;
username?: string;
primaryEmail?: string;
primaryPhone?: string;
avatar?: string;
profile?: Profile;
};
  • 查看 profile 了解 Profile 类型的更多细节。
  • user 变量为 UserPermissionValidationBindNewIdentifier 模板的必填项。
  • inviter 变量为 OrganizationInvitation 模板的可选项,仅在组织邀请请求中提供 inviterId 时可用。

邮件模板示例

你可以参考以下邮件模板代码示例,作为自定义 UI 的起点。要创建类似如下的用户界面:

内置邮件模板示例

由于 Logto 不同场景下使用的邮件模板非常相似,唯一的区别在于当前场景和操作的描述。

这里不详细展示所有模板的 HTML 代码,仅以登录场景为例。其他如注册、忘记密码等场景与以下示例类似。

你可以参考此模板并根据实际情况调整。

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>验证你的邮箱以登录</title>
<style>
.auth-service-by:hover .mini-logo {
display: none !important;
}
.auth-service-by:hover .mini-logo-color {
display: block !important;
}
body {
font-family:
'SF Pro Text',
-apple-system,
system-ui,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Arial,
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-smooth: always;
background-color: #fff;
color: #191c1d;
max-width: 640px;
padding: 32px 0;
font-size: 14px;
font-weight: 400;
line-height: 20px;
}
h1 {
font-size: 24px;
font-weight: 700;
line-height: 32px;
margin-top: 32px;
}
.verification-code {
margin: 20px 0;
background: #eff1f1;
border-radius: 12px;
padding: 36px;
font-size: 32px;
font-weight: 600;
line-height: 40px;
}
.footer {
text-align: center;
color: #a9acac;
margin-top: 48px;
}
</style>
</head>
<body>
<div style="max-width: 698px; border-radius: 16px; border: 1px solid #E0E3E3;">
<div style="padding: 0 24px;">
<center>
<img src="{{logoUrl}}" alt="Logo" width="auto" height="40" />
<h1>验证你的邮箱以登录</h1>
<p>我们已收到一次登录尝试,验证码如下。请在你打开的页面输入该验证码以完成登录流程。</p>
<div class="verification-code">000000</div>
<p style="color: #747778;">
如果你并未尝试登录却收到了此邮件,请忽略。验证码将在 10 分钟内有效。
</p>
<hr style="margin: 64px 0 24px; max-width: 420px;" />
<p style="color: #747778; margin: 16px 0 0;">{{companyInfo}}</p>
</center>
</div>
</div>
<div class="footer">
<hr />
<p style="font-size: 14px; line-height: 20px; margin: 20px 0;">
<a href="https://logto.io" style="color: #A9ACAC; text-decoration: underline;">Logto</a>:
更好的开发者身份基础设施。
</p>
<table style="margin: 0 auto; width: auto; border-spacing: 0;">
<tbody>
<tr>
<td style="vertical-align: middle;">
<a href="{{discordServerUrl}}" style="display: block; margin: 0 12px;">
<img src="{{discordLogoUrl}}" style="width: 20px;" />
</a>
</td>
<td style="vertical-align: middle;">
<a href="{{githubUrl}}" style="display: block; margin: 0 12px;">
<img src="{{githubLogoUrl}}" style="width: 20px;" />
</a>
</td>
<td style="vertical-align: middle;">
<a href="{{twitterUrl}}" style="display: block; margin: 0 12px;">
<img src="{{twitterLogoUrl}}" style="width: 20px;" />
</a>
</td>
<td style="vertical-align: middle;">
<a href="{{mailToUrl}}" style="display: block; margin: 0 12px;">
<img src="{{emailIconUrl}}" style="width: 20px;" />
</a>
</td>
</tr>
</tbody>
</table>
<p style="font-size: 12px; line-height: 16px;">
© Silverhand, Inc., 2810 North Church Street, Wilmington, DE 19802
</p>
<p style="color: #A9ACAC; font-size: 12px; line-height: 16px;">
有问题或需要帮助?
<a href="{{mailToUrl}}" style="color: #A9ACAC; text-decoration: underline;">联系我们</a>
</p>
</div>
</body>
</html>

你可以将上述 HTML 代码转义后,添加到配置中的连接器 “Template” 字段,例如(以 SendGrid 连接器为例):

{
"subject": "<sign-in-template-subject>",
"content": "<table cellpadding=\"0\" cellspacing=\"0\" ...",
"usageType": "SignIn",
"type": "text/html"
}

邮件模板本地化

针对不同语言自定义邮件模板

Logto 支持通过 Management API 为不同语言创建自定义邮件模板。你可以为不同语言和模板类型创建自定义邮件模板,为用户提供本地化体验。

type EmailTemplate = {
languageTag: string;
templateType: TemplateType;
details: {
subject: string;
content: string;
contentType?: 'text/html' | 'text/plain';
replyTo?: string;
sendFrom?: string;
};
};
字段 (Field)说明 (Description)
subject邮件主题模板。
content邮件内容模板。
contentType某些邮件服务商可能会根据内容类型渲染邮件模板(如 Sendgrid、Mailgun)。可用此字段指定邮件模板内容类型。
replyTo接收邮件回复的邮箱地址。请咨询你的邮件服务商是否支持该字段。
sendFrom邮件发送者的名称别名。请咨询你的邮件服务商是否支持该字段。

创建邮件模板后,Logto 会根据用户的语言偏好自动选择合适的邮件模板,优先级如下:

  1. 对于客户端 体验 API (Experience APIs)用户账号 API (User Account APIs),语言偏好由请求头中的 Accept-Language 决定。对于 Management API(如 组织邀请),可在请求体的 messagePayload 字段中指定 locale 参数。
  2. 检测到语言偏好后,Logto 会根据 languageTagtemplateType 查找匹配的自定义邮件模板。如果存在指定语言和模板类型的模板,则使用该模板渲染邮件。
  3. 如果未检测到语言偏好,或未找到对应语言和模板类型的自定义模板,则使用登录体验中配置的租户默认语言。详见本地化语言配置说明。
  4. 若仍未找到匹配模板,则使用连接器配置中的默认邮件模板。

支持的邮件连接器

服务商侧邮件模板本地化

对于使用由服务商管理邮件模板的邮件连接器的开发者:

用户的语言偏好会通过模板 payload 中的 locale 参数传递给服务商。你可以在服务商控制台为不同语言创建多个模板,并通过 locale 参数指定语言偏好。

常见问题

如果未在 Logto 配置模板,如何使用第三方邮件模板服务?

你可以在自己的 Web 服务中添加一个新接口用于发送邮件,然后使用 Logto HTTP 邮件连接器 调用你维护的接口。

这样你就可以在自己的服务器上处理邮件模板逻辑。

是否可以用 Logto 邮件向用户发送自定义的“欢迎邮件”?

我们提供了 Webhook 功能。你可以实现自己的 API 接口来接收 Logto Webhook 发送的 User.Created 事件,并在 webhook 处理器中添加发送自定义欢迎邮件的逻辑。

Logto 邮件连接器仅为认证 (Authentication) 流程相关事件提供邮件通知。欢迎邮件属于业务需求,邮件连接器原生不支持,但可通过 Webhook 实现该功能。

最大化验证码邮件送达率,保障用户访问