LearnEmail authentication

What is an SPF record?

An SPF record is one TXT record at your domain root listing the servers permitted to send mail using your domain in the envelope sender. A receiver compares the connecting IP against that list. Exactly one record is legal per domain; publishing a second voids SPF entirely rather than combining them.

Written by the SieveGuard team from the checks our own free tools run. Last reviewed .

What the record actually contains

One line, read left to right. The first mechanism that matches the connecting IP decides the result, and evaluation stops there.

v=spf1 ip4:203.0.113.7 include:_spf.google.com include:sendgrid.net ~all
│      │                 │                        │                  └ what to do with everything else
│      │                 └ delegate to Google's record          └ and SendGrid's
│      └ this specific IP is allowed
└ version tag — always first, always exactly this

Left-to-right ordering matters more than it looks. Put ~all in the middle and everything after it is unreachable, because the catch-all matches every IP that reached it.

The mechanisms, and which you actually need

MechanismMatchesDNS lookupsVerdict
ip4: / ip6:A literal address or CIDR range0Use freely — free, and exact
include:Anything the named domain’s SPF record allows1 (plus theirs)The standard way to add a provider
aThe domain’s own A/AAAA records1Rarely needed — your web server is not your mail server
mxThe hosts in the domain’s MX records1 (plus one per MX host)Only if your inbound servers also send
exists:A macro-expanded lookup that resolves1Niche; almost never in a hand-written record
ptrReverse DNS of the connecting IPSeveralDeprecated — do not use
redirect=Replaces this record with another domain’s1For domains that share one policy

ptr is worth calling out: RFC 7208 explicitly says do not publish it, and some receivers skip it entirely. If you inherited a record containing it, that record has been partly ignored for years.

The qualifier at the end is the part with teeth

Every mechanism can carry a qualifier; in practice the only one people set is the last.

EndingNameTells the receiverWhen to use it
-allHard failRefuse anything not listedOnce you are certain every sender is listed
~allSoft failAccept, but treat as suspiciousWhile ramping, and the sane default
?allNeutralNo opinion whatsoeverEffectively the same as no record — avoid
+allPass everythingAny server may send as this domainNever. This is a spoofing invitation

The practical difference between -all and ~all is smaller than the names suggest, because under DMARC the policy verdict comes from DMARC, not from SPF’s qualifier. Where the qualifier still matters is with receivers that check SPF independently — and there, a hard fail on a legitimate forwarded message is a bounce you did not need.

The four ways an SPF record breaks

Two records

RFC 7208 permits exactly one. A domain publishing two v=spf1 TXT records is a permerror, and a permerror is treated as no SPF at all — not as "use the first one". This is the most common way a working setup breaks, because adding a provider by pasting their suggested record is the natural thing to do.

✗ two records — SPF is now void
yourdomain.com  TXT  "v=spf1 include:_spf.google.com ~all"
yourdomain.com  TXT  "v=spf1 include:sendgrid.net ~all"

✓ one record, both senders
yourdomain.com  TXT  "v=spf1 include:_spf.google.com include:sendgrid.net ~all"

Too many DNS lookups

Ten is the ceiling, and include: chains nest, so you can cross it without adding anything yourself — a provider expanding their own record is enough. It has its own page because it is the failure that arrives without warning.

The 255-character string limit

A single DNS character-string cannot exceed 255 bytes. Long records must be split into multiple quoted strings inside one TXT record, which resolvers concatenate:

"v=spf1 include:_spf.google.com include:sendgrid.net " "include:servers.mcsv.net ~all"

Two strings, one record — legal. Two records, as above — not. Some DNS UIs do the split for you and some silently truncate, which is why the resolved value is worth checking rather than the value you typed.

Publishing at the wrong name

SPF lives at the domain root. There is no _spf prefix and no subdomain involved — that is DKIM and DMARC you are thinking of. A record at _spf.yourdomain.com is never read by anything.

What SPF does not do

Three limits worth internalising, because each one surprises people:

  • It authenticates the envelope, not the visible From. The address a reader sees is not what SPF checked. Closing that gap is DMARC’s entire job.
  • It breaks on forwarding. A forwarder connects from its own IP, which your record does not list. Nothing is wrong with your setup; SPF simply cannot survive the hop. DKIM can, which is why having both matters.
  • A pass is not a reputation. Spammers publish valid SPF records too. Passing proves the server was authorised, and says nothing about whether the mail is wanted.

Sources

FAQ

Where exactly does the SPF record go?+

A TXT record at the domain root — the same name as the domain itself. Most DNS interfaces represent that as a blank host field or an @ symbol. There is no _spf prefix; a record published under one is never read.

Can I have two SPF records?+

No. RFC 7208 permits exactly one v=spf1 TXT record per domain, and two is a permanent error that voids SPF entirely rather than merging them. Combine the mechanisms from both into a single record instead.

Should I use -all or ~all?+

Start on ~all and stay there while you confirm every sender is listed. Move to -all once you are sure, and only if you also have DMARC — under DMARC the enforcement decision comes from the DMARC policy anyway, so -all mainly affects receivers checking SPF on its own.

Do I need an SPF record for a domain that never sends mail?+

Yes, and it is the shortest useful record you can publish: v=spf1 -all. It states that nothing is authorised to send for this domain, which makes parked and internal-only domains a much less attractive spoofing target.

Does SPF need to be on subdomains too?+

Subdomains do not inherit the parent record for SPF purposes. If you send from a subdomain, publish a record on the subdomain. If you do not, publish v=spf1 -all there so it cannot be used.

Why does my record show permerror when it looks correct?+

Two causes account for nearly all of it: a second SPF record on the same name, or more than ten DNS lookups once every include is expanded. Both void the record. Syntax errors are a distant third, because most DNS interfaces reject the obviously malformed ones.

Check it on a real domain

Free, no signup, DNS-only. Nothing you type leaves the lookup.

Keep reading