SPF record
Lists the hosts allowed to send mail using a domain in the SMTP envelope sender.
Last updated July 27, 2026
Zone-file example
example.com. 3600 IN TXT "v=spf1 mx include:_spf.provider.net -all"Typical uses
- Authorising a hosted mail provider to send using your domain
- Authorising marketing, ticketing, and monitoring platforms that send on your behalf
- Publishing v=spf1 -all on names that never send mail
- Feeding the SPF half of DMARC alignment
When it breaks, check
- Only one v=spf1 record may exist per name; two is a permerror, not a merge
- Evaluation is capped at 10 DNS-querying mechanisms, and include: chains blow through it
- -all asks receivers to reject unlisted senders, ~all only marks them
- SPF checks the envelope sender, not the From: header a recipient sees
What the SPF record does
An SPF policy is a small program. Mechanisms are evaluated in order and the
first one matching the connecting address decides the result, with a trailing
all catching the rest. ip4: and ip6: match literal
addresses, a and mx match whatever those records resolve to, and
include: pulls in another domain’s policy wholesale.
The identity checked is the envelope sender from the SMTP MAIL FROM command,
not the From: address a human reads. A forwarded message keeps its
From: and acquires a new envelope sender, so SPF breaks on forwarding by
design. That gap is what DMARC alignment exists to close.
TXT record syntax
The value is one quoted string beginning v=spf1, followed by
space-separated mechanisms, each optionally prefixed with a qualifier:
+ pass, - fail, ~ softfail,
? neutral. A bare mechanism defaults to pass. There is no dedicated
record type any more: type 99 existed, and
RFC 7208 §3.1 deprecated it in favour of publishing in
TXT. Exactly one v=spf1 record may exist at a name; two
is a permanent error, not a union of the pair.
; mechanisms are evaluated left to right, first match wins
example.com. 3600 IN TXT "v=spf1 mx ip4:203.0.113.0/24 include:_spf.provider.net -all"
; a name that never sends mail
parked.example.com. 3600 IN TXT "v=spf1 -all"
; INVALID: two v=spf1 records at one name is a permerror, not a merge
; example.com. 3600 IN TXT "v=spf1 include:vendor-a.net ~all"
; example.com. 3600 IN TXT "v=spf1 include:vendor-b.net ~all"
Common uses
The realistic job of SPF is authorising the handful of platforms that send
as you: the mail provider, the transactional sender, the CRM, the ticketing system. Each
arrives with an include: to paste in, and the set grows quietly until
something breaks. Publishing v=spf1 -all on names that never send is the
higher-value half of the work, since a hard fail there has no false positives.
Troubleshooting
The most common real-world failure is the lookup limit.
RFC 7208 §4.6.4 caps evaluation at ten DNS-querying mechanisms —
include, a, mx, ptr,
exists, and the redirect modifier — counted across the whole
nested tree, not just the record you wrote. Exceed it and the result is permerror, which
many receivers treat as a failure, so adding one more vendor breaks mail that worked
yesterday. Count the expansion, not your own line.
The trailing qualifier is the other conscious choice. -all asks receivers to
reject unlisted senders and will bite on forwarded mail; ~all merely flags
them. Under DMARC the difference matters less than people assume, because alignment does
the real work.
# the policy itself
dig example.com TXT +short | grep -i 'v=spf1'
# expand every include: and count DNS-querying mechanisms against the limit of 10
dig _spf.provider.net TXT +short
# type 99 is deprecated; nothing should answer here
dig example.com TYPE99 +noall +answer
The defining RFC
SPF is RFC 7208, a Proposed Standard obsoleting the earlier experimental RFC 4408. Section 3.1 deprecates the dedicated SPF resource record, type 99, and requires publication in a TXT record; section 4.6.4 sets the ten-lookup limit behind most production breakage, and section 8 defines each result code. The retired type is still listed, marked obsolete, in the IANA DNS Parameters registry. Check a policy with the DNS lookup tool.
Reference and tooling
Every record type and its assigned numeric value is listed in theIANA DNS Parameters registry. To query a live zone from the browser, use theDNS lookup tool. If the record you are chasing is TLS-related, the TLS inspector andCertificate Transparency lookup are usually the next two stops.