Consolidate into one record
Merge all v=spf1 entries, remove the old record. The DNS tool must return exactly one TXT with v=spf1 — anything else is a misconfiguration.
@ IN TXT "v=spf1 include:_spf.google.com include:sendgrid.net ~all"
Tool
See instantly whether your SPF record is syntactically correct and stays below the 10-lookup limit.
Permalink:?domain=… works too.
—
——
—
—
SPF (Sender Policy Framework) is the oldest of the three email authentication standards and answers a single question: which servers are allowed to send mail on behalf of your domain? The mechanism is straightforward — a TXT record on the domain lists allowed IPs, IP ranges or references to other SPF records (includes), and closes with an all-directive defining what should happen to non-listed senders.
For every mail, receiving servers check the Return-Path domain (envelope-from) against the SPF record found there. If the sending IP isn't on the allowed list, the all-directive kicks in: -all means hardfail (reject), ~all softfail (mark as suspicious), ?all neutral, +all allows everything — the last one makes the record practically worthless.
The most important technical limit is the 10-DNS-lookup ceiling from RFC 7208: each include:, a:, mx:, ptr: and exists: counts as a lookup. Anyone going over 10 fails with PermError, and SPF is treated as unevaluated — dangerous, because DMARC then fails too. With many marketing and CRM tools this limit is exceeded quickly.
The RFC allows exactly one TXT with v=spf1. Two records → PermError, receivers ignore both. Common after a provider switch or acquisition — remove the old record, consolidate all includes into one.
Each include:, a:, mx: counts — transitively too. Marketing tool, CRM, ticketing, newsletter service: quickly at 12 lookups. Result: PermError, SPF is treated as failed, DMARC fails along with it.
Softfail only flags suspicious mail but doesn't reject it. For serious anti-spoofing protection, -all is required. ~all only makes sense as a transition step, not as the end state.
New sending provider rolled out, SPF not updated: their mail lands in spam. SPF must be kept current with every provider change — best maintained as an inventory list in IT.
include: without subdomain coverageSPF only applies to the exact domain, not to subdomains. news.example.com needs its own SPF record — otherwise it counts as unauthorized as soon as receivers ask for it.
redirect= used incorrectlyredirect= replaces the entire record and only takes effect when no mechanisms precede it. include:, on the other hand, supplements. Confusion leads to unexpected behavior — almost always include: is the right choice.
Mailchimp, Sendgrid, Mailgun — all have changed their include hosts over the past years. If you don't replace the old include:, you have dead references in the record and waste lookups.
Merge all v=spf1 entries, remove the old record. The DNS tool must return exactly one TXT with v=spf1 — anything else is a misconfiguration.
@ IN TXT "v=spf1 include:_spf.google.com include:sendgrid.net ~all"
Check the lookup counter online. If over 10: drop unused includes, or use a flattening service that replaces include: with concrete IP ranges — with automatic updates on provider changes.
Once you're confident that all legitimate senders are in the record: replace ~all with -all. Receivers now strictly reject any unauthorized mail.
@ IN TXT "v=spf1 include:_spf.google.com include:sendgrid.net -all"
SPF alone doesn't show who violates the policy. With DMARC p=none + rua=mailto:… you get daily reports on pass/fail per IP — the data foundation for any SPF optimization.
The full SelfCheck additionally tests SPF/DKIM/DMARC, BIMI, MTA-STS, TLS-RPT, DNSSEC and MX in a single run.
Start full SelfCheck →include:, a:, mx:, ptr: and exists: counts as a DNS lookup. SPF allows a maximum of 10 lookups per evaluation — beyond that the receiver returns PermError and treats SPF as failed.-all or ~all?-all (hardfail) is stricter and instructs receivers to reject unauthorized mail. ~all (softfail) only flags it as suspicious. For production domains, -all is the right choice once the sender list is complete.v=spf1 per domain. Two records cause PermError; receivers ignore both. Consolidate all includes into a single record.include: references with the actual IP ranges to stay below the 10-lookup limit. Caution: when provider IPs change, you have to update the record manually — automated flattening services help here.~all (softfail), enable DMARC with p=none + rua, and evaluate the aggregate reports for 1–2 weeks. Once all legitimate sources are aligned, switch to -all.