跳到主要内容

RFC 7208 - 发件人策略框架(SPF)用于授权在电子邮件中使用域名,版本1

  • 状态: Proposed Standard
  • 发布日期: April 2014
  • Stream: IETF
  • 废弃了: RFC4408
  • 勘误: 无勘误

摘要​

互联网上的电子邮件可以通过多种方式伪造.特别是,现有协议对发送主机可以用作消息的"MAIL FROM"或SMTP HELO/EHLO命令中给出的域没有限制.本文档描述了发件人策略框架(SPF)协议的版本1,通过该协议,管理域(ADMDs)可以明确授权允许使用其域名的主机,并且接收主机可以检查此类授权.

本文档废弃RFC 4408.

目录​


1. 引言​

当前的电子邮件基础设施具有以下特性:向系统注入邮件的任何主机都可以在[RFC5321]和[RFC5322]指定的各种标识符中使用任何它想要的DNS域名.尽管这一特性在某些情况下是可取的,但它是减少未经请求的批量电子邮件(UBE,也称为垃圾邮件)的主要障碍.此外,管理域(ADMDs,如[RFC5598]中所述)理所当然地担心其他实体使用其域名的便利性,这些实体通常具有恶意意图.

本文档定义了一个协议,通过该协议,ADMDs可以授权主机在"MAIL FROM"或"HELO"身份中使用其域名.符合要求的ADMDs在DNS中发布发件人策略框架(SPF)记录,指定哪些主机被允许使用其名称,符合要求的邮件接收者使用发布的SPF记录来测试在邮件事务期间使用给定"HELO"或"MAIL FROM"身份的发送邮件传输代理(MTA)的授权.

对于邮件接收者的一个额外好处是,在验证了身份的使用之后,可以根据发件人的域而不是主机的IP地址做出关于邮件的本地策略决策.这是有利的,因为域名的声誉可能比主机IP地址的声誉更准确,因为域在更长时间内可能更稳定.此外,如果声称的身份未能通过验证,本地策略可以对此类电子邮件采取更强的行动,例如拒绝它.

1.1. 术语​

1.1.1. 关键词​

本文档中的关键词"MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"NOT RECOMMENDED"、"MAY"和"OPTIONAL"应按照[RFC2119]中的描述进行解释.

1.1.2. 导入的定义​

ABNF(增强巴科斯-瑙尔范式)ABNF在[RFC5234]中定义,标记"ALPHA"、"DIGIT"和"SP"(空格)也是如此.

标记"Local-part"、"Domain"和"Mailbox"在[RFC5321]中定义.

"dot-atom"、"quoted-string"、"comment"、"CFWS"(注释折叠空白)、"FWS"(折叠空白)和"CRLF"(回车/换行)在[RFC5322]中定义.

1.1.3. MAIL FROM定义​

本文档关注邮件消息发件人的身份,如[RFC5321]中所述:

事务从给出发件人标识的MAIL命令开始.

由于此身份有许多其他名称,因此选择一个满足以下条件的名称很重要:

  1. 常用
  2. 定义明确

因此,在本文档中将使用术语"MAIL FROM",它被定义为[RFC5598]中描述的RFC5321.MailFrom(反向路径)身份.

1.1.4. HELO定义​

本文档还使用HELO/EHLO身份."HELO"身份源自SMTP HELO或EHLO命令(参见[RFC5321]).由于HELO和EHLO在许多情况下可以互换使用,因此在本文档中通常将它们标识为"HELO".这意味着[RFC5598]中定义的RFC5321.HELO/.EHLO.这些命令提供SMTP会话的SMTP客户端(发送主机)的身份.

1.2. check_host()​

第4节介绍了一种算法,用于根据到达的电子邮件事务评估SPF策略.在早期实现中,该算法被编码在一个名为check_host()的函数中.该名称在本文档中用作SPF评估算法的符号,但当然实现者不需要使用此名称.


2. 操作概述​

2.1. 发布授权​

符合SPF的域按照第3节的描述发布有效的SPF记录.这些记录授权由其中指定的MTA在"HELO"和"MAIL FROM"身份中使用相关域名.

SPF结果可用于做出肯定(来源已授权)和否定(来源未授权)的判定.如果ADMDs选择发布SPF记录并希望支持接收者做出否定授权判定,则它们需要发布以"-all"结尾的记录,或重定向到这样做的其他记录;否则,无法做出明确的授权判定.与否定判定相关的潜在问题和缓解措施在第10节中讨论.

希望声明在SMTP会话期间没有主机被授权在HELO或MAIL FROM命令中使用其DNS域名的ADMDs可以为既不用于电子邮件地址的域部分也不期望发起邮件的域名发布表明这一点的SPF记录.

在更改SPF记录时,必须注意确保有一个过渡期,以便旧策略在所有合法电子邮件可以合理地预期已被检查之前保持有效.[RFC5321]第4.5.4.1节讨论了消息可能在传输中的时间.虽然离线检查是可能的,但检查执行时间越接近原始传输时间,就越有可能获得与发送ADMD在发送消息时的意图相匹配的SPF结果.

2.2. 检查授权​

邮件接收者可以对其接收的每封邮件消息执行一组SPF检查.SPF检查测试客户端主机使用给定身份发送邮件的授权.通常,此类检查由接收MTA执行,但可以在邮件处理链中的其他位置执行,只要所需的信息可用且可靠."MAIL FROM"和"HELO"身份分别按照第2.4节和第2.3节的描述进行检查.

如果没有发布ADMD的明确批准,不建议针对SPF版本1记录检查其他身份,因为已知存在会给出错误结果的情况.例如,几乎所有邮件列表都会重写"MAIL FROM"身份(参见第10.3节),但有些不会更改消息中的任何其他身份.定义其他身份的文档将必须定义明确批准的方法.

邮件接收者可能将SPF检查用作对传入邮件进行更大测试集的一部分.其他测试的结果可能会影响是否执行特定的SPF检查.例如,在本地白名单上找到发送主机的IP地址可能会导致跳过所有其他测试并接受来自该主机的所有邮件.

当邮件接收者决定执行SPF检查时,它必须使用正确实现的check_host()函数(第4节)并使用正确的参数进行评估.尽管整个测试是可选的,但一旦决定执行测试,就必须按照规定执行,以便在发布者和接收者之间保留正确的语义.

要进行测试,邮件接收者必须使用第4.1节中描述的参数评估check_host()函数.

尽管无效、格式错误或不存在的域会导致SPF检查返回"none",因为找不到SPF记录,但长期以来许多MTA的策略是拒绝来自此类域的电子邮件,尤其是在无效的"MAIL FROM"的情况下.拒绝电子邮件将防止一种规避SPF记录的方法.

实现必须注意从SMTP MAIL FROM命令给出的数据中正确提取,因为许多MTA仍然接受诸如源路由(参见[RFC5321]的附录C)、%-hack(参见[RFC1123])和bang路径(参见[RFC1983])之类的东西.这些过时的功能已被恶意使用来绕过安全系统.

2.3. "HELO"身份​

建议SPF验证者不仅检查"MAIL FROM"身份,还通过将check_host()函数(第4节)应用于"HELO"身份作为来单独检查"HELO"身份.检查"HELO"可以促进结果的一致性并减少DNS资源使用.如果可以基于"HELO"检查对消息做出决定性的判定,则可以避免使用DNS资源来处理通常更复杂的"MAIL FROM".此外,由于为"HELO"身份发布的SPF记录指的是单个主机,因此在可用时,它们是主机授权状态的非常可靠的来源.如果同时检查两者,建议的顺序是在"MAIL FROM"之前检查"HELO".

请注意,在EHLO或HELO命令中提供的域的要求对发送方并不总是清楚,SPF验证者必须准备好身份是IP地址字面量(参见[RFC5321]第4.1.3节)或只是格式错误.只有当"HELO"字符串是有效的多标签域名时,才能执行此SPF检查.

2.4. "MAIL FROM"身份​

如果未执行"HELO"检查或未通过将check_host()函数应用于"MAIL FROM"身份作为达到明确的策略结果,则SPF验证者必须检查"MAIL FROM"身份.

[RFC5321]允许反向路径为空(参见[RFC5321]第4.5.5节).在这种情况下,没有明确的发件人邮箱,这样的消息可以被假定为来自邮件系统本身的通知消息.当反向路径为空时,本文档将"MAIL FROM"身份定义为由本地部分"postmaster"和"HELO"身份(之前可能已单独检查过,也可能没有)组成的邮箱.

2.5. 检查位置​

授权检查应该在处理接收邮件的SMTP事务期间执行.这降低了确定用作check_host()输入的正确IP地址的复杂性,并允许通过SMTP回复直接向发送MTA返回错误.[RFC7001]的附录D提供了对此主题的更深入讨论.

授权检查在SMTP事务期间的MAIL命令时执行,并使用MAIL FROM值和客户端IP地址.在以后的时间或使用其他输入执行检查可能会导致以下问题:

  • 可能难以从可能具有欺骗性的标头中准确提取所需信息.
  • 合法电子邮件可能会因为发件人的策略已更改而未通过授权检查.

向未通过授权检查的伪造身份生成不可送达通知通常构成反向散射,即无法采取行动的令人讨厌的拒绝通知.强烈建议运营商避免此类做法.[RFC3834]的第2节描述了反向散射及其引起的问题.

2.6. 评估结果​

第4节定义了check_host(),这是一个模型函数定义,它使用上面定义的输入和在DNS中发布的发件人策略来得出关于客户端授权的结论.SPF验证者实现与那里定义的函数在语义上等效的东西.

本节枚举并简要定义该函数的可能输出.但是,请注意,协议未建立处理任何特定结果的规范性要求.有关每个结果的处理选项的讨论可以在第8节中找到.

2.6.1. None​

"none"结果意味着(a)没有从可以用作要授权的的SMTP会话中提取语法有效的DNS域名,或(b)未从DNS检索到SPF记录.

2.6.2. Neutral​

"neutral"结果意味着ADMD已明确声明它不断言IP地址是否已授权.

2.6.3. Pass​

"pass"结果是客户端被授权使用给定身份注入邮件的明确声明.

2.6.4. Fail​

"fail"结果是客户端未被授权在给定身份中使用域的明确声明.

2.6.5. Softfail​

"softfail"结果是发布ADMD的弱声明,表明主机可能未被授权.它尚未发布导致"fail"的更强、更明确的策略.

2.6.6. Temperror​

"temperror"结果意味着SPF验证者在执行检查时遇到了瞬态(通常是DNS)错误.稍后的重试可能会成功,而无需进一步的DNS操作员操作.

2.6.7. Permerror​

"permerror"结果意味着无法正确解释域发布的记录.这表示错误条件,肯定需要DNS操作员干预才能解决.


3. SPF记录​

SPF记录是一个DNS记录,声明哪些主机被授权或未被授权使用域名作为"HELO"和"MAIL FROM"身份.粗略地说,该记录将主机划分为允许和不允许的集合(尽管某些主机可能不属于任何一类).

SPF记录表示为在单个DNS TXT资源记录的RDATA中找到的单个文本字符串;同一所有者名称不允许有多个SPF记录.记录格式和选择记录的过程在下面的第4节中描述.示例记录如下:

v=spf1 +mx a:colo.example.com/28 -all

此记录的版本为"spf1",包含三个指令:"+mx"、"a:colo.example.com/28"("+"是隐含的)和"-all".

每个SPF记录都放置在DNS树中与其相关的所有者名称处,而不是在所有者名称下的子域中.这类似于SRV记录[RFC2782]的做法.

本节中的示例可能通过域区域文件中的这些行发布:

example.com. TXT "v=spf1 +mx a:colo.example.com/28 -all"

由于TXT记录有多种用途,请注意为其他目的发布的其他TXT记录.它们可能会导致大小限制问题(参见第3.4节),必须注意确保只有SPF记录用于SPF处理.

发布SPF记录的ADMDs应该将评估记录所需的DNS信息量保持在最低限度.第4.6.4节和第10.1.1节提供了一些关于"include"机制和链式"redirect"修饰符的建议.

3.1. DNS资源记录​

SPF记录必须仅作为DNS TXT(类型16)资源记录(RR)[RFC1035]发布.记录的字符内容编码为[US-ASCII].在SPF的实验阶段支持使用替代DNS RR类型,但现已停止.

2003年,当SPF首次开发时,分配新DNS RR类型的要求比现在要严格得多.此外,对新DNS RR类型的轻松部署的支持在DNS服务器和配置系统中没有广泛部署.因此,SPF的开发人员发现使用TXT RR类型作为SPF记录更容易且更实用.

在审查[RFC4408]时,SPFbis工作组得出结论,其双RR类型转换模型存在根本缺陷,因为它不包含实现者必须提供和必须检查的通用RR类型.考虑了许多替代方案来解决此问题,但最终工作组得出结论,在可预见的将来大幅迁移到SPF RR类型的可能性很小,解决此互操作性问题的最佳解决方案是从SPF版本1中放弃对SPF RR类型的支持.有关更多信息,请参阅[RFC6686]的附录A.

十年前围绕SPF初始部署的情况是独特的.如果开发了不重用现有SPF记录的SPF未来更新,它可以使用SPF RR类型.SPF对用于结构化数据的TXT RR类型的使用绝不应被视为未来协议设计者的先例.有关使用新DNS RR类型时的设计考虑的进一步讨论,请参阅[RFC5507].

3.2. 多个DNS记录​

域名不得有多个记录会导致授权检查选择多个记录.有关选择规则,请参阅第4.5节.

3.3. 单个DNS记录中的多个字符串​

如[RFC1035]第3.3节和第3.3.14节所定义,单个文本DNS记录可以由多个字符串组成.如果发布的记录包含多个字符字符串,则必须将该记录视为这些字符串连接在一起而不添加空格.例如:

IN TXT "v=spf1 .... first" "second string..."

等同于:

IN TXT "v=spf1 .... firstsecond string..."

包含多个字符串的TXT记录在构造超过单个TXT记录中字符字符串的255八位字节最大长度的记录时很有用.

3.4. 记录大小​

给定域名的已发布SPF记录应该保持足够小,以便对其查询的结果适合512八位字节内.否则,可能会超过DNS协议限制.此UDP限制在[RFC1035]第2.3.4节中定义,尽管它已由[RFC2671]提高.保持在512八位字节以下应该可以防止较旧的DNS实现故障转移到TCP,并且在没有EDNS0 [RFC6891]支持的情况下也可以与UDP一起使用.由于应答大小取决于本文档范围之外的许多因素,因此只能给出以下指导原则:如果DNS消息的大小,即DNS名称和给定类型的所有记录文本的组合长度小于450八位字节,则DNS应答应该适合UDP数据包.由于防火墙和其他干扰TCP上的DNS操作或使用EDNS0的问题,SPF验证者可能会静默忽略过长而无法放入单个UDP数据包的记录.

请注意,在计算TXT格式查询回复的大小时,必须考虑在域名处发布的任何其他TXT记录.同样,必须评估与SPF相关的所有查询的回复大小,以适合单个512八位字节的UDP数据包(即,DNS消息大小限制为450八位字节).

3.5. 通配符记录​

不鼓励使用通配符记录进行发布,如果使用它们则必须小心.如果区域包括通配符MX记录,它可能希望发布通配符声明,但受相同的要求和问题约束.特别是,对于任何具有任何RR记录的主机以及其子域,必须重复该声明.考虑[RFC1034]第4.3.3节中的示例.基于此,我们可以执行以下操作:

EXAMPLE.COM. MX 10 A.EXAMPLE.COM
EXAMPLE.COM. TXT "v=spf1 a:A.EXAMPLE.COM -all"

*.EXAMPLE.COM. MX 10 A.EXAMPLE.COM
*.EXAMPLE.COM. TXT "v=spf1 a:A.EXAMPLE.COM -all"

A.EXAMPLE.COM. A 203.0.113.1
A.EXAMPLE.COM. MX 10 A.EXAMPLE.COM
A.EXAMPLE.COM. TXT "v=spf1 a:A.EXAMPLE.COM -all"

*.A.EXAMPLE.COM. MX 10 A.EXAMPLE.COM
*.A.EXAMPLE.COM. TXT "v=spf1 a:A.EXAMPLE.COM -all"

对于区域内的每个名称,SPF记录必须列出两次:一次用于名称本身,一次使用通配符来覆盖名称下的树,以便覆盖传出邮件中使用的所有域.


4. check_host() 函数​

此描述不是应用程序编程接口定义,而是用于说明算法的函数描述.符合要求的SPF实现必须产生与此描述在语义上等效的结果.

check_host()函数获取SPF记录、解析它们,并评估它们以确定特定主机是否被允许使用给定身份发送邮件.执行此检查的接收ADMD必须按此处所述正确评估check_host()函数.

实现可以使用与此处定义的规范算法不同的算法,只要在所有情况下结果相同即可.

4.1. 参数 (Arguments)​

check_host()函数接受这些参数:

  • - 发出邮件的SMTP客户端的IP地址,可以是IPv4或IPv6.

  • - 提供所寻求的授权信息的域;最初是"MAIL FROM"或"HELO"身份的域部分.

  • - "MAIL FROM"或"HELO"身份.

对于递归评估,的域部分可能与最初评估check_host()时的参数不同.在大多数其他情况下它们将相同 (参见下文第5.2节).下文第4.6.4节中描述的SPF术语的整体DNS查询限制必须作为所有评估的单一全局限制来跟踪,而不仅仅是针对递归评估的单个实例.

注意,参数可能不是格式良好的域名.例如,如果反向路径为空,则使用EHLO/HELO域,这会带来相关问题 (参见第2.3节).在这些情况下,check_host()在第4.3节中定义为返回"none"结果.

4.2. 结果 (Results)​

check_host()函数可以返回第2.6节中描述的几个结果之一.根据结果,要采取的行动由接收方的本地策略决定.这在第8节中讨论.

4.3. 初始处理 (Initial Processing)​

如果格式错误 (例如, 标签长度超过63个字符, 非末尾的零长度标签等)或不是多标签域名,或者如果DNS查询返回"Name Error"(RCODE 3, 也称为"NXDOMAIN" [RFC2308]),check_host()立即返回结果"none".DNS RCODE在[RFC1035]中定义.格式正确的域是[RFC1983]中定义的完全限定域.也就是说,在DNS中它们隐式地相对于根进行限定(参见[RFC1034]的第3.1节).国际化域名必须编码为A-labels,如[RFC5890]的第2.3节所述.

如果没有local-part,则用字符串"postmaster"替换local-part.

4.4. 记录查找 (Record Lookup)​

根据记录的发布方式 (参见上文第3节),需要对名称进行DNS查询,仅查询TXT类型.

如果DNS查询返回服务器故障 (RCODE 2)或其他错误 (RCODE不是0或3),或者如果查询超时,则check_host()立即终止并返回结果"temperror".

4.5. 选择记录 (Selecting Records)​

记录以版本部分开始:

record = version terms *SP
version = "v=spf1"

从查询返回的记录集开始,丢弃不以"v=spf1"版本部分开头的记录.注意,版本部分由SP字符或记录末尾终止.例如,版本部分为"v=spf10"的记录不匹配并被丢弃.

如果结果记录集不包含任何记录,check_host()产生"none"结果.如果结果记录集包含多个记录,check_host()产生"permerror"结果.

4.6. 记录评估 (Record Evaluation)​

check_host()函数解析和解释SPF记录以找到当前测试的结果.首先验证记录的语法,如果记录中任何地方有任何语法错误,check_host()立即返回结果"permerror",而不进行进一步的解释或评估.

4.6.1. 术语评估 (Term Evaluation)​

有两种类型的术语:机制 (mechanisms, 在第5节中定义) 和修饰符 (modifiers, 在第6节中定义).记录包含按以下增强巴科斯-瑙尔范式 (ABNF)指定的这些的有序列表.

terms = *( 1*SP ( directive / modifier ) )

directive = [ qualifier ] mechanism
qualifier = "+" / "-" / "?" / "~"
mechanism = ( all / include / a / mx / ptr / ip4 / ip6 / exists )
modifier = redirect / explanation / unknown-modifier
unknown-modifier = name "=" macro-string
; where name is not any known modifier

name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )

大多数机制允许在名称后使用":"或"/"字符.

修饰符总是在名称后立即包含等号('=')字符,并在可能是macro-string一部分的任何":"或"/"字符之前.

不包含"="、":"或"/"的术语是机制,如第5节中定义的.

根据[RFC5234]中ABNF符号的定义,机制和修饰符名称不区分大小写.

4.6.2. 机制 (Mechanisms)​

每个机制从左到右依次考虑.如果没有更多机制,结果是第4.7节中描述的默认结果.

当评估机制时,可能发生三种情况之一:它可以匹配、不匹配或返回异常.

如果匹配,处理结束,限定符值作为该记录的结果返回.如果不匹配,处理继续下一个机制.如果返回异常,机制处理结束并返回异常值.

可能的限定符及其导致check_host()返回的结果如下:

"+" pass
"-" fail
"~" softfail
"?" neutral

限定符是可选的,默认为"+".

当机制匹配且限定符为"-"时,返回"fail"结果,并按第6.2节所述计算解释字符串.

具体机制在第5节中描述.

4.6.3. 修饰符 (Modifiers)​

修饰符不是机制.它们不返回匹配或不匹配.相反,它们提供附加信息.尽管修饰符不直接影响记录的评估,但"redirect"修饰符在评估所有机制后会产生影响.

4.6.4. DNS 查询限制 (DNS Lookup Limits)​

某些机制和修饰符(统称为"术语")在评估时会导致DNS查询,而某些则不会.以下术语会导致DNS查询:"include"、"a"、"mx"、"ptr"和"exists"机制,以及"redirect"修饰符.SPF实现必须在SPF评估期间将这些术语的总数限制为10个,以避免对DNS造成不合理的负载.如果超过此限制,实现必须返回"permerror".其他术语——"all"、"ip4"和"ip6"机制,以及"exp"修饰符——在SPF评估时不会导致DNS查询("exp"修饰符仅在稍后时间导致查询),并且它们的使用不受此限制.

当评估"mx"机制时,查询的"MX"资源记录数量包含在上述导致DNS查询的机制/修饰符的总限制10个中.除了该限制之外,每个"MX"记录的评估不得导致查询超过10个地址记录——"A"或"AAAA"资源记录.如果超过此限制,"mx"机制必须产生"permerror"结果.

当评估"ptr"机制或%{p}宏时,查询的"PTR"资源记录数量包含在上述导致DNS查询的机制/修饰符的总限制10个中.除了该限制之外,每个"PTR"记录的评估不得导致查询超过10个地址记录——"A"或"AAAA"资源记录.如果超过此限制,除前10个以外的所有记录必须被忽略.

差异的原因是MX记录的集合和内容由发布ADMD控制,而PTR记录的集合和内容由实际建立连接的IP地址的所有者控制.

这些限制是每个记录中每个机制或宏的限制,并且是对上述指定的查询限制的补充.

MTA或其他处理器应该对评估check_host()的最大经过时间施加限制.这样的限制应该允许至少20秒.如果超过这样的限制,授权的结果应该是"temperror".

如第11.1节末尾所述,在某些情况下,限制DNS查询返回答案计数为0的正面答案(RCODE 0)或"Name Error"(RCODE 3)答案的"术语"数量可能很有用.这些有时统称为"void lookups"(空查询).SPF实现应该将"void lookups"限制为2个.实现可以选择使这样的限制可配置.在这种情况下,建议默认值为2.超过限制会产生"permerror"结果.

4.7. 默认结果 (Default Result)​

如果没有任何机制匹配且没有"redirect"修饰符,则check_host()返回"neutral"结果,就像最后一个指令指定了"?all"一样.如果有"redirect"修饰符,check_host()按第6.1节中定义的方式继续.

最好使用"redirect"修饰符或"all"机制来明确终止处理.尽管在每个未明确终止的记录末尾都有一个隐式的"?all",但明确提供它有助于调试工作.

例如:

v=spf1 +mx -all

或

v=spf1 +mx redirect=_spf.example.com

4.8. 域规范 (Domain Specification)​

这些机制和修饰符中的几个有一个部分.该字符串受宏扩展的约束(参见第7节).结果字符串是完全限定DNS名称的通用表示形式:由句点分隔的一系列标签.此域在本文档的其余部分称为.

注意:宏扩展的结果不受任何进一步的转义.因此,此功能无法产生DNS标签中合法的所有字符(例如,控制字符).然而,此功能足够强大,可以表达合法的主机名和DNS中使用的常见实用标签(例如"_spf").

对于几个机制,是可选的.如果未提供,则使用check_host()参数中的(参见第4.1节)作为.在宏扩展后,"domain"和在语法上是相同的."domain"是check_host()的输入值,而由check_host()计算.

使用语法无效的域评估check_host()的结果是未定义的.

注意:本文档及其前身没有规定如何正确处理语法无效的(这可能是宏扩展的结果),根据[RFC1035].示例包括具有空标签的名称,例如"foo..example.com",以及长度超过63个字符的标签.一些实现选择将这些错误视为不匹配,因此忽略这些名称,而其他实现返回"permerror"异常.


5. 机制定义 (Mechanism Definitions)​

本节定义两种类型的机制:基本语言框架机制和指定发件人机制.

基本机制有助于语言框架.它们不指定特定类型的授权方案.基本机制如下:

  • all
  • include

指定发件人机制用于识别一组地址,这些地址被允许或不被允许使用发送邮件.指定发件人机制如下:

  • a
  • mx
  • ptr (不推荐使用)
  • ip4
  • ip6
  • exists

以下约定适用于在任何时候执行与IP地址之间比较的所有机制:

  • 如果指令中没有给出CIDR前缀长度,则比较和IP地址是否相等.(这里,CIDR是无类域间路由,在[RFC4632]中描述.)

  • 如果指定了CIDR前缀长度,则仅比较和IP地址的指定数量的高位比特是否相等.

当任何机制获取主机地址以与进行比较时,当是IPv4时,获取"A"记录;当是IPv6地址时,获取"AAAA"记录.IPv6服务器上的SPF实现需要处理"AAAA"和"A"记录,以适应IPv4映射的IPv6地址[RFC4291]上的客户端.IPv4地址仅使用"ip4"机制在SPF记录中列出.

几种机制依赖于从DNS获取的信息.对于这些DNS查询,除非另有说明,如果DNS服务器返回错误(RCODE不是0或3)或查询超时,机制停止,最顶层的check_host()返回"temperror".如果服务器返回"Name Error"(RCODE 3),则机制的评估继续进行,就好像服务器返回无错误(RCODE 0)和零个答案记录一样.

5.1. "all"​

all = "all"

"all"机制是一个总是匹配的测试.它用作记录中最右边的机制以提供明确的默认值.

例如:

v=spf1 a mx -all

"all"之后的机制永远不会被测试."all"之后列出的机制必须被忽略.当记录中存在"all"机制时,任何"redirect"修饰符(第6.1节)必须被忽略,无论术语的相对顺序如何.

5.2. "include"​

include = "include" ":" domain-spec

"include"机制触发check_host()的递归评估.

  1. 按第7节进行扩展.

  2. 使用结果字符串作为评估check_host().和参数与当前check_host()评估中的保持相同.

  3. 递归评估返回匹配、不匹配或错误.

  4. 如果返回匹配,则使用"include"机制的适当结果(例如,include或+include产生"pass"结果,-include产生"fail").

  5. 如果返回不匹配或错误,父check_host()按下表恢复处理,的先前值被恢复.

事后看来,名称"include"的选择不当.仅使用引用的SPF记录的评估结果,而不是字面上包含引用记录的机制.例如,评估引用记录中的"-all"指令不会终止整体处理,也不一定导致整体"fail".(此机制更好的名称应该是"if-match"、"on-match"等.)

"include"机制使一个域可以指定多个管理上独立的域.例如,虚荣域"example.net"可能使用管理上独立的域example.com和example.org的服务器发送邮件.

Example.net可以说:

IN TXT "v=spf1 include:example.com include:example.org -all"

这将指示check_host()实际上检查example.com和example.org的记录以获得"pass"结果.只有当主机不被这两个域中的任何一个允许时,结果才是"fail".

此机制是否匹配、不匹配或返回异常取决于check_host()的递归评估结果:

递归 check_host() 结果导致 "include" 机制
pass匹配 (match)
fail不匹配 (not match)
softfail不匹配 (not match)
neutral不匹配 (not match)
temperror返回 temperror
permerror返回 permerror
none返回 permerror

"include"机制旨在跨越管理边界.当保持在一个管理机构内时,"include"通常不是最佳选择.例如,如果example.com和example.org由同一实体管理,并且如果两个域的允许主机集是"mx:example.com",则example.org可以指定"include:example.com",但最好指定"redirect=example.com"甚至"mx:example.com".

使用"include"机制,可以授权管理上外部的主机集,但发件人策略的确定仍然是原始域的SPF记录的功能(由该记录中的"all"机制确定)."redirect"修饰符更适合将授权和策略整合到要在ADMD内共享的公共集合中.Redirect更像是要在单个ADMD中的记录之间共享的公共代码元素.可以从单个记录中控制任意数量域的授权主机和策略.

5.3. "a"​

如果是的IP地址之一,则此机制匹配.为清楚起见,这意味着"a"机制也匹配AAAA记录.

a = "a" [ ":" domain-spec ] [ dual-cidr-length ]

使用适合连接类型(IPv4或IPv6)的查询类型(A或AAAA)对进行地址查询.将与返回的地址进行比较.如果任何地址匹配,则机制匹配.

5.4. "mx"​

如果是域名的MX主机之一,则此机制匹配.

mx = "mx" [ ":" domain-spec ] [ dual-cidr-length ]

check_host()首先对执行MX查询.然后,它对返回的每个MX名称执行地址查询.将与每个返回的IP地址进行比较.为了防止拒绝服务(DoS)攻击,必须遵循第4.6.4节中定义的处理限制.如果超过MX查询限制,则返回"permerror"并终止评估.如果任何地址匹配,则机制匹配.

关于隐式MX的注意事项:如果没有MX记录,check_host()不得通过查询同名的A或AAAA记录来应用[RFC5321]的隐式MX规则.

5.5. "ptr" (不推荐使用)​

此机制测试的DNS反向映射是否存在并正确指向特定域内的域名.此机制不应该被发布.有关更多信息,请参阅本节末尾的注释.

ptr = "ptr" [ ":" domain-spec ]

使用以下过程查找的名称:

  1. 对执行DNS反向映射:如果地址是IPv4地址,则在"in-addr.arpa."中查找相应的PTR记录;如果是IPv6地址,则在"ip6.arpa."中查找.

  2. 对于返回的每条记录,通过查找其IP地址来验证域名.为了防止DoS攻击,必须应用第4.6.4节中定义的PTR处理限制.如果超过限制,处理终止,机制不匹配.

  3. 如果在返回的IP地址中,则该域名被验证.

检查所有已验证的域名,看它们是否匹配或是的子域.如果有任何匹配,此机制匹配.如果找不到已验证的域名,或者如果已验证的域名都不匹配或不是的子域,则此机制无法匹配.如果在执行PTR RR查询时发生DNS错误,则此机制无法匹配.如果在执行A RR查询时发生DNS错误,则跳过该域名并继续搜索.

如果满足以下条件,此机制匹配:

  • 是已验证域名的子域,或
  • 和已验证域名相同.

例如,"mail.example.com"在域"example.com"内,但"mail.bad-example.com"不在.

注意:此机制速度慢,在DNS错误的情况下不如其他机制可靠,并且对.arpa名称服务器造成很大负担.如果使用,则域的主机必须有适当的PTR记录,并且"ptr"机制应该是最后检查的机制之一.经过多年的SPF部署经验,已经得出结论,它是不必要的,应该使用更可靠的替代方案.然而,它仍然作为SPF协议的一部分在使用,因此符合要求的check_host()实现必须支持它.

5.6. "ip4" 和 "ip6"​

这些机制测试是否包含在给定的IP网络中.

ip4 = "ip4" ":" ip4-network [ ip4-cidr-length ]
ip6 = "ip6" ":" ip6-network [ ip6-cidr-length ]

ip4-cidr-length = "/" ("0" / %x31-39 0*1DIGIT) ; 值范围 0-32
ip6-cidr-length = "/" ("0" / %x31-39 0*2DIGIT) ; 值范围 0-128
dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]

ip4-network = qnum "." qnum "." qnum "." qnum
qnum = DIGIT ; 0-9
/ %x31-39 DIGIT ; 10-99
/ "1" 2DIGIT ; 100-199
/ "2" %x30-34 DIGIT ; 200-249
/ "25" %x30-35 ; 250-255

例如,"ip4:192.0.2.128/28"匹配从192.0.2.128到192.0.2.143的IPv4地址.

如果的网络部分等于,则被认为在给定网络中.如果未提供CIDR前缀长度,则假定为"/32"用于"ip4"和"/128"用于"ip6".

5.7. "exists"​

此机制用于构造任意域名,该域名用于A记录查询.它允许更复杂的决策.此机制匹配当且仅当对结果域名的A查询返回任何地址.

exists = "exists" ":" domain-spec

按第7节进行扩展.然后对结果执行A查询.如果返回任何A记录,此机制匹配.

实现应该注意,查询结果的唯一相关部分是代码本身.生成的地址记录(如果有)并不重要.

"exists"机制旨在允许将SPF授权决策委托给信息索引服务.例如,查询"client_ip.quarantine.example.org"对IP地址的SPF实现是微不足道的.但是该域可以用于发布各种隔离的IP地址列表.


6. 修饰符定义 (Modifier Definitions)​

修饰符是提供附加信息的名称/值对.修饰符总是使用"="分隔名称和值.

本文档中定义的修饰符("redirect"和"exp")应该出现在记录的末尾,在所有机制之后,尽管在语法上它们可以出现在记录中的任何位置.这两个修饰符的顺序无关紧要.这两个修饰符不得在一个记录中各出现超过一次.如果出现,则check_host()退出并返回"permerror"结果.

未识别的修饰符必须被忽略,无论它们出现在记录中的何处或出现多少次.这允许符合本文档的实现优雅地处理在其他规范中定义的修饰符的记录.

6.1. redirect: 重定向查询 (Redirected Query)​

"redirect"修饰符旨在将授权和策略整合到要在单个ADMD内共享的公共集合中.可以从单个记录中控制任意数量域的授权主机和策略.

redirect = "redirect" "=" domain-spec

如果所有机制都无法匹配,并且存在"redirect"修饰符,则处理按如下方式进行:

redirect部分的部分按第7节中的宏规则进行扩展.然后使用结果字符串作为评估check_host().和参数与当前check_host()评估中的保持相同.

这个新的check_host()评估的结果然后被视为当前评估的结果,但如果找不到SPF记录,或者如果格式错误,则结果是"permerror"而不是"none".

注意,新查询的域本身可以指定重定向处理.

此功能旨在供希望将相同记录应用于多个域的组织使用.例如:

la.example.com. TXT "v=spf1 redirect=_spf.example.com"
ny.example.com. TXT "v=spf1 redirect=_spf.example.com"
sf.example.com. TXT "v=spf1 redirect=_spf.example.com"
_spf.example.com. TXT "v=spf1 mx:example.com -all"

在此示例中,来自这三个域中任何一个的邮件由相同的记录描述.这可能是一个管理优势.

注意:一般来说,域"A"不能可靠地使用重定向到不在相同管理控制下的另一个域"B".由于保持不变,无法保证域"B"的记录对域"A"中的邮箱正确工作,特别是如果域"B"使用涉及local-parts的机制."include"指令通常更合适.

为清楚起见,任何"redirect"修饰符应该作为记录中的最后一个术语出现.如果记录中任何地方存在"all"机制,则必须忽略任何"redirect"修饰符.

6.2. exp: 解释 (Explanation)​

explanation = "exp" "=" domain-spec

如果check_host()由于机制匹配(例如"-all")导致"fail",并且存在"exp"修饰符,则按下文所述计算返回的解释字符串.如果不存在"exp"修饰符,则必须向调用应用程序返回默认解释字符串或空解释字符串.

被宏扩展(参见第7节)并成为.获取的DNS TXT RRset.

如果有任何DNS处理错误(任何RCODE不是0),或者如果没有返回记录,或者如果返回多个记录,或者如果解释字符串中有语法错误,则按照没有给出"exp"修饰符的方式进行.

获取的TXT记录的字符串连接在一起,不加空格,然后被视为解释字符串,进行宏扩展.这个最终结果就是解释字符串.实现可以限制结果解释字符串的长度,以允许其他协议约束和/或合理的处理限制.由于解释字符串旨在用于SMTP响应,[RFC5321]的第2.4节说响应是[US-ASCII],因此解释字符串必须限制为[US-ASCII].

评估check_host()的软件可以使用此字符串以短消息或URL的形式从发布域传达信息.软件应该明确解释字符串来自第三方.例如,它可以在解释前面加上宏字符串"%{o} explains: ",如第8.4节中的示例所示.

假设example.com有此记录:

v=spf1 mx -all exp=explain._spf.%{d}

以下是explain._spf.example.com处可能的解释TXT记录的一些示例:

"Mail from example.com should only be sent by its own servers."

-- 一个简单的常量消息

"%{i} is not one of %{d}'s designated mail servers."

-- 一个包含更多信息的消息,包括未通过检查的IP地址

"See http://%{d}/why.html?s=%{S}&i=%{I}"

-- 一个复杂的示例,使用check_host()的参数构造URL,以便可以生成包含详细自定义说明的网页

注意:在递归到"include"机制期间,不得使用的"exp"修饰符.相反,当执行"redirect"修饰符时,不得使用原始域的"exp"修饰符.这是因为"include"旨在跨越管理边界,提供的解释应该是来自接收ADMD的解释,而"redirect"旨在作为在ADMD内整合策略记录的工具运行,因此重定向的解释是应该优先的解释.


7. 宏 (Macros)​

当评估SPF策略记录时,某些字符序列旨在被消息或连接的参数替换.这些字符序列称为"宏".

7.1. 正式规范 (Formal Specification)​

宏的ABNF描述如下:

domain-spec = macro-string domain-end
domain-end = ( "." toplabel [ "." ] ) / macro-expand

toplabel = ( *alphanum ALPHA *alphanum ) /
( 1*alphanum "-" *( alphanum / "-" ) alphanum )
alphanum = ALPHA / DIGIT

explain-string = *( macro-string / SP )

macro-string = *( macro-expand / macro-literal )
macro-expand = ( "%{" macro-letter transformers *delimiter "}" )
/ "%%" / "%_" / "%-"
macro-literal = %x21-24 / %x26-7E
; visible characters except "%"
macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" /
"c" / "r" / "t" / "v"
transformers = *DIGIT [ "r" ]
delimiter = "." / "-" / "+" / "," / "/" / "_" / "="

"toplabel"构造受字母-数字-连字符(LDH)规则以及附加顶级域(TLD)限制的约束.有关背景,请参见[RFC3696]的第2节.

一些特殊情况:

  • 字面"%"表示为"%%".
  • "%_"扩展为单个" "空格.
  • "%-"扩展为URL编码的空格,即"%20".

7.2. 宏定义 (Macro Definitions)​

以下宏字母在术语参数中扩展:

s = <sender>
l = <sender>的local-part
o = <sender>的domain
d = <domain>
i = <ip>
p = <ip>的已验证域名(不推荐使用)
v = 如果<ip>是ipv4则为字符串"in-addr",如果<ip>是ipv6则为"ip6"
h = HELO/EHLO域

、和在第4.1节中定义.

以下宏字母仅允许在"exp"文本中使用:

c = SMTP客户端IP(易读格式)
r = 执行检查的主机的域名
t = 当前时间戳

7.3. 宏处理细节 (Macro Processing Details)​

'%'字符后面没有跟随'{'、'%'、'-'或'_'字符是语法错误.因此:

-exists:%(ir).sbl.example.org

是不正确的,将导致check_host()产生"permerror".相反,以下是合法的:

-exists:%{ir}.sbl.example.org

可选的transformers如下:

  • *DIGIT = 零个或多个数字
  • 'r' = 反转值,默认在点上分割

如果提供了transformers或delimiters,则宏字母的替换值被分割成由一个或多个指定分隔符字符分隔的部分.在执行任何反转操作后,必要时再次连接部分.

如果指定了DIGIT,则它指示要使用的部分数量,从右边开始.如果指定的部分数量大于可用的部分数量,则使用所有可用的部分.如果未指定数字,则使用所有部分.

宏字母'p'、'c'、'r'和't'不推荐使用,因为它们可能会导致额外的DNS查询、不可靠的结果或其他问题,如第11.6节和第5.5节所述.

处理示例:

假设是"[email protected]",宏字母"l"扩展为"strong-bad".

如果使用transformers "{l}",结果不变:"strong-bad".

如果使用"{l-}"并指定分隔符为"-",结果被分割为"strong"和"bad"两部分,然后用点连接:"strong.bad".

如果使用"{lr-}",先分割为["strong", "bad"],然后反转为["bad", "strong"],再连接:"bad.strong".

如果使用"{l1r-}",先分割,反转后只取最右边1个部分,结果为:"strong".

7.4. 扩展示例 (Expansion Examples)​

在以下示例中,假设是"192.0.2.3",是"[email protected]",是"email.example.com".

%{s}   = [email protected]
%{o} = email.example.com
%{d} = email.example.com
%{d4} = email.example.com
%{d3} = email.example.com
%{d2} = example.com
%{d1} = com
%{dr} = com.example.email
%{d2r} = example.email
%{l} = strong-bad
%{l-} = strong.bad
%{lr} = strong-bad
%{lr-} = bad.strong
%{l1r-} = strong

对于IPv4地址192.0.2.3:

%{i}  = 192.0.2.3
%{ir} = 3.2.0.192
%{v} = in-addr
%{c} = 192.0.2.3

对于IPv6地址2001:db8::cb01:

%{i}  = 2001:db8::cb01
%{ir} = 1.0.b.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2
%{v} = ip6
%{c} = 2001:db8::cb01

8. 结果处理 (Result Handling)​

本节为SPF验证器操作者提供了针对消息上check_host()各种可能输出的响应指导.SPF结果的定义在第2.6节中提供;本节为每个结果提供更多细节,用于开发消息处理的本地策略.

每个操作环境都不同.对于一些接收者来说,严格遵守SPF是合适的,明确处理被评估为明确未授权("fail",有时是"softfail")的消息是常态.对于其他接收者来说,"假阴性"的情况更令人担忧.这种担忧通常通过仅将结果记录在标头中并允许消息传递以进行附加处理来处理.还有其他情况,SPF是消息处理决策的几个输入之一.因此,对于任何特定结果,没有全面的规范性消息处理要求.本节旨在呈现每个结果可能原因的完整图景,以及在可用时在实验性部署期间获得的经验.

本质上有两类处理选择:

  • 在尝试传递消息的SMTP会话中进行处理,例如通过返回永久SMTP错误(拒绝)或临时SMTP错误("稍后再试");

  • 允许消息通过(成功的SMTP回复代码)并添加一个附加标头字段,指示check_host()返回的结果和其他突出细节;这在第9节中更详细地讨论.

8.1. None​

对于"none"结果,SPF验证器完全没有关于客户端使用已检查身份或多个身份的授权或缺乏授权的信息.check_host()函数在没有错误的情况下完成,但无法得出任何结论.

8.2. Neutral​

"neutral"结果表示虽然发现了身份的策略,但没有关于客户端的明确断言(正面或负面).

"neutral"结果必须被完全像"none"结果一样处理;该区别仅用于信息目的.比"none"更严厉地处理"neutral"会阻碍ADMD测试SPF记录的使用(参见第10.1节).

8.3. Pass​

"pass"结果意味着客户端被授权使用给定身份注入邮件.就声誉而言,该域现在可以被认为负责发送消息.进一步的策略检查现在可以有信心地进行,相信身份的合法使用.这在附录G.1中进一步讨论.

8.4. Fail​

"fail"结果是一个明确声明,表示客户端未被授权在给定身份中使用该域.SPF失败消息的处置是本地策略的问题.有关开发本地策略的考虑,请参见附录G.2.

如果检查软件选择在SMTP事务期间拒绝邮件,则应该使用SMTP回复代码550(参见[RFC5321]),如果支持,还应该使用5.7.1增强状态代码(参见[RFC3463]第3.8节),以及适当的回复文本.check_host()函数将返回默认解释字符串或来自发布SPF记录的域的解释字符串(参见第6.2节).如果信息不是源自检查软件,最好清楚地表明文本是由发件人的域提供的.例如:

550 5.7.1 SPF MAIL FROM check failed:
550 5.7.1 The domain example.com explains:
550 5.7.1 Please see http://www.example.com/mailpolicy.html

如果检查软件选择不在SMTP事务期间拒绝邮件,则应该添加Received-SPF或Authentication-Results标头字段(参见第9节)以将此结果传达给下游消息处理器.虽然这对所有SPF结果都是正确的,但对于"fail"结果尤为重要,因为消息明确未被ADMD授权.

8.5. Softfail​

"softfail"结果应该被视为介于"fail"和"neutral"/"none"之间的某处.ADMD认为主机未被授权,但不愿意做出强有力的策略声明.接收软件不应该仅基于此结果拒绝消息,但可以对消息进行比正常更仔细的审查.

ADMD希望阻止此主机的使用,因此希望在出现"softfail"结果时获得有限的反馈.例如,收件人的MUA可以突出显示"softfail"状态,或者接收MTA可以使用灰名单[RFC6647]向发件人提供消息,在第一次接收消息时提供注释,但根据接收方策略在稍后的尝试中接受它.

8.6. Temperror​

"temperror"结果意味着SPF验证器在执行检查时遇到临时(通常是DNS)错误.检查软件可以选择接受或临时拒绝消息.如果由于这个原因在SMTP事务期间拒绝消息,软件应该使用SMTP回复代码451,如果支持,还应该使用4.4.3增强状态代码(参见[RFC3463]的第3.5节).这些错误可能由发件人或接收方的DNS软件中的问题引起.有关开发本地策略的考虑,请参见附录G.4.

8.7. Permerror​

"permerror"结果意味着域的已发布记录无法正确解释.这表明一个错误条件,肯定需要DNS操作者干预才能解决.如果由于这个原因在SMTP事务期间拒绝消息,软件应该使用SMTP回复代码550,如果支持,还应该使用5.5.2增强状态代码(参见[RFC3463]第3.6节).请注意,如果ADMD使用宏(第7节),则此结果可能是由于已检查的身份具有意外格式.也有可能某些SPF验证器由于输入参数具有意外格式而生成此结果;参见第4.8节.有关开发本地策略的考虑,请参见附录G.3.


9. 记录结果 (Recording the Result)​

为了向下游代理(例如MUA)提供它们在评估或表示消息内容的表面安全性方面可能需要的信息,建议SMTP接收器在消息标头中记录SPF处理的结果.对于选择在消息标头中记录SPF结果以供内部过滤器或MUA处理的SPF验证器操作者,提供了两种方法:第9.1节定义了Received-SPF字段,这是最初为SPF使用定义的结果字段.第9.2节讨论了Authentication-Results标头字段[RFC7001],该字段是最近指定的,旨在供SPF和其他身份验证方法使用.

两者都在常用中,因此两者都包含在此处.然而,重要的是要注意,它们被设计用于略有不同的目的.Received-SPF旨在包含足够的信息以能够重建消息的SPF评估,而Authentication-Results仅旨在中继结果本身以及可能对最终用户有用的相关输出细节(例如,实际验证的消息属性是什么以及它包含什么),将重建工作留给系统日志和Received字段内容的范围.此外,Received-SPF依赖于接收ADMD内的代理遵守[RFC5321]和[RFC5322]的标头字段排序规则,而Authentication-Results包含一些保护措施以防止不符合要求的实现.

SPF验证器操作者可以选择同时使用两者来服务不同的下游代理.在这种情况下,需要注意确保两个字段传达相同的细节,否则可能会出现意外结果.

9.1. Received-SPF 标头字段 (The Received-SPF Header Field)​

Received-SPF标头字段是一个跟踪字段(参见[RFC5322]第3.6.7节),应该预先添加到现有标头之上,位于SMTP接收器生成的Received:字段之上.它必须出现在消息中所有其他Received-SPF字段之上.标头字段具有以下格式:

header-field = "Received-SPF:" [CFWS] result FWS [comment FWS]
[ key-value-list ] CRLF

result = "pass" / "fail" / "softfail" / "neutral" /
"none" / "temperror" / "permerror"

key-value-list = key-value-pair *( ";" [CFWS] key-value-pair ) [";"]

key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string )

key = "client-ip" / "envelope-from" / "helo" /
"problem" / "receiver" / "identity" /
"mechanism" / name

identity = "mailfrom" ; for the "MAIL FROM" identity
/ "helo" ; for the "HELO" identity
/ name ; other identities

标头字段应该在结果后包含"(...)"样式的注释,传达结果的支持信息,例如、和.

以下键值对设计用于以后的机器解析.SPF验证器应该提供足够的信息以便可以验证SPF结果——即至少"client-ip"、"helo",以及如果检查了"MAIL FROM"身份,则还包括"envelope-from".

  • client-ip - SMTP客户端的IP地址
  • envelope-from - 信封发件人邮箱
  • helo - 在HELO或EHLO命令中给出的主机名
  • mechanism - 匹配的机制(如果没有机制匹配,则替换为单词"default")
  • problem - 如果返回错误,则是关于错误的详细信息
  • receiver - SPF验证器的主机名
  • identity - 被检查的身份;参见 ABNF规则

其他键可以由SPF验证器定义.

SPF验证器必须确保Received-SPF标头字段不包含无效字符,不过长(参见[RFC5322]第2.1.1节),并且不包含发件人提供的恶意数据.

可能生成的各种标头字段样式的示例如下:

Received-SPF: pass (mybox.example.org: domain of
[email protected] designates 192.0.2.1 as permitted sender)
receiver=mybox.example.org; client-ip=192.0.2.1;
envelope-from="[email protected]"; helo=foo.example.com;

Received-SPF: fail (mybox.example.org: domain of
[email protected] does not designate 192.0.2.1 as permitted sender)
identity=mailfrom; client-ip=192.0.2.1;
envelope-from="[email protected]";

Received-SPF: pass (mybox.example.org: domain of
[email protected] designates 192.0.2.1 as permitted sender)
receiver=mybox.example.org; client-ip=192.0.2.1;
mechanism=ip4:192.0.2.1; envelope-from="[email protected]";
helo=foo.example.com;

9.2. Authentication-Results 标头字段中的 SPF 结果​

如第9节所述,Authentication-Results标头字段旨在传达边界MTA进行的测试列表及其结果.该字段的指定元素提供的信息少于Received-SPF字段:

Authentication-Results: myhost.example.org; spf=pass
smtp.mailfrom=example.net

Received-SPF: pass (myhost.example.org: domain of
[email protected] designates 192.0.2.1 as permitted sender)
receiver=mybox.example.org; client-ip=192.0.2.1;
envelope-from="[email protected]"; helo=foo.example.com;

然而,如果需要,可以在Authentication-Results标头字段的"reason"部分添加CFWS并提供等效信息.

例如,扩展的Authentication-Results标头字段可能看起来像(对于本示例中的"MAIL FROM"检查):

Authentication-Results: myhost.example.org; spf=pass
reason="client-ip=192.0.2.1; smtp.helo=foo.example.com"
[email protected]

10. 对基础设施的影响 (Effects on Infrastructure)​

本节概述了采用此协议对涉及互联网电子邮件的各个实体将产生的主要影响.它旨在向读者明确此协议在何处明确影响此类实体的运行.本节不是"操作手册"或"最佳实践"文档,也不是此类实体根据本规范应该做什么的全面列表.

本节仅提供操作建议和指导.它不是规范性的.

[RFC5598]描述了互联网电子邮件架构.本节根据架构的不同部分进行组织.

10.1. 发送域 (Sending Domains)​

希望符合本规范的发起ADMD(管理域——[RFC5598]的第2.2.1和2.3节)将需要确定它们允许在中继到其他ADMD时在"HELO"和"MAIL FROM"身份中使用其域名的中继列表([RFC5598]第2.2.2节).人们认识到,形成这样的列表不仅仅是一个简单的技术练习,而是涉及具有技术和管理考虑的策略决策.

10.1.1. DNS 资源考虑 (DNS Resource Considerations)​

通过选择需要较少DNS信息的指令并将成本较低的机制放在SPF记录的早期位置,可以最小化SPF查找所需的DNS资源.

第4.6.4节指定了接收器必须使用的限制.发布不超过这些要求的记录至关重要.还需要仔细权衡合法解决方案的成本和可维护性.

例如,考虑如下设置的域:

example.com.     IN MX  10 mx.example.com.
IN MX 20 mx2.example.com.
mx.example.com. IN A 192.0.2.1
mx2.example.com. IN A 192.0.2.129

假设管理要点是授权(pass)mx和mx2,同时使所有其他主机失败.比较以下解决方案:

最佳记录:

example.com. IN TXT "v=spf1 ip4:192.0.2.1 ip4:192.0.2.129 -all"

良好记录:

$ORIGIN example.com.
@ IN TXT "v=spf1 a:authorized-spf.example.com -all"
authorized-spf IN A 192.0.2.1
IN A 192.0.2.129

昂贵记录:

example.com. IN TXT "v=spf1 mx:example.com -all"

浪费的、不良记录:

example.com. IN TXT "v=spf1 ip4:192.0.2.0/24 mx -all"

10.1.2. 管理员的考虑 (Administrator's Considerations)​

可能存在管理考虑:使用"a"而不是"ip4"或"ip6"允许主机轻松重新编号,代价是每个接收器需要进行DNS查询.使用"mx"而不是"a"允许邮件主机集轻松更改.除非这样的更改很常见,否则最好使用资源密集程度较低的机制,如"ip4"和"ip6"而不是"a",或"a"而不是"mx".

在某些特定情况下,关于记录内容的标准建议是适当的.为不发送邮件的域发布SPF记录是一个成熟的最佳实践.不发送邮件的域的记录是:

www.example.com. IN TXT "v=spf1 -all"

为单个主机发布SPF记录也是最佳实践.主机名通常是5321.HELO/.EHLO命令中使用的身份.在具有空5321.MailFrom的消息的情况下,除了用于基于5321.HELO/.EHLO的SPF检查外,这还用作5321.MailFrom SPF检查的域.参与邮件处理的单个主机的标准SPF记录是:

relay.example.com. IN TXT "v=spf1 a -all"

验证正确的部署很困难.[RFC6652]描述了一种征求SPF失败反馈的机制.另一个建议可以在附录C中找到.

无论使用哪种方法,理解ADMD的出站邮件架构对于有效部署至关重要.

10.1.3. 退信 (Bounces)​

如第2.4节所述,[RFC5321]允许MAIL FROM为空,这是某些传递状态通知[RFC3464]的典型情况,通常称为电子邮件退信.在这种情况下,可用于执行SPF检查的唯一实体是第1.1.4节中定义的"HELO"身份.管理员确保正确设置此身份并具有适当的SPF记录可以增强SPF功能.将"HELO"身份设置为主机名而不是域是正常的.对于大量主机的区域文件生成可以使用"redirect"修饰符进行整合,并为初始部署编写脚本.具体的部署建议在上面的第10.1.2节中给出.

10.2. 接收者 (Receivers)​

SPF结果可以与其他方法结合使用,以确定消息的最终本地处置(正面或负面).它也可以单独被视为决定性的.

试图让一个组织(发件人)指导另一个组织(接收方)的电子邮件处理策略本质上是具有挑战性的,并且经常是有争议的.如本文档其他地方所述,没有基于SPF结果的消息特定处理的全面规范性要求.在形成本地处理策略时,第8节和附录G中提供的信息可供接收方考虑.

主要考虑因素是,SPF可能会为最终有害的邮件返回"pass"(例如,使用一次性域名安排SPF通过的垃圾邮件发送者,或来自受信任源内的病毒或垃圾邮件爆发),也可能会为最终合法的邮件返回"fail"(例如,已通过邮件别名的合法邮件).在建立本地处理策略时,重要的是要考虑这两种情况.

10.3. 中介者 (Mediators)​

中介者是一种用户参与者[RFC5598].也就是说,中介者"接收"一条消息并"提交"一条新消息.中介者可以使新发布的消息与原始消息尽可能相似或尽可能不同.示例包括邮件列表(参见[RFC5598]的第5.3节)和转发者([RFC5598]的第5.2节).这在[RFC5321]第3.9节中讨论.对于SPF的操作,关键问题是新消息的5321.MailFrom命令中的电子邮件地址.

由于SPF评估基于"最后"发送SMTP服务器的IP地址,因此将使用中介者的地址,而不是向中介者发送消息的SMTP服务器的地址.一些中介者保留原始消息的电子邮件地址,而一些使用新地址.

如果地址与原始消息相同,并且原始消息具有关联的SPF记录,则SPF评估将失败,除非使用附录D中描述的缓解措施.


11. 安全考虑 (Security Considerations)​

11.1. 处理限制 (Processing Limits)​

与电子邮件的大多数方面一样,恶意方可以通过多种方式将协议用作DoS攻击的途径.第4.6.4节中概述的处理限制旨在防止以下攻击:

  • DNS放大攻击:恶意方可以创建包含许多对受害者域的引用的SPF记录,并向不同的SPF验证器发送许多电子邮件;这些SPF验证器随后会创建DoS攻击.实际上,SPF验证器被用来通过在SMTP会话中使用较少的八位字节而在DNS查询中使用更多的八位字节来放大攻击者的带宽.使用SPF验证器还允许攻击者隐藏攻击的真实来源.这种潜在的攻击基于传输大量邮件.

  • 资源耗尽攻击:虽然check_host()的实现应该限制DNS查询的数量,但恶意域可以发布超过这些限制的记录,试图在向它们发送邮件时浪费目标的计算努力.恶意域还可以设计导致特定实现使用过多内存或CPU或触发错误的SPF记录.如果接收器配置为接受SPF结果为"temperror"的邮件,则这样的攻击可能导致原本会因SPF"fail"结果而被拒绝的邮件被接受.这种潜在的攻击基于使用特制的SPF记录来耗尽受害者的DNS资源.

  • 间接DNS负载:恶意方可以向各种合法邮件主机发送大量声称来自预期目标的邮件.这些合法机器在获取相关记录时会对目标施加DNS负载.

  • 查询放大攻击:理论上,恶意方可以使用SPF记录作为DoS攻击的DNS查询放大的载体.在这种情况下,攻击者在其自己的DNS中发布一个SPF记录,该记录使用针对预期受害者的"a"和"mx"机制,例如"a:example.com a:foo.example.com a:bar.example.com ...",然后向各种目的地大量分发包含其自己域的MAIL FROM值的邮件.任何运行SPF验证器的这样的目的地都会开始查询该记录中与"a"机制关联的所有名称.记录中使用的名称无需存在即可使攻击有效.自[RFC4408]发布以来的运行经验表明,通过在遇到超过两个"void lookups"(在第4.6.4节中定义)时让验证器中止处理并返回"permerror"(第2.6.7节),可以在对已部署基础的影响最小的情况下缓解这类攻击.

在这些情况中,SPF记录中引用的第三方的情况是DoS攻击最容易有效利用的.因此,对于单个邮件服务器可能看起来合理的限制仍然可能允许不合理的带宽放大量.因此,处理限制需要非常低.

11.2. SPF 授权的电子邮件可能包含其他虚假身份​

"MAIL FROM"和"HELO"身份授权不提供关于消息中使用的其他身份的授权/真实性的保证.恶意发件人完全有可能在SPF使用的身份中使用其自己的域注入消息,并让该域的SPF记录授权发送主机,然而消息可以轻松地在其标头中列出其他身份.除非用户或MUA注意到授权身份与其他更常见呈现的身份(例如From:标头字段)不匹配,否则用户可能会被诱入虚假的安全感.

11.3. 伪造的 DNS 和 IP 数据 (Spoofed DNS and IP Data)​

恶意方可以利用此协议的两个方面来破坏check_host()函数的有效性:

  • DNS欺骗:check_host()的评估严重依赖DNS.恶意攻击者可以攻击DNS基础设施并导致check_host()看到伪造的DNS数据,然后返回不正确的结果.这可能包括为实际域的记录会评估为"fail"的值返回"pass".有关DNS弱点的描述,请参见[RFC3833],有关对策,请参见[RFC4033].

  • IP地址欺骗:客户端IP地址被假设为正确.在现代正确配置的系统中,这不真实的风险为零.

11.4. 跨用户伪造 (Cross-User Forgery)​

根据定义,SPF策略只是将域名映射到授权MTA集,而不是将整个电子邮件地址映射到授权用户集.尽管"l"宏(第7节)提供了一种有限的方式来为特定电子邮件地址定义授权MTA的单独集,但通常不可能通过SPF验证同一MTA的各个用户对特定电子邮件地址的使用.

邮件服务及其MTA需要直接防止跨用户伪造:基于SMTP AUTH([RFC4954]),用户必须被限制为仅使用实际在其控制下的那些电子邮件地址(参见[RFC6409]的第6.1节).验证各个用户身份的另一种方法是消息加密,例如Pretty Good Privacy (PGP)([RFC4880])或S/MIME([RFC5751]).

11.5. 不可信的信息源 (Untrusted Information Sources)​

符合SPF的接收器从它接收的SMTP命令和发送域持有者的已发布DNS记录(例如,"HELO"域名、信封中的"MAIL FROM"地址,以及域持有者发布的SPF DNS记录)收集信息.这些参数在SMTP过程中未经验证.

所有这些信息都由接收器权限之外的参与者生成,因此不能保证准确或合法.

11.5.1. 记录的结果 (Recorded Results)​

在Received-SPF:或Authentication-Results:跟踪字段中传递给接收器的此信息可以作为SMTP拒绝消息返回给客户端MTA.如果生成这样的SMTP拒绝消息,则必须检查来自跟踪字段的信息是否存在诸如无效字符和过长行之类的问题.

11.5.2. 外部解释 (External Explanations)​

当授权检查失败时,拒绝响应中可以包含解释字符串.发件人和拒绝接收器都需要意识到解释是由检查的SPF记录的发布者确定的,一般来说,不是接收器.解释可能包含恶意URL,或者它可能是冒犯性的或误导性的.

由于"exp"修饰符(第6.2节)返回给发件人域的解释是由域持有者自己发布的发件人策略生成的.只要消息仅使用未传递通知([RFC3464])返回到从其自己的DNS SPF记录发布解释字符串的域,唯一受影响的方就是域的SPF记录的原始发布者.

实际上,此类未传递通知可能被误导,例如当MTA接受电子邮件并且仅在稍后向伪造地址生成通知时,或者当电子邮件转发器未将退信定向回原始发件人时.

11.5.3. 宏扩展 (Macro Expansion)​

宏(第7节)允许发件人向接收器DNS查询中注入任意文本(任何非空[US-ASCII]字符).必须准备好应对敌对或意外的内容.

11.6. 隐私暴露 (Privacy Exposure)​

检查SPF记录会导致DNS查询被发送到域所有者.这些DNS查询,特别是如果它们是由"exists"机制引起的,可以包含关于谁在发送电子邮件以及可能向哪个MTA发送电子邮件的信息.这可能会引入一些隐私问题,根据当地法律以及ADMD与发送电子邮件的人之间的关系,这或多或少是一个问题.

11.7. 传递产生 "Fail" 结果的邮件 (Delivering Mail Producing a "Fail" Result)​

选择传递SPF产生"fail"结果的邮件的操作者需要理解,他们正在接纳声称的发件人明确未授权的内容.虽然存在可以被视为"假阴性"的已知故障模式,但接纳这些消息的明确选择会增加最终用户遭受可能伤害的风险.对于属于已知良好参与者的域尤其如此,这些域通常表现良好;来自这些来源的未授权邮件很可能会受到更高的怀疑和内容分析.

然而,SPF不包括区分良好参与者和不良参与者的能力,也不处理已知参与者与未知参与者的概念.这些概念超出了本规范的范围.


Appendix A. 扩展示例 (Extended Examples)​

这些示例基于以下DNS设置:

; 一个具有两个邮件服务器、两个主机和两个服务器的域
; 在域名处
$ORIGIN example.com.
@ MX 10 mail-a
MX 20 mail-b
A 192.0.2.10
A 192.0.2.11
amy A 192.0.2.65
bob A 192.0.2.66
mail-a A 192.0.2.129
mail-b A 192.0.2.130
www CNAME example.com.

; 一个相关域
$ORIGIN example.org.
@ MX 10 mail-c
mail-c A 192.0.2.140

; 这些地址的反向IP
$ORIGIN 2.0.192.in-addr.arpa.
10 PTR example.com.
11 PTR example.com.
65 PTR amy.example.com.
66 PTR bob.example.com.
129 PTR mail-a.example.com.
130 PTR mail-b.example.com.
140 PTR mail-c.example.org.

; 一个声称是某物但实际不是的恶意反向IP域
$ORIGIN 0.0.10.in-addr.arpa.
4 PTR bob.example.com.

A.1. 简单示例 (Simple Examples)​

这些示例显示了example.com的各种可能发布的记录,以及哪些值会导致check_host()返回"pass".注意是"example.com".

v=spf1 +all

  • 任何都通过

v=spf1 a -all

  • 主机192.0.2.10和192.0.2.11通过

v=spf1 a:example.org -all

  • 没有发送主机通过,因为example.org没有A记录

v=spf1 mx -all

  • 发送主机192.0.2.129和192.0.2.130通过

v=spf1 mx:example.org -all

  • 发送主机192.0.2.140通过

v=spf1 mx mx:example.org -all

  • 发送主机192.0.2.129、192.0.2.130和192.0.2.140通过

v=spf1 mx/30 mx:example.org/30 -all

  • 192.0.2.128/30或192.0.2.140/30中的任何发送主机通过

v=spf1 ptr -all

  • 发送主机192.0.2.65通过(反向DNS有效且在example.com中)
  • 发送主机192.0.2.140失败(反向DNS有效,但不在example.com中)
  • 发送主机10.0.0.4失败(反向IP无效)

v=spf1 ip4:192.0.2.128/28 -all

  • 发送主机192.0.2.65失败
  • 发送主机192.0.2.129通过

A.2. 多域示例 (Multiple Domain Example)​

这些示例显示相关记录的效果:

example.org: "v=spf1 include:example.com include:example.net -all"

如果来自example.org的邮件实际上通过example.com和example.net的服务器传输,则会使用此记录.Example.org的指定服务器是example.com和example.net的指定服务器的并集.

la.example.org: "v=spf1 redirect=example.org" ny.example.org: "v=spf1 redirect=example.org" sf.example.org: "v=spf1 redirect=example.org"

这些记录允许一组都使用相同邮件系统的域使用该邮件系统的记录.这样,当邮件设置更改时,只需更新邮件系统的记录.这些域的记录永远不必更改.

A.3. DNS 黑名单 (DNSBL) 样式示例​

假设除了上面列出的域记录之外,还有这些(参见[RFC5782]):

$ORIGIN _spf.example.com.
mary.mobile-users A 127.0.0.2
fred.mobile-users A 127.0.0.2
15.15.168.192.joel.remote-users A 127.0.0.2
16.15.168.192.joel.remote-users A 127.0.0.2

以下记录描述了从任意服务器发送邮件或从个人服务器发送邮件的example.com用户.

example.com:

v=spf1 mx
include:mobile-users._spf.%{d}
include:remote-users._spf.%{d}
-all

mobile-users._spf.example.com:

v=spf1 exists:%{l1r+}.%{d}

remote-users._spf.example.com:

v=spf1 exists:%{ir}.%{l1r+}.%{d}

A.4. 多重要求示例 (Multiple Requirements Example)​

假设您的发件人策略要求IP地址在某个范围内并且IP的反向DNS匹配.这可以通过多种方式完成,包括以下方式:

example.com.         SPF  ( "v=spf1 "
"-include:ip4._spf.%{d} "
"-include:ptr._spf.%{d} "
"+all" )
ip4._spf.example.com. SPF "v=spf1 -ip4:192.0.2.0/24 +all"
ptr._spf.example.com. SPF "v=spf1 -ptr +all"

此示例显示了"-include"机制如何有用,以"+all"结尾的SPF记录如何非常严格,以及德摩根定律的使用.


Appendix B. 与 RFC 4408 实现要求的变更​

与[RFC4408]的实现要求的修改都是(a)[RFC4408]中错误的更正或(b)基于自[RFC4408]发布以来获得的运行经验共识的附加文档.

  • 删除了 DNS RR type SPF (99) 的使用:已从协议中删除;有关背景,请参见[RFC6686].

  • 新增基于"void lookups"的 DNS 相关处理限制:已添加(第4.6.4节).

  • 强烈不鼓励使用 ptr 机制和 %p 宏:(第5.5节和第7.2节).ptr机制和%p宏仍然是协议的一部分,因为发现它们正在使用中,但应该更新记录以避免它们.

  • 讨论了使用 "Authentication-Results" 标头字段:[RFC7001]作为使用"Received-SPF"标头字段的可能替代方案(第9.2节).

  • 对 ABNF 进行了许多次要更正:使其更加清晰和正确(第12节).SPF库实现者应该仔细审查修订后的ABNF,以确定是否需要实现更改.

  • 删除了 ABNF 中对 X- 字段的使用:有关背景,请参见[RFC6648].

  • 记录了宏扩展后如何处理无效 的歧义:必须避免依赖一种特定行为(第4.8节).

  • 根据运行经验更新和扩展了一般运行信息:基于[RFC4408]发布后八年的运行经验.参见第10节和下面的附录D到G.

  • 审查和更新了安全考虑事项:(第11节).


Appendix C. 进一步测试建议 (Further Testing Advice)​

另一种可能有用的方法是发布包含"跟踪exists:"机制的记录.通过查看名称服务器日志,然后可以生成粗略的列表.例如:

v=spf1 exists:_h.%{h}._l.%{l}._o.%{o}._i.%{i}._spf.%{d} ?all

此关联的宏扩展将导致发送HELO域、发送电子邮件地址的local-part、发送电子邮件地址的域部分,以及接收连接的IP地址被嵌入到SPF查询中并记录在发件人的DNS日志中.

这种方法自SPF项目的早期就已被使用,允许发件人单方面收集数据以评估其SPF记录的正确性.与较新的反馈机制不同,它不需要SPF验证器的任何特殊合作.在撰写本文时,仍然可以在altavista.net找到类似的示例,这是最早发布的SPF记录之一.


Appendix D. SPF/中介者交互 (SPF/Mediator Interactions)​

有三个地方可以使用技术来改善与中介者的意外SPF失败.

D.1. 发起 ADMD (Originating ADMDs)​

开始时,当电子邮件首次发送时:

  • 为可能的转发器提供"Neutral"结果:可以为可能是转发器的IP地址提供"neutral"结果,而不是基于已知可靠转发器列表的"fail"结果.例如:
"v=spf1 mx ?exists:%{ir}.whitelist.example.org -all"

这将导致在DNS白名单(DNSWL)上查找,并且仅对不是来自域的mx主机(SPF pass)或白名单来源(SPF neutral)的电子邮件导致"fail"结果.这实际上是将发件人策略的一个要素外包给白名单的维护者.

  • 在 "MAIL FROM" 身份中添加加密信息:"MAIL FROM"身份可以在local-part中包含加密标识邮件来自授权来源的附加信息.在这种情况下,可以使用如下的SPF记录:
"v=spf1 mx exists:%{l}._spf_verify.%{d} -all"

然后,可以设置专门的DNS服务器来服务验证local-part的_spf_verify子域.尽管这需要额外的DNS查找,但这仅在电子邮件否则会被拒绝为不是来自已知良好来源时发生.

注意,由于域标签有63个字符的限制,此方法仅在local-part签名方案保证仅产生最多63个字符的local-parts或优雅地处理截断的local-parts时才能可靠工作.用于保护local-part的方法是本地实现问题;它不需要是标准的.可以在[BATV]中找到一种方法的示例.

  • 速率限制意外IP:类似地,可以设置专门的DNS服务器,该服务器将对来自意外IP地址的电子邮件进行速率限制.
"v=spf1 mx exists:%{ir}._spf_rate.%{d} -all"

然后,专门的DNS服务器可以回答查询,以便允许有限数量的邮件通过来自特定IP地址的检查,然后开始返回NXDOMAIN.这具有降级伪造邮件的效果,这些邮件将开始因"fail"而被拒绝.

D.2. 中介 ADMD (Mediating ADMDs)​

中间,在中介者转发邮件时:

中介者可以使用一种技术,例如Sender Rewriting Scheme (SRS),在转发邮件之前重写发件人地址,使用它们自己的域.这样,中介者接受责任,并使用它们自己的SPF记录.

D.3. 接收 ADMD (Receiving ADMDs)​

最后,当邮件最终被传递时:

接收域可以在其本地策略中为已知合法的中介者(例如众所周知的邮件列表)选择白名单处理.它们还可以识别未通过SPF检查的消息,并对其应用额外的启发式方法以确定邮件是否实际上是合法的.


Appendix E. 邮件服务 (Mail Services)​

提供第三方域邮件服务的MSP(邮件服务提供商——[RFC5598]的第2.3节),例如发送批量邮件,可能希望根据本文档中描述的授权检查调整其配置.如果用于此类电子邮件的"MAIL FROM"身份的域部分使用MSP的域之一,则提供商只需确保其发送主机由其自己的SPF记录(如果有)授权.

如果"MAIL FROM"身份不使用MSP的域,则必须格外小心.SPF记录格式有几个选项供第三方域授权服务提供商的MTA代表其发送邮件.对于MSP,例如ISP,它们有各种各样的客户使用相同的MTA,需要采取步骤来减轻跨客户伪造的风险(参见第11.4节).


Appendix F. MTA 中继 (MTA Relays)​

中继在[RFC5598]第2.2.2节中描述.授权检查通常排除了在电子邮件消息的发件人和接收者之间使用任意MTA中继.

在组织内,MTA中继可以有效部署.然而,就本文档而言,此类中继实际上是透明的.SPF授权检查是不同ADMD的边界MTA之间的检查.

对于邮件发件人,这意味着已发布的SPF记录必须授权实际跨互联网发送的任何MTA.通常,这些只是边界MTA,因为内部MTA只是将邮件转发到这些MTA以进行中继.

接收ADMD通常会希望在边界MTA处执行授权检查,包括所有辅助MX.然后,内部MTA(包括可能在处理中继邮件流时既充当边界MTA又充当来自辅助MX的内部中继的MTA)不执行授权测试.要在边界以外执行授权测试,必须确定首先将消息传输到接收ADMD的主机,这可能难以从消息标头中提取,因为(a)标头字段可能被伪造或格式错误,并且(b)没有标准方法来编码该信息以便可以可靠地提取.在边界以外进行测试可能会产生不可靠的结果.这在[RFC7001]的附录D中进一步描述.


Appendix G. 本地策略考虑 (Local Policy Considerations)​

SPF结果可以与其他方法结合使用,以确定消息的最终本地处置(正面或负面).它也可以单独被视为决定性的.

G.1. SPF Pass 的策略 (Policy for SPF Pass)​

SPF "pass"结果可以与已知"良好"域的"白名单"结合使用,以绕过部分或全部附加的预传递电子邮件检查.具体检查哪些以及如何确定适当的白名单条目必须基于本地条件和要求.

G.2. SPF Fail 的策略 (Policy for SPF Fail)​

SPF "fail"结果可用于在SMTP事务期间基于"MAIL FROM"或"HELO"身份结果拒绝消息.这减少了各种内容过滤方法的资源需求,并节省了带宽,因为可以在传输SMTP内容之前进行拒绝.它还向发件人提供即时反馈,然后发件人可能能够解决问题.由于本节(附录G)中描述的一些问题,基于SPF的拒绝确实在基于"MAIL FROM"结果拒绝电子邮件时存在拒绝合法电子邮件的一些风险.

SPF "fail"结果也可以用作更大评估集的一个输入,该评估集可能基于SPF "fail"结果与其他评估技术的组合,导致电子邮件以某种方式被负面标记(这可能是通过传递到特殊的垃圾邮件文件夹、修改主题行或其他本地确定的方式).开发此类方法的细节必须基于本地条件和要求.以这种方式使用SPF结果没有与SMTP拒绝相关的资源节约和向发件人提供即时反馈的优势,但在设计良好的系统中可能产生更少的不良拒绝.这样的方法可能导致未经发送ADMD授权的电子邮件在不知不觉中被传递给最终用户.

两种一般方法都可以使用,因为它们都留下了电子邮件的明确处置;它们要么以某种方式被传递,要么发件人被通知失败.其他处置,例如在接受后"丢弃"或删除电子邮件,是不合适的,因为它们留下不确定性并降低互联网上电子邮件的整体可靠性和实用性.

G.3. SPF Permerror 的策略 (Policy for SPF Permerror)​

"permerror"结果(参见第2.6.7节)表明接收器的SPF处理模块确定无法解释检索到的SPF策略记录.这不能真正表明信封中找到的数据的授权使用.

与所有结果一样,实现者必须选择如何处理产生此结果的消息.SMTP只允许几个基本选项.

拒绝消息是一个选项,因为这是接收器可以做的一件事,以引起对遇到的困难的注意,同时保护自己免受没有某种明确SPF结果的消息的影响.但是,如果SPF实现有缺陷并返回虚假的"permerror"结果,则只有发件人会主动收到缺陷通知(以被拒绝的邮件的形式),而不是使用SPF的接收器.

侵入性较小的处理选择是传递消息,可能带有遇到的困难的某种注释和/或类似性质的日志记录.但是,对于希望尽可能严格地实施SPF检查的SPF验证器操作者来说,这不是理想的,这种被动的问题报告通常也不是有效的.

当然,可以选择将这种选择交给SPF验证器操作者而不是实现者,因为这种选择通常是本地策略的问题,而不是具有通用解决方案的条件,但这为已经非平凡的环境增加了一个复杂性.

实现者和SPF验证器操作者在处理SPF结果时都需要谨慎对待所有选择和结果.

G.4. SPF Temperror 的策略 (Policy for SPF Temperror)​

"temperror"结果(参见第2.6.6节)表明接收器的SPF处理模块由于(可能的)临时条件而无法检索SPF策略记录.这不能真正表明信封中找到的数据的授权使用.

与所有结果一样,实现者必须选择如何处理产生此结果的消息.SMTP只允许几个基本选项.

延迟消息是一个选项,因为这是接收器可以做的一件事,以引起对遇到的困难的注意,同时保护自己免受没有某种明确SPF结果的消息的影响.但是,如果SPF实现有缺陷并返回虚假的"temperror"结果,则只有发件人会主动收到缺陷通知(以在超时从发送队列后被拒绝的邮件的形式),而不是使用SPF的接收器.

由于队列生命周期长,邮件可能会被反复延迟几天,因此发件人对问题的任何意识可能会相当延迟.如果"temperrors"在多次传递尝试中持续存在,则最好将错误视为永久性的,并减少消息在传输中的时间.

侵入性较小的处理选择是传递消息,可能带有遇到的困难的某种注释和/或类似性质的日志记录.但是,对于希望尽可能严格地实施SPF检查的SPF验证器操作者来说,这不是理想的,这种被动的问题报告通常也不是有效的.

当然,可以选择将这种选择交给SPF验证器操作者而不是实现者,因为这种选择通常是本地策略的问题,而不是具有通用解决方案的条件,但这为已经非平凡的环境增加了一个复杂性.

实现者和SPF验证器操作者在处理SPF结果时都需要谨慎对待所有选择和结果.