Sender Policy Framework (SPF) records range from the very simple (v=spf1 a -all) to the rather complex, to account for the multitude of different outgoing email server configurations that exist on the Internet. Here is a general guide for successfully setting up SPF on your domains.
1. Make a list of your email servers
The purpose of SPF is to advertise your domain’s email servers. It often helps to make a list before starting. Consider whether any of the following are used to send email:
- Web server
- In-office or on-prem email server
- Your ISP’s email relay server
- Email server of your end users’ home ISPs
- Any other email servers through which you send messages
Only the final email server (“gateway”) is relevant. If your company has a more complicated setup where an internal email server routes or forwards email through an outgoing email server for delivery to the world, only the outgoing email server or gateway email server would be listed in the SPF record.
2. Create a list of your domains
Chances are you have more than just one domain or zone. Domains that are not used by you could still be abused by spammers. As such, you may wish to publish null SPF records to protect your domains that you do not use to send email. More on this in a moment.
3. List a server only once
Ultimately, SPF lookups resolve to an IP address. It is not necessary to list the same server using multiple host names (e.g., example.com and www.example.com which both resolve to the same IP). In fact doing so will increase DNS query count, as a receiving server progressing through your record may be forced to make multiple DNS lookups, when simply referencing the server hostname once would have sufficed.
If the server’s IP rarely changes, consider using the ip4:x.x.x.x (or ip6) notation so recipients can avoid DNS lookups entirely. Since there is a limit of 10 DNS lookups per SPF record, specifying an IP address or address range is preferable for long lists of outgoing email servers.
Often an SPF record can be condensed down to something like v=spf1 ip4:x.x.x.x -all if there is only a single outgoing email server IP address.
4. Only list outgoing email servers
The purpose of an SPF record is to publish a list of outgoing email servers. Any servers that do not deliver email to the world, such as web servers or incoming-only (non-relaying) email servers, should not be listed.
5. Only use mx if your MX servers are used for outgoing email
MX records are used to route incoming email for your organization, and the same server(s) may or may not be used for your outgoing email. If the IP address of your outgoing server is covered by an A, ip4, or other mechanism, it is not necessary to reference that server again using the mx mechanism. If the servers listed in your MX records are only used for incoming email, it is not necessary to use the mx mechanism.
6. Use mx with domain names, not email server names
Specifying mx:server.example.com is generally incorrect, unless you truly want SPF validation to look up all the hosts that accept email for the server.example.com domain. (Usually, there will not be any such hosts, because server.example.com is itself a host, not a domain.) This will not show up as a syntax error; however, it will simply not match anything.
The correct usage for validating against the MX records for example.com is mx:example.com, or if you want to specify a particular email server's hostname or IP, a:server.example.com or ip4:x.x.x.x. Finally, note that when your SPF rule is stored as a DNS record associated with example.com, then example.com is the default domain for the rule, so mx on its own (with no explicit domain specified) is sufficient to check the sender IP against all the MX email hosts listed for example.com, in that context.
7. Don’t assume – especially if you are an ISP
If you host email for others, do not just create an SPF record for a customer without researching what email servers that customer uses. You may find you have blocked or hindered your customer’s outgoing email delivery from their in-office email server, for example, or from end users who send email through their home ISP’s email server.
8. Only include existing SPF records
Let’s say you want to include your web hosting company’s outgoing email servers in your SPF record. Let’s also say that example.net hosts your website and email. You may be tempted to use something like include:example.net in your SPF record. However, there are two potential problems with this. If example.net does not publish an SPF record for the example.net domain, then using include:example.net instantly makes your SPF record invalid.
The other problem is more subtle. include:example.net would include email servers authorized to send email from the domain example.net. This may or may not be the same list of email servers example.net uses to send email out using other customer domains! Sometimes an ISP will create a special SPF record that customers can include with their record, such as _spf.example.com. If you want to use an ISP’s email server(s) you should ask them if they maintain an SPF record for their customers to include, or else you will need to change your record every time your ISP adds, removes, or changes a email server’s name and/or address.
9. Publish SPF records for HELO/EHLO names used by your email servers
Checking HELO/EHLO names is recommended by RFC 4408. Publishing records for these hostnames is an important part of the SPF protocol. HELO, or its modern version EHLO, is used when the email from field is empty even if a receiver does not do 100% HELO checking.
Publishing a HELO rule involves creating an SPF record linked to the HELO FQDN used by your email server (example: server.example.com). Normally this should be an entirely separate SPF rule to the one which checks the from addresses in your domain which might be associated with say example.com. A simple example of two policies might be:
example.com. IN TXT "v=spf1 mx -all" server.example.com. IN TXT "v=spf1 a -all"
The first rule would be activated by any message from an address ending with @example.com, and would validate such an email only if it comes from an IP address associated with an MX record for example.com. The second rule would be activated by a HELO identification of server.example.com, and would validate the email only if it comes from the IP address associated with that server.
Another reason to take HELO names into account has to do with publishing null SPF records for your domains that don’t send email, as you could inadvertently deny servers the right to send email. For example, a cloud of web servers sends email forms out using [email protected] as the sender address. Each web server uses (as it should) its own name as the HELO parameter.
www.example.com. IN TXT "v=spf1 -all" web01.example.com. IN TXT "v=spf1 a -all" web02.example.com. IN TXT "v=spf1 a -all" web03.example.com. IN TXT "v=spf1 a -all"
Even though there are no email addresses like [email protected], the name web03.example.com is used for email. If you don't publish an SPF policy for such domains, they are game for spoofers. And if you do publish an SPF policy, you better allow your host to use its own name.
10. Publish null SPF records for your domains that don’t send email
Once you’ve protected your email-sending domains with SPF, if someone is trying to spoof you, then first thing they will try is to spoof your non-email sending domains. Publishing v=spf1 -all says that a domain sends no email. For example, you might publish:
example.com. IN TXT "v=spf1 a:email.example.com -all" email.example.com. IN TXT "v=spf1 a -all" www.example.com. IN TXT "v=spf1 -all"