What is an SPF record?
SPF is one TXT record at a domain, starting with v=spf1, that lists the servers allowed to send mail for it. Receivers check the sending server against it. On its own SPF only checks the hidden return address; DMARC ties it to the From address people see.
The SPF 10 DNS lookup limit
While checking SPF, a receiver may do at most 10 DNS lookups (RFC 7208, section 4.6.4). include, a, mx, ptr, exists and redirect each cost one, and so does every one of those inside the records they include. ip4, ip6 and all are free. Past 10, the result is a permanent error and all mail fails SPF. Lookups that find nothing ("void" lookups) are limited to 2.
To get under the limit: remove services you no longer use, replace a and mx with the servers' ip4: ranges, or send bulk mail from a subdomain (news.example.com) that has its own SPF record.
SPF syntax
| include:domain | Also allow the servers in another domain's SPF (a mail service's). One lookup, plus its own |
|---|---|
| ip4:, ip6: | An address or range, for example ip4:203.0.113.0/24. No lookup |
| a, mx | The domain's own address, or its mail servers. One lookup each |
| redirect=domain | Use another domain's SPF instead, when there is no all |
| -all | Fail everything else |
| ~all | Soft fail everything else: accept but mark |
| ?all | Say nothing about everything else: protects nothing |
| +all | Allow everyone: never use it |
Questions
With DMARC at quarantine or reject, either works, because DMARC decides what happens to failing mail. ~all is safer while you make sure every sender is listed; -all is stricter.
Replacing includes with the addresses they contain, to save lookups. It works until a provider changes its addresses, which they do without warning, and then mail fails. Prefer removing unused services or using a subdomain.
v=spf1 include:spf.protection.outlook.com -all, plus an include for every other service that sends as the domain. For Google Workspace it is include:_spf.google.com.