Skip to content
Auth

电子邮件模板

Learn how to manage the email templates in Supabase.

Supabase 的电子邮件模板分为两类:身份验证和安全通知。

🌐 Email templates in Supabase fall into two categories: authentication and security notifications.

验证邮件:

🌐 Authentication emails:

  • 确认注册
  • 邀请用户
  • 魔法链接或一次性密码
  • 更改邮箱地址
  • 重置密码
  • 重新认证

安全通知邮件:

🌐 Security notification emails:

  • 密码已更改
  • 邮箱地址已更改
  • 电话号码已更改
  • 已关联登录方式
  • 登录方式已移除
  • 已添加验证方式
  • 验证方式已移除

只有当在项目级别启用了相应的安全通知时,才会向用户发送安全电子邮件。

🌐 Security emails are only sent to users if the respective security notifications have been enabled at a project-level.

术语 #

🌐 Terminology

模板系统提供以下变量可供使用:

🌐 The templating system provides the following variables for use:

名称描述
{{ .ConfirmationURL }}包含确认网址。例如,注册确认网址看起来像这样:https://project-ref.supabase.co/auth/v1/verify?token={{ .TokenHash }}&type=email&redirect_to=https://example.com/path
{{ .Token }}包含一个6位数的一次性密码(OTP),可以用来代替 {{. ConfirmationURL }}
{{ .TokenHash }}包含 {{ .Token }} 的哈希版本。这对于在邮件模板中构建你自己的邮箱链接很有用。
{{ .SiteURL }}包含你应用的网站 URL。你可以在项目的身份验证设置中进行配置。
{{ .RedirectTo }}包含在调用 signUpsignInWithOtpsignInWithOAuthresetPasswordForEmailinviteUserByEmail 时传入的重定向 URL。可以在你项目的认证设置中配置重定向 URL 允许列表。
{{ .Data }}包含来自 auth.users.user_metadata 的元数据。使用它来个性化电子邮件内容。
{{ .Email }}包含用户的原始电子邮件地址。当尝试将电子邮件地址链接到匿名用户时为空。
{{ .NewEmail }}包含用户的新电子邮件地址。此变量仅在“更改电子邮件地址”模板中支持。
{{ .OldEmail }}包含用户的旧电子邮件地址。此变量仅在“电子邮件地址更改通知”模板中支持。
{{ .Phone }}包含用户的新电话号码。此变量仅在“电话号码更改通知”模板中支持。
{{ .OldPhone }}包含用户的旧电话地址。此变量仅在“电话号码变更通知”模板中支持。
{{ .Provider }}包含已关联或已移除的登录方式的提供商。此变量仅在“已关联登录方式”和“已移除登录方式”通知模板中支持。
{{ .FactorType }}包含已添加或已移除的验证方法类型。此变量仅在“已添加验证方法”和“已移除验证方法”通知模板中受支持。

编辑电子邮件模板 #

🌐 Editing email templates

你编辑模板的位置取决于你如何运行 Supabase。

🌐 Where you edit templates depends on how you run Supabase.

托管项目 #

🌐 Hosted projects

在仪表板的 电子邮件模板 页面上编辑模板。模板生成器使用与本页面中记录的 术语 和变量相同的内容。

🌐 Edit templates on the Email Templates page in the dashboard. The template builder uses the same terminology and variables documented on this page.

本地开发和自建托管 #

🌐 Local development and self-hosted

仪表板模板构建器在使用 本地开发 CLI自托管 Supabase不起作用。请改为在 supabase/config.toml 和本地 HTML 文件中自定义模板。

🌐 The dashboard template builder does not apply when running local development with CLI or self-hosted Supabase. Customize templates in supabase/config.toml and local HTML files instead.

你也可以用管理 API 来管理邮件模板:

🌐 You can also manage email templates using the Management API:

1
# Get your access token from https://supabase.com/dashboard/account/tokens
2
export SUPABASE_ACCESS_TOKEN="your-access-token"
3
export PROJECT_REF="your-project-ref"
4
5
# Get current email templates
6
curl -X GET "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \
7
-H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
8
| jq 'to_entries | map(select(.key | startswith("mailer_templates"))) | from_entries'
9
10
# Update email templates
11
curl -X PATCH "https://api.supabase.com/v1/projects/$PROJECT_REF/config/auth" \
12
-H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
13
-H "Content-Type: application/json" \
14
-d '{
15
"mailer_subjects_confirmation": "Confirm your email address",
16
"mailer_templates_confirmation_content": "<h2>Confirm your email address</h2><p>Follow the link below to confirm this email address and finish signing up.</p><p><a href=\"{{ .ConfirmationURL }}\">Confirm email address</a></p>",
17
"mailer_subjects_magic_link": "Your sign-in link",
18
"mailer_templates_magic_link_content": "<h2>Your sign-in link</h2><p>Follow the link below to sign in. This link expires shortly and can only be used once.</p><p><a href=\"{{ .ConfirmationURL }}\">Sign in</a></p>",
19
"mailer_subjects_recovery": "Reset your password",
20
"mailer_templates_recovery_content": "<h2>Reset your password</h2><p>We received a request to reset your password. Follow the link below to choose a new one.</p><p><a href=\"{{ .ConfirmationURL }}\">Reset password</a></p><p>If you didn't request this, you can safely ignore this email.</p>",
21
"mailer_subjects_invite": "You've been invited",
22
"mailer_templates_invite_content": "<h2>You've been invited</h2><p>You've been invited to create an account. Follow the link below to accept.</p><p><a href=\"{{ .ConfirmationURL }}\">Accept invitation</a></p>",
23
"mailer_subjects_reauthentication": "{{ .Token }} is your verification code",
24
"mailer_templates_reauthentication_content": "<h2>Your verification code</h2><p>Use the code below to verify your identity. It expires shortly.</p><p>{{ .Token }}</p>",
25
"mailer_subjects_email_change": "Confirm your new email address",
26
"mailer_templates_email_change_content": "<h2>Confirm your new email address</h2><p>Follow the link below to confirm {{ .NewEmail }} as your new email address.</p><p><a href=\"{{ .ConfirmationURL }}\">Confirm new email address</a></p><p>If you didn't request this change, you can safely ignore this email.</p>",
27
"mailer_notifications_password_changed_enabled": true,
28
"mailer_subjects_password_changed_notification": "Your password was changed",
29
"mailer_templates_password_changed_notification_content": "<h2>Your password was changed</h2>\n\n<p>The password for your account was recently changed.</p>\n<p>If you didn't make this change, reset your password and contact support immediately.</p>",
30
"mailer_notifications_email_changed_enabled": true,
31
"mailer_subjects_email_changed_notification": "Your email address was changed",
32
"mailer_templates_email_changed_notification_content": "<h2>Your email address was changed</h2>\n\n<p>The email address for your account was changed from {{ .OldEmail }} to {{ .Email }}.</p>\n<p>If you didn't make this change, contact support immediately.</p>",
33
"mailer_notifications_phone_changed_enabled": true,
34
"mailer_subjects_phone_changed_notification": "Your phone number was changed",
35
"mailer_templates_phone_changed_notification_content": "<h2>Your phone number was changed</h2>\n\n<p>The phone number for your account was changed from {{ .OldPhone }} to {{ .Phone }}.</p>\n<p>If you didn't make this change, contact support immediately.</p>",
36
"mailer_notifications_mfa_factor_enrolled_enabled": true,
37
"mailer_subjects_mfa_factor_enrolled_notification": "A new verification method was added to your account",
38
"mailer_templates_mfa_factor_enrolled_notification_content": "<h2>A new verification method was added</h2>\n\n<p>Sign-in verification method {{ .FactorType }} was added to your account.</p>\n<p>If you didn't make this change, contact support immediately.</p>",
39
"mailer_notifications_mfa_factor_unenrolled_enabled": true,
40
"mailer_subjects_mfa_factor_unenrolled_notification": "A verification method was removed from your account",
41
"mailer_templates_mfa_factor_unenrolled_notification_content": "<h2>A verification method was removed</h2>\n\n<p>Sign-in verification method {{ .FactorType }} was removed from your account.</p>\n<p>If you didn't make this change, contact support immediately.</p>",
42
"mailer_notifications_identity_linked_enabled": true,
43
"mailer_subjects_identity_linked_notification": "A sign-in method was linked to your account",
44
"mailer_templates_identity_linked_notification_content": "<h2>A sign-in method was linked</h2>\n\n<p>Your {{ .Provider }} account was linked as a sign-in method for {{ .Email }}.</p>\n<p>If you didn't make this change, contact support immediately.</p>",
45
"mailer_notifications_identity_unlinked_enabled": true,
46
"mailer_subjects_identity_unlinked_notification": "A sign-in method was removed from your account",
47
"mailer_templates_identity_unlinked_notification_content": "<h2>A sign-in method was removed</h2>\n\n<p>Your {{ .Provider }} account was removed as a sign-in method for {{ .Email }}.</p>\n<p>If you didn't make this change, contact support immediately.</p>"
48
}'

手机深度链接 #

🌐 Mobile deep linking

对于移动应用,你可能需要链接或重定向到应用中的某个特定页面。查看移动深度链接指南来设置这个功能。

🌐 For mobile applications, you might need to link or redirect to a specific page within your app. See the Mobile Deep Linking guide to set this up.

限制 #

🌐 Limitations

电子邮件预取 #

🌐 Email prefetching

某些邮箱提供商可能有垃圾邮件检测或其他安全功能,会预先获取收到邮件中的 URL 链接(例如 Microsoft Defender for Office 365 的安全链接)。 在这种情况下,发送的 {{ .ConfirmationURL }} 会被立即使用,从而导致“令牌已过期或无效”的错误。 为防止这种情况,可以考虑以下选项:

🌐 Certain email providers may have spam detection or other security features that prefetch URL links from incoming emails (e.g. Safe Links in Microsoft Defender for Office 365). In this scenario, the {{ .ConfirmationURL }} sent will be consumed instantly which leads to a "Token has expired or is invalid" error. To guard against this there are the options below:

选项 1

  • 改用电子邮件一次性密码,只需在邮件模板中加入 {{ .Token }}
  • 创建你自己的自定义电子邮件链接,将用户重定向到一个页面,在那里他们可以输入他们的电子邮件和令牌来登录
1
<a href="{{ .SiteURL }}/confirm-signup">Confirm email address</a>
1
const { data, error } = await supabase.auth.verifyOtp({ email, token, type: 'email' })

选项 2

  • 创建你自己的自定义电子邮件链接,将用户重定向到一个页面,在那里他们可以点击按钮确认操作
1
<a href="{{ .SiteURL }}/confirm-signup?confirmation_url={{ .ConfirmationURL }}">
2
Confirm email address
3
</a>
  • 这个按钮应该包含实际的确认链接,可以通过解析 URL 中的 confirmation_url={{ .ConfirmationURL }} 查询参数来获取。

邮件追踪 #

🌐 Email tracking

如果你使用的是支持“邮件追踪”的外部邮箱服务,Supabase 邮件模板里的链接会被覆盖,无法正常使用。我们建议关闭邮件追踪,以确保邮件里的链接不被覆盖。

🌐 If you are using an external email provider that enables "email tracking", the links inside the Supabase email templates will be overwritten and won't perform as expected. We recommend disabling email tracking to ensure email links are not overwritten.

将用户重定向到服务器端的端点 #

🌐 Redirecting the user to a server-side endpoint

如果你打算使用 服务端渲染,你可能希望电子邮件链接将用户重定向到一个服务端端点,以便在返回页面之前检查他们是否已认证。不过,默认的电子邮件链接在验证后会将用户重定向到带有查询片段的重定向 URL,因为默认情况下会在查询片段中返回会话,所以你无法在服务端访问它。

🌐 If you intend to use Server-side rendering, you might want the email link to redirect the user to a server-side endpoint to check if they are authenticated before returning the page. However, the default email link will redirect the user after verification to the redirect URL with the session in the query fragments. Since the session is returned in the query fragments by default, you won't be able to access it on the server-side.

你可以在电子邮件模板中自定义电子邮件链接,让用户成功跳转到服务器端的端点。例如:

🌐 You can customize the email link in the email template to redirect the user to a server-side endpoint successfully. For example:

1
<a
2
href="https://api.example.com/v1/authenticate?token_hash={{ .TokenHash }}&type=invite&redirect_to={{ .RedirectTo }}"
3
>
4
Accept the invite
5
</a>

当用户点击链接时,请求会到达 https://api.example.com/v1/authenticate,你可以从 URL 中获取 token_hashtyperedirect_to 查询参数。然后,你可以调用 verifyOtp 方法获得一个经过身份验证的会话,然后再重定向用户回客户端。由于 verifyOtp 方法会向 Supabase Auth 发起 POST 请求以验证用户,返回的响应体中会包含会话信息,服务器可以读取。例如:

🌐 When the user clicks on the link, the request will hit https://api.example.com/v1/authenticate and you can grab the token_hash, type and redirect_to query parameters from the URL. Then, you can call the verifyOtp method to get back an authenticated session before redirecting the user back to the client. Since the verifyOtp method makes a POST request to Supabase Auth to verify the user, the session will be returned in the response body, which can be read by the server. For example:

1
import { createClient, type EmailOtpType } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
const { token_hash, type } = Object.fromEntries(new URLSearchParams(window.location.search))
7
const {
8
data: { session },
9
error,
10
} = await supabase.auth.verifyOtp({ token_hash, type: type as EmailOtpType })
11
12
// subsequently redirect the user back to the client using the redirect_to param
13
// ...

自定义 #

🌐 Customization

Supabase Auth 使用 Go 模板。这意味着可以根据模板属性有条件地渲染信息。

🌐 Supabase Auth makes use of Go Templates. This means it is possible to conditionally render information based on template properties.

给提前体验用户发送不同的邮件 #

🌐 Send different email to early access users

给通过早期访问域名(https://www.earlyaccess.trial.com)注册的用户发送不同的邮件。

🌐 Send a different email to users who signed up via an early access domain (https://www.earlyaccess.trial.com).

1
{{ if eq .Data.Domain "https://www.example.com" }}
2
<h1>Welcome to Our Database Service!</h1>
3
<p>Dear Developer,</p>
4
<p>Welcome to Billy, the scalable developer platform!</p>
5
<p>Best Regards,<br>
6
Billy Team</p>
7
{{ else if eq .Data.Domain "https://www.earlyaccess.trial.com" }}
8
<h1>Welcome to Our Database Service!</h1>
9
<p>Dear Developer,</p>
10
<p>Welcome Billy, the scalable developer platform!</p>
11
<p> As an early access member, you have access to select features like Point To Space Restoration.</p>
12
<p>Best Regards,<br>
13
Billy Team</p>
14
{{ end }}