Home | Sitemap | Recent Changes | Login

SPF Logo

Sender Policy Framework

SPF Record Syntax

Showing revision 7

THIS IS WORK IN PROGRESS

Domains define zero or more mechanisms. Mechanisms can be used to describe the set of hosts which are designated outbound mailers for the domain. Mechanisms can also be used to describe other kinds of email policy; for example, that all legitimate mail originating from a certain domain is GPG-signed, or has Habeas headers.

  • all
  • a
  • mx
  • ptr
  • ip4
  • ip6
  • include
  • exists
  • extensions

Domains may also define modifiers. Each modifier can appear only once.

  • redirect
  • exp

Mechanism Syntax

Mechanisms can be prefixed with one of four characters:

- fail
~ softfail
+ pass
? neutral

If a mechanism results in a hit, its prefix value is used. The default prefix value is 'pass".

Mechanisms are evaluated in order.

If a domain has no SPF record at all, its value is "none". If a domain has a temporary error during DNS processing, you get the value "error". If some kind of syntax or evaluation error occurs (eg. the domain specifies an unrecognized mechanism) the value is "unknown".

"v=spf1 -all"
"v=spf1 a -all"
"v=spf1 a mx -all"
"v=spf1 +a +mx -all"

Evaluation of the SPF record can return any of these results:

ResultExplanationIntended action
noneThe domain does not have an SPF record or the SPF record does not evaluate to a resultAccept
neutralThe SPF record specifies explicitly that nothing can be said about validityAccept
passThe SPF record designates the host to be allowed to sendAccept
failThe SPF record does not designate the host to be allowed to sendReject
softfailThe SPF record does not designate the host to be allowed to send, but is in transitionAccept but mark
TempErrorA transient error has occuredAccept or Reject
PermErrorA permanent error has occured (eg. badly formatted SPF record)Unspecified

all

all

This mechanism always matches. It goes at the end of your record.


a

a
a:domain
a:domain/cidr-length
a/cidr-length

All the A records for domain are tested. 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 cidr-length is provided, in which case each IP address returned by the A lookup will be expanded to its corresponding CIDR subnet, and the client IP will be sought within that subnet.

"v=spf1 a -all"
The current-domain is used.
"v=spf1 a:example.com -all"
Equivalent if the current-domain is example.com.
"v=spf1 a:mailers.example.com -all"
Perhaps example.com has chosen to explicitly list all the outbound mailers in a special A record under mailers.example.com.
"v=spf1 a/24 a:offsite.example.com/24 -all"
If example.com resolves to 192.0.2.1, the entire class C of 192.0.2.0/24 would be searched for the client IP. Similarly for offsite.example.com. If more than one A record were returned, each one would be expanded to a CIDR subnet.

mx

mx
mx:domain
mx:domain/cidr-length
mx/cidr-length

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 cidr-length is provided, in which case each IP address returned by the A lookup will be expanded to its corresponding CIDR subnet, and the client IP will be sought within that subnet.

"v=spf1 mx mx:deferrals.domain.com -all"
Perhaps a domain sends mail through its MX servers plus another set of servers whose job is to retry mail for deferring domains.
"v=spf1 mx/24 mx:offsite.domain.com/24 -all"
Perhaps a domain's MX servers receive mail on one IP address, but send mail on a different but nearby IP address.

ptr

	

ptr
ptr:domain

The hostname or hostnames for the client IP are looked up using PTR queries. The hostnames are then validated: at least one of the A records for a PTR hostname must match the original client IP. Invalid hostnames are discarded. If a valid hostname ends in domain, this mechanism matches.

If domain is not specified, the current-domain is used.

"v=spf1 ptr -all"
A domain which directly controls all its machines (unlike a dialup or broadband ISP) allows all its servers to send mail. For example, hotmail.com or paypal.com might do this.
"v=spf1 ptr:otherdomain.com -all"
Any server whose hostname ends in otherdomain.com is designated.

ip4

	

ip4:cidr-spec

A CIDR-spec is an IP network range. If no prefix-length is given, /32 is assumed (singling out an individual host address).

"v=spf1 ip4:192.168.0.1/16 -all"
Allow any IP address between 192.168.0.1 and 192.168.255.255.

ip6

ip6:ipv6-address/prefix-length

The argument to the ip6: mechanism as an IPv6 network range. If no prefix-length is given, /128 is assumed (singling out an individual host address).

"v=spf1 ip6:1080::8:800:200C:417A/64 -all"
Allow any IPv6 address between 1080::8:800:0000:0000 and 1080::8:800:ffff:ffff.
"v=spf1 ip6:1080::8:800:68.0.3.1/64 -all"
Allow any IPv6 address between 1080::8:800:0000:0000 and 1080::8:800:ffff:ffff.

exists

	

Perform an A query on the provided domain. If a result is found, this constitutes a match. It doesn't matter what the lookup result is: it could be 127.0.0.2.

When you use macros with this mechanism, you can perform RBL-style reversed-IP lookups, or set up per-user exceptions.

In the following example, the client IP is 1.2.3.4 and the current-domain is example.com.

"v=spf1 exists:example.net -all"
If example.net does not resolve, the result is fail. If it does resolve, this mechanism results in a match.

include

include:otherdomain

The specified otherdomain is searched for a match. If the lookup does not return a match or an error, processing proceeds to the next directive. Warning: If otherdomain does not have a valid SPF record, the result is a Permanent Error. Some mail receivers will reject based on a Permanent Error.

In the following example, the client IP is 1.2.3.4 and the current-domain is example.com.

"v=spf1 include:example.net -all"
If example.net has no SPF record, the result is PermError.
Suppose example.net's SPF record were "v=spf1 a -all".
Look up the A record for example.net. If it matches 1.2.3.4, return Pass.
If there is no match, the include as a whole fails to match, but the -all value is not used; 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.net -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.)


Modifiers

Modifiers are optional. A modifier may appear only once per directive-set. Unknown modifiers are ignored.


redirect

	

redirect=domain-macro

The SPF directives for domain-macro replace the current set of directives. The expanded domain-macro is also substituted for the current-domain in those lookups.

In the following example, the client IP is 1.2.3.4 and the current-domain is example.com.

"v=spf1 redirect=example.net"
If example.net has no SPF record, that is an error; the result is unknown.
Suppose example.net's SPF record were "v=spf1 a -all".
Look up the A record for example.net. If it matches 1.2.3.4, return allow.
If there is no match, the exec fails to match, and the -all value is used.

exp

exp=domain-macro

If an SMTP receiver rejects a message, it can include an explanation. An SPF publisher can specify the explanation string that senders see. This way, an ISP can direct nonconforming users to a web page that provides further instructions about how to configure SASL.

The domain-macro is expanded; a TXT lookup is performed. The result of the TXT query is then macro-expanded and shown to the sender.