← 返回博客

邮箱验证:六位验证码 vs 确认链接(2026)

对比六位邮箱验证码与确认/魔法链接:选型表、钓鱼与投递差异,以及同一条 POST /emails 发送路径。

更新于 2026年11月4日
邮箱验证:六位验证码 vs 确认链接(2026)

大多数产品会做两次的选择

几乎每个 SaaS / AI 应用迟早都要证明同一件事:「这个邮箱属于正在用产品的人」。主流有两种形态——六位验证码与确认 / 魔法链接——团队常先抄教程里的第一种,等移动端体验、钓鱼投诉或企业邮箱过滤器出现后才后悔。

无论哪种,Rovela 的职责相同:用 POST /emails 投递事务邮件。应用负责生成密钥、存哈希、做过期与一次性核销,以及校验用户输入或点击。Rovela 没有独立的「OTP 产品」或「魔法链接产品」——只有发送 API,加上文档里的安全模式。

本文是对比文:何时用码、何时用链接,以及投递与客户端怪癖如何 tipping。完整实现见下方兄弟文与文档——这里用来选型,再深链进去。

「验证码」和「链接」分别指什么

六位验证码(OTP / 邮箱验证码)

  • 应用用密码学安全随机源生成短数字(或字母数字)一次性值。
  • 存 HMAC 等带密钥哈希、过期时间与尝试次数——不存明文(邮箱验证码示例)。
  • 用户在你的界面输入(或从通知 / 主题行读取)。
  • 实现深挖:用邮件 API 发 OTP、邮箱 OTP 安全。

确认链接或魔法链接

从 ESP 视角,两者都是「发验证邮件 API」问题:一次 HTTP 发送、html + text、已验证域名、幂等重试。

决策表

维度六位验证码确认 / 魔法链接
UX 摩擦输入 6 位(或粘贴)一次点按 / 点击
移动端数字键盘;邮箱与 App 分离时仍可用邮件客户端能打开 HTTPS 时很爽;需手动切回 App 时别扭
桌面端从另一标签复制或重输收件箱已开着时通常最快
钓鱼 / 社工用户习惯在你的界面输码;仍怕「把码填到这里」的诱导用户习惯点链接;更易伪造「验证」按钮;需教育「我们不会在流程外索要原始 token」
邮件客户端改写很少影响正文/主题里的数字安全链接扫描、代理,以及点击追踪可能包装或预取 URL
无障碍跨设备输入对部分用户难;数字对读屏友好(标记得当)text 里放完整 URL 有帮助;HTML 链接文案要清晰
短信兜底易与同码通道对齐短信也能带链接,但长 URL 易折行;短信更偏短码
限流 / 爆破空间极小 → HMAC + 尝试上限 + 重发节流是刚需Token 空间巨大;仍要限制签发与核销频率
过期常见 5–15 分钟归属确认可达数小时;登录/重置常见 15–60 分钟
一次性成功后删除(或轮换)单条 SQL 核销即删
投递 / 扫描器正文短;主题放码利于预览;少「引诱点击」风险URL 更长;预取机器人可能撞链接——核销应对 GET 安全,或要求显式确认
共用 / 一体机更好:若只证明「在场」,不会因一点击就意外登录魔法登录在共用设备上更危险,除非会话 UX 谨慎

什么时候验证码更合适

优先六位(或短字母数字)码,当:

  • 高风险二次验证——敏感操作(导出、改账单、新设备)前要证明「此刻能读到这封邮件」。
  • 共用或受监督设备——一点击登录可能悄悄开会话;在 App 里输码意图更清晰。
  • 不信任链接的用户——金融、医疗、安全敏感人群常拒绝点击。
  • 跨通道一致——已有或将有短信/语音同码;心智模型统一。
  • 以 App 为中心的移动流程——人留在 App;邮件只是传数字的旁路(主题行可选)。

从官方验证码示例起步,并用邮箱 OTP 安全加固。

什么时候链接更合适

优先确认或魔法链接,当:

  • 个人设备上的无密码登录——从收件箱一键进会话(魔法登录邮件链接)。
  • 邮箱归属 / 双重确认——要的是持久「这地址是我的」,不是 10 分钟「在场」(邮箱验证链接)。
  • 桌面低摩擦注册——另一标签已开着收件箱。
  • 更换邮箱——链接发到新地址;核销后再切换。
  • 密码重置——URL 里放长 token 是文档模式(安全密码重置)。

混合模式(谨慎使用)

生产里常见的诚实混合:

  • 同一封邮件里码 + 链接——「输入 482913 或在浏览器确认」。设备不可预知时有用。代价:要签发、限流、过期两套秘密;意图要说清(同一会话目的)。
  • 归属用链接,登录用码——干净常见:一次链接验证地址,之后登录/升权用 OTP。
  • 链接落到仍要输码的页面——通常更差;除非合规强制,否则别这么做。

混合不是 Rovela 功能——仍是应用设计,发送还是一次 POST /emails。

会改变选型的投递与客户端细节

安全类邮件与 newsletter 的失败方式不同:

  • 验证码更短。 HTML 更少,text/html 更易对齐;主题放码利于锁屏预览(验证码文档)。高度共享屏幕上可省略主题码。
  • 链接会招扫描。 企业「安全链接」、杀毒抓取、部分客户端会预取 GET。若裸 GET 就登录或核销,预取可能烧掉 token 或建会话。更宜 POST 确认,或让 GET 只展示「继续」而无副作用。
  • 点击追踪会改写 URL。 密码重置文档提醒:追踪会把链接包到追踪主机;虽仍可用,但安全 token 应直达你的应用——认证邮件用关闭点击追踪的发送域/子域(密码重置示例)。
  • 务必发 text,带完整 URL 或验证码。 会剥 HTML 链接的过滤器仍能留下纯文本。
  • 声誉隔离。 认证信从子域发(security@mail.example.com),别和营销共命运(为什么验证码/魔法登录进垃圾箱)。

同一条发送路径:POST /emails

正文是数字还是 <a href>,线路格式相同。在已验证域名上,用 sending_access 密钥(鉴权、快速开始):

curl -X POST https://api.rovela.dev/emails \
  -H "Authorization: Bearer re_your_sending_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: verify-user_123-2026-11-04" \
  -d '{
    "from": "Acme <security@mail.acme.com>",
    "to": "alice@example.com",
    "subject": "Confirm your Acme email",
    "html": "<p>Your code is <strong>482913</strong> (10 minutes).</p><p>Or <a href=\"https://app.acme.com/verify?token=…\">confirm in the browser</a>.</p>",
    "text": "Your code is 482913 (10 minutes).\n\nOr confirm: https://app.acme.com/verify?token=…"
  }'

两种形态通用注意:

  • 200 表示已入队,不等于进收件箱——看消息事件或 Webhook(API: emails)。
  • Idempotency-Key(≤256 字符,24 小时)避免 worker 重试连发两封。
  • 抑制:400「recipient is suppressed」时不要假装已发码/链接——换地址。
  • 量级与套餐:见定价;本文不编造额度。

AI 产品语境(码、邀请、登录链接作为一组)见面向 AI 应用的事务邮件。

2026 产品的建议默认

流程默认原因
注册邮箱确认链接(约 24 小时级过期)归属证明,桌面摩擦低
无密码登录魔法链接 或 验证码消费级偏链接;共用设备 / 不信链接则偏码
升权 / 敏感操作验证码证明在场,避免邮件一点击就建持久会话
密码重置链接与文档长 token 模式一致
接受邀请链接动作是「加入组织」,不是「输六位数」

若工单堆在「码没收到」或「我不敢点」——常常是投递问题(垃圾箱指南),不一定是 UX 原语选错。

本文不是什么

  • 不是完整 OTP 实现(见 send-otp + 文档)。
  • 不是完整魔法登录 / 验证链接教程(见对应博客)。
  • 不宣称 Rovela 替你存或校验码/token。
  • 不是国内厂商对比或编造价格。

下一步

  1. 用上面的表选型。
  2. 应用侧秘密:验证码 或 密码重置 / 链接模式。
  3. 投递:POST /emails · 快速开始。
  4. 投递加固:验证码/魔法登录进垃圾箱。
  5. 额度:定价。

一句话: 六位验证码优化在场证明与对链接的不信任;确认链接优化摩擦与持久归属。发验证邮件 API 相同——Rovela 入队并做域名认证投递;密码学在你的应用里。