Home | Sitemap | Recent Changes | Login

SPF Logo

Sender Policy Framework

Mechanisms

SPF syntax: a quick overview

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
    * explanation 

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"

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.

    "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:.........

Could someone with IPv6 experience please provide some input?

exists

	The Exists Mechanism

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.)

Extension Mechanisms

If the above directive syntax is not sufficiently expressive to describe the email policy for your domain, you are welcome to come up with your own mechanisms. Note, however, that SPF clients will abort with an "unknown" if they encounter a mechanism they do not recognize.

    "v=spf1 habeas -all"
    This might indicate that mail from a domain is sent with Habeas headers. 

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.


Edit text of this page | View other revisions
Last edited 2006-04-20 19:54 (UTC) by Koen Martens (diff)