SPF Record Syntax
Mechanisms
Mechanisms can be prefixed with one of four qualifiers:
"+" | Pass |
"-" | Fail |
"~" | SoftFail |
"?" | Neutral |
If a mechanism results in a hit, its qualifier value is used. The default qualifier is "+", i.e. "Pass". For example:
"v=spf1 -all"
"v=spf1 a -all"
"v=spf1 a mx -all"
"v=spf1 +a +mx -all"
Mechanisms are evaluated in order. If no mechanism or modifier matches, the default result is "Neutral".
If a domain has no SPF record at all, the result is "None". If a domain has a temporary error during DNS processing, you get the result "TempError" (called "error" in earlier drafts). If some kind of syntax or evaluation error occurs (eg. the domain specifies an unrecognized mechanism) the result is "PermError" (formerly "unknown").
Evaluation of an SPF record can return any of these results:
Result | Explanation | Intended action |
Pass | The SPF record designates the host to be allowed to send | accept |
Fail | The SPF record has designated the host as NOT being allowed to send | reject |
SoftFail | The SPF record has designated the host as NOT being allowed to send but is in transition | accept but mark |
Neutral | The SPF record specifies explicitly that nothing can be said about validity | accept |
None | The domain does not have an SPF record or the SPF record does not evaluate to a result | accept |
PermError | A permanent error has occured (eg. badly formatted SPF record) | unspecified |
TempError | A transient error has occured | accept or reject |
The "all
" mechanism
all
This mechanism always matches. It usually goes at the end of the SPF record.
Examples:
"v=spf1 mx -all"
"v=spf1 -all"
"v=spf1 +all"
The "ip4
" mechanism
ip4: ip4:/
The argument to the "ip4:
" mechanism is an IPv4 network range. If no prefix-length is given, /32 is assumed (singling out an individual host address).
Examples:
"v=spf1 ip4:192.168.0.1/16 -all"
The "ip6
" mechanism
ip6: ip6:/
The argument to the "ip6:
" mechanism is an IPv6 network range. If no prefix-length is given, /128 is assumed (singling out an individual host address).
Examples:
"v=spf1 ip6:1080::8:800:200C:417A/96 -all"
"v=spf1 ip6:1080::8:800:68.0.3.1/96 -all"
The "a
" mechanism
a a/ a: a:/
All the A records for domain are tested. If the client IP is found among them, this mechanism matches. If the connection is made over IPv6, then an AAAA lookup is performed instead.
If domain is not specified, the current-domain is used.
The A records have to match the client IP exactly, unless a prefix-length is provided, in which case each IP address returned by the A lookup will be expanded to its corresponding CIDR prefix, and the client IP will be sought within that subnet.
"v=spf1 a -all"
"v=spf1 a:example.com -all"
"v=spf1 a:mailers.example.com -all"
"v=spf1 a/24 a:offsite.example.com/24 -all"
The "mx
" mechanism
mx mx/ mx: mx:/
All the A records for all the MX records for domain are tested in order of MX priority. If the client IP is found among them, this mechanism matches.
If domain is not specified, the current-domain is used.
The A records have to match the client IP exactly, unless a prefix-length is provided, in which case each IP address returned by the A lookup will be expanded to its corresponding CIDR prefix, and the client IP will be sought within that subnet.
Examples:
"v=spf1 mx mx:deferrals.domain.com -all"
"v=spf1 mx/24 mx:offsite.domain.com/24 -all"
The "include
" mechanism
include:
The specified domain is searched for a match. If the lookup does not return a match or an error, processing proceeds to the next directive. Warning: If the domain does not have a valid SPF record, the result is a permanent error. Some mail receivers will reject based on a PermError.
Examples:
In the following example, the client IP is 1.2.3.4 and the current-domain is example.com.
"v=spf1 include:example.com -all"
-all
", the include as a whole fails to match; the eventual result is still Fail from the outer directive set in this example.Trust relationships — The "include:
" mechanism is meant to cross administrative boundaries. Great care is needed to ensure that "include:
" mechanisms do not place domains at risk for giving SPF Pass results to messages that result from cross user forgery. Unless technical mechanisms are in place at the specified otherdomain to prevent cross user forgery, "include:
" mechanisms should give a Neutral rather than Pass result. This is done by adding "?" in front of "include:
". The example above would be:
"v=spf1 ?include:example.com -all"
In hindsight, the name "include" was poorly chosen. Only the evaluated result of the referenced SPF record is used, rather than acting as if the referenced SPF record was literally included in the first. For example, evaluating a "-all
" directive in the referenced record does not terminate the overall processing and does not necessarily result in an overall Fail. (Better names for this mechanism would have been "if-pass", "on-pass", etc.)