SPF is all about publishing a list of servers that are authorized to send on behalf of a domain.
After writing out a list of servers in the form of an SPF record, the right thing to do is to end an SPF record with something that says "and everything else on the Internet is NOT authorized".
The way the above is written is to use the "all" mechanism. This mechanism matches everything. By adding a prefix of "~" or "-", the meaning of the mechanism is changed to be:
- "softfail" in the case of "~"
- "fail" in the case of "-"
Both mean "NOT PASS", but there is a subtle difference, and it has to do with history.
Before DMARC came along, SPF tried to allow its users to express policy -- that is, what should be done if SPF fails. "softfail" was largely interpreted to mean "NOT PASS". "fail" was interpreted by a few operators to mean "NOT PASS AND DISCARD THIS FAILING EMAIL".
Discarding email based on SPF results ended up causing too much legitimate email to be dropped (because of improperly configured SPF records, or vendors who didn't understand how to send SPF-compliant email), and almost all receivers ended up using SPF as input for anti-spam engines. However, a few operators still interpreted "fail" as meaning "NOT PASS AND DISCARD".
Fast forward to the world of DMARC. Now receivers are using DMARC to find any positive assertion that a domain is associated with a piece of email. In this context, ~all is the same thing as -all... "NOT PASS".
However, if you operate with "-all" in your SPF record, you might run into an operator (once in a blue moon) that discards otherwise legitimate email. Debugging this issue can be difficult. This issue could be sidestepped by using "~all" instead of "-all". Alternatively, use of "-all" can still be quite valuable in conveying confidence in the correctness of your SPF record; with that flag it is more likely that a failed match will result in fraudulent messages being discarded by MTAs which do not yet support DMARC.