发布时间:2026 年 7 月 8 日
在收集电子邮件地址作为注册、登录、订阅、结账、账号恢复或其他流程的一部分时,通常的做法是确认电子邮件地址归输入该地址的人所有。现有的验证方法(例如一次性密码 (OTP) 或电子邮件验证链接(魔法链接))要求用户离开您的网站。这种中断性流程可能会增加用户(无论是真人还是代理)完全放弃会话并永远无法完成身份验证流程的风险。
电子邮件验证 API 是一项提案,允许浏览器直接与电子邮件提供商通信,以验证用户是否拥有该电子邮件地址。 用户从浏览器的自动填充或自动完成建议中选择电子邮件,提交表单,网站会与提供商验证电子邮件地址,而无需发送电子邮件或中断用户流程。
电子邮件收集是用户历程中的一个关键转化点,Chrome 希望从想要验证电子邮件的网站、可以执行验证的电子邮件提供商以及体验该流程的用户那里获得有关该提案的反馈。您可以 立即注册源试用 ,并按照此处的实现说明进行操作。如需了解常规源试用 配置,请参阅源试用使用入门。
您可以使用演示账号试用该流程:
邮箱验证流程
以下部分介绍了您和您的用户需要哪些内容才能开始电子邮件验证流程,以及在使用电子邮件验证协议时的整个工作流程。
关键词
电子邮件验证 API 的关键词如下:
- 验证者:收集电子邮件地址并想要验证 该地址的网站。验证者也称为依赖 方。
- 电子邮件提供商:提供用户电子邮件地址的服务,例如
gmail.com。 - 颁发者:管理用户电子邮件账号的服务,例如
accounts.google.com。颁发者也称为身份 提供方。
在某些情况下,电子邮件提供商和颁发者可能在同一网域中运营。但是,务必区分拥有电子邮件地址和拥有关联账号的有效会话。
前提条件
- 用户必须在同一浏览器个人资料中登录其邮件服务提供商或发卡机构。例如,如果他们使用 Gmail,则必须登录其 Google 账号。
- 作为参与的验证者网站,您 必须注册源试用,并在与电子邮件表单相同的页面上提供令牌。
用户必须从自动填充或自动完成下拉列表中选择其电子邮件地址。
- 如果用户之前在字段中输入了电子邮件地址,系统将使用自动完成功能提供该地址。
如果用户使用 Chrome 设置“自动填充和密码”(
chrome://settings/autofill) 添加了电子邮件地址,系统将使用自动填充功能提供该地址。
用户首次提供电子邮件地址进行验证时,系统会显示权限提示。每个电子邮件地址仅显示一次。
用户在其浏览器中拥有该有效会话后,即可开始该流程:
- 在包含电子邮件字段的表单中,用户从自动完成下拉列表中选择其电子邮件地址。验证者网站会在表单中提供一个隐藏字段,其中包含每个实例的随机数,以验证此请求。
然后,浏览器将检索电子邮件网域的邮箱验证 DNS 记录。这会将浏览器指向颁发者。然后,颁发者将确认他们拥有该电子邮件地址的有效会话。
然后,颁发者将提供其地址的 电子邮件验证令牌 (EVT)。浏览器会将该令牌与 EVT、网站来源和输入表单中的随机数合并到密钥绑定的 JWT 中。
提交表单后,EVT 软件包会添加到隐藏字段并发送到网站。
然后,验证者网站会验证每个详细信息:预期的电子邮件地址、随机数以及来自浏览器和颁发者的签名。
用户会看到一条小通知,告知其电子邮件提供商已验证其地址。
此流程会向验证者网站确认电子邮件地址有效且归当前用户所有,这意味着网站可以跳过发送验证电子邮件的步骤。
用户可以在设置 > 自动填充和密码 > 联系信息 > 已验证的电子邮件地址 (或打开 chrome://settings/contactInfo)下管理其已验证的电子邮件地址。
应用场景注意事项
电子邮件验证是对现有流程的渐进式增强,无需用户离开您的网站即可检索 OTP 或点击链接。网站可以将电子邮件验证字段添加到所有相关表单,例如登录、简报注册、账号创建和密码恢复。只有在浏览器支持 EVP 时,才会触发 EVP。如果在提交时未收到任何代码或任何验证步骤失败,您可以回退到默认的电子邮件确认流程。这也意味着 API 没有功能检测;验证者网站会将 EVT 视为可选,如果请求中存在 EVT,则会对其进行处理。
邮箱验证会确认用户与其电子邮件地址的提供方之间存在有效会话。它 不会 验证您的电子邮件是否已送达用户。您可能仍希望发送现有的欢迎电子邮件或入职电子邮件,并且可能希望或需要提示用户检查其垃圾邮件设置。
实现验证者网站
如需了解更多详细信息,您可以逐步了解端到端演示 代码 ,并参阅电子邮件验证 API和电子邮件验证 协议 提案中的验证步骤。
配置表单字段
确保您的表单字段具有正确的属性:
<input
name="email-address"
type="email"
autocomplete="email">
<input
type="hidden"
name="token"
nonce="rAnD0m-VaLuE"
autocomplete="email-verification-token">
将 email 输入的 type 和 autocomplete 属性设置为 email,以便浏览器为电子邮件地址提供自动完成功能。
提交表单后,新的 hidden 字段将填充电子邮件验证令牌。必要的属性包括:
- 设置
type="hidden",因为此字段不需要用户输入。 - 设置
nonce="rAnD0m-VaLuE"。网站必须提供与会话绑定的唯一随机数,以验证表单提交。 - 设置
autocomplete="email-verification-token"。浏览器使用此属性来标识要填充的字段。
通过检查开发者工具中的“网络”面板来验证表单元素。选择电子邮件地址后,您会看到浏览器为电子邮件提供商和颁发者触发 DNS 和后续账号查找查询。这些是内部浏览器请求;在提交表单之前,您的网站不会收到任何内容。
验证 EVT
验证 EVT 软件包的每个组件需要五个步骤。
- 解析令牌。
- 验证预期值。
- 验证密钥绑定。
- 验证 DNS 记录。
- 发现颁发者并验证 EVT 签名。
1. 解析令牌
表单提交的原始数据包含 EVT 和
选择性披露 JSON Web 令牌
(SD-JWT+KB)中的签名声明,这些声明以波浪号
(~ 字符) 分隔。您需要将这些声明分开,并解码 Javascript
对象签名和加密 (JOSE) 标头和载荷(例如使用
jose for Node.js)。
如果 example.com 验证 demo@gmail.com,则解码后的载荷类似于以下示例:
{
"evtJwtDecodedPayload": {
"cnf": {
"jwk": {
"crv": "Ed25519",
"kty": "OKP",
"x": "pUbLiCkEy123pUbLiCkEy123pUbLiCkEy123"
}
},
"email": "demo@gmail.com",
"email_verified": true,
"iat": 1782911685,
"iss": "https://accounts.google.com"
},
"kbJwtDecodedPayload": {
"aud": "https://example.com",
"iat": 1782911685,
"nonce": "rAnDoM123rAnDoM123rAnDoM123rAnDoM123",
"sd_hash": "hAsH456hAsH456hAsH456hAsH456hAsH456"
}
}
2. 验证预期值
检查载荷中的基本值是否与您提供的值匹配:
- 验证
email_verified是否设置为true。 - 验证
email是否与表单中提供的电子邮件地址匹配。 - 验证
nonce是否与表单中提供的随机数匹配。 - 验证
aud是否与您网站的来源匹配。 - 验证
iat是否具有相对较新的时间戳,例如在呈现表单之后。
3. 验证密钥绑定
浏览器会为交易创建临时密钥,以确认其已签署令牌。从 EVT 中的 cnf(确认)声明中提取此密钥,然后使用它来验证密钥绑定的 JWT。
然后,计算预期哈希值并将其与 sd_hash 声明进行比较。以下 Node.js 示例展示了如何执行此计算:
const calculatedHash = createHash("sha256")
.update(evtJwt + "~")
.digest("base64url");
4. 验证 DNS 记录
验证电子邮件地址网域的 _email-verification DNS 记录。例如,对于 demo@gmail.com,查询 _email-verification.gmail.com TXT 记录。对于此提供商,查询会返回账号提供商的位置,即 accounts.google.com。
$ dig +short TXT _email-verification.gmail.com
"iss=accounts.google.com"
5. 发现颁发者并验证 EVT 签名
确保颁发者提供 /.well-known/email-verification 资源,该资源提供用于颁发令牌的端点、网站的 JSON Web 密钥 (JWK) 以及受支持的签名算法。
$ curl https://accounts.google.com/.well-known/email-verification
{
"issuance_endpoint": "https://accounts.google.com/gsi/email-verification/issue",
"jwks_uri": "https://verifiablecredentials-pa.googleapis.com/.well-known/vc-public-jwks",
"signing_alg_values_supported": ["EdDSA"]
}
使用 JWK 验证从令牌中提取的 EVT JWT。大多数 JOSE 库都提供用于处理此验证的函数。
如果所有五个步骤都成功,则您已针对提供商验证了电子邮件地址。否则,请按照正常流程向用户发送确认电子邮件。
实现电子邮件提供商和颁发者服务
如需了解更多详细信息,您可以逐步了解模拟电子邮件提供商演示 代码 ,并参阅电子邮件验证 API和电子邮件验证 协议 提案中的颁发者步骤。
作为颁发者,您 无需 注册源试用或提供令牌,因为浏览器行为由依赖方网站触发。您只需确保预期端点已就位,以响应这些请求。
配置颁发者发现
如需允许浏览器在选择属于您网域的电子邮件地址时自动发现您的验证端点,请使用 DNS 和 .well-known HTTP 端点公开您的配置。
配置 DNS 委托记录
在您的电子邮件网域中配置 DNS TXT 记录,该记录会将验证权限委托给您的颁发者标识符。根据您的基础架构,这些标识符可以使用相同的网域。
记录格式:_email-verification.<email-domain>
示例区域文件:
_email-verification.example.com IN TXT "iss=accounts.issuer.example"
托管 .well-known/email-verification 端点
在颁发者网域的 /.well-known/ 路径下托管 JSON 元数据文件。
此文件概述了您的颁发功能以及您的基础架构支持的加密签名算法。
端点:https://<issuer-domain>/.well-known/email-verification
示例响应:
{
"issuance_endpoint": "https://accounts.issuer.example/email-verification/issuance",
"jwks_uri": "https://accounts.issuer.example/.well-known/vc-public-jwks",
"signing_alg_values_supported": ["EdDSA", "ES256"]
}
托管 .well-known/web-identity 端点
您可能已实现的其他 .well-known JSON 资源,作为
Federated Credentials (FedCM)
API的一部分。
这提供了指向您的账号端点和登录网址的链接。
端点:https://<domain>/.well-known/web-identity
示例响应:
{
"accounts_endpoint": "https://accounts.issuer.example/accounts",
"login_url": "https://accounts.issuer.example/login"
}
使用账号端点
FedCM API 中的账号端点目前提供已登录账号的列表。以下示例展示了最小响应。如需了解更多 详情,请参阅身份提供方实现 指南。
端点:如 .well-known/web-identity 中所指定
以下是一个示例响应:
{
"accounts": [
{
"id": "demo-example",
"name": "Demo User",
"email": "demo@example.com",
"given_name": "Demo"
}
]
}
与登录状态 API 集成
用户需要与提供商建立有效会话,并且您必须使用 登录状态 API 向浏览器发出信号。
当用户成功登录或退出时,提供匹配的 HTTP 响应标头:
Set-Login: logged-in
Set-Login: logged-out
或者,在 Web 应用上下文中使用 JavaScript 更新状态:
navigator.login.setStatus("logged-in");
navigator.login.setStatus("logged-out");
处理颁发请求
您的 issuance_endpoint 会收到包含 request_token 的 application/x-www-form-urlencoded POST 请求。
以下部分展示了处理颁发请求的完整流程。
1. 验证颁发请求
解析并验证传入的浏览器载荷:
- 方法:
POST - 会话验证: 验证与请求一起传输的用户第一方
session/authenticationCookie,以确保存在有效的授权身份上下文。 - 参数验证: 提取
request_token参数(由浏览器生成的签名 JWT)。验证它是否包含预期的临时公钥、目标电子邮件、正确的目标受众群体和有效的时间戳。
解码后的令牌应如下所示:
{
"decodedHeader": {
"alg": "ES256",
"typ": "JWT",
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "pUbLiCKeY123pUbLiCKeY123pUbLiCKeY123",
"y": "pUbLiCKeY456pUbLiCKeY456pUbLiCKeY456"
}
},
"decodedPayload": {
"iss": "https://accounts.issuer.example",
"sub": "demo@example.com",
"email": "demo@example.com",
"iat": 1780272000,
"exp": 1780272300
},
"signature": "SIGnatURE-123_SIGnatURE-123_SIGnatURE-123"
}
2. 使用令牌进行响应
成功验证会话和请求令牌后,使用载荷生成签名选择性披露 JWT (SD-JWT):
{
"iss": "https://accounts.issuer.example",
"iat": 1780272000,
"exp": 1780272300,
"cnf": {
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "pUbLiCKeY123pUbLiCKeY123pUbLiCKeY123",
"y": "pUbLiCKeY456pUbLiCKeY456pUbLiCKeY456"
}
},
"email": "demo@example.com",
"email_verified": true
}
使用私钥和受支持的算法对载荷签名。例如, 在 Node.js 中使用 jose:
const evtJwt = await new SignJWT(evtPayload)
.setProtectedHeader({
alg: "EdDSA",
kid: PRIVATE_KEY_JWK.kid, // Key ID corresponding to our JWKS keys
typ: "evt+jwt", // Standard Token Type for EVTs
})
.sign(privateKey);
// Standard SD-JWT compatibility requires appending a trailing tilde "~"
// to separate the signed token from the key binding section.
const issuanceToken = `${evtJwt}~`;
成功响应示例 (HTTP 200):
{
"issuance_token": "tOkEn123tOkEn123tOkEn123...~"
}
源试用注意事项
源试用是收集反馈的实验,因此如果您作为依赖方或身份提供方参与,您的意见至关重要。如需报告问题,请使用以下 GitHub 代码库:
- 浏览器电子邮件验证 API:WICG/email-verification
- 电子邮件验证协议:dickhardt/email-verification
如果您在 Chrome 实现中遇到 bug,请针对该组件提出 bug:
是否启用源试用功能由您是否包含 OT 令牌来控制,并且是按响应控制的。这意味着,如果您希望将该功能限制为部分用户使用,则可以进行精细控制。例如,如果您已有 A/B 测试框架,则可以在其中集成源试用,以便对受控实验人群进行实验。或者,如果您有 Beta 版测试或早期预览版用户群组,您可能希望或需要为他们启用该功能。在这种情况下,请先针对提供的电子邮件地址进行检查,然后再颁发或验证令牌。
源试用还具有流量限制,以最大限度地减少网站在发布前依赖该功能。颁发者 API 正在开发中,您应该会看到向后不兼容的变更以及 Chrome 界面更新。
随着开发的进展,我们将在博客和 evp-announce@chromium.org 邮件列表上发布更多更新。