WHAT IS SPF?
Overview
An SPF record is a TXT record published in the DNS by the domain owner, which specifies a whitelist of IP addresses allowed to send emails on behalf of the domain. When an email reaches the receiving server, the server will look up the SPF record in the DNS, and perform a check to determine if the email comes from an authorized IP address.
SPF stands for "Sender Policy Framework", which is a mechanism that allows a receiving email server to check if the incoming email is from an IP addresses permitted by a predefined IP address whitelist (SPF record) specified in the DNS (Domain Name System).
For more information on SPF, refer to: RFC 7208
SPF record syntax
An SPF record is a single string of text published on the domain in the DNS.
All SPF records start with exactly "v=spf1", followed by a series of "terms". Note that the version part "v=spf1" is mandatory: everything else like "v=spf2" would render the SPF record invalid and cause the receiving server to ignore the record.
Here is an example SPF record:
v=spf1 mx a:example.com/28 -all
When published, the above SPF record looks like this in a domain zone file:
example.com. TXT "v=spf1 mx a:example.com/28 -all"
A SPF record must be published as a TXT record, rather than the now deprecated SPF record. Support for the SPF RR (Resource Record) type has been dropped since SPF version 1.
SPF Record evaluation
The SPF module returns an authentication result to the receiving server by evaluating the terms in an SPF record.
There are 2 types of terms in SPF: mechanisms and modifiers, which I will explain below.
An SPF authentication result is one of:
- None: either no valid DNS domain name was found, or no SPF record was found on the domain;
- Neutral: it's not stated whether the client IP address is allowed;
- Pass: the client IP address is allowed;
- Fail: the client IP address is not allowed;
- Softfail: the client IP address is probably not allowed;
- Temperror: the SPF module encountered a transient (network) error while performing the check;
- Permerror: the domain’s published records could not be correctly interpreted. This signals an error condition that definitely requires DNS operator intervention to be resolved.
Note that if there is no match when it reaches the end of an SPF record, neutral is returned. This is what SPF record evaluation defaults to.
It's recommended to use either ~all
or -all
at the end of an SPF record to explicitly indicate what the result should be when no match is found.
SPF qualifiers
An SPF qualifier is optionally prepended to an SPF mechanism to denote the result of evaluating that mechanism.
The possible qualifiers, and the results they indicate are:
- "+" pass
- "-" fail
- "~" softfail
- "?" neutral
For example, qualifier "+" indicates pass, while "-" indicates fail, etc.
When no qualifier is prepended to an SPF mechanism, it defaults to "+" (pass).
SPF mechanisms
SPF mechanisms are evaluated one by one from left to right.
The result of evaluating an SPF mechanism is one of:
- match; evaluation ends and the qualifier value is returned as the result of evaluating the SPF record;
- not match; moves on to evaluate the next mechanism;
- exception; evaluation ends and the exception value is returned.
Two types of SPF mechanisms are available: basic mechanisms and designated sender mechanisms.
Basic mechanisms are all
and include
.
Designated sender mechanisms are a
, mx
, ptr
, ip4
, ip6
, and exists
.
Let's explore each one of them below.
ip4 mechanism
The ip4 mechanism can be one of:
- ip4/<ip4-address>: if the client IP address is the same as ip4-address, it matches;
- ip4:<ip4-network>/<prefix-length>: if the client IP address is among ip4-network, it passes; if no prefix-length is provided, /32 is assumed.
For example, this SPF record:
v=spf1 ip4:192.168.0.1/16 -all
allows any email sent from any IP address between 192.168.0.1 and 192.168.255.255 to pass SPF authentication.
ip6 mechanism
The ip6 mechanism can be one of:
- ip6/<ip6-address>: if the client IP address is the same as ip6-address, it matches;
- ip6:<ip6-network>/<prefix-length>: if the client IP address is among ip6-network, it passes; if no prefix-length is provided, /128 is assumed.
For example, this SPF record:
v=spf1 ip6:1080::8:800:200C:417A/96 -all
allows any email sent from any IP address between 1080::8:800:0000:0000 and 1080::8:800:FFFF:FFFF to pass SPF authentication.
all mechanism
The all mechanism matches any IP address. It's often used at the end of an SPF record to provide an explicit result when no match is found for all previous mechanisms. Mechanisms after "all" will never be checked.
For example, in the SPF record below:
v=spf1 mx -all
if "mx" doesn't match, "-all" is evaluated and returns a hardfail result as it has a "-" qualifier.
include mechanism
The include mechanism makes it possible to allow 3rd-party IP addresses defined in another SPF record to be included in the "master" SPF record.
This is especially useful when you need to use external email delivery/marketing services to send emails for you. To properly authenticate the emails sent from their servers, you must "include" their SPF records in yours. To do so, use the include mechanism on each one of such services.
For example, if you want to use SendGrid to deliver emails for you, you need to include SendGrid's SPF record:
v=spf1 include:sendgrid.net ~all
once this is added, all the emails sent from SendGrid servers will pass SPF authentication.
a mechanism
The a mechanism matches if the client IP address is one of the IP addresses specified in the mechanism.
The a mechanism can be one of:
- a: matches if client IP address is the same as the IP address that the current domain (where the SPF is published on) resolves to;
- a/<prefix-length>: matches if client IP address is within the IP range specified by a/<prefix-length>;
- a:<domain>: matches if client IP address is the same as the IP address that the specified domain resolves to;
- a:<domain>/<prefix-length>: matches if client IP address is within the IP range specified by a:<domain>/<prefix-length>.
For example, suppose this SPF record is published on domain example.com with IP address 199.1.1.1:
v=spf1 a -all
now the client server running on IP address 199.1.1.1 sends an email to the receiving server, it will pass SPF authentication when the a mechanism above is evaluated.
mx mechanism
All the A records for all the MX records for domain are tested. If the client IP is found among them, this mechanism matches.
If domain is not specified, the current domain (where the SPF record is published on) is used.
The mx mechanism can be one of:
- mx
- mx/<prefix-length>
- mx:<domain>
- mx:<domain>/<prefix-length>
For example, this SPF record published on example.com:
v=spf1 mx mx:deferrals.domain.com -all
allows emails sent from any of:
- A records for all the MX records for example.com
- A records for all the MX records for deferrals.domain.com
ptr mechanism
The ptr mechanism can be one of:
- ptr
- ptr:<domain>
If domain is not specified, the current domain (where the SPF record is published on) is used.
First the hostnames for the client IP are looked up using reverse IP queries. Then SPF tries to find a match using the hostnames as described below.
This mechanism matches if any of the following is true:
- at least one of the A records for a PTR hostname is the same as the original client IP
- a valid hostname ends in domain, this mechanism matches.
Invalid hostnames are discarded in this process.
For example, this SPF record is published on example.com, and the client IP address is 199.1.1.1:
v=spf1 ptr -all
suppose 199.1.1.1 reverse-resolves to example.com, and example.com resolves to 199.1.1.1, emails from 199.1.1.1 will pass SPF authentication.
Note that you are advised against using the ptr mechanism in your SPF record as it results in many DNS lookups.
exists mechanism
The exists mechanism takes a domain parameter. SPF performs an A query on the domain, and if a result is returned, this mechanism matches.
For example, if the SPF record published on example.com is:
v=spf1 exists:microsoft.com -all
and microsoft.com resolves to some IP address (no matter what the value is), all emails sent on behalf of example.com pass SPF authentication.
SPF modifiers
There are 2 modifiers in SPF: redirect and exp.
SPF modifiers are optional. Any may appear only once per record. Unknown modifiers are ignored.
redirect modifier
The redirect modifier takes a domain value:
- redirect=<domain>
The SPF record on domain replace the current SPF record.
For example, the SPF record is published on domain.com:
v=spf1 redirect=example.com
If there is no SPF record on example.com, the result is unknown. Otherwise, the SPF record on example.com is evaluated and the result of the evaluation is returned.
exp modifier
The exp modifier takes a domain value:
- exp=<domain>
If the evaluation of an SPF record fails due to a mechanism match like "-all", and the exp modifier is present, an explanation string is returned.
For example, this SPF record is published on example.com:
v=spf1 mx -all exp=explain._spf.%{d}
and you've created a TXT record at explain._spf.example.com with this string:
Emails from example.com must only be sent by its own mail servers.
When some host other than example.com's mail servers sends an email, which will fail SPF authentication, the above string will be returned.
SPF records for email delivery/email marketing services
Here is a list of popular email delivery/email marketing services and their SPF records:
- Google Workspace (Gmail), formerly known as G Suite: _spf.google.com
- SendGrid: sendgrid.net
- Ontraport: _spf-moon-ray.ontramail.com, AND _spf-ontramail.ontramail.com
- Constant Contact: spf.constantcontact.com
- HubSpot: refer to HubSpot SPF Guide
- Campaign Monitor: _spf.createsend.com
- AWeber: send.aweber.com
- Infusionsoft: infusionsoft.com
- ActiveCampaign: emsd1.com
- SendLane: creatensend.com, icmessage.com, slsv1.com, AND slsv2.com
- Mailer Lite: _spf.mlsend.com
- GetResponse: _spf.getresponse.com
To add any of the services above, simply insert an include mechanism for each of its SPF records right before the terminating mechanism of your existing SPF record.
For example, if your existing SPF record looks like this:
v=spf1 a -all
and you want to add Ontraport to your SPF record, you need to add both of Ontraport's SPF records right before "-all" so that your SPF record looks like this:
v=spf1 a include:_spf-moon-ray.ontramail.com include:_spf-ontramail.ontramail.com -all
Now all emails from Ontraport servers will pass SPF authentication on the receiving servers.
SPF record FAQs
Can I have multiple SPF records on my domain?
Only one SPF record can be published on any particular domain. If multiple SPF records are found, an SPF PermError is returned.
What if there are syntax errors in my SPF record?
If your SPF record has syntax errors, the receiving server immediately returns a PermError without further record evaluation. This means all your emails will fail SPF authentication and might not reach the inbox.
To check if your SPF record has any syntax errors, use DMARCLY's free SPF Record Checker.
Here is a FREE SPF RECORD GENERATOR.
(This page was sourced from DMARCLY, here: https://dmarcly.com/blog/what-is-an-spf-record-and-how-does-it-work-spf-record-explained )