Reading an SPF Record: How Mail Servers Decide Who May Send for Your Domain

Email forgery is easy in principle, because nothing in the basic design of email proves that the sender is who they claim to be. SPF, short for Sender Policy Framework, is one of the mechanisms that closes that gap. A domain owner publishes a record listing which mail servers are allowed to send mail for that domain, and receiving mail servers check incoming mail against that list. If the sending server is on the list, the message passes the SPF check. If it is not, the message fails, and the receiver can reject it, quarantine it, or mark it as suspicious, depending on its policy. The SPF Checker helps you read a record you paste in, checking its format and its logic, so you can find the errors that cause legitimate mail to fail or that leave the door open to forgery.

An SPF record is a text record published in DNS, and it reads as a short string of mechanisms and qualifiers. A typical record begins with v=spf1, which declares the version, and then lists mechanisms such as ip4 for an IPv4 address or range, ip6 for IPv6, a for the domain's own address records, mx for its mail servers, include for another domain's SPF record, and all as the final catch-all. Each mechanism can carry a qualifier: a plus sign means pass, a minus sign means fail, a tilde means soft fail, and a question mark means neutral. The final mechanism matters most, because it decides what happens to senders that match nothing else. A record ending in -all says that anything not listed is not authorised, which is strict and correct for a domain whose senders are fully known. A record ending in +all says that everything is authorised, which defeats the entire purpose of SPF and should never appear in a real record.

How it works

Checking a pasted SPF record is a format and logic exercise performed on text you supply, not a live interrogation of someone else's mail system. The checker splits the record into its mechanisms, verifies that the version declaration is present and first, and checks that each mechanism is spelled correctly and carries a valid value. An ip4 mechanism must contain a valid IPv4 address or range, an ip6 mechanism a valid IPv6 value, and an include mechanism a valid domain name. It also counts the DNS lookups the record would cause, because SPF has a hard limit: a record may cause no more than ten DNS lookups during evaluation, counting the lookups triggered by mechanisms such as a, mx, and include, and by nested includes. Exceeding that limit causes a permanent error, and the check fails regardless of whether the sender would otherwise have matched.

The checker also looks for structural problems that humans commonly create. A record with two separate SPF records for the same domain is invalid, because receivers use only one, and having two is an error, not a backup. A record with no final all mechanism leaves the result ambiguous for unmatched senders. A record that includes another domain's record inherits that domain's lookups and its errors, so a chain of includes can silently push a record over the ten-lookup limit or import a syntax error from a provider you do not control. A good checker reports the lookup count, the mechanism list in order, and any mechanism that would never be reached because an earlier all mechanism already decided the result.

Worked example

Consider this sample record, with sample values that do not belong to any real domain:

v=spf1 ip4:203.0.113.10 ip4:203.0.113.0/24 include:_spf.examplemail.com -all

Reading it in order: the version is SPF version 1. The first mechanism authorises a single server at 203.0.113.10. The second authorises the whole range 203.0.113.0 to 203.0.113.255, which is 256 addresses, including the first one, so the first mechanism is redundant but harmless. The third mechanism includes the SPF record of _spf.examplemail.com, authorising whatever that record authorises, and costing at least one DNS lookup. The final mechanism, -all, says that any sender matching none of the above is not authorised, so it fails the check.

Now suppose the owner adds a second include for a marketing platform, and that platform's record itself includes three more domains, pushing the total lookup count from 3 to 11. The record now exceeds the ten-lookup limit, and receivers return a permanent error instead of a pass or fail. Legitimate mail from the listed servers starts failing, not because the servers are unauthorised, but because the record is too expensive to evaluate. The fix is to flatten part of the record: replace an include chain with the actual IP ranges where they are stable, or remove a provider that is no longer used. Counting lookups before publishing would have caught the problem at the cost of a minute, whereas discovering it from bounced mail costs far more.

Mistakes to avoid

The most dangerous mistake is ending a record with +all, which authorises the entire internet and makes the record worse than useless, because it gives receivers a false sense of a check having passed. If you see +all in a record you manage, remove it immediately and replace it with -all or, during a cautious transition, ~all. A second mistake is publishing two SPF records for one domain, which often happens when a new provider's instructions are added without removing the old record. There must be exactly one. A third mistake is forgetting a sending service: a website contact form, a ticketing system, or a marketing platform that sends on your behalf must be listed, or its mail will fail the check, and the failure will look like a provider problem when it is really a missing mechanism.

A fourth mistake is ignoring the ten-lookup limit until mail starts bouncing, as the example shows. Count lookups whenever a provider is added, and be especially careful with includes, which hide their cost. A fifth mistake is copying a record from a tutorial without adapting it. A record that authorises a tutorial author's example addresses authorises nobody you use and may authorise strangers, so every address and include in a record should be one you recognise and can explain. Finally, the usual handling rule applies: an SPF record is public DNS data, but your DNS provider credentials, API keys, and mail account passwords are not. Never paste those into a checker, and if a tool asks for them to read a record, use a different tool.

Putting it into practice

Treat SPF as part of onboarding for every service that sends mail for your domain. When a new service is added, add its mechanism, count the lookups, paste the updated record into the checker, and confirm the format and the count before publishing. When a service is retired, remove its mechanism promptly, because stale authorisations are a standing invitation to abuse. Pair SPF with its companion checks: the DMARC Checker for the policy that tells receivers what to do with failures, and the DKIM Checker for the signing mechanism that survives forwarding better than SPF does. For background reading, the related guide explains DMARC policy in detail, which is the natural next step once your SPF record is clean.

Key points

  • SPF lists the servers allowed to send mail for a domain, and receivers check senders against it
  • A record must begin with v=spf1, contain exactly one record per domain, and end with an all mechanism
  • Evaluation is limited to ten DNS lookups, and includes count toward that limit
  • Never use +all, and never paste provider credentials or secrets into a checker