每个mechanism有四种前缀(默认前缀为“+”):
前缀 | |
"+" | Pass |
"-" | Fail |
"~" | SoftFail |
"?" | Neutral |
在一条SPF记录中,从左到右依次对每个mechanism进行验证。对一个mechanism进行检测,有三种结果可能发生:IP匹配成功,IP匹配失败或者返回异常。如果IP匹配成功,处理结果返回该mechanism的前缀;如果IP匹配失败,继续下一个mechanism;如果返回异常,则mechanism结束并返回该异常值;如果没有mechanism或者modifier匹配,则结果返回“Neutral”。
如果不存在SPF记录,则返回“None”;如果在DNS解析过程中出现临时性错误,则返回“TempError”;如果存在某些语法错误或者评估错误(如该域指向不为人知的机制),则返回“PermError”。
SPF记录验证可能返回的结果如下:
Result | Explanation | Intended action |
Pass | SPF记录验证该发信IP为合法的 | 接收邮件 |
Fail | SPF记录验证该发信IP是不合法的 | 拒绝邮件 |
SoftFail | SPF验证该发信IP不是合法的,但是不采取强制措施 | 接收邮件但作标识 |
Neutral | SPF记录没有明确说明发信IP是否合法的信息 | 接收邮件 |
None | 域名没有设置SPF记录或者SPF记录验证没有结果 | 接收邮件 |
PermError | 发生永久性错误(如:SPF记录格式错误) | 没有规定 |
TempError | 发生临时性错误 | 接收邮件或拒绝邮件 |
1、“all”机制
“all”表示所有IP都匹配。通常放在SPF记录末尾,表示处理剩下的所有情况。
例如:
"v=spf1 mx -all" 表示允许所有该域的MX邮件服务器发送邮件,禁止其他的。
"v=spf1 -all" 表示该域不会发送任何邮件。
"v=spf1 +all" 表示域名所有者认为SPF是没有用的或者并不关心(任何服务器都可使用该域名发送邮件)。
2、“ip4”机制
格式为:
ip4:<ip4-address>
ip4:<ip4-network>/<prefix-length>
如果没有提供 prefix-length ,默认为 /32。
例如:
"v=spf1 ip4:192.168.0.1/16 -all"
表示只允许192.168.0.1192.168.255.255范围内的IP地址。
3、“ip6”机制
格式为:
ip6:<ip6-address>
ip6:<ip6-network>/<prefix-length>
如果没有提供 prefix-length ,默认为 /128 。
例如:
"v=spf1 ip6:1080::8:800:200C:417A/96 -all"
表示只允许1080::8:800:0000:00001080::8:800:FFFF:FFFF范围内的IP地址
"v=spf1 ip6:1080::8:800:68.0.3.1/96 -all"
表示只允许1080::8:800:0000:00001080::8:800:FFFF:FFFF范围内的IP地址
4、“a”机制
格式为:
a
a/<prefix-length>
a:<domain>
a:<domain>/<prefix-length>
所有A记录都会检测。如果客户端IP在这些记录中,则该机制结果匹配。
若没有指定域,则使用当前域。
A记录必须与客户端IP地址完全匹配,除非提供前缀长度,在这种情况下,A记录查询返回的IP地址将扩展到其相应的CIDR前缀,且客户端IP将在其子网中查询。
例如:
"v=spf1 a -all"
表示当前域被使用。
"v=spf1 a:example.com -all"
等价于当前域为example.com。
"v=spf1 a:mailers.example.com -all"
表示指定mailers.example.com的主机IP可以外发邮件。
"v=spf1 a/24 a:offsite.example.com/24 -all"
如果example.com解析到192.0.2.1,那么整个C类地址192.0.2.0/24将作为客户端IP地址外发邮件。同样,如果offsite.example.com返回多个A记录,每个IP地址将被扩展到CIDR子网。
5、“mx”机制
格式:
mx
mx/<prefix-length>
mx:<domain>
mx:<domain>/<prefix-length>
所有域的MX记录对应的A记录按照MX优先级进行验证。如果客户端IP在这些记录中,那么该机制匹配。
如果没有指定域,则使用当前域。
A记录必须与客户端IP地址完全匹配,除非提供前缀长度,在这种情况下,A记录查询返回的IP地址将扩展到其相应的CIDR前缀,且客户端IP将在其子网中查询。
例如
"v=spf1 mx mx:deferrals.domain.com -all"
表示允许当前域通过其MX服务器发送邮件,并通过deferrals.domain.com的MX服务器重试延迟的邮件。
"v=spf1 mx/24 mx:offsite.domain.com/24 -all"
也许一个域的MX服务器使用一个IP地址接收邮件,使用另一个相邻IP地址发送邮件。
6、“ptr”机制
格式:
ptr
ptr:<domain>
通过PTP查询客户端IP对应的主机名。对主机名进行验证:PTR主机名对应的A记录至少有一个与原客户端IP匹配,无效主机名将被丢弃。如果一个有效主机名以该域结尾,则该机制匹配。
若没有指定域,则使用当前域。
尽量避免使用该机制,因为会带来很大开销的DNS查询。
例如:
"v=spf1 ptr -all"
直接控制所有机器的域(不像拨号或宽带ISP)允许其所有服务器发送邮件。比如,hotmail.com或者paypal.com。
"v=spf1 ptr:otherdomain.com -all"
表示允许所有以otherdomain.com结尾的主机名的服务器发送邮件。
7、“exists”机制
格式为:
exists:<domain>
对提供的域进行A记录查询。如果有返回结果,则为匹配,无论查询结果是什么。
例如:在下面例子中,客户端IP为1.2.3.4 a,当前域为example.com。
"v=spf1 exists:example.com -all"
若example.com不能解析,则结果返回失败;若能解析,则该机制匹配。
当使用该机制的宏,可以执行RBL方式反向IP查询或者设置每个用户异常。
"exists:%{i}.spf.sparkpostmail.com"用于SPF验证,%{i}为连接的ip地址,通过查询"%{i}.spf.sparkpostmail.com"的A记录,若有返回结果,则允许该ip以MAIL FROM域的名义发送邮件。
以下为两个在审议中的特别的IP地址:
$ host 35.167.215.19.spf.sparkpostmail.com
35.167.215.19.spf.sparkpostmail.com has address 35.167.215.19
$ host 35.167.179.82.spf.sparkpostmail.com
35.167.179.82.spf.sparkpostmail.com has address 35.167.179.82
两者均需通过exists机制。
值得注意的是,SPF记录也包括ptr机制,虽然在最近的SPF RFC版本中已正式弃用,且推荐不使用,但是在执行SPF验证时必须支持。我们发布ptr机制是因为今天美国的邮箱提供商也不能完全解析exists机制。同样,指定的两个IP地址也需通过ptr机制:
$ host 35.167.215.19
19.215.167.35.in-addr.arpa domain name pointer mta523b.sparkpostmail.com.
$ host 35.167.179.82
82.179.167.35.in-addr.arpa domain name pointer mta522b.sparkpostmail.com.
8、“include”机制
格式为:
include:<domain>
表示指定域查询匹配。若查询返回不匹配或者有错误,接着处理下一个机制。警告:如果指定域没有一个有效的SPF记录,结果将返回永久性错误。某些邮件接收者会根据“PermError”拒绝接收邮件。
例如:在下面例子中,客户端IP为1.2.3.4,当前域为example.com.
"v=spf1 include:example.com -all"
若example.com没有SPF记录,结果为“PermError”。
假设example.com的SPF记录为“v=spf1 a -all”,查询example.com的A记录,
若与1.2.3.4匹配,返回“Pass”;
若不匹配,处理包含域的“-all”,include整个匹配失败;
从这个例子的外部指令集可见,最终的结果仍为失败。
因为信任关系,“include”机制可能会被认为有越权行为。需要确保“include”机制不会给跨用户伪造的信息SPF验证返回“Pass”。除非对指定的其他域技术机制到位,从而反正跨用户伪造,“include”机制应该提供“Neutral”处理结果而非“Pass”。即在“include:”前添加“?”前缀。例如:
"v=spf1 ?include:example.com -all"
如此看来,“include”机制不宜选择。