SPF Qualifiers Explained: The Four RFC 7208 Section 4.6.2 Qualifiers (+ Pass, - Fail, ~ SoftFail, ? Neutral) with a Receiver-Side Interpretation Matrix

A focused per-qualifier dimensional analysis of the four SPF qualifiers defined by RFC 7208 section 4.6.2: + (Pass, the default qualifier producing spf=pass when a sender matches), - (Fail, producing spf=fail with optional SMTP rejection per §4.7), ~ (SoftFail, producing spf=softfail as a weak unauthorised signal), and ? (Neutral, producing spf=neutral equivalent to no SPF record). Each qualifier is presented with the canonical Definition / Syntax / Receiver behaviour / When to use / When NOT to use / Common pitfalls structure, plus a side-by-side comparison table, a receiver-side interpretation matrix showing how Gmail / Microsoft 365 / Yahoo / Apple iCloud actually treat each result code, four worked deployment examples covering production / deployment monitoring / null-sender / vendor deprecation scenarios, and the seven most common qualifier-choice mistakes. For operators answering "should I use -all or ~all", "is +all dangerous", "what does spf=softfail mean", or "how do I migrate from ~all to -all safely" — every situation where the SPF qualifier choice matters.

This reference is provided in English. SPF is specified in an English-language RFC (RFC 7208 section 4.6.2) and the canonical qualifier vocabulary (Pass, Fail, SoftFail, Neutral) does not translate. We keep the body in the source language so technical terms remain consistent with the specification.

TL;DR

The four SPF qualifiers (RFC 7208 section 4.6.2) determine the receivers result code when a mechanism matches. Each qualifier is a single-character prefix on a mechanism token:

  • + (Pass) — default qualifier when none is specified. Produces spf=pass. Receiver treats the sender as authorised.
  • - (Fail) — strong unauthorised signal. Produces spf=fail. Receiver may reject, discard, or quarantine per RFC 7208 §4.7. Use -all in production for any domain with a complete sender inventory.
  • ~ (SoftFail) — weak unauthorised signal. Produces spf=softfail. Receiver should not reject solely on SoftFail. Use ~all only during initial deployment as a monitoring-mode placeholder.
  • ? (Neutral) — no definitive statement. Produces spf=neutral, treated equivalent to no SPF record. Rarely the right choice; avoid ?all in production.

The qualifier almost always attaches to the terminal all mechanism — and -all is the canonical production answer. The default Pass qualifier (implicit when no prefix is written) is what makes ip4:198.51.100.42 identical to +ip4:198.51.100.42. The Domain Security Checker surfaces your records terminal qualifier and flags suboptimal choices like +all (authorises everything) or ?all (no enforcement value).

1. What SPF qualifiers are and where they appear

A qualifier in an SPF record is a single-character prefix that determines the result code the receiver returns when a sender matches the qualified mechanism. The four qualifiers defined in RFC 7208 section 4.6.2 are:

  • + → Pass (the default; produces spf=pass)
  • - → Fail (produces spf=fail)
  • ~ → SoftFail (produces spf=softfail)
  • ? → Neutral (produces spf=neutral)

The qualifier attaches to any mechanism token — ip4, ip6, a, mx, ptr, include, exists, or all. In practice the qualifier other than + is overwhelmingly used on the terminal all mechanism to express "what should the receiver do with anything not matched by an earlier mechanism." Per-mechanism qualifiers other than + are rare but legal: -include:ex-vendor.example is valid SPF that says "treat any match in the ex-vendors include subtree as Fail."

Why qualifiers matter: the qualifier is the policy signal SPF gives to the receiver. A sender that produces spf=fail tells the receiver "I know this is unauthorised — act on it." A sender that produces spf=softfail tells the receiver "I think this is unauthorised but do not act on this alone." A sender that produces spf=neutral tells the receiver "I have no opinion." DMARC consumes these results when determining alignment, so the qualifier choice indirectly affects DMARC enforcement.

Scope note: this page covers the four qualifiers in depth. The mechanism vocabulary (a, mx, include, ip4, ip6, ptr, exists, all) and the modifiers (redirect=, exp=) are covered in the comprehensive SPF mechanisms explained reference.

2. The four qualifiers at a glance

Side-by-side comparison of the four SPF qualifiers (RFC 7208 section 4.6.2). The result code is what the receiver returns in the Authentication-Results header when a sender matches the qualified mechanism.

+ / - / ~ / ? — RFC 7208 section 4.6.2 SPF qualifiers compared
Qualifier Result code Default? Receiver action (typical) Canonical use case
+ Pass (spf=pass) Yes (default when no qualifier specified) Treat sender as authorised; deliver normally Implicit on every listed mechanism; +all almost always a misconfiguration
- Fail (spf=fail) No May reject at SMTP, discard, or quarantine per RFC 7208 §4.7 -all in production for any domain with complete sender inventory
~ SoftFail (spf=softfail) No Record result; typically do NOT reject; weight other signals (DKIM, reputation, DMARC) ~all during initial 30-90 day SPF deployment monitoring
? Neutral (spf=neutral) No Treat equivalent to no SPF record; rarely actionable on its own Rare; avoid ?all in favour of -all with explicit sender inventory

3. The + (Pass) qualifier (RFC 7208 §4.6.2)

Definition: The plus qualifier (+) marks a mechanism as producing the Pass result code when the sender matches. Pass means the receiver should treat the sender as authorised by the domains SPF policy. Pass is the default qualifier when no prefix is specified on a mechanism.

Syntax: +<mechanism> or simply <mechanism> with no prefix (the two forms are byte-equivalent at the receiver). So +ip4:198.51.100.42 and ip4:198.51.100.42 produce identical behaviour; +include:_spf.google.com and include:_spf.google.com are identical. The terminal +all is legitimately distinct (and almost always a misconfiguration — see below).

Receiver behaviour: A sender that matches a +-qualified mechanism causes the receiver to record Received-SPF: pass and spf=pass in the Authentication-Results header (RFC 8601). The receiver treats the SPF check as successful. For DMARC purposes, Pass also enables the SPF half of DMARC alignment (the SPF-authenticated MAIL FROM domain is checked for alignment with the From: header domain per RFC 7489).

When to use: The implicit Pass qualifier applies to every explicitly listed mechanism in your SPF record — ip4:198.51.100.42, include:spf.protection.outlook.com, a:mail.example.com, mx. You do not need to write the + prefix; the default is Pass. The explicit + prefix is useful only when you want to be unambiguous in documentation or when a tool auto-generates SPF records and wants explicit qualifiers throughout.

When NOT to use: Do NOT use +all at the end of an SPF record — it authorises EVERY IP address on the internet to send mail as your domain. This is the most-warned-against SPF anti-pattern: it defeats SPF entirely, provides zero protection against spoofing, and effectively declares your domain open for impersonation. Always terminate the record with -all (strict enforcement, recommended) or ~all (monitoring mode, during deployment).

Common pitfalls: (1) Copy-pasting +all from an outdated tutorial — replace with -all immediately. (2) Treating the explicit + prefix as somehow different from the implicit default — they are byte-equivalent at the receiver. (3) Writing +ip4:0.0.0.0/0 "to authorise everything" — equivalent to +all and equally catastrophic. (4) Confusing per-mechanism + (harmless explicit-default) with terminal +all (catastrophic open-relay semantic).

4. The - (Fail) qualifier (RFC 7208 §4.6.2)

Definition: The minus qualifier (-) marks a mechanism as producing the Fail result code when the sender matches. Fail means the receiver should treat the sender as explicitly unauthorised by the domains SPF policy. RFC 7208 section 4.7 allows the receiver to reject at SMTP, discard, or quarantine, though the standard does not mandate any specific action.

Syntax: -<mechanism>. The two canonical usages: (a) -all at the end of the record (Fail anything not previously matched), and (b) per-mechanism -include:ex-vendor.example or -ip4:<range> to revoke a specific senders authorisation while keeping the rest of the record permissive.

Receiver behaviour: A sender that matches a --qualified mechanism causes the receiver to record Received-SPF: fail and spf=fail in the Authentication-Results header. Per RFC 7208 §4.7, the receiver MAY reject the SMTP transaction with a 550 5.7.1 response, MAY quarantine to a spam folder, or MAY deliver with the Fail result recorded for downstream filtering. Major receivers (Gmail, Microsoft 365, Yahoo, Apple iCloud) typically combine spf=fail with DMARC enforcement: if DMARC is p=reject and SPF fails, the message is rejected; if DMARC is p=none and SPF fails, the message is usually delivered with spf=fail recorded.

When to use: Use -all in production for any domain with a complete sender inventory. This is the canonical production answer and the recommended end-state of every SPF deployment. Also use per-mechanism - for: (a) revoking an ex-vendors authorisation while keeping their include subtree visible (-include:ex-vendor.example), (b) explicitly blocking a known-bad IP range while permitting the rest of a CIDR (-ip4:198.51.100.42 ip4:198.51.100.0/24 — note first-match-wins means the more specific Fail wins).

When NOT to use: Do NOT use -all until you have confirmed every legitimate sender is listed in the record — switching to -all with a missing sender will cause that senders mail to be rejected. Do NOT use -all if you have not enabled DMARC aggregate reporting (rua=) to surface unexpected rejections. Do NOT use -all on a domain whose sender inventory is volatile (frequent vendor adds/removes) — stay on ~all until inventory stabilises.

Common pitfalls: (1) Flipping to -all before completing sender discovery — breaks legitimate mail. (2) Combining -all with an incomplete include tree (the include resolves but lacks the actual sending IPs — every message Fails). (3) Forgetting that -all only affects senders NOT matched by an earlier mechanism; a stale +include:ex-vendor.example still authorises that vendors infrastructure regardless of the terminal -all. (4) Expecting -all alone to enforce rejection without DMARC — many receivers tolerate spf=fail unless DMARC also says reject. (5) Writing --all (typo) — the second minus is parsed as part of a malformed mechanism and the record is invalid.

5. The ~ (SoftFail) qualifier (RFC 7208 §4.6.2)

Definition: The tilde qualifier (~) marks a mechanism as producing the SoftFail result code when the sender matches. SoftFail means "the domain believes the sender is probably unauthorised but is not willing to make a strong policy statement." RFC 7208 section 4.6.2 explicitly defines SoftFail as a weaker signal than Fail; receivers should record the result but not reject solely on this signal.

Syntax: ~<mechanism>. The overwhelmingly common usage is ~all at the end of an SPF record. Per-mechanism SoftFail (~include:soon-to-be-removed.example or ~ip4:<deprecating-range>) is rare but legal — useful as a transition state when deprecating a sender without immediate hard-fail.

Receiver behaviour: A sender that matches a ~-qualified mechanism causes the receiver to record Received-SPF: softfail and spf=softfail in the Authentication-Results header. Most receivers (Gmail, Microsoft 365, Yahoo) treat SoftFail as a non-pass signal but do not reject solely on this result. The practical delivery effect is typically: the message is delivered (often to the inbox if other signals are good) with spf=softfail recorded. DMARC counts SoftFail as a non-pass for the SPF half of alignment, so DMARC enforcement may still fire if DMARC is at quarantine or reject.

When to use: Use ~all during the initial 30-90 day SPF deployment window when you are still discovering legitimate senders. The SoftFail signal lets DMARC aggregate reports surface unexpected senders without breaking their delivery while you complete the inventory. Once 30 consecutive days show zero unexplained SoftFails for legitimate sources, flip to -all for production enforcement. Per-mechanism ~ is useful during a sender deprecation: flag the soon-to-be-removed mechanism with ~ for two weeks, monitor for any remaining legitimate traffic, then remove.

When NOT to use: Do NOT use ~all indefinitely in production — it provides weak enforcement and signals to spoofers that your domain is not seriously protected. Do NOT use ~all as a permanent fixture on a domain at DMARC p=reject — the combination is incoherent (DMARC reject says "reject the message" but SPF SoftFail says "do not reject solely on this"; you want SPF Fail + DMARC reject for consistent semantics). Do NOT use ~all if your domain sends no mail (use v=spf1 -all instead, the null-sender canonical form).

Common pitfalls: (1) Leaving ~all in place indefinitely after initial deployment — the canonical SPF deployment ramp is ~all → -all over 30-90 days. (2) Expecting SoftFail to cause rejection at SMTP — most receivers deliver SoftFailed mail. (3) Pairing ~all with DMARC p=reject — incoherent policy signal; pair -all with DMARC p=reject instead. (4) Using ~all on a domain whose sender inventory is supposedly complete — flip to -all and let aggregate reports flag any missed senders. (5) Misreading the tilde as a no-op — SoftFail does affect DMARC alignment computation even if it does not affect SMTP-time delivery.

6. The ? (Neutral) qualifier (RFC 7208 §4.6.2)

Definition: The question-mark qualifier (?) marks a mechanism as producing the Neutral result code when the sender matches. Neutral means "the domain has explicitly declined to make a statement about this sender." RFC 7208 section 4.6.2 defines Neutral as equivalent to "no SPF record found" for the matching senders — the receiver should treat it the same as if SPF were not deployed at all.

Syntax: ?<mechanism>. The overwhelmingly rare canonical form is ?all at the end of an SPF record. Per-mechanism Neutral (?include:unverified.example) exists in the spec but has essentially no production use case — most operators reach for SoftFail or Fail instead.

Receiver behaviour: A sender that matches a ?-qualified mechanism causes the receiver to record Received-SPF: neutral and spf=neutral in the Authentication-Results header. The receiver treats the result as equivalent to no SPF record — the message is delivered, but SPF provides no positive or negative signal. DMARC counts Neutral as a non-pass for SPF alignment, so the DMARC verdict depends entirely on DKIM (which must pass and align for the message to pass DMARC).

When to use: Almost never. The canonical use case sometimes cited is a parent domain whose subdomains have their own SPF records and the parent itself sends no mail — but even there, the more correct answer is v=spf1 -all (explicit "no senders authorised, reject any direct send from the parent domain"). The Neutral qualifier exists in the spec for completeness and to give operators a way to publish a record that intentionally provides no enforcement signal — but in practice this is rarely the right answer.

When NOT to use: Do NOT use ?all as a "weak default" — if you want weak enforcement, use ~all instead (SoftFail at least signals non-pass; Neutral signals nothing). Do NOT use ?all on a domain that sends mail — it tells receivers nothing about your sending posture and weakens DMARC alignment. Do NOT use ?all as a placeholder during SPF deployment — use ~all with DMARC rua reporting instead.

Common pitfalls: (1) Treating ?all as equivalent to "I have not decided yet" — receivers cannot distinguish intentional Neutral from accidental Neutral, and you get zero protective value either way. (2) Confusing ?all with "the safe choice" — it is strictly weaker than ~all which is strictly weaker than -all; moving down the ladder removes protection. (3) Inheriting ?all from a copy-pasted template and never revisiting — audit your SPF records quarterly and replace any ?all with -all (or ~all if still in deployment monitoring). (4) Using ?all on a null-sender parking domain — use v=spf1 -all for the canonical "this domain does not send mail" semantic.

7. Receiver-side interpretation matrix

How major receivers actually treat each SPF result code in 2026, based on observable Authentication-Results headers, public documentation, and DMARC enforcement behaviour. Specific SMTP-time rejection behaviour depends on per-tenant policy and may vary.

Receiver-side SPF qualifier interpretation — Gmail / Microsoft 365 / Yahoo / Apple iCloud
Receiver + (Pass) - (Fail) ~ (SoftFail) ? (Neutral)
Gmail / Google Workspace spf=pass; DMARC alignment proceeds spf=fail; DMARC reject fires if p=reject; otherwise delivered with spf=fail recorded spf=softfail; usually delivered; non-pass for DMARC spf=neutral; delivered; non-pass for DMARC; relies on DKIM
Microsoft 365 / Outlook.com spf=pass; Defender chain proceeds spf=fail; reject at SMTP if DMARC p=reject; otherwise to Junk/Quarantine spf=softfail; usually delivered; SCL bump possible spf=neutral; treated as no SPF; DKIM/DMARC determine
Yahoo Mail / AOL spf=pass; DMARC alignment proceeds spf=fail; reject if DMARC p=reject; otherwise spam folder spf=softfail; usually delivered; reputation-weighted spf=neutral; treated as no SPF
Apple iCloud Mail spf=pass; alignment proceeds spf=fail; combine with DMARC for final disposition spf=softfail; usually delivered spf=neutral; non-pass for DMARC

Key takeaways:

  1. Fail (-) is necessary but not sufficient for rejection. Most receivers only reject spf=fail when DMARC is also at p=quarantine or p=reject. SPF Fail alone usually results in delivery-to-spam, not rejection.
  2. SoftFail (~) is almost always delivered. The qualifier signals "probably not legitimate" but receivers do not act on it alone. SoftFail mainly affects DMARC alignment (counts as non-pass) and downstream reputation scoring.
  3. Neutral (?) provides no protective value. Receivers treat it equivalent to no SPF record; the only way to pass DMARC for a Neutral-qualified sender is via DKIM.
  4. Pass (+) enables DMARC alignment. Without Pass on the connecting senders mechanism, DMARC must rely on DKIM to pass — a single point of failure if DKIM also fails (e.g. message forwarded and body modified).

8. Four worked deployment examples

8.1 Production: complete inventory with hard fail

Scenario: a company has audited every legitimate sender (Microsoft 365 for corporate mail, SendGrid for transactional, on-prem MTA at 198.51.100.42 for monitoring alerts) and is ready for strict enforcement.

example.com.  IN  TXT  "v=spf1 ip4:198.51.100.42 include:spf.protection.outlook.com include:sendgrid.net -all"

Rationale: -all declares Fail for any sender not matched above. The complete sender inventory protects legitimate mail; spoofing attempts return spf=fail and (paired with DMARC p=reject) are rejected. This is the canonical production end-state for any DMARC-enforcement-bound domain.

8.2 Deployment monitoring: ~all with DMARC rua

Scenario: a company is rolling out SPF for the first time. They have published an initial sender list but want 60 days of aggregate reports to surface any missed senders before switching to strict enforcement.

example.com.  IN  TXT  "v=spf1 ip4:198.51.100.42 include:spf.protection.outlook.com include:sendgrid.net ~all"
_dmarc.example.com.  IN  TXT  "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"

Rationale: ~all returns SoftFail for unmatched senders — they are still delivered (so legitimate-but-missed mail does not break) but the SoftFail result is logged in the receivers Authentication-Results header and surfaces in the DMARC aggregate reports. After 60 days of clean reports (no SoftFail for legitimate sources), flip ~all to -all and DMARC p=none to p=quarantine.

8.3 Null-sender domain (no mail expected)

Scenario: a parked domain or apex-only domain that sends no mail (e.g. example-brand.com whose only use is the marketing website — no transactional mail, no corporate mail, no automation alerts).

example-brand.com.  IN  TXT  "v=spf1 -all"

Rationale: -all with no preceding mechanisms declares "no IP is authorised to send mail as this domain." Any spoofing attempt returns spf=fail. Pair with DMARC p=reject for explicit rejection. Do NOT use v=spf1 ?all (Neutral, no enforcement) or v=spf1 ~all (SoftFail, weak enforcement) for a null-sender domain — the canonical answer is v=spf1 -all.

8.4 Vendor deprecation: per-mechanism SoftFail

Scenario: a company is migrating off SendGrid to Mailgun. They want SendGrid traffic to start SoftFailing immediately to surface any forgotten integrations, while keeping Mailgun fully authorised.

example.com.  IN  TXT  "v=spf1 ip4:198.51.100.42 include:spf.protection.outlook.com include:mailgun.org ~include:sendgrid.net -all"

Rationale: the per-mechanism ~include:sendgrid.net returns SoftFail for any sender that matches the SendGrid include subtree — the message is still delivered but the spf=softfail result surfaces in DMARC aggregate reports. After two weeks of clean reports (no legitimate SendGrid traffic remaining), remove the ~include:sendgrid.net entirely; the terminal -all then Fails any remaining SendGrid traffic.

9. The seven most common qualifier-choice mistakes

  1. Using +all in production. Authorises every IP on the internet to send mail as your domain; defeats SPF entirely. Almost always a copy-paste error from an outdated tutorial. Fix: replace with -all (recommended) or ~all if still in deployment monitoring.
  2. Leaving ~all indefinitely after initial deployment. SoftFail is a deployment-monitoring state, not a production end-state. Spoofers learn that your domain is not under strict enforcement. Fix: after 30-90 days of clean aggregate reports, flip ~all to -all.
  3. Using ?all for "soft enforcement". Neutral provides ZERO protective signal — receivers treat it equivalent to no SPF record. Strictly weaker than ~all for the same scenario. Fix: replace with ~all (during deployment) or -all (in production).
  4. Omitting the terminal qualifier entirely. A record like v=spf1 ip4:198.51.100.42 with no terminal all clause has an implicit Neutral terminal per RFC 7208 — provides zero enforcement for unmatched senders. Fix: always end the record with an explicit qualified all token (-all, ~all, or rarely ?all).
  5. Pairing ~all with DMARC p=reject. Incoherent policy: SPF says "do not reject solely on this" but DMARC says "reject the message." The DMARC reject still fires (DMARC is the controlling policy) but the qualifier mismatch suggests confused operator intent. Fix: use -all when DMARC is at quarantine or reject; reserve ~all for DMARC p=none.
  6. Flipping to -all before completing sender inventory. Switching to hard fail with a missing legitimate sender causes that senders mail to be rejected — a production outage for the missed sender. Fix: stay on ~all until 30 consecutive days of aggregate reports show no unexplained SoftFails for legitimate sources, THEN flip.
  7. Writing per-mechanism - on an include you do not control. A record like -include:partner.example attempts to revoke a partners include — but the partner can change their record at any time and the revoke may need re-targeting. Fix: simply remove the include:partner.example entirely; the terminal -all then Fails any partner-originated traffic by default.

10. FAQ

What is the difference between SPF -all and ~all?
The minus-all (-all, Fail) qualifier tells the receiver that any sender not explicitly authorised in the SPF record should be treated as Fail — receivers may reject, discard, or quarantine the message per RFC 7208 section 4.7 guidance. The tilde-all (~all, SoftFail) qualifier tells the receiver that any unauthorised sender should be treated as SoftFail — the message is probably not legitimate, but receivers should not reject solely on this result. The practical difference: -all delivers strong enforcement (receivers act on the fail signal), ~all delivers monitoring-mode behaviour (the result is recorded but typically not acted upon at SMTP time). Use -all in production for any domain with a complete sender inventory. Use ~all only during initial deployment when you are still discovering legitimate senders and want to avoid blocking them by accident. Migrating from ~all to -all is the canonical SPF enforcement-ramp playbook.
What does +all mean in an SPF record?
The plus-all (+all, Pass) qualifier authorises EVERY IP address on the internet to send mail as the domain — it makes SPF unconditionally pass for any sender. This is almost always a misconfiguration: it defeats SPF entirely (every spam, phishing, and impersonation message gains SPF pass) and provides zero protection. The plus qualifier (+) is the default qualifier when none is specified, so +ip4:198.51.100.42 is identical to ip4:198.51.100.42. But +all means "authorise everything" which is never the operator intent. If you find +all in an SPF record, replace it with -all (strict enforcement, recommended) or ~all (soft enforcement, monitoring mode). Some sources confuse +all with the more reasonable +ip4:... or +include:... forms — only +all is dangerous; the plus prefix on a specific mechanism is just an explicit version of the default Pass qualifier.
When should I use SPF ?all instead of -all or ~all?
Almost never. The question-mark-all (?all, Neutral) qualifier makes no statement about senders not explicitly listed — the receiver treats the result as equivalent to no SPF record at all. This is sometimes recommended for a parent domain whose subdomains have their own SPF records and the parent itself sends no mail — but even there, the more correct answer is a v=spf1 -all record (explicit "no senders authorised"). The ?all qualifier is rarely the right choice because (1) it provides no protective signal, (2) it tells receivers nothing about your sending posture, and (3) it makes DMARC alignment harder to reason about. Use -all for production enforcement, ~all only during initial deployment monitoring, and ?all essentially never. The fourth qualifier (?) exists in the spec for completeness but has no canonical production use case.
What is SPF SoftFail and how do receivers treat it?
SPF SoftFail (~, tilde) is the result code receivers return when a sender matches a mechanism prefixed with ~ — typically ~all at the end of an SPF record. RFC 7208 section 4.6.2 defines SoftFail as "the domain believes the host is not authorised but is not willing to make a strong policy statement." Most receivers treat SoftFail as a soft signal: Gmail and Microsoft 365 record spf=softfail in the Authentication-Results header but typically do not reject or move to spam based on SoftFail alone (DMARC, content filtering, and reputation drive the final disposition). The practical effect: a SoftFailed message is usually delivered, but the result counters DMARC pass if DMARC is also failing (DMARC requires either SPF or DKIM to pass and align; SoftFail counts as a non-pass for DMARC purposes). Use ~all only during pre-enforcement monitoring; switch to -all once you have confirmed the legitimate sender inventory is complete.
Does the default SPF qualifier matter if I do not write it?
The default qualifier for ANY SPF mechanism with no explicit prefix is Pass (+). So v=spf1 ip4:198.51.100.42 include:_spf.google.com -all is exactly equivalent to v=spf1 +ip4:198.51.100.42 +include:_spf.google.com -all. The default Pass means a match on that mechanism produces spf=pass. The default does not extend to the terminal all mechanism: v=spf1 ip4:198.51.100.42 (with NO all clause) is a record that produces Pass for the listed IP and Neutral for everything else (per RFC 7208 the implicit terminal is Neutral, not Pass). Best practice is to ALWAYS terminate the record with an explicit qualified all clause (-all, ~all, or rarely ?all) so the records intent is unambiguous to the receiver.
Can I use SPF qualifiers on specific mechanisms instead of just all?
Yes. Any mechanism token in an SPF record can carry an explicit qualifier prefix (+, -, ~, or ?). So -include:ex-vendor.example is a valid mechanism that says "if the sender matches this include, treat the match as Fail" — useful for selectively flagging a sender that should never legitimately send mail as your domain. Similarly ~ip4:198.51.100.0/24 says "if the sender is in this range, treat it as SoftFail." In practice, per-mechanism qualifiers other than + are rare: most operators rely on the default Pass for explicitly listed mechanisms and use the qualifier only on the terminal all token. The two notable exceptions: (1) a -include:vendor.example to revoke authorisation for a known-bad provider whose include subtree might still authorise their IPs, and (2) ~ip4:... during traffic-shifting to mark IPs as soon-to-be-removed without immediate hard-fail. The DMARC Analyzer Domain Security Checker surfaces per-mechanism qualifier choices in its SPF analysis.
Is SPF -all required for DMARC enforcement?
No, SPF -all is not technically required for DMARC enforcement — DMARC operates on the aligned authentication result (either SPF or DKIM passing and aligning), not on the SPF qualifier specifically. However, -all is STRONGLY recommended for any domain at DMARC p=quarantine or p=reject. The reason: DMARC enforcement only takes effect when authentication fails or fails to align. If your SPF record is ~all (SoftFail), a spoofed message from an unauthorised IP returns spf=softfail (counted as non-pass for DMARC) — and DMARC reject still fires. The qualifier matters for non-DMARC-aware receivers and for SPF-only enforcement at the SMTP layer. Modern best practice is -all + DMARC p=reject — they reinforce each other and provide both pre-DMARC-evaluation (SPF rejection at SMTP) and post-DMARC-evaluation (DMARC reject) defence layers. Always pair -all with a complete sender inventory; -all with a missing legitimate sender breaks delivery.
Why do receivers sometimes ignore SPF Fail and deliver the message anyway?
Receivers may deliver an spf=fail message for several reasons that all stem from RFC 7208 section 4.7 explicitly NOT mandating rejection. The RFC says "the receiver MAY take Local Policy action on a Fail result" but does not require rejection. Common reasons receivers deliver despite Fail: (1) the receiver weights other signals (DKIM pass, sender reputation, content filtering, DMARC p=none) more heavily than raw SPF, (2) the message was forwarded and the receiver detects the forwarder pattern, (3) the receiver runs ARC-validation and trusts an upstream ARC chain, (4) the receiver applies different policies to different mailbox tenants (an enterprise customer with strict policy may reject; a consumer mailbox may deliver to spam folder), (5) DMARC is at p=none which overrides SPF Fail with a "monitor only" disposition. The qualifier (-all) is necessary but not sufficient for actual rejection — pair with DMARC p=reject for predictable behaviour.
How do I migrate from SPF ~all to -all safely?
The canonical SPF enforcement-ramp playbook: (1) Deploy v=spf1 ... ~all in production for 30-90 days with DMARC rua reporting enabled. (2) Review aggregate reports daily to identify any legitimate sender that returns spf=softfail — add it to the SPF record via include, ip4, or a as appropriate. (3) Verify the cumulative DNS-lookup cost stays under 10 (RFC 7208 section 4.6.4) as you add senders. (4) Once 30 consecutive days show ZERO unexplained softfails for legitimate sources, flip ~all to -all. (5) Monitor the next 30 days for new spf=fail entries in aggregate reports and add any missed senders. (6) For DMARC-enforcement-bound domains, also confirm DMARC alignment — SPF pass alone is not enough; the SPF-authenticated MAIL FROM domain must align with the From: header domain (relaxed alignment by default; see help_dmarc_alignment.php). The DMARC Analyzer rolling SPF + DMARC dashboard surfaces softfail-to-fail trend lines for exactly this migration.

12. Audit your SPF record qualifier now

The fastest way to confirm your SPF records terminal qualifier is correct for your deployment stage:

  1. Look up your current SPF record. Use dig +short TXT example.com or the Domain Security Checker to see what qualifier currently terminates your record.
  2. Identify your deployment stage. New deployment with incomplete sender inventory → ~all + DMARC p=none. Confirmed inventory + ready for enforcement → -all + DMARC p=quarantine or p=reject. Null-sender domain → v=spf1 -all.
  3. Flag the four anti-patterns: +all (authorises everything, replace immediately), ?all (provides no enforcement, replace with -all or ~all), missing terminal (implicit Neutral, add an explicit qualified all), and ~all + DMARC p=reject (incoherent, switch to -all).
  4. Inspect a real outbound message with the Email Header Analyzer to confirm the Authentication-Results header reports the expected spf=pass for legitimate senders.