Writing an SPF record that works
The syntax, the ten-lookup limit, and the mistakes that quietly turn SPF off.
Updated 19 September 2026 · 1 min read
SPF is a TXT record at your domain listing the servers allowed to send mail using your domain in the envelope sender. A receiver checks the connecting server against the list and gets pass, fail, softfail or neutral.
A good record
v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.10 -all
v=spf1must be first.include:pulls in a provider's list.ip4:/ip6:list your own servers directly.aandmxallow the domain's own A record and MX hosts.-allfails everything else.~all(soft fail) is a transitional setting;?alland+allare effectively no policy.
The ten-lookup limit
Every include, a, mx, ptr, exists and redirect costs a DNS lookup, and includes count recursively. After ten, receivers stop and return permerror, which most treat as a fail. Providers' includes grow over time; Microsoft 365 alone can cost several. The Mail facet counts lookups for you and raises SPF-LOOKUPS-EXCEEDED past ten.
Common mistakes
- Two SPF records. Receivers see multiple records as an error. Merge them.
- A record on a subdomain but mail sent from the apex, or the reverse. SPF applies to the exact domain in the envelope sender.
- Using
ptr. Deprecated and unreliable; replace with addresses. - Forgetting a sender. Helpdesks, CRMs, invoicing and newsletter tools all send as you. DMARC reports show what you missed.
- Relying on SPF alone. Forwarding breaks SPF because the forwarder's server is not yours. DKIM survives forwarding; DMARC needs one of the two to pass and align.
No mail from this domain?
Publish v=spf1 -all and a null MX (MX 0 .) so nobody can use the name.
Check your own domain
