ZeroHookZeroHook
Back to Blog

SPF Record Syntax: Complete Reference

Every SPF mechanism, qualifier, and lookup limit explained with copy-paste examples for M365, Google Workspace, and ESP mail.

ZeroHook TeamJun 29, 2026~6 min read
SPF Record Syntax: Complete Reference

You copy an SPF record from a vendor doc. Paste it into DNS. Mail breaks the next morning. A 33-person fintech in Dublin added include:sendgrid.net to an already crowded TXT record in November 2025. The record looked valid in a basic TXT lookup. SPF evaluation returned permerror. DMARC failed on the SPF leg. Onboarding emails bounced at two banks' gateways. The include was syntactically fine. The total DNS lookup count was twelve. SPF (Sender Policy Framework) answers one question: is this IP address allowed to send mail claiming to be from this domain? The spf record syntax looks simple. One TXT string starting with v=spf1. Under the hood, receivers walk mechanisms left to right, chase DNS lookups, and stop hard at ten evaluations per RFC 7208. This guide is the complete reference we use before touching production DNS: every common mechanism, qualifier, modifier, failure mode, and the M365/Google/ESP patterns that actually work in 2026.

SPF Basics: What Gets Published Where

Record location

Publish SPF as a single TXT record on the domain that appears in the SMTP envelope-from (Return-Path), usually the root domain or a dedicated bounce subdomain.

Version token

Every record must start with v=spf1 followed by a space and one or more mechanisms. Only one SPF TXT per domain. Two records = permerror.

How receivers evaluate

Receiving MTAs fetch the TXT record, parse mechanisms in order, and match the connecting IP against each mechanism until one matches or the record ends with the default result from all.

SPF is not inbox placement

SPF pass authorizes an IP for the envelope domain. DMARC still requires alignment with the visible From: header. SPF pass alone does not guarantee inbox placement.

Mechanisms and Qualifiers (The Building Blocks)

Each mechanism can be prefixed with a qualifier. Default qualifier is + (pass), usually omitted.

QualifierMeaningExample
+ passMatch = authorizedip4:203.0.113.10
- failMatch = not authorized-all
~ softfailWeak fail~all
? neutralNo statementrare

Common mechanisms

  • ip4:203.0.113.0/24 — authorize IPv4 range
  • ip6:2001:db8::/32 — authorize IPv6 range
  • a — authorize A record IPs of current domain (1 lookup)
  • a:mail.example.com — authorize A record of named host (1 lookup)
  • mx — authorize MX host IPs of current domain (1+ lookups)
  • include:spf.protection.outlook.com — delegate to another SPF record (1 lookup + nested)
  • exists:macro — advanced, rare in SMB records
  • all — always matches; must be last mechanism

The all mechanism (non-negotiable on sending domains)

  • -all hard fail: unauthorized IPs should be rejected (use on production senders in 2026)
  • ~all softfail: weak signal; acceptable only during short migration windows
  • ?all neutral: useless for security
Pro Tip
If your record ends with +all, you have authorized the entire internet. Remove it immediately.
“SPF is a whitelist, not a suggestion. If you forget -all, you never finished the record.”

The 10 Lookup Limit (Where Records Go to Die)

RFC 7208 caps DNS lookups during SPF evaluation at ten. These mechanisms consume lookups:

  • include: (each one, plus whatever nested includes expand to)
  • a, mx, ptr, exists

Exceeding ten triggers permerror. Receivers treat the SPF result as broken. DMARC fails if you rely on SPF alignment.

Real-world stack that breaks

M365 (include:spf.protection.outlook.com) + Google (include:_spf.google.com) + Mailchimp + HubSpot + Zendesk + Salesforce + legacy ESP + mx + a on the same root domain often crosses ten without looking "too long" in the TXT field.

Fix strategies

  1. Remove dead includes from retired tools.
  2. Split mail streams: corporate on root, marketing on mail.domain.com with its own SPF and its own 10-lookup budget.
  3. SPF flattening (replace nested includes with IP lists) as last resort with documented maintenance.

Deep dive on permerror: zerohook.org/blog/spf-permerror-too-many-dns-lookups and zerohook.org/fix/spf-permerror

Modifiers: redirect and exp (Rare but Important)

redirect=

Delegates the entire SPF check to another domain's record. Example:

v=spf1 redirect=_spf.example.net

The evaluated domain must have no other mechanisms besides v=spf1 and redirect. Misuse causes permerror. Common on child domains managed by a parent.

exp=

Specifies a domain whose TXT provides an explanation if SPF fails. Almost never needed for SMB mail. If present, it consumes a lookup.

Most production records should use includes and -all, not redirect, unless your DNS architect documented why.

Copy-Paste Templates: Microsoft 365

M365 only (single path)

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

Publish at root yourdomain.com TXT if all mail flows through Microsoft 365.

M365 + one ESP

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

Replace Mailchimp include with your ESP's documented include host. Count nested lookups before publish.

Common M365 mistakes

  • Publishing SPF on the wrong domain (marketing subdomain sends but SPF only on root)
  • Forgetting to remove Google's include after migrating off Workspace
  • Leaving ~all because "it was recommended in 2018"

In Microsoft 365 admin, outbound mail uses Exchange Online IPs covered by spf.protection.outlook.com. Third-party connectors need their own includes.

Copy-Paste Templates: Google Workspace

Google Workspace only

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

Google + ESP

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

Verify SendGrid's current include string in their docs; includes change more often than you expect.

Subdomain sending

If marketing sends from news.yourdomain.com, publish a separate SPF on that subdomain. Do not keep stacking includes on root "because it is easier."

Syntax Errors That Cause PermError

  1. Multiple SPF TXT records on one name. Merge into one.
  2. Missing v=spf1 or typo v=spf1 with wrong spacing.
  3. Duplicate mechanisms that break parsers on strict receivers (rare but real).
  4. Empty include: or include pointing at a domain with no SPF.
  5. Lookup overflow from nested includes (most common in 2026).
  6. String splitting across multiple TXT strings incorrectly in DNS (some hosts concatenate; some do not).

Validate before and after every change at zerohook.org/spf-checker. Paste the full record in Validate mode, not just dig output with quotes mangled.

SPF vs. DMARC vs. DKIM (One Minute)

ProtocolQuestion it answers
SPFIs this IP allowed to use this envelope domain?
DKIMDid someone with the private key sign this message?
DMARCDoes the authenticated domain align with the From: header, and what should receivers do on failure?

SPF syntax mastery does not replace DKIM or DMARC. Gmail and Yahoo bulk sender rules expect all three in 2026. SPF permerror on root can still damage domain reputation even when DKIM passes on a subset of mail.

Frequently Asked Questions

Can I use both ~all and -all?

No. One all mechanism at the end. ~all and -all in the same record is invalid or undefined behavior depending on parser.

Does SPF apply to subdomains automatically?

No. Subdomains need their own TXT unless you use redirect= to a parent policy intentionally. mail.example.com does not inherit example.com SPF.

How fast do SPF changes propagate?

TTL-bound. Many teams see 15 minutes to 4 hours. Do not declare victory at 60 seconds.

Is SPF flattening compliant with audits?

It is a technical control if documented: who maintains IP lists, how updates happen when ESPs rotate IPs, review cadence. Undocumented flattening is a finding waiting to happen.

What is the difference between SPF and TXT for DKIM?

SPF lives on the envelope domain (often root). DKIM publishes on selector._domainkey.domain. Different records, different jobs. Do not merge them.

Key takeaways

1

One SPF TXT per domain, starting with v=spf1, ending with -all on production senders.

2

Count every include toward the 10 lookup cap, including nested expansion.

3

Use provider includes (M365, Google) plus ESP includes only when each path is live and owned.

4

Split high-volume marketing to subdomains when root SPF gets crowded.

5

Validate syntax and lookup count before and after every DNS edit.

Paste your record into zerohook.org/spf-checker to catch permerror and lookup overflow before your next DNS change reaches Gmail.

Share this analysis

Help others discover this content

About the author

ZeroHook Logo
ZeroHook Team
Security Analysts

The ZeroHook Team documents SPF and DKIM misconfigurations that still pass basic lookups but fail at Gmail and Microsoft 365.

Fix DNS before the next audit
Provider-specific copy-paste fixes for Cloudflare, Route53, GoDaddy, and more.
Start free scan