一封电子邮件,三种身份:SPF、DKIM 和 DMARC 解析
一封电子邮件携带三个不同的域身份,以及它实际送达的 IP 地址,并且这些身份之间没有任何要求匹配。关于 SPF、DKIM 和 DMARC 的大多数混淆来自于假设检查的只有一个“发件人”。这三个身份由不同的机制进行检查,消息可以通过 DMARC,而其中两个身份指向不同的方向。以下是一个构造的示例(不是实际客户消息,但一个现实且常见的配置),它展示了所有这些身份:通过电子邮件服务提供商(ESP)发送的发票电子邮件,这是大多数 SaaS 计费系统实际发送邮件的方式。 一条消息中的身份 邮件客户端向 acme-example.com 的客户展示来自“Acme Billing”的发票。在下面,这些值决定了该消息是否通过身份验证: Return-Path: <bounces+4471-acmecorp=acme-example.com@bounce.esp-example.net> Received: from mta7.esp-example.net (mta7.esp-example.net [198.51.100.23]) From: "Acme Billing" <billing@acme-example.com> DKIM-Signature: v=1; a=rsa-sha256; d=acme-example.com; s=s2; ... Authentication-Results: mx.recipientdomain.com; spf=pass (sending IP 198.51.100.23) smtp.mailfrom=bounce.esp-example.net; dkim=pass header.d=acme-example.com header.s=s2; dmarc=pass (p=REJECT sp=REJECT) header.from=acme-example.com 三个域身份和一个支持 IP,一条消息: 可见的发件人:billing@acme-example.com,从发件人头部读取。这是一个人查看的唯一身份,也是 DMARC 关心对齐的唯一身份。 信封发件人:bounce.esp-example.net,从 Return-Path 读取(相当于 SMTP MAIL FROM)。这是退信的去处,它属于 ESP,而不是 Acme。 SPF 检查这个域,而不是可见的发件人。 DKIM 域:acme-example.com,从 DKIM-Signature 头部的 d= 读取。Acme 配置了一个与其 ESP 的自定义签名域,而不是使用 ESP 的默认域。这是一个与信封和可见发件人都不同的独立身份。 发送 IP:198.51.100.23,是 ESP 平台上的共享 IP,从 Received 头部读取。这不是域身份;它是交付源。 SPF 的工作是检查这个 IP 是否被授权为信封域发送,而不是针对 acme-example.com。 检查实际上是如何运行的 SPF (RFC 7208) 提出了一个问题:发送 IP 198.51.100.23 被授权为信封域 bounce.esp-example.net 发送吗?ESP 为该子域发布了 SPF 记录,列出了其自己的发送 IP,因此答案是肯定的。acme-example.com 在这个检查中没有出现。 DMARC 使用 SPF 验证的 MAIL FROM 身份进行对齐,因此比较的永远是信封域,而不是发送 IP 本身。 DKIM (RFC 6376) 提出了不同的问题:DKIM-Signature 中的加密签名是否与在 s2._domainkey.acme-example.com 上发布的公钥匹配?Acme 在与其 ESP 设置自定义 DKIM 时生成了该密钥对,因此它是匹配的。这个检查也从不检查信封或发送 IP。它只证明消息的签名部分(头字段和实际被签名覆盖的正文内容)与 acme-example.com 的私钥持有人所签署的内容匹配,并且在传输过程中没有被更改。排除在签名之外的字段不受保护。 DMARC (RFC 9989) 并不添加第三个检查。它采用已经产生结果的两个中的任何一个,并询问该结果的域是否与可见的发件人域 acme-example.com 对齐。在这里,SPF 验证的 MAIL FROM 域是 bounce.esp-example.net,在任何 DMARC 对齐模式下都与 acme-example.com 不一致,因此,尽管 SPF 本身通过了,DMARC 的 SPF 部分失败。DKIM 的验证域正好是 acme-example.com,在放宽和严格对齐下都是完全匹配,因此 DKIM 部分通过。 DMARC 只需要一个对齐的通过,因此仅凭 DKIM,消息就通过了 DMARC。这就是为什么上面的头部块显示 spf=pass 旁边的域不是 Acme 的,然而 dmarc=pass 的原因。 flowchart TD M[电子邮件] --> V[可见的发件人:acme-example.com] M --> E[信封发件人:bounce.esp-example.net] M --> K[DKIM d=: acme-example.com] M --> I[交付 IP:198.51.100.23] E --> SPF{SPF 验证信封} I --> SPF SPF -->|pass,但信封与发件人不对齐| SPFALIGN[SPF 部分:失败对齐] K --> DKIM{DKIM 签名验证} DKIM -->|pass,d=与发件人完全匹配| DKIMALIGN[DKIM 部分:通过对齐] SPFALIGN --> DMARC{任何一部分对齐?} DKIMALIGN --> DMARC DMARC -->|是的,DKIM 部分| PASS([DMARC 通过]) 同一条消息,在两个独立的部分上进行评估。SPF 通过但未对齐。DKIM 通过并对齐。DMARC 只需要一个。 问题出在哪 如果变更这个示例中的一个细节,结果会翻转。如果 Acme 从未与其 ESP 配置自定义 DKIM,则消息将携带 ESP 的默认签名,d=esp-example.net,而不是。
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡