Correct and complete SPF configurations seem to escape the grasp and understanding of many a sysadmin, Managed Service Providers, and web developers; from the small business with often simple needs, through to larger firms with dedicated staff to deal with the configuration and management of this record.

Common pitfalls, and unintended consequences in the configurations are seen more often than not - As one of the simplest and most overlooked DNS entries, it is often not taught or described in great detail other than by the use of checking tools and copy/paste solutions in knowledge-base articles.

This working knowledge of SPF records can result in several scenarios from normality, to rejected emails, or worse - a security incident. As the penetration of DMARC expands, this stable foundation must underpin its operation.

The legacy record type

SPF record (type 99)

This record type was intended to be dedicated for SPF records, it never saw full adoption and was formally killed off in RFC 7208. The final verdict and wording was:

SPF records MUST be published as a DNS TXT (type 16) Resource Record (RR) ... only.

It is best practice to remove any lingering type 99 records and ensure the correct type 16 (TXT) record is created/updated in its place.

Looking up SPFs (and other records!)

For the MSPs in this world - I suggest using CIPP and specifically the individual domain lookup / domains Analyser.

For others who aren't a Microsoft Partner - MXToolbox

For anyone wanting a consistent, and ongoing check of their domains: URIPorts

Structure of SPF

The beginning of any SPF record must start with the version e.g. v=spf1, followed by the successive mechanisms and qualifiers. The end of the record will usually end in a variation of all, except for the redirection modifier.

Qualifiers

Each of the follow descriptions can be expanded by clicking the section to expand with more details.

+ Pass

The default condition for any included entry in the mechanism and is usually omitted from the record due to the default nature, Allow the email to proceed.

? Neutral

Nothing explicitly stated about the mechanism, Allow the email to proceed.

~ SoftFail

In transition mechanism, Allow the email to proceed, but mark/flag it.

- Fail

Reject the email, delivery should fail (but mostly doesn't due to SPF misconfigurations).

Mechanisms

all

This mechanism goes at the end of almost every record except for a redirect, this is the catch all for any returns not listed in the record. The only valid entries in production are - i.e. fail, or ~ i.e. soft fail. 

In my professional opinion, if you don't know about the third party it should not be sending on your behalf. Therefore fail should be used exclusively combined with DMARC reporting on failures for either SPF, or DKIM alignment.

IP4 / IP6

This set of mechanisms allows a specific IPv4 host, IPv6 host, or network range to be authorised in the record for sending. These mechanism types do not incur any DNS lookups, and are often used to limit the DNS lookups. It is best practice to ensure any allowances are limited in scope to ensure wide swaths of public cloud/IP ranges are not allowed.

a

Looks up the A/AAAA records on the DNS entry provided to ensure they match, this can be everything from the current domain, DNS subdomain, or a network range. It is best practice to ensure any allowances are limited in scope to ensure wide swaths of public cloud/IP ranges are not allowed.

mx

Includes all entries under the current, or specified domain. A network range can be given on this mechanism.

ptr

Rarely used due to the expensive use of DNS lookups. This mechanism uses forward confirmed reverse DNS to validate the sender is valid.

exists

Not typically used other than with SPF macros and DNSBL queries.

include

References, and includes an SPF record located on another domain, this can be an effective way to delegate to a third party when they need to send on your behalf. It is best practice to check and validate the third party record completely and understand the implications of who, and what, can send on your behalf.

Modifiers

redirect

This can be used to simplify the management of multiple domains by redirecting the entire record to another entry.

exp

Rarely used, this record type can give reasons for a rejection.

Void Lookups

Void lookup are not often discussed, and it isn't that common to come across it. SPF void lookups relate to the DNS lookups on the SPF record.

SPF void lookups are separate to the 10 DNS queries lookup limit, and are capped to a maximum of 2 void lookups.

The void lookup count increases every time an answer returns with either an empty, or null response. Once this maximum count is exceeded an SPF PermError i.e. hardfail will occur, and the message will typically be rejected.

Common Issues / FAQ

No record at all?

Please, please, PLEASE just enter a basic record, monitor with DMARC p=none and work your way from there.

DNS lookup limits

The hard cut off for DNS lookups during an SPF record check is 10 additional DNS lookups. Beyond this limit the record is invalid, and may result in emails being marked as junk, quarantined, or rejected - depending on DMARC configuration, and the configuration of the receiving mail server.

The first DNS lookup is used during the lookup of the initial record, leaving 10 for additional mechanism lookups. This includes any further DNS lookups down the line e.g. include:domain.com, domain.com's record includes two other domains. Meaning four DNS lookups have occurred (three additional). One initially for the full record, one direct include on the original record, followed by two lookups for the referenced include. This scales with each subsequent lookup.

Using the MX, and Include mechanisms can be quite costly in terms of lookups depending on the number of mail servers listed, and the subsequent chain of DNS lookups. Where possible these should be shifted into the IP4 and IP6 mechanisms to reduce the count.

Please note, this needs to be monitored when you include third party entries - they can, and will modify their entries on occasion and this may result in your record pushing over the 10 additional DNS entries lookup limit.

SPF Length limit

The hard limit for the length of the type 16 (txt) record is 255 characters, anything beyond this will result in a failure/invalid record. At this point it is worth expanding out to including a subdomain SPF entry e.g. domain.com references spf1.domain.com which has more of the record to bypass the limit per entry.

Multiple Records

Having multiple type 16 (txt) records will result in "PermError" which usually means the recipient will junk or quarantine the mail.

This results in an inability to correctly interpret the domain’s published records.

Should DMARC with a Reject configuration be involved - this will result in the email not being received at all.

Missing entries

Forgetting to include a third party service in your SPF may result in deliverability issues. It is best to pair SPF/DKIM with DMARC reporting in order to get visibility over the hosts sending on your behalf, this not only ensures you're getting through successfully, it can also give you an early warning on spoofing and abuse of your domains.

Spaces?

Another common issue is having spaces between the mechanism such as:

v=spf1 include: sendgrid.net -all

The inclusion of the space will cause the entry to interpreted as an empty value i.e. no entry at all. The value after the space is then interpreted with an unknown mechanism.

In this specific example, no senders would be authorised to send on behalf of the domain, in others it may result in a particular third party service, IP or other mechanism from being used as a valid sender.

Being overly specific with the plus operator

One of the worst qualifiers to use is + with the all mechanism, in effect, allowing ANY host to send email on behalf of the domain. Unfortunately I still see this even in 2022.

I'm not sending email from a domain, what record should i use?

The following txt record type specifies no authorised mechanisms, and has a hard fail

v=spf1 -all

This would reject all email, as long as the recipient server is configured to take action on the SPF.

SPF Macros

Wait, what? Macros in a text record?

This one is definitely beyond the scope of this post, and a follow up post will happen in the near future with further details.