← Back to Learning Hub

Email Delivery • Intermediate • 5 min read

SPF ~all vs -all vs ?all: Softfail, Hardfail, and Neutral

What each SPF qualifier tells a receiver, why ~all is the safe default while testing, when to move to -all, and how DMARC changes what all really does.

Every SPF record ends with some form of the all mechanism, and the single character in front of it decides how a receiver treats mail that was not sent by any of your authorized sources. The choice between ~all, -all, and ?all is the most consequential part of an SPF record, because it is the catch-all verdict for everything your record did not explicitly permit. Get it wrong one way and spoofed mail sails through; get it wrong the other way and your own legitimate mail gets rejected. Here is exactly what each qualifier means and how to choose.

How SPF evaluation reaches "all"

An SPF record is a single TXT record read left to right. Each term is a mechanism that may carry a qualifier, and the receiver checks the sending server's IP against each mechanism in turn. The first mechanism that matches decides the result. The all mechanism at the end always matches, so it is the default verdict for any sender that did not match an earlier include, a, mx, or ip4/ip6 term.

$ dig TXT example.com +short
"v=spf1 include:_spf.google.com ip4:198.51.100.10 ~all"

In this record, a server inside Google's ranges or at 198.51.100.10 matches and passes. Anything else falls through to ~all, whose qualifier decides the outcome.

The four qualifiers

Four qualifier characters can prefix any mechanism, including all. A plus is the default and is almost always omitted.

QualifierNameSPF resultMeaning on all
+PasspassAllow everything (never use on all)
~SoftfailsoftfailProbably unauthorized, accept but mark
-FailfailUnauthorized, reject or discard
?NeutralneutralNo assertion, treat as if no SPF

Softfail: ~all

Softfail tells the receiver that a message from an unlisted server is probably not legitimate, but to accept it anyway, usually with a note in the headers or a small spam-score penalty. It is the safe default while you are building or auditing your SPF record, because a source you forgot to list will still get through rather than bouncing. Most receivers treat softfail as a mild negative signal, not a reason to reject on its own.

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

Hardfail: -all

Hardfail is an explicit instruction: any server not listed is not authorized, and the receiver should reject or silently drop the message. This is the strongest protection against someone spoofing your domain, and it is where you want to end up once you are certain every legitimate sender is covered. The risk is real, though. If a marketing platform, help desk, invoicing tool, or someone's forwarding setup sends as your domain and is not in the record, hardfail can cause that mail to be rejected outright.

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

Neutral: ?all

Neutral makes no claim at all about unlisted senders. The result is treated essentially the same as having no SPF record, so it offers no protection. It exists mainly for domains in a transitional state or for publishers who want to declare known-good sources without making any assertion about the rest. In practice there is rarely a good reason to end a real record with ?all; if you are not ready for hardfail, softfail is the better waypoint.

Why +all is dangerous

A record ending in +all passes every sender in the world, which means anyone can spoof your domain and pass SPF. It completely defeats the purpose of publishing SPF. It almost always appears by accident, usually from a copy-paste error, and it should never be used deliberately.

The recommended progression

The safe way to deploy SPF is to start permissive and tighten as your confidence grows, watching DMARC reports at each step to catch sources you missed.

StageRecord endingWhen to use it
Build and audit~allWhile confirming every legitimate source is listed
Monitor~all with DMARC p=noneCollect reports to find unlisted senders
Enforce-allOnce reports show only authorized sources

How DMARC changes what "all" really does

Here is the part that surprises people: once you publish DMARC, the practical difference between ~all and -all shrinks, because DMARC does not care which of the two you chose. DMARC looks at whether SPF produced a pass that is aligned with the visible From domain, and it treats softfail and hardfail identically as a non-pass. The policy in your DMARC record, not the qualifier on all, then decides whether unaligned mail is quarantined or rejected.

That has two consequences. First, with DMARC enforcing, you can safely leave SPF at ~all and let DMARC do the rejecting, which avoids the edge case where a receiver rejects on SPF hardfail before DMARC's alignment logic even runs. Second, SPF hardfail still matters for the minority of receivers that act on SPF alone and do not implement DMARC. Many operators keep -all for that coverage while relying on DMARC for the aligned-identity enforcement.

$ dig TXT _dmarc.example.com +short
"v=DMARC1; p=reject; aspf=s; rua=mailto:dmarc@example.com"

One catch: redirect has no all

There is one structural case where all disappears. The redirect modifier hands the entire SPF decision to another domain's record, and when you use it you must not also include an all mechanism, because the redirected-to record supplies its own final verdict. Mixing redirect with all in the same record makes all win and the redirect pointless. If you manage SPF for many domains from one place, this is how you centralize the policy, and the qualifier that matters then lives in the target record, not yours.

v=spf1 redirect=_spf.example-corp.com

Quick checklist

  1. Keep exactly one SPF record, under the 10-lookup limit.
  2. Start with ~all while you enumerate every sender.
  3. Publish DMARC at p=none and read the reports to find anything missing.
  4. Move to -all once the reports are clean, or stay at ~all and let DMARC enforce.
  5. Never publish +all.

Verify the qualifier that is actually live

A one-character typo at the end of your SPF record changes your entire anti-spoofing posture, and a local lookup only shows one resolver's cached copy. After any change, run your domain through the Valla DNS propagation checker to confirm the exact record, including its final qualifier, has gone live everywhere. When you are ready to tighten enforcement, our guides on the DMARC policy ramp and on the SPF 10-lookup limit will help you move from softfail to a confident hardfail without losing a single legitimate message.

Troubleshooting box

If results look inconsistent, compare authoritative nameservers first, then recursive resolvers by region. Capture snapshots every 10 minutes for deterministic incident timelines.

Try VallaDNS free →