邮件认证机制详解:SPF、DKIM、DMARC
SPF 把发信 IP 和 DNS 白名单比对;DKIM 附上能经受转发的密码学签名;DMARC 通过对齐检查和策略把两者联系起来。解释三者如何配合、如何读懂 Authentication-Results 头,以及正确的部署顺序。

三条 DNS 记录——SPF、DKIM、DMARC——协同工作,向全世界证明从你的域名发出的邮件确实来自你。理解每一条的作用以及它们如何配合,能大幅降低排查送达率问题的难度。
它们要解决的问题
邮件协议最初的设计里没有验证发件人的机制,任何人都可以在 From 头里填任意地址。SPF、DKIM、DMARC 是基于 DNS 的扩展,它们在不改变邮件协议本身的前提下添加了验证能力。
SPF:哪些服务器有资格替你发信
SPF(发件人策略框架)是你 DNS 里的一条 TXT 记录,列出了被授权以你的域名发信的 IP 地址和主机名。
yourdomain.com. TXT "v=spf1 include:_spf.rovela.dev ~all"
接收方服务器收到一封声称来自 @yourdomain.com 的邮件时,会查这条记录,检查发信 IP 是否在列表里。~all 表示「软拒绝其余所有」——当作可疑邮件但不直接拒绝;-all 表示「硬拒绝其余所有」。
SPF 检查的是:信封发件人——SMTP 会话中 MAIL FROM 里的地址,这个地址通常和收件人看到的 From 头不一样。
SPF 的局限:SPF 在邮件转发时会失效。转发服务器 relay.example.com 用自己的 IP 重发你的邮件,而这个 IP 不在你的 SPF 记录里,SPF 就失败了。
DKIM:每封邮件上的密码学签名
DKIM(域名密钥识别邮件)给每封发出的邮件附上一个密码学签名,签名覆盖关键头部和邮件正文。公钥以选择器子域的形式发布在 DNS 里。
rovela._domainkey.yourdomain.com. TXT "v=DKIM1; k=rsa; p=MIIBIjAN..."
接收方服务器收到带签名的邮件时,从 DNS 取出公钥并验证签名。如果邮件在传输途中被修改——哪怕改了一个字符——签名就失效。
DKIM 能经受住的考验:转发。签名随着邮件头部一起传递,不管哪个服务器中转都不影响。
DKIM 做不到的事:它不直接验证 From 头,它验证的是 DKIM 签名里的 d= 域名。把两者关联起来的是 DMARC。
DMARC:对齐与策略
DMARC(基于域的消息认证、报告和一致性)回答两个问题:认证通过的域名和 From 头里的域名是否对齐?如果不对齐,接收方应该怎么处理?
_dmarc.yourdomain.com. TXT "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com"
一封邮件满足以下任意一条即可通过 DMARC:
- SPF 认证通过的域名与
From头的域名对齐 - DKIM 签名的域名与
From头的域名对齐
宽松模式下的「对齐」指两个域名属于同一个组织域。mail.yourdomain.com 与 yourdomain.com 对齐。严格模式要求完全一致。
p= 标签设定策略:none(监控)、quarantine(进垃圾箱)、reject(丢弃邮件)。
三者如何配合
一封邮件到达接收方服务器后,按以下顺序处理:
- SPF 检查:发信 IP 是否匹配
MAIL FROM中域名的 SPF 记录? - DKIM 检查:签名能否验证通过,
d=域名是否能在 DNS 找到对应公钥? - DMARC 检查:至少有一个认证通过的域名和
From头对齐吗?有则 DMARC 通过,不论是哪项检查提供的;否则执行p=策略。
三项检查相互独立,但 DMARC 消费它们的结果。一封邮件可以 SPF 失败(因为被转发了)、DKIM 通过(签名在转发中存活)、DMARC 通过(DKIM 域名和 From 对齐)。
读懂 Authentication-Results 头
每个接收方服务器都会在收到的邮件里加这个头,它是诊断送达率问题最快的工具:
Authentication-Results: mx.google.com;
dkim=pass header.d=yourdomain.com;
spf=pass smtp.mailfrom=yourdomain.com;
dmarc=pass (p=REJECT) header.from=yourdomain.com
如果看到 dmarc=fail,检查 spf 和 dkim 是否都显示 fail。如果有一个通过,是对齐检查失败了——认证通过的域名和 From 头不匹配。
快速部署顺序
- 先加 SPF——一条记录,立即生效。
- 加 DKIM——Rovela 生成密钥对,你把公钥发布到 DNS。
- 加 DMARC,设为
p=none,rua=指向你的收件箱。 - 读两周报告。
- 升级到
p=quarantine,再到p=reject。