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"身份。
对于递归评估,
注意,
4.2. 结果 (Results)
check_host()函数可以返回第2.6节中描述的几个结果之一。根据结果,要采取的行动由接收方的本地策略决定。这在第8节中讨论。
4.3. 初始处理 (Initial Processing)
如果
如果
4.4. 记录查找 (Record Lookup)
根据记录的发布方式(参见上文第3节),需要对
如果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)
这些机制和修饰符中的几个有一个
注意:宏扩展的结果不受任何进一步的转义。因此,此功能无法产生DNS标签中合法的所有字符(例如,控制字符)。然而,此功能足够强大,可以表达合法的主机名和DNS中使用的常见实用标签(例如"_spf")。
对于几个机制,
使用语法无效的域评估check_host()的结果是未定义的。
注意:本文档及其前身没有规定如何正确处理语法无效的