SPF neutral

Your record explicitly declines to say anything

Where you saw it: An Authentication-Results header reading spf=neutral, or a DMARC aggregate report where the spf column says neutral rather than pass or fail.

Why it happens

  • The record ends in ?all. That is a deliberate statement that unlisted senders are neither authorized nor unauthorised.
  • A setup guide recommended ?all as a safe starting point and nobody came back to tighten it.
  • A specific mechanism carries a ? prefix, which produces neutral for anything it matches.
  • A DNS migration dropped the qualifier from the end of the record and the default behavior filled in.

The fix, in order

  1. Read the end of your record

    Run dig +short TXT yourdomain.com and look at the last mechanism. A ?all there is the whole explanation.

  2. Confirm every legitimate sender is listed

    Before tightening the qualifier, check that each platform you send from appears in the record. Moving to a stricter policy with a missing sender causes the outage you were trying to avoid.

  3. Move to ~all and watch for a week

    Soft fail marks unlisted senders as suspicious without rejecting them. Your DMARC reports will show anything you missed while mail keeps flowing.

  4. Move to -all once the reports are clean

    Hard fail is the position you want. It tells receivers that anything not listed is forged, which is the entire point of publishing SPF.

How to know it worked

The short version

  • dig +short TXT yourdomain.com ends with ~all or -all rather than ?all.
  • A test message shows spf=pass in Authentication-Results.
  • DMARC reports over the following week show no legitimate source failing.

One platform missing from the record

Say your record reads v=spf1 include:_spf.google.com include:sendgrid.net ?all. Mail from Google Workspace and SendGrid passes. Then the support team starts sending from a helpdesk tool that uses its own servers, and those messages show spf=neutral.

The receiver walked your mechanisms left to right, the helpdesk's IP matched none of them, and evaluation fell through to ?all. A neutral in the header is telling you which platform is missing from the record, by way of the IP it names. Gmail's wording is "is neither permitted nor denied by domain of", followed by the envelope sender. Find which vendor owns that IP and add its include.

Watch for one variant. If Gmail's line says "neither permitted nor denied by best guess record for domain of", the domain it checked has no SPF record at all and Google guessed one. The usual cause is a bounce domain or subdomain (the smtp.mailfrom value) that differs from the domain you were looking at.

The record with no all at the end

A record doesn't need ?all to produce neutral. RFC 7208 says that when no mechanism matches and there's no redirect modifier, the result is neutral, just as if ?all had been written as the last directive. So v=spf1 include:_spf.google.com with nothing after it treats every unlisted sender the same way.

The same RFC tells receivers to treat neutral exactly like none, the result for a domain with no record. It doesn't count against you the way a fail does, and it doesn't help.

The question mark can also sit on a single mechanism, as in ?include:thirdparty.example. Mail from that vendor then comes back neutral even though the vendor appears in the record. Qualifiers work the same on every mechanism: a plus sign (the default when you write nothing) means pass, a minus means fail, a tilde means softfail and a question mark means neutral. If you find a ?include, someone probably added it as a trial. Remove the question mark once that vendor's mail is confirmed legitimate.

Questions people ask

Is neutral better than no SPF record?

Barely. Both leave the receiver without a useful signal. Neutral at least proves the domain owner published something, which is a weak positive and not much else.

Does neutral pass DMARC?

No. DMARC needs an SPF pass with alignment, or a DKIM pass with alignment. Neutral is not a pass.

When is ?all the right choice?

Almost never for a live sending domain. It is occasionally useful for a few days during a migration, and it should never be the permanent state.

Bounces from addresses that never existed are a different problem

We check a list before you send and label what nobody can resolve. 100 free checks a month, no card.