email

SPF Record Syntax Explained: A Practical Guide (With Real Examples)

Learn SPF record syntax step by step with real examples. Understand mechanisms, qualifiers, and how to correctly configure SPF to prevent email authentication issues.

SPF Record Syntax Explained: A Practical Guide (With Real Examples)

Why SPF Syntax Matters More Than You Think

Here's a scenario that happens to sysadmins and email marketers every week:

You set up a new sending domain, configure Google Workspace, add your SPF record — and everything looks fine. Then a week later, your emails start landing in spam at Outlook. You check the headers, and there it is:

code
Authentication-Results: spf=permerror

Not fail. Not softfail. Permerror — which means Gmail or Outlook couldn't even read your SPF record properly. One syntax mistake is enough.

That's what this guide is about. Not just listing SPF mechanisms, but helping you understand why the syntax works the way it does — so you can write records that actually pass.

🔧 Already have an SPF record? Check its syntax instantly with our free SPF checker tool — it flags errors, counts DNS lookups, and shows you exactly what's wrong.


The Anatomy of an SPF Record

Every SPF record is a DNS TXT record. At its simplest:

code
v=spf1 include:_spf.google.com ~all

That single line tells every receiving mail server in the world: "Only Google's servers are authorized to send email for this domain. Everyone else — treat with suspicion."

The structure always follows this pattern:

code
v=spf1  [mechanisms]  [qualifiers]  [modifiers]

Let's go through each piece.


v=spf1 — The Version Tag (Non-Negotiable)

Every SPF record must start with v=spf1. No exceptions.

There's no v=spf2. If you omit the version tag or mistype it, receiving servers won't recognize the record as SPF at all — it simply gets ignored. Your domain then has no SPF policy, which is almost as bad as having a broken one.


Mechanisms: Who's Allowed to Send?

Mechanisms are the core of your SPF record. They define which servers are authorized.

ip4: and ip6: — Direct IP Authorization

code
v=spf1 ip4:203.0.113.5 ~all
v=spf1 ip4:192.168.1.0/24 ~all
v=spf1 ip6:2001:db8::1 ~all

These are the cleanest, most reliable mechanisms — they require zero DNS lookups, which matters because SPF has a hard limit of 10 lookups per evaluation. Use ip4: and ip6: whenever you know your sending server's IP address directly.

For CIDR ranges: /24 covers 256 IPs, /16 covers 65,536. Don't use /8 (16 million IPs) unless you genuinely control that entire range.


include: — Delegating to a Third-Party Sender

code
v=spf1 include:_spf.google.com ~all
v=spf1 include:sendgrid.net include:spf.protection.outlook.com ~all

This is what you use when a service like Google, SendGrid, or Mailchimp sends email on your behalf. The include: tells receiving servers: "Go check that domain's SPF record too, and apply the same rules."

A few things to understand about include::

  • It costs at least 1 DNS lookup (and the included record may itself trigger more)
  • The included domain's all qualifier is ignored — only its mechanisms are used
  • You're allowed multiple includes, but the 10-lookup ceiling applies globally

⚠️ Real-world problem: A company using Google Workspace, SendGrid, Amazon SES, Mailchimp, and Salesforce Marketing Cloud can easily blow past 10 lookups just from their include: chains — triggering permerror for every email they send. See our guide on fixing SPF permerror if this sounds familiar.


a and mx — Your Own Domain's Servers

code
v=spf1 a ~all           ← Authorizes your domain's A record IP
v=spf1 mx ~all          ← Authorizes your domain's MX servers

Use mx if your inbound and outbound mail server is the same machine — common with self-hosted setups. Each costs 1 DNS lookup.

Most modern setups (Google Workspace, O365) don't need mx — you're better off using include: for those.


ptr: — Don't Use This

code
ptr:domain.com   ← Avoid

Technically valid, but RFC 7208 explicitly discourages it. It's slow, uses extra DNS lookups, and some providers ignore it entirely. Skip it.


Qualifiers: What Happens When a Mechanism Matches?

Each mechanism can be prefixed with a qualifier symbol:

**+** = Pass : Authorized (this is the default — usually omitted) **-** = Fail : Hard reject — not authorized **~** = SoftFail : Probably not authorized — accept but flag **?** = Neutral : No opinion — treat like no SPF

In practice, you'll mainly use qualifiers on the all mechanism at the end of your record (not on individual mechanisms).


The all Mechanism — Your Catch-All Policy

all must always be the last thing in your SPF record. It applies to any sender not matched by your earlier mechanisms.

**~all** = SoftFail — Outlook and Gmail usually accept these but may junk them

**-all** = Hard fail —servers should reject unauthorized senders outright

**?all** = Neutral — no policy, not recommended

**+all** = Authorize everyone — never use this, it defeats the purpose of SPF

Which should you use? Start with ~all while you're verifying your setup. Once you're confident every legitimate sender is in the record, switch to -all. It's stricter and more protective against spoofing.

💡 Note: For -all to actually reject emails, the receiving server's DMARC policy also needs to be set to reject or quarantine. SPF alone doesn't enforce rejection — it just reports results. Learn how this works in our DKIM and email authentication guide.


Modifiers: Advanced Control

redirect= — Point to Another Domain's SPF

code
v=spf1 redirect=_spf.example.com

This replaces your entire SPF record with another domain's record. Useful if you manage SPF centrally for multiple domains. Important: you cannot use redirect= and all in the same record — it's one or the other.

exp= — Custom Error Messages

code
v=spf1 ip4:203.0.113.5 exp=explain.example.com ~all

Rarely used. Lets you provide a human-readable explanation when SPF fails. Most mail servers don't surface this to end users anyway.


Real SPF Record Examples

Google Workspace only

code
v=spf1 include:_spf.google.com ~all

Office 365 only

code
v=spf1 include:spf.protection.outlook.com ~all

Google Workspace + SendGrid (transactional email)

code
v=spf1 include:_spf.google.com include:sendgrid.net ~all

Self-hosted mail server with specific IPs

code
v=spf1 ip4:203.0.113.10 ip4:198.51.100.5 ~all

Mixed setup: dedicated IPs + cloud provider (strict)

code
v=spf1 ip4:203.0.113.0/24 ip6:2001:db8::/32 include:_spf.google.com include:sendgrid.net -all

What Real SPF Failures Look Like

When SPF syntax is broken, here's what you see in email headers:

Gmail → Outlook, broken SPF:

code
Received-SPF: permerror (google.com: permanent error in processing
during lookup of sender@yourdomain.com: too many DNS lookups)

Missing v=spf1:

code
Received-SPF: none (domain has no SPF policy)

Unauthorized sender (correct syntax, wrong IP):

code
Received-SPF: fail (yourdomain.com: domain of sender@yourdomain.com
does not designate 203.0.113.99 as permitted sender)

The difference matters: permerror = broken record. fail = valid record, wrong sender. none = no record exists. Each has a different fix.

🔧 See what your record actually returns: Use our SPF syntax checker to test your domain and get a parsed breakdown of every mechanism.


Common SPF Syntax Mistakes

Missing version tag include:_spf.google.com ~all

✔ Always start with v=spf1 — without it, the SPF record is invalid.

Invalid IP notation ip4:192.168.1

✔ Use proper CIDR format like ip4:192.168.1.0/24.

Wrong placement of all mechanism ~all include:google.com

✔ The all mechanism must always be at the end of the record.

Multiple SPF TXT records Two or more v=spf1 records on the same domain

✔ Merge everything into a single SPF record to avoid permerror.

Too many DNS lookups (over 10 limit) Excessive use of include, mx, or redirect

✔ Keep total DNS lookups under 10 or flatten SPF records.

Typo in mechanism name incldue:domain.com

✔ Always use correct spelling: include:domain.com.

Using +all (critical security risk) v=spf1 +all

✔ Never use this — it allows anyone to send email from your domain. Use ~all for testing or -all for strict protection.


How to Validate Your SPF Syntax Before Publishing

Don't guess — validate. Here are reliable tools:

  • Our SPF Record Checker — checks syntax, counts lookups, explains each mechanism
  • MXToolbox SPF Lookup — good for quick pass/fail results
  • Google Admin Toolbox — useful if you're troubleshooting Gmail specifically
  • dmarcian SPF Surveyor — visual tree of all your includes and sub-includes After you publish, send a test email to a Gmail or Outlook address, open the original message, and look for the Authentication-Results header. You want to see spf=pass.

SPF Is Only One Layer — Don't Stop Here

SPF tells the world which servers can send for your domain. But on its own, it doesn't protect the From: header that users actually see. That requires DKIM — a cryptographic signature attached to every email.

Together, SPF + DKIM + DMARC form a complete email authentication stack:

  • SPF → validates the sending server
  • DKIM → validates the message content hasn't been tampered with
  • DMARC → tells receivers what to do when SPF or DKIM fails If you've got SPF working correctly, your next step is setting up DKIM for your domain.

FAQ

What is an SPF record used for? An SPF record tells receiving mail servers which IP addresses and services are authorized to send email on behalf of your domain. It's a core part of email authentication and helps prevent spammers from spoofing your domain.

How many SPF records can I have per domain? Exactly one. RFC 7208 requires a single SPF TXT record per domain. If you have two, receiving servers return permerror and your emails may be rejected. See our guide on handling multiple SPF records.

What does ~all vs -all mean? ~all is a SoftFail — unauthorized senders are accepted but flagged. -all is a HardFail — receiving servers should reject unauthorized senders. Most domains start with ~all and move to -all once their setup is confirmed.

What is SPF permerror? permerror means the receiving server encountered a permanent error while evaluating your SPF record — usually a syntax error, too many DNS lookups (over 10), or duplicate SPF records. Read the full breakdown in our SPF permerror guide.

Is SPF required for email delivery? Not technically required, but practically essential. Without SPF, major providers like Gmail and Outlook will treat your emails with greater suspicion. Combined with DKIM and DMARC, SPF significantly improves your deliverability and protects your domain from spoofing.

What's the maximum number of DNS lookups allowed in SPF? 10. Every include:, a, mx, and redirect= counts toward this limit. ip4: and ip6: use zero lookups. Exceeding 10 causes an immediate permerror.


Quick Reference: SPF Syntax Cheatsheet

code
v=spf1                            ← Required — always first
  ip4:1.2.3.4                     ← Single IP (0 lookups)
  ip4:1.2.3.0/24                  ← IP range — 256 addresses (0 lookups)
  ip6:2001:db8::1                 ← IPv6 address (0 lookups)
  include:_spf.google.com         ← Third-party sender (1+ lookups)
  a                               ← This domain's A record (1 lookup)
  mx                              ← This domain's MX servers (1 lookup)
  redirect=_spf.example.com       ← Use another domain's SPF (no 'all')
  ~all                            ← SoftFail catch-all (end of record)
  -all                            ← HardFail catch-all (strict mode)

Lookup budget: You have 10. ip4: and ip6: are free. Everything else costs.


Conclusion

SPF syntax isn't complicated once you understand what each piece does. The version tag is mandatory, mechanisms define your authorized senders, qualifiers set the policy, and all closes the record.

The mistakes that actually break email delivery — duplicate records, too many lookups, invalid IPs — are all avoidable with a quick validation step before you publish.

🔧 Ready to check your record? Run it through our SPF record checker and get a clear diagnosis in seconds.