以下内容来自 Supabase 在 2026 年 10 月 23 日的文档。当前的限制和设置请以其文档为准。基础内容(发送第一封测试邮件和设置发件服务)请从 测试 Supabase Auth 邮件 开始。
邮件一直没有收到
内置发件服务不会给你的测试人员发邮件。 Supabase 自带的邮件服务只发送给你项目团队的成员,每小时最多 2 封。它对你有效是因为你在团队里,对其他人则以 “Email address not authorized” 拒绝。在 Authentication, Emails 下设置自定义 SMTP。
你的 SMTP 服务商仍处于沙盒模式。 新的 Resend 账号在你验证域名之前只能发送到你自己的地址,Amazon SES 只能发送到你已验证的地址。Supabase 把邮件交出去,服务商却悄悄丢弃了它。
你再次请求得太快。 默认情况下,每个用户每 60 秒只能收到一封确认、魔法链接、验证码或重置邮件,每个 IP 地址每 5 分钟只能发起 30 次注册和登录请求。快速重试的测试,或在一台 CI 机器上运行的测试套件,会触发这些限制并收到 429。在 Authentication, Rate Limits 下为你的预发布项目调高限制。
该地址已有账号。 为了避免泄露谁注册过,Supabase 对已确认地址的注册请求会像成功一样响应,返回一个没有身份信息的用户,并且不发送邮件。复用地址的测试会一直等待一封永远不会来的邮件。每次运行都使用新地址。
Confirm email 已关闭。 这时注册会立即让用户登录,什么也不发送。检查 Authentication, Sign In / Providers, Email。它常在开发时被关闭,之后再没打开。
链接显示无效或已过期
你点击链接后进入应用,地址栏中出现 error_code=otp_expired(“Email link is invalid or has expired”)。
- 链接已被使用过。 链接只能使用一次,默认有效期 1 小时。再次请求邮件会替换之前的链接,所以请使用最新的那个。
- 扫描程序先打开了它。 有些邮件服务,以及链接扫描器等公司安全工具,会打开新邮件中的每个链接进行检查。这会在用户点击之前用掉一次性链接。Supabase 建议改为发送 6 位验证码(模板中的
{{ .Token }}),或链接到你自己的页面,让用户按按钮确认。Proxy Mail QA 从不打开链接,所以如果链接在你的测试中有效、对真实用户却失败,很可能是扫描程序导致的。
链接能打开,但没有人登录
链接是在另一个浏览器中打开的。 在 PKCE 流程中(Supabase 的服务端辅助工具使用该流程),发起注册的浏览器保存着链接所需的密钥。在另一个浏览器、隐私窗口或另一台设备上打开链接,交换就会失败,常见报错是 “both auth code and code verifier should be non-empty”。测试人员应在注册时使用的浏览器中打开链接。如果需要在任何地方都能用的链接,请用 {{ .TokenHash }} 构建链接,并在你的服务器上用 verifyOtp 验证。
没有代码完成登录。 链接打开你的应用时,地址中带有 code(或令牌),需要某个页面把它换成会话。如果缺少这个路由,用户会看到你的首页,处于未登录状态。检查链接的目标页面是否调用了 exchangeCodeForSession,或带令牌哈希调用了 verifyOtp。
服务器看不到会话。 默认链接把会话放在地址中的 # 之后,只有浏览器能读取。服务端渲染的应用需要使用上面的令牌哈希链接。
链接指向 localhost 或错误的环境
Site URL 初始为 http://localhost:3000,任何不在 Redirect URLs 列表中的 redirectTo 都会回退到它。把 Site URL 设为已部署的应用,并列出每个环境。详见 为什么邮件链接指向 localhost;Proxy Mail QA 会在地址所在行标记这类链接。
注册失败,提示 “Database error saving new user”
数据库中的某个东西拒绝了新用户,几乎总是 auth.users 上的触发器,例如在 profiles 中创建一行的触发器。常见原因:它写入的表或列不存在;函数不是 security definer,因此无法写入 public;或它填充的某列是 not null,而注册时没有发送该值。Supabase 的 Auth 和 Postgres 日志会显示真正的错误。
也要用特殊值测试:带撇号的名字、其他文字或 255 个字符,可能会破坏普通测试数据永远碰不到的资料列。特殊的名字和密码 提供了一份可以尝试的列表。
收到了重置邮件,但密码没有改变
重置链接会用恢复会话让用户登录,并触发 PASSWORD_RECOVERY 事件。你的应用需要捕获该事件,显示设置新密码的表单,并用新密码调用 updateUser。否则,用户只是登录了,密码还是旧的。使用 PKCE 时,链接还必须在发起请求的浏览器中打开。详见 测试密码重置邮件。
验证码拦截了你的自动化测试
开启验证码保护(Authentication, Attack Protection)后,每次注册和登录都需要验证码令牌,自动化浏览器因此无法通过。在你的预发布项目中,使用验证码服务商的测试密钥(总能通过),真实密钥留给生产环境。
在本地 Supabase 上能用,在托管项目上却不行
Supabase CLI 会把本地邮件拦截到自己的邮件查看器中(通常在 localhost:54324),并从 supabase/config.toml 读取模板。托管项目使用控制台中的模板、发件服务和速率限制。上线前请在托管的预发布项目上测试,把真实邮件发到能收信的地址。
一次全部检查
- 为每个场景创建一个新的 Proxy Mail QA 地址:新用户、已有用户、密码重置、魔法链接。
- 在你的应用中走一遍流程。验证码或链接会在几秒内出现在地址所在行。
- 查看该行:指向 localhost 的链接会被标记,收件箱会显示邮件是否说明了链接何时过期。
- 在注册时使用的浏览器中打开链接,并检查你是否已在正确的网站上登录。
用 Lovable、Bolt 或 v0 构建的?vibe coding 应用中注册和登录的问题 介绍了这类应用在上述问题之外通常还会出错的地方。