SPF Record Setup: Syntax, Examples and the 10-Lookup Limit

Updated: 5 min read Editorial team haveibeenhacked.de
Short answer

An SPF record is a single TXT record on your domain that starts with v=spf1, lists every service allowed to send mail for you (for example include:_spf.google.com) and ends with ~all or -all. You may publish only one per hostname, and evaluating it must not take more than 10 DNS lookups, or receivers return permerror.

Most SPF breakage doesn’t come from the first setup. It happens a year later, when someone in marketing connects a new email platform, follows the vendor’s instructions literally and adds a second TXT record starting with v=spf1. From that moment on, SPF fails for the whole domain. Nobody notices until invoices start landing in spam.

What SPF checks, and what it doesn’t

SPF, the Sender Policy Framework, is defined in RFC 7208. It answers one narrow question: is the IP address delivering this message allowed to send for the domain in the SMTP envelope? That domain comes from the MAIL FROM command, which ends up in the Return-Path header.

That is not necessarily the address your recipient sees. A newsletter platform will often send with a Return-Path like bounces.vendor.net while the visible From says [email protected]. SPF then passes for the vendor’s domain, not yours. That gap is the reason DMARC exists, and why the next step after SPF is to set up DMARC.

Anatomy of an SPF record

An SPF record is an ordinary TXT record. It always begins with v=spf1, followed by mechanisms that receivers evaluate left to right. The first match wins.

example.com.  3600  IN  TXT  "v=spf1 include:_spf.google.com include:sendgrid.net ip4:198.51.100.25 ~all"
MechanismMeaningCosts a DNS lookup?
ip4:198.51.100.25This IPv4 address may sendno
ip6:2001:db8::/32This IPv6 range may sendno
aThe domain’s A/AAAA addresses may sendyes
mxThe domain’s MX hosts may sendyes
include:domainPull in another domain’s SPF policyyes, plus whatever that record costs
exists:Macro-based lookup, rarely neededyes
redirect=domainHand evaluation to another record entirelyyes
ptrReverse DNS match; the RFC says do not use ityes
allMatches everything; goes lastno

Each mechanism can carry a qualifier: + pass (the default), - fail, ~ softfail, ? neutral.

~all versus -all

The argument over the last four characters predates DMARC. -all tells receivers that anything not listed is a hard fail. ~all says it is suspicious, but don’t treat it as definitive.

My view for domains with DMARC: use ~all. Some receivers reject on an SPF fail during the SMTP conversation, before they look at DKIM. Forwarded mail almost always fails SPF, because the forwarding server is not in your record, while the DKIM signature usually survives. With -all, a legitimate signed message can be rejected that DMARC would have let through. Let DMARC with p=reject do the enforcing.

For domains that never send email, -all is exactly right. IANA does it for example.com:

$ dig +short TXT example.com
"_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9"
"v=spf1 -all"

The 10 DNS lookup limit

This is where most real-world SPF setups break. RFC 7208 caps the number of mechanisms that trigger DNS queries at 10 per evaluation. include, a, mx, ptr, exists and the redirect modifier all count, and they count recursively. An include pointing at a record with three more includes costs four. Go over and the receiver returns permerror, which DMARC treats as a failure.

A typical small-business stack looks like this:

EntryLookups
include:spf.protection.outlook.com (Microsoft 365)1
mx1
Marketing platform with two nested includes3
CRM2
Helpdesk2
Invoicing tool1
Total10

One more vendor and you are over. The RFC also allows at most two “void” lookups, queries that return no answer. An include for a service that shut down years ago counts toward that.

Ways out, roughly in order of how often they fix the problem:

  • Remove services you no longer use. This is the biggest lever by far.
  • Replace mx and a with literal ip4:/ip6: ranges if those addresses rarely change.
  • Move bulk and transactional mail to a subdomain such as mail.example.com. It gets its own record and its own budget of 10.
  • Use SPF flattening (resolving includes into IP lists) only through a tool that re-resolves automatically. Providers change their ranges, and a stale flattened record silently starts failing.

Checking your record with dig

Once the record is published, query it directly:

$ dig +short TXT example.com
"v=spf1 include:spf.protection.outlook.com ~all"

If you see two lines starting with v=spf1, fix that first. To count lookups, follow each include down:

$ dig +short TXT spf.protection.outlook.com
"v=spf1 ip4:40.92.0.0/15 ip4:40.107.0.0/16 ... -all"

Microsoft’s record contains only IP ranges, so it costs exactly one lookup. Google’s _spf.google.com currently does the same. Other vendors nest several levels deep.

Long records hit a second limit: a single string inside a TXT record can hold at most 255 characters. Longer records are split into several quoted strings, which receivers concatenate without spaces. Most DNS control panels handle the split for you.

Common SPF mistakes

  • Two records. Covered above; the result is permerror.
  • The old SPF record type (type 99). RFC 7208 retired it. Only TXT counts.
  • +all at the end. That authorises every server on the internet to send as you. It is worse than having no record.
  • Forgetting the web server. WordPress contact forms often send through PHP mail() from the hosting server, whose IP is not in your record.
  • Pasting a smart quote. Copying from a word processor can turn " into ”, and the record stops parsing.

SPF is only half of authentication. The other half is a cryptographic signature, covered in DKIM setup, and the reason SPF alone does not stop forged From addresses is explained in prevent email spoofing.

Where the record lives

SPF goes in your domain’s DNS zone, not in your mailbox settings. If your domain sits with a registrar and your mail with someone else, you edit the record at whoever runs your DNS. At betadomain, the DNS records sit right next to the domain itself, and DNSSEC can be switched on in the same place. A .com with DNS management costs €14.99 a year, and renewals cost the same.

If you are about to register your own domain for email, set SPF, DKIM and DMARC on day one, before any service starts sending. Retrofitting later is harder, because by then there are senders nobody remembers adding. The full price list shows what a second domain just for newsletters would cost.

Step by step

  1. List everything that sends as your domainWrite down your mailbox provider, newsletter tool, CRM, helpdesk, invoicing software and any web server that sends contact-form mail.
  2. Collect each provider's SPF mechanismLook up the include each service documents, such as include:_spf.google.com for Google Workspace or include:spf.protection.outlook.com for Microsoft 365.
  3. Build one record and count lookupsCombine everything into one v=spf1 record ending in ~all. Count include, a, mx, exists and redirect, including nested ones. Stay at 10 or below.
  4. Publish the TXT recordCreate a TXT record at the root of your domain (host @) with your DNS provider, and delete any older SPF record so only one remains.
  5. Verify with dig and a test messageRun dig +short TXT example.com, then send a message to a Gmail account and check Show original for SPF: PASS.

Found your domain? You can check and register it directly at register a domain – yearly price from €2.99.

FAQ

Can I have two SPF records on one domain?

No. RFC 7208 says a receiver that finds more than one v=spf1 record must return permerror, which means SPF fails for everything you send. Merge all services into one record instead.

Do subdomains inherit the SPF record?

No. SPF is looked up for the exact domain in the envelope sender. If a tool sends as bounce.example.com, that hostname needs its own record. Subdomains that never send mail are best given v=spf1 -all.

Should I use ~all or -all?

If you run DMARC, ~all is usually the safer choice, because some receivers reject on an SPF hard fail before DKIM and DMARC are even evaluated. That can kill forwarded mail that DMARC would have accepted. For domains that send no mail at all, use -all.

Why does my SPF check pass but DMARC still fails?

SPF checks the envelope domain (Return-Path), not the From address people see. If your email provider uses its own bounce domain, SPF passes for them, not for you. DMARC needs that domain to match yours, or a DKIM signature from your domain.