SPF ~all vs -all: Softfail or Hardfail in 2026?
Every SPF record ends with an all mechanism, and the character in front of it is probably the most debated character in email authentication. Should your record end in ~all (softfail) or -all (hardfail)?
The short answer for 2026: if your domain sends email and you run DMARC, use ~all. If your domain never sends email, use -all. The longer answer explains why the stricter looking option is not automatically the safer one, and why neither matters if your SPF record is broken.
The four qualifiers at a glance
| Ending | SPF result | What it says | Typical receiver behavior |
|---|---|---|---|
+all | pass | Every server on the internet may send as you | Accepts everything. Never use this. |
?all | neutral | No statement about unlisted servers | Treated much like having no SPF policy |
~all | softfail | Unlisted servers are probably not authorized | Accepts the message, may add spam weight, lets DKIM and DMARC decide |
-all | fail | Unlisted servers are not authorized | May reject during the SMTP conversation |
The qualifier only applies to mail from servers that did not match anything earlier in the record. Mail from your listed ip4:, ip6: and include: sources gets pass, no matter how the record ends.
What softfail and hardfail mean on paper
RFC 7208 defines fail as an explicit statement that the sending host is not authorized to use the domain. softfail is a weaker statement: the host is probably not authorized, but the domain owner does not want to make a strong claim. Neither result tells a receiver exactly what to do. That is left to local policy, and receivers differ.
Without DMARC, that difference matters, because the qualifier is the only policy signal you send. With DMARC, the picture changes completely.
Why DMARC makes the qualifier matter less
DMARC does not care how SPF failed. It asks one question about SPF: did it pass, with a domain aligned to the From: header? Softfail, fail and neutral are all simply "not a pass".
So with DMARC at p=reject:
~allwith DMARCp=reject: spoofed mail is rejected.-allwith DMARCp=reject: spoofed mail is rejected.
The protection against spoofing is the same. Enforcement lives in your DMARC policy, not in the last four characters of your SPF record. (New to alignment? Read SPF vs DKIM vs DMARC first.)
The real risk of -all: rejection before DMARC runs
Some receivers check SPF as soon as the sending server issues MAIL FROM, before the message itself has arrived. If your record says -all and the sending IP is not listed, they can reject right there. DKIM is never verified and DMARC never runs.
The DMARC specification warns about exactly this. RFC 7489 (section 10.1) points out that a -all can cause rejection early in handling, before any DMARC processing takes place.
That hurts in the situations where DMARC would have saved the message:
- Forwarding. A recipient forwards your mail from an old address, or a mailing list relays it. The forwarding server is not in your SPF record, so SPF fails. DKIM would still have passed and aligned, but the message was already bounced.
- A sender nobody told you about. Marketing starts using a new platform that signs with DKIM but is not in your SPF record yet. With
~all, DMARC passes on DKIM. With-all, some receivers bounce it. - Stale IP lists. A provider adds sending ranges and your hand-flattened record does not include them yet.
This is why M3AAWG (the Messaging, Malware and Mobile Anti-Abuse Working Group) recommends ~all for domains that send email in its Email Authentication Recommended Best Practices.
Which one should you use?
| Your situation | Recommended ending |
|---|---|
Domain sends email, DMARC at p=quarantine or p=reject | ~all |
Domain sends email, DMARC at p=none or not set up yet | ~all, and make DMARC enforcement your next step |
| Changing providers and not sure you know every sender | ~all until your DMARC reports are clean |
| Domain never sends email (parked, brand protection) | v=spf1 -all |
For a domain that never sends email, lock it down completely:
example.com. TXT "v=spf1 -all"
_dmarc.example.com. TXT "v=DMARC1; p=reject"
example.com. MX 0 .
The last line is a null MX (RFC 7505): the domain does not accept mail either. Here -all has no downside, because there is no legitimate mail to lose.
~all to -all. It is ~all, plus aligned DKIM for every sender, plus DMARC at p=reject. That combination blocks spoofing and still lets forwarded, DKIM signed mail through.Neither one helps if SPF is broken
All of this assumes SPF actually gets evaluated. If your record needs more than 10 DNS lookups, the check stops with a PermError before it ever reaches all. Your carefully chosen qualifier is never read, and for DMARC the result is simply that SPF did not pass.
The same goes for two SPF records on one domain, a syntax error, or too many void lookups. Before you debate ~all versus -all, make sure the record works:
- What SPF lookups actually count (and what doesn't)
- How to Fix SPF PermError in 2026
- SPF Flattening Explained
With spFlat! your record becomes one short spFlat! include. spFlat! suggests ending it with ~all, in line with the advice above, and keeps the IP list behind that include current. The record itself lives in your own DNS, so for a domain where you deliberately want -all, you can still change the ending yourself. Because the IP list stays current, the stale list problem that makes -all risky on hand-flattened records also goes away.
Before you change the qualifier
- Check that your SPF record evaluates without errors and stays under 10 lookups.
- Confirm every sending service signs with DKIM, aligned to your domain.
- Read your DMARC aggregate reports for a few weeks and look for legitimate sources that fail SPF.
- Move DMARC to
p=quarantine, then top=reject. - Only then decide on the qualifier. For most sending domains,
~allstays.
Summary
~allfor domains that send email,-allfor domains that never do.- With DMARC enforced, softfail and hardfail give the same protection against spoofing.
-allcan cause rejection before DKIM and DMARC run, which breaks forwarded mail.- A PermError makes the whole question irrelevant. Fix the record first.
Check your SPF record first
Free, no signup. See your evaluated DNS lookup count (including nested includes) and whether a PermError occurs right now.
Check Your SPFOr start your free 14-day trial →
