Cybersecurity

SPF Record Syntax: Complete Guide to Creating Valid SPF

Master SPF syntax including ip4, ip6, include, mx, and all mechanisms, plus qualifiers like ~all and -all for proper email authentication.

By Inventive HQ Team

A valid SPF record is a single DNS TXT record on your domain that begins with v=spf1, lists every server permitted to send mail from that domain using mechanisms like ip4, include, and mx, and closes with an all mechanism that tells receivers what to do with everything else — for example v=spf1 include:_spf.google.com ip4:203.0.113.5 ~all. SPF (Sender Policy Framework, defined in RFC 7208) lets a receiving mail server check whether the machine connecting to it is actually allowed to send for the envelope-sender domain, using nothing but a DNS query.

That is the summary an AI Overview will hand you. Here is what it can't show you: the order mechanisms are evaluated in, why ~all vs -all quietly decides whether spoofed mail lands in the inbox, the invisible 10-lookup ceiling that silently voids your record, and the exact mechanism-by-mechanism reference you need to write one correctly the first time. The animated diagram, the syntax anatomy, the mechanism table, and the copy-ready checklist below are the parts that don't compress into two sentences.

How a receiver evaluates your SPF record (animated)

When mail arrives, the receiving server takes the domain from the SMTP MAIL FROM (the envelope, not the visible From:), looks up its SPF TXT record, and walks the mechanisms left to right. The first mechanism that matches the connecting IP wins, and its qualifier decides the result. If nothing matches before all, the all qualifier applies.

SPF evaluation flow from incoming mail to result A sending server connects, the receiver queries the SPF TXT record, walks mechanisms left to right, and the first match decides pass or fail. Sending IP 203.0.113.5 Receiver Reads MAIL FROM Queries SPF TXT Walk mechanisms left → right include:... ip4 match ~all PASS IP is authorized FAIL / SOFTFAIL falls through to all

First matching mechanism wins — order matters. No match before the end means the qualifier on all decides the outcome.

The single most common misunderstanding: SPF checks the envelope sender (Return-Path), which recipients never see, not the From: header they do see. That gap is exactly why SPF alone cannot stop display-name spoofing and why DMARC exists to tie the two together.

Anatomy of an SPF record

Every SPF record is three parts: the version tag, one or more mechanisms (each optionally carrying a qualifier), and a closing all.

Anatomy of an SPF record broken into version, mechanisms, and all The record v=spf1 include:_spf.google.com ip4:203.0.113.5 -all labeled by part. v=spf1 include:_spf.google.com ip4:203.0.113.5 -all v=spf1 version tag include:_spf.google.com mechanism (costs 1 DNS lookup) ip4:203.0.113.5 mechanism (no lookup) -all hardfail catch-all Read left to right. `-all` at the end means "anything not matched above is unauthorized — reject it." Publish exactly one such TXT record per domain.
Advertisement

SPF mechanisms reference

Mechanisms are the building blocks that describe who is allowed to send. The ones that require a DNS query count against the 10-lookup limit — track them carefully.

MechanismWhat it authorizesDNS lookup?When to use
ip4:x.x.x.x / ip4:x.x.x.x/24A specific IPv4 address or CIDR rangeNoYour own static mail servers — cheapest, most reliable
ip6:...A specific IPv6 address or rangeNoIPv6-capable senders you control
a / a:domain.comIPs in the A/AAAA record of the domainYes (1)When your sending host's IP tracks its A record
mx / mx:domain.comIPs of the domain's MX hostsYes (1+)Only if your inbound MX servers also send mail
include:domain.comDelegates to another domain's SPF recordYes (1, plus its own)SaaS senders: Google, Microsoft 365, Mailchimp, SendGrid
exists:domain.comPasses if the domain resolves at allYes (1)Advanced macro-based / per-IP validation
ptrReverse-DNS of the connecting IPYesDeprecated — do not use (slow, spoofable)
allMatches everything; always lastNoThe mandatory catch-all, with a qualifier

Which should I use? Prefer ip4/ip6 for infrastructure you own (they cost zero DNS lookups), and include for third-party senders (they hand you the provider's ranges and keep updating them). Avoid a, mx, and especially ptr unless you have a specific reason — they burn lookups and add fragility.

Qualifiers: the four prefixes and what receivers do

Every mechanism can carry a qualifier. If you omit it, the default is + (pass). The qualifier on the final all is the most consequential character in the whole record.

QualifierNameSymbol on allReceiver behavior
+Pass+allNever use — authorizes the entire internet to send as you
-Fail-allHardfail: unlisted senders are rejected/discarded
~SoftFail~allAccepted but marked suspicious — the safe testing state
?Neutral?allNo policy assertion; effectively no protection

The standard rollout is: publish ~all first, watch DMARC aggregate reports until every legitimate source passes, then tighten to -all. Jumping straight to -all before you've inventoried every sender (marketing platform, ticketing system, CRM, ERP) is the classic way to bounce your own invoices.

Worked examples

Google Workspace only:

v=spf1 include:_spf.google.com -all

Microsoft 365 only:

v=spf1 include:spf.protection.outlook.com -all

Google Workspace + a marketing platform + one on-prem server:

v=spf1 include:_spf.google.com include:servers.mcsv.net ip4:198.51.100.20 ~all

A domain that sends no mail at all (lock it down so it can't be spoofed):

v=spf1 -all

You can build and lookup-count these interactively with our SPF Record Generator, which flags when you cross the 10-lookup line before you publish.

The 10-DNS-lookup limit (the silent killer)

RFC 7208 caps SPF evaluation at 10 DNS-querying mechanisms. Each include, a, mx, ptr, and exists counts — and an include can itself pull in nested includes that each count. Cross the line and receivers return permerror, which most treat as an outright SPF failure, undoing the whole record. ip4, ip6, and all are free.

Because major providers chain includes (a single include:_spf.google.com expands to several sub-lookups), it is easy to blow the budget with just three or four SaaS senders. Fixes, in order of preference: remove senders you no longer use, replace broad include statements with the specific ip4 ranges they resolve to (flattening), and consolidate. We cover this in depth in SPF's 10 DNS lookup limit.

Deployment checklist

  1. Inventory every sender. List all systems that send mail as your domain — email platform, CRM, helpdesk, billing, monitoring, transactional mail (SendGrid/Mailgun/SES), marketing tools.
  2. Build one record. Combine all senders into a single v=spf1 ... TXT record. Use include for SaaS, ip4/ip6 for your own IPs.
  3. Start with ~all. Publish with softfail so nothing bounces during validation.
  4. Confirm you have exactly one SPF TXT record. Two v=spf1 records = automatic permerror.
  5. Count your DNS lookups. Stay at 10 or fewer querying mechanisms; verify with a validator.
  6. Wait for propagation. DNS TTL can delay changes — see SPF record propagation time.
  7. Watch DMARC reports. Confirm every legitimate source passes SPF (or DKIM) before tightening.
  8. Move to -all. Once reports are clean, switch softfail to hardfail for real protection.
  9. Pair with DKIM and DMARC. SPF alone doesn't protect the visible From: — layer DKIM and DMARC on top.

Common syntax mistakes

  • Two SPF records. Merge them into one. The second v=spf1 TXT record breaks everything.
  • Using +all. This authorizes the whole internet. It is never correct.
  • Leaving ptr in. Deprecated; remove it and use ip4/include.
  • Assuming SPF covers the From: header. It only checks the envelope sender. Forwarding routinely breaks it — that's why forwarding and SPF conflict.
  • Publishing as an SPF record type. Use TXT; the type-99 SPF record was retired in 2014.
  • A trailing space or split string that malforms the record — keep it under 255 characters per string.

Bottom line

SPF is deceptively small — one TXT record — but its rules are unforgiving: exactly one record, correct left-to-right mechanism order, no more than 10 lookups, and a deliberately chosen all qualifier. Get those four right, roll out ~all-all under DMARC observation, and combine it with DKIM and DMARC. That combination, not SPF by itself, is what actually stops attackers from sending mail as your domain.

Frequently Asked Questions

What is the correct SPF record syntax?

A valid SPF record is a single DNS TXT record that starts with v=spf1, lists the servers allowed to send mail using mechanisms (ip4, ip6, a, mx, include), and ends with an all mechanism carrying a qualifier — almost always ~all (softfail) or -all (hardfail). Example: v=spf1 include:_spf.google.com ip4:203.0.113.5 ~all.

What is the difference between ~all and -all?

-all (hardfail) tells receivers that any server not listed is unauthorized and mail from it should be rejected or discarded. ~all (softfail) marks unlisted senders as suspicious but still accepts the mail, usually flagging it. Use ~all while testing, then move to -all once you have confirmed every legitimate sender is included and DMARC reporting is clean.

How many DNS lookups can an SPF record have?

SPF allows a maximum of 10 DNS-querying mechanisms per evaluation (include, a, mx, ptr, and exists all count; ip4, ip6, and all do not). Exceeding 10 causes a permerror, which most receivers treat as an SPF failure. There is also a limit of 2 "void" lookups that return no records.

Can a domain have more than one SPF record?

No. A domain must publish exactly one TXT record beginning with v=spf1. Two or more SPF records cause a permerror and the domain fails authentication entirely. To add another sender, merge its mechanisms into your single existing record — usually with an include.

Should SPF be a TXT record or an SPF record type?

Always use a TXT record. RFC 7208 retired the dedicated SPF (type 99) DNS record type in 2014; receivers only query TXT. If your DNS host still offers an "SPF" record type, ignore it and publish TXT.

What does v=spf1 mean at the start of an SPF record?

v=spf1 is the version tag that identifies the record as SPF version 1, the only version in use. Receivers use it to distinguish the real SPF record from other TXT records on the domain. A record that does not start exactly with v=spf1 is ignored as an SPF policy.

Why should I avoid the ptr mechanism?

The ptr mechanism is deprecated by RFC 7208 because it is slow, unreliable, and easily spoofed via reverse-DNS. Many receivers ignore or penalize it. Use ip4/ip6 or include instead and remove any ptr terms from existing records.

Does SPF alone stop email spoofing?

No. SPF only validates the hidden envelope (Return-Path) sender, not the visible From: address users see, and it breaks on forwarding. It must be paired with DKIM and a DMARC policy with alignment to actually prevent display-name and header-From spoofing of your domain.

How do I fix "too many DNS lookups" in SPF?

Reduce the number of include, a, mx, and exists mechanisms below 11 total. Replace broad include statements with the specific ip4 ranges they resolve to, remove providers you no longer use, or flatten the record. SPF flattening and macro-based delegation services can also keep you under the limit.

SPF syntaxemail securityDNS recordsSPF configuration