← RFC Reference

电子邮件身份验证说明

Email Concepts Encyclopedia Published March 2026
ELI5: 想象一下收到一封声称来自你的银行的信件。SPF 就像检查这封信是否从你的银行实际使用的地址寄出。DKIM 就像一个防篡改印章——如果有人在传输过程中改变了这封信,印章就会破裂。DMARC 是你的银行发布的政策,说"如果一封信同时未通过两项检查,就扔掉它"。ARC 是当邮件通过转发服务等中介传递时的监管链。

SPF、DKIM、DMARC 和 ARC 如何作为一个系统协同工作 — 以及当消息到达接收服务器时每个步骤会发生什么。

为什么电子邮件需要身份验证

SMTP 在 20 世纪 80 年代初设计时没有内置的发件人验证。任何服务器都可以连接到任何其他服务器,并声称从任何地址发送邮件。这不是一个错误 — 这就是协议的设计方式。

电子邮件身份验证是一组建立在 SMTP 之上的标准,用于回答三个问题:

  1. SPF:此服务器是否被授权为该域名发送邮件?
  2. DKIM:此消息确实是由声称的域名发送的吗,并且未被修改?
  3. DMARC:如果 SPF 和 DKIM 都失败,我应该做什么 — 任一结果是否与 From: 标头一致?

每种机制针对不同的攻击面。它们一起形成了一个纵深防御系统。

SPF:谁被允许发送

SPF(发件人策略框架,RFC 7208)让一个域名发布被授权代表其发送邮件的服务器列表。它是一个 DNS TXT 记录:

example.com. IN TXT "v=spf1 include:_spf.mailertogo.com ip4:198.51.100.0/24 -all"

当消息到达时,接收服务器从 MAIL FROM(信封发件人)中提取域名并查询 DNS 以获取 SPF 记录。它检查连接服务器的 IP 地址是否与任何授权机制匹配。

SPF 评估结果:

SPF 的局限性

SPF 验证 信封发件人,而不是用户看到的 From: 标头。网络钓鱼者可以通过在信封中使用自己的域名而在 From: 标头中冒充你的域名来通过 SPF。当邮件被转发时,SPF 也会中断,因为转发服务器的 IP 不在原始域名的 SPF 记录中。这些局限性是为什么 SPF 单独不足够的原因。

DKIM:加密消息签名

DKIM(DomainKeys Identified Mail,RFC 6376)向消息添加数字签名。发送服务器使用私钥签名选定的标头和正文。对应的公钥发布在 DNS 中:

selector._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqh..."

签名作为 DKIM-Signature 标头添加:

DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=selector;
c=relaxed/relaxed; q=dns/txt;
h=from:to:subject:date:message-id:mime-version:content-type;
bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yA...

关键的 DKIM-Signature 字段:

接收服务器从 DNS 获取公钥,重新计算签名标头和正文的哈希,并验证签名。如果匹配,则消息由能访问该域名私钥的人签名,签名内容未被改动。

DKIM 的局限性

DKIM 在转发中保留(不像 SPF),因为签名随消息传播。但是,修改主题或正文的邮件列表会破坏签名。DKIM 也不告诉接收者对失败的签名 做什么 — 这是 DMARC 的工作。

DMARC:策略层

DMARC(基于域的消息身份验证、报告和合规性,RFC 7489)将 SPF 和 DKIM 绑定在一起并添加策略。它作为 DNS TXT 记录发布在 _dmarc.example.com 上:

_dmarc.example.com. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100"

DMARC 引入了 一致性 的关键概念 — 身份验证结果中的域名必须与用户看到的 From: 标头中的域名匹配:

如果 SPF 或 DKIM 至少有一项通过并具有一致性,消息就通过 DMARC。两者都可以单独失败,只要其中一个通过并具有一致性。

DMARC 策略

rua= 标签指定聚合报告的发送位置 — 显示所有声称你的域名的消息的身份验证结果的 XML 报告。这些报告对于在收紧策略之前了解你的电子邮件生态系统至关重要。

当消息到达时会发生什么

以下是完整的身份验证序列,当 mx.receiver.com 收到声称来自 alice@example.com 的消息时的逐步过程:

  1. 连接:发送服务器从 IP 198.51.100.42 连接并发送 MAIL FROM:<bounce-123@sender.example.com>。
  2. SPF 检查:接收方查询 sender.example.com 的 SPF 记录。IP 198.51.100.42 被列出 → SPF 通过。但信封域名是 sender.example.com,而 From: 标头说 example.com — 这些不匹配,所以 没有 SPF 一致性。
  3. 收到消息:DATA 阶段传递标头和正文。
  4. DKIM 检查:接收方找到一个 DKIM-Signature 标头,带有 d=example.com; s=mtg。它从 mtg._domainkey.example.com 获取公钥,验证签名 → DKIM 通过。d= 域名与 From: 标头匹配 → DKIM 一致。
  5. DMARC 检查:接收方获取 _dmarc.example.com。策略是 p=reject。SPF 通过但不一致。DKIM 通过并一致。至少一个机制通过并一致 → DMARC 通过。
  6. Authentication-Results:接收方在标头中记录结果:
Authentication-Results: mx.receiver.com;
spf=pass (sender SPF authorized) smtp.mailfrom=sender.example.com;
dkim=pass header.d=example.com header.s=mtg;
dmarc=pass (policy=reject) header.from=example.com

此标头(RFC 8601)由接收服务器添加,是该跳的身份验证结果的权威记录。

ARC:通过转发保留身份验证

ARC(已验证接收链,RFC 8617)解决了转发问题。当消息通过中介(如邮件列表或转发服务)时,SPF 中断(转发者的 IP 不在原始 SPF 记录中),DKIM 可能中断(如果列表修改消息)。

ARC 的工作方式是让每个中介记录它在修改消息之前观察到的身份验证结果,然后签名这些结果。它为每个跳添加三个标头:

每个标头集都被编号(i=1、i=2 等),形成一条链。最终接收方可以检查链以查看消息最初在跳 1 处通过 DMARC,即使现在因为转发者在跳 2 处修改了消息而失败。

ARC 不覆盖 DMARC。它提供最终接收方可以选择信任的证据。是否遵守 ARC 结果由接收方自行决定。

常见配置:通过第三方发送

当你使用事务性电子邮件服务(如 Mailer To Go)以 your-domain.com 名义发送邮件时,你需要配置所有三层:

; SPF - authorize the service's IPs
your-domain.com. IN TXT "v=spf1 include:_spf.mailertogo.com -all"

; DKIM - publish the service's signing key
mtg._domainkey.your-domain.com. IN CNAME mtg._domainkey.mailertogo.com.

; DMARC - set your policy
_dmarc.your-domain.com. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@your-domain.com"

电子邮件服务以你的域名在 DKIM d= 字段中发送,确保 DKIM 一致性。SPF include: 指令授权他们的服务器。DMARC 将它们绑定在一起。

什么会出错

SPF DNS 查询过多

SPF 有一个硬限制为 10 个 DNS 查询。每个 include:、a:、mx: 和 redirect= 机制计为一个查询。嵌套的 include 计入总数。如果超过 10,SPF 评估返回 permerror,DMARC 将其视为失败。使用验证工具审计你的 SPF 记录。

DKIM 密钥轮换失败

如果你在发送基础设施开始使用新私钥之前轮换 DKIM 密钥(发布新公钥),所有正在进行的消息都会 DKIM 验证失败。始终先发布新密钥,等待 DNS 传播,切换到新私钥,然后在宽限期后删除旧公钥。

DMARC 一致性不匹配

你的 SPF 通过,你的 DKIM 通过,但 DMARC 仍然失败。这发生在任一结果都不与 From: 标头一致时。例如,SPF 验证 bounces.esp.com(信封发件人)但 From: 标头说 your-domain.com。修复:确保 DKIM 使用 d=your-domain.com 签名。

转发的邮件被拒绝

用户转发他们的 old@example.com 邮件到 new@gmail.com。你的消息在原始服务器上通过 DMARC,但 Gmail 看到转发服务器的 IP(SPF 失败)和消息可能被修改(DKIM 失败)。使用 p=reject,转发的副本被拒绝。ARC 可能有帮助,但采用率不一。

子域策略缺口

你在 _dmarc.example.com 上发布 p=reject,但网络钓鱼者从 billing.example.com 发送,其中没有 DMARC 记录。没有 sp=reject(子域策略)在你的 DMARC 记录中,子域继承组织策略 — 但只有在没有单独记录时才可以。明确设置 sp=reject 或为所有子域发布 DMARC 记录。

关键要点

进一步阅读

Related RFCs