Multiple SPF Records Do’s and Don’ts

Sender Policy Framework (SPF) is a protocol used by mail servers to authenticate emails. It is implemented via TXT type records known as SPF records. Earlier in “SPF Records Explained” we provided a detailed look into this concept. In this article, we’ll talk about practical matters and how to avoid common SPF issues. The focus will be on the second most common error setting up multiple SPF records for a single domain.

Don’t use multiple SPF records!

Here is an off-the-reel axiom: one SPF record for one domain. This is explicitly defined in RFC4408:

A domain name MUST NOT have multiple records that would cause an authorization check to select more than one record.

In practice, multiple SPF records of your domain will be declined by the recipient server, so what’s the point of having more than one entry? As a rule, duplication of DNS TXT record happens by accident. The following is an example:

You are asked by a new email service provider, let’s say Mailgun, to create an SPF record. You forget that you already have a functioning record for Gmail and create a new one. In the end, you have two SPF entries as follows:

v=spf1 include:_spf.google.com ~all

v=spf1 include:mailgun.org ~all

The rule of thumb: multiple SPF records will fail the SPF authentication.

How to check my SPF record existence?

The best way to validate an SPF record for your domain is to use a dedicated tool. Let’s see how some of them work by looking up the SPF record of Mailtrap.io:

SPF Record Check by MXToolbox

SPF Record Check provides detailed diagnostics of the SPF record. Just enter your domain name or IP Address and click the button. You can also check other information, such as MX records, DNS, sender reputation and much more. 

SPF Record Lookup by Easy DMARC

SPF Record Lookup emphasizes lookups for a particular domain. The validation outcome is the SPF Lookup Tree that you can expand to find main and additional lookups, like the following:

Look Up SPF Records by Agari

Agari offers a bare-bones tool for SPF record verification. Look Up SPF Records just shows the valid record and provides some general insights, such as the number of DNS querying mechanisms and IP addresses authorized.

Checking the SPF record by hand

You can also check the record manually using nslookup. For this, run the command line and type nslookup -type=txt <domain-name>. In the response, there must be only one v=spf1 entry. For example:

$ nslookup -type=txt mailtrap.io 
Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
mailtrap.io	text = "v=spf1 include:_spf.google.com include:sendgrid.net include:smtp1.uservoice.com ~all"

Multiple SPF records have been found for my domain – What should I do?

Let’s say that you’ve gotten yourself into a trap of duplicated SPF records:

  •  You have added a new entry

 v=spf1 ip6:2001:4860:4000::/37 ~all 

  • But you already had one 

v=spf1 include:_spf.google.com ~all

If you’re using a large email provider like Microsoft Exchange or Gmail, the issue with duplicated SPF records should be corrected automatically. Smaller email providers do not usually offer such intelligent features, so you’re likely going to have to handle this all by yourself. The best solution is to merge both of your DNS TXT entries into a consolidated version. To accomplish this, expand the newly added entry with the data from the existing entry, as follows:

v=spf1 ip6:2001:4860:4000::/37 include:_spf.google.com ~all

NB: You can’t just copy one TXT record and paste it into another one like this:

 v=spf1 ip6:2001:4860:4000::/37 ~all v=spf1 include:_spf.google.com ~all 

or 

 v=spf1 ip6:2001:4860:4000::/37 v=spf1 include:_spf.google.com ~all 

When merging multiple SPF records, you can use v=spf1 only once in the beginning and all only once at the end. 

Best practices for properly handling SPF records

Using proper multiple SPF records syntax is essential for merging, but there are also other important keynotes.

Meeting the DNS lookup limits

The total number of mechanisms and modifiers that do DNS lookups must not exceed ten. Every instance of the following: include, a, mx, ptr [deprecated], exists, or redirect, will generate one lookup. If this number is exceeded, the SPF authentication will fail. For example, this is an incorrect entry:

v=spf1 include:email-od.com include:customerexample.com include:spf.protection.outlook.com include:_spf.google.com include:qa-test.spf.example.org include:production.spf.example.net mx a include:getresponse.com include:servers.mcsv.net ~all

What if I need to create an SPF for multiple IP addresses (for example, more than 10)? Mechanisms, such as all, ip4, and ip6, do not require DNS lookups, so they are not included in the specified limit number. For example, the following SPF record multiple ip4 won’t cause any issues:

v=spf1 ip4:10.3.1.0/24 ip4:10.4.8.0/24 ip4:10.11.5.0/28 ip4:10.13.6.0/24 ip4:192.168.1.0 ip4:10.232.87.0/25 ip4:10.190.185.0/24 include:spf.protection.outlook.com ip4:10.10.119.0/24 ip4:10.99.14.0/24 ip4:10.240.176.0/20 ip4:10.0.14.0/24 ~all

Be attentive to nested include mechanisms

When we checked Mailtrap.io using SPF Record Lookup by Easy DMARC (above), the tool detected nine lookups, whereas there were only three include mechanisms:

Is anything wrong with the tool? Not really! Each include statement of this record requires a DNS lookup according to their own SPF records. You can see them all when expanding the SPF Lookup Tree:

So, when you include a new email service provider, make sure that your final SPF record won’t exceed the total 10 permitted DNS queries. 

Meeting the character limits in SPF records

Another limit associated with SPF records that you should take into account is the 255-character limit for a single string. For example, the following string has 241 characters (including spaces):

v=spf1 ip4:10.3.1.0/24 ip4:10.4.8.0/24 ip4:10.11.5.0/28 ip4:10.13.6.0/24 ip4:192.168.1.0 ip4:10.232.87.0/25 ip4:10.190.185.0/24 include:spf.protection.outlook.com ip4:10.10.119.0/24 ip4:10.99.14.0/24 ip4:10.240.176.0/20 ip4:10.0.14.0/24 ~all

So, how can I add an IP address or another parameter here? You can’t exceed the 255-character limit, but you can split your text DNS record into several. For example, the following is the entry that contains all your parameters:

v=spf1 ip4:10.3.1.0/24 ip4:10.4.8.0/24 ip4:10.11.5.0/28 ip4:10.13.6.0/24 ip4:192.168.1.0 ip4:10.232.87.0/25 ip4:10.190.185.0/24 include:spf.protection.outlook.com ip4:10.10.119.0/24 ip4:10.99.14.0/24 ip4:10.240.176.0/20 ip4:10.0.14.0/24 include:email-od.com include:customerexample.com include:_spf.google.com include:qa-test.spf.example.org ~all

Unfortunately, you can’t use it as is because it has 346 characters. Let’s try to split it into two subrecords: record.com TXT and spf2.record.com TXT. Here’s how they will look:

record.com TXT “v=spf1 ip4:10.3.1.0/24 ip4:10.4.8.0/24 ip4:10.11.5.0/28 ip4:10.13.6.0/24 ip4:192.168.1.0 ip4:10.232.87.0/25 ip4:10.190.185.0/24 ip4:10.10.119.0/24 ip4:10.99.14.0/24 ip4:10.240.176.0/20 ip4:10.0.14.0/24 include:spf2.record.com ~all”

spf2.record.com TXT “include:spf.protection.outlook.com include:email-od.com include:customerexample.com include:_spf.google.com include:qa-test.spf.example.org ~all”

Warning: Each split will cause an additional DNS query since you add the include statement.

To wrap up

A properly created SPF record is just a variable in the formula for reliable email delivery. Other variables include the DMARC record and the DKIM signature. Check our dedicated blog posts to set them up properly.