Skip to content

What is an SPF record and how do you set it up correctly?

Last updated: 25:10:2026

Wersja polska

What SPF does

SPF (Sender Policy Framework, RFC 7208) lets a receiving mail server ask a simple question: is the server handing me this message allowed to send mail for this domain? The answer comes from a TXT record you publish in DNS. The receiver looks up the record for the domain in the message's envelope sender (theMAIL FROM address, which ends up in the Return-Path header), compares the connecting IP address against the list, and gets a result such as pass, fail or softfail.

Two things follow from that. SPF checks the envelope sender, not the From: address people see in their mail app - tying the two together is the job of DMARC alignment. And SPF breaks when a message is forwarded, because the forwarding server is not on your list. That is why SPF works best alongside DKIM, whose signature survives forwarding.

SPF record syntax

An SPF record is a TXT record on the domain itself (the apex, often written as @). It starts with the version tag and is followed by mechanisms, evaluated left to right until one matches:

Example SPF record for example.com

example.com.  3600  IN  TXT  "v=spf1 ip4:192.0.2.10 include:_spf.mailprovider.example ~all"
MechanismMatches whenDNS lookup
ip4:The sender IP is in the given IPv4 address or range (192.0.2.0/24)No
ip6:The sender IP is in the given IPv6 address or rangeNo
include:The other domain's SPF record passes - how you authorize a mail providerYes
a / mxThe sender IP is one of the domain's A/AAAA or MX hostsYes
redirect=Use another domain's SPF record instead of this oneYes
allAlways - the catch-all at the end of the recordNo
ip4:
Matches when: The sender IP is in the given IPv4 address or range (192.0.2.0/24)
DNS lookup: No
ip6:
Matches when: The sender IP is in the given IPv6 address or range
DNS lookup: No
include:
Matches when: The other domain's SPF record passes - how you authorize a mail provider
DNS lookup: Yes
a / mx
Matches when: The sender IP is one of the domain's A/AAAA or MX hosts
DNS lookup: Yes
redirect=
Matches when: Use another domain's SPF record instead of this one
DNS lookup: Yes
all
Matches when: Always - the catch-all at the end of the record
DNS lookup: No

Each mechanism can carry a qualifier: + pass (the default), - fail, ~ softfail and ? neutral. In practice the qualifier only matters on the final all. The ptr mechanism is deprecated - don't use it.

~all or -all?

The ending decides what happens to mail from servers you didn't list. -all (fail) says "reject anything else"; ~all (softfail) says "treat anything else as suspicious". Both are fine, and both are far better than having no SPF record at all.

  • Once you publish an enforcing DMARC policy, most large receivers make the final decision from DMARC, so the practical difference between ~all and -all is small.
  • Some receivers reject on an SPF -all fail before they ever evaluate DMARC or DKIM, which can cost you legitimately forwarded mail. That's why many providers, AnyMail included, generate ~all.
  • If a domain never sends mail at all, publish v=spf1 -all so nobody can use it.
  • Never use +all (anyone may send as you) or ?all (no opinion) - they defeat the purpose.

The 10 DNS lookup limit

To keep SPF checks cheap, a receiver will perform at most 10 DNS lookups while evaluating your record. Every include:, a, mx, exists: and redirect= counts - including the ones nested inside the records you include. Go over the limit and the result is permerror, which most receivers treat like a failure. A separate rule allows at most two lookups that return nothing ("void lookups").

To stay under the limit:

  • Remove includes for services you no longer use - old newsletter or CRM tools are the usual suspects.
  • Prefer ip4:/ip6: for servers you run yourself; they cost nothing.
  • Send bulk or marketing mail from a subdomain (for example news.example.com) with its own SPF record. Each hostname has its own SPF record, and the subdomain's lookups don't count against the apex.
  • Be careful with "SPF flattening" (replacing includes with the IPs they resolve to): it works until the provider changes its addresses, and then your mail starts failing silently.

One SPF record per domain

A domain may publish only one TXT record that starts with v=spf1. Two of them is a permerror, and it is the most common SPF mistake: someone adds a new provider by creating a second record instead of editing the first. If you send through more than one service, merge them into one record:

Wrong - two SPF records

example.com.  TXT  "v=spf1 include:_spf.provider-a.example ~all"
example.com.  TXT  "v=spf1 include:_spf.provider-b.example ~all"

Right - one merged record

example.com.  TXT  "v=spf1 include:_spf.provider-a.example include:_spf.provider-b.example ~all"

Other TXT records on the same name (domain verification tokens, for instance) are fine - only records starting with v=spf1 count.

Common SPF mistakes

Forgetting a sender

Invoices from your accounting tool, notifications from a web shop, a contact form on your website: everything that sends with your domain in the envelope sender needs to be covered, or its mail will fail SPF.

Expecting subdomains to inherit the record

SPF is not inherited. mail.example.com or shop.example.com need their own record if they appear as envelope senders.

Long records and quoting

A single string in a TXT record can hold at most 255 characters. Longer SPF records must be split into several quoted strings inside the same record, which receivers join without spaces - so put the break inside a mechanism boundary and keep the space at the end of the first part. Most DNS panels do this for you; see how to add DNS records at your registrar.

Typos that silently break the record

v=spf1 must be the very first thing in the record, mechanisms are separated by single spaces, and include: takes a domain name, not a URL. Use the deprecated SPF record type (type 99) and nothing will read it - SPF lives in TXT records only.

How to check your SPF record

Look the record up with dig TXT example.com +short (or nslookup -type=TXT example.com on Windows), or use the email authentication checker. Then send a message to an external mailbox and open the original headers: the Authentication-Results header shows spf=pass when everything is right. DNS changes can take as long as the record's TTL to reach every resolver, so allow some time before you re-test.

When you attach a domain to AnyMail, the dashboard shows the exact SPF record to publish and checks it for you. If you already have an SPF record for another service, add AnyMail's value to that record rather than creating a second one.

Let AnyMail handle these records for you

AnyMail generates the MX, SPF, DKIM and DMARC records for your domain, checks every one of them automatically and tells you exactly which record to fix - then hosts your inboxes, operated from the EU.