SPF, or Sender Policy Framework, is a DNS-based technique aimed at stopping sender address forgery on emails. If you’re using ~all in yours and you’re not actively in the process of migrating over to using SPF, you’re doing it wrong. (Yes, Google, Apple, Microsoft, that includes all of you too!)

The above-listed tech giants all have ~all at the end of their SPF records, which you’re only supposed to use for domains that are transitioning. Transitioning in this case meaning they’re in the process of implementing SPF, but don’t dare make a hard Fail statement about hosts which do not pass the check.

True, the official RFC (RFC 4408, see section 2.5.5) doesn’t state it this way explicitly, somehow that got a little lost from earlier drafts, but that doesn’t change the fact it was never meant to be used indefinitely. Not only does openspf.org have the following to say about it on their “SPF Record Syntax page”:

Result: SoftFail
Explanation: The SPF record has designated the host as NOT being allowed to send but is in transition
Intended action: accept but mark

but Julian Mehnle, one of the people who helped draft SPF, in 2008 stated on the spf-discuss mailing list that ~ has always been meant as a tool for testing during roll-out, providing some pretty hard to argue facts to go along with his statement:

~ was meant as a tool for testing during roll-out. Unfortunately RFC 4408 does not make this sufficiently clear, but it can be seen from both older versions of the spec and all versions of Mail::SPF::Query, which has long been "the" SPF reference implementation:

draft-mengwong-spf-00 and -01:

| 9.3 Phased Rollout
| At an adopting domain, adoption of SPF could occur in phases.
| A domain might move through these phases by changing its default
| response type from "neutral" to "softfail" to "fail".
| The phases are characterized by different levels of awareness
| among the domain's userbase, and different levels of strictness
| on the part of SPF-conformant receivers.
| When a sufficient majority of its users are SPF-conformant, a
| domain SHOULD change its default to "fail". [...]

draft-mengwong-spf-00 and -01, and draft-schlitt-spf-classic-00:

| [6.3 / 7.2] The Received-SPF header
| [...]
| Example headers generated by mybox.example.org:
| [...]
|        Received-SPF: softfail (mybox.example.org: domain of
|                      transitioning myname(_at_)example(_dot_)com
|                      does not designate as permitted
|                      sender)


| 2.4.4  SoftFail
| A SoftFail result should be treated as somewhere between a
| Fail and a Neutral.  This value is used by domains as an
| intermediate state during roll-out of publishing records.
| The domain believes the host isn't authorized but isn't
| willing to make that strong of a statement. [...]

| 4.2  Results
| [...]
| Results from interpreting valid records:
|    Neutral  (?): published data is explicitly inconclusive
|    Pass     (+): the <ip> is in the permitted set
|    Fail     (-): the <ip> is in the not permitted set
|    SoftFail (~): the <ip> may be in the not permitted set,
|                  its use is discouraged and the domain
|                  owner may move it to the not permitted
|                  set in the future
| [...]

And check out these -- search for "transitioning":


Finally, even Google’s own filters mention a domain is transitioning when getting a SoftFail:

Received-SPF: softfail (google.com: best guess record for domain of transitioning foo@bar.tld does not designate www.xxx.yyy.zzz as permitted sender) client-ip=www.xxx.yyy.zzz;

So can we please all start using SPF records the way they’re meant to be used? Either -all if you’re certain your record includes all MTA’s you want to allow, or ?all if you just want to mark everything not covered in your record as neutral.

It’ll make the ’net a better place, trust me.