# SPF sender policy framework: how the DNS check works

> SPF (Sender Policy Framework) lets a domain publish authorized senders in DNS. RFC 7208 defines how receivers check it and the results it returns.

SPF (Sender Policy Framework) is a DNS-based email authentication method defined in RFC 7208. A domain owner publishes a DNS TXT record listing the mail servers authorized to send using that domain's address in the SMTP transaction. When a message arrives, the receiving mail system checks the sending server against that record and returns one of seven results, including pass, fail, or softfail. SPF authenticates the envelope sender domain, not the visible From address a recipient reads.

## Quick takeaways

- SPF records publish only as DNS TXT records that start with exactly `v=spf1`; a domain with more than one matching record breaks the check with a permerror result, per [RFC 7208](https://www.rfc-editor.org/rfc/rfc7208).
- A receiver checks the RFC5321.MailFrom (envelope sender) domain, and separately checking the HELO/EHLO domain is recommended; an empty MAIL FROM, as in a bounce, falls back to checking `postmaster` at the HELO domain.
- Each mechanism in the record carries a qualifier that sets its result: `+` for pass, `-` for fail, `~` for softfail, `?` for neutral. The qualifier defaults to `+` when omitted.
- A record with no `all` mechanism and no `redirect` modifier still returns neutral for unmatched senders, the same as an implicit `?all`.
- DNS-querying mechanisms (`include`, `a`, `mx`, `ptr`, `exists`) and the `redirect` modifier are capped at 10 lookups total; going over the limit forces a permerror rather than a soft failure.
- SPF checks the envelope sender, not the visible From address; DMARC only credits an SPF pass when the checked domain aligns with the visible From domain, per [RFC 7489](https://www.rfc-editor.org/rfc/rfc7489).

## How the SPF check works

This page covers the RFC 7208 mechanics behind SPF. For the full topic cluster, see the [SPF hub](/learning/spf).

SPF version 1 works because a domain owner publishes, in DNS, which hosts are allowed to use that domain's name during the SMTP transaction, specifically in the HELO/EHLO identity and the MAIL FROM (envelope sender) identity. A receiving mail server compares the connecting IP address against that published record during the mail transaction, before the message is fully accepted, per [RFC 7208, Section 1](https://www.rfc-editor.org/rfc/rfc7208).

The record itself is published only as a DNS TXT (type 16) resource record. A verifier keeps only the record that begins with exactly `v=spf1`, and a domain must not publish more than one such record; if a lookup returns more than one, that is an error condition, not something the check merges together.

RFC 7208 requires a verifier to check the MAIL FROM identity whenever a HELO check was not performed or was not definitive, and it recommends checking HELO separately as well. Because MAIL FROM can be empty (a bounce or delivery-status notification uses a null reverse path), SPF defines that case explicitly: the checked identity becomes `postmaster` at the HELO domain instead.

Evaluation walks through the record's mechanisms in order and stops at the first match. Each mechanism carries a qualifier that determines the result once it matches:

![SPF qualifiers and the result each one produces](/images/editorial/spf-sender-policy-framework/spf-sender-policy-framework-qualifiers.webp "1200x600")

*Source: Palisade.*

Seven results are defined in total: `none`, `neutral`, `pass`, `fail`, `softfail`, `temperror`, and `permerror`. A `pass` is an explicit statement that the client is authorized to use the domain; `fail` is an explicit statement it is not; `softfail` is a weaker statement that the host is probably not authorized, without asking a receiver to reject outright, per [RFC 7208, Section 2.6](https://www.rfc-editor.org/rfc/rfc7208).

## When the result changes

### No match and no redirect

If none of a record's mechanisms match and the record has no `redirect` modifier, the result is `neutral`, exactly as though the record ended with an implicit `?all`. A record that lists authorized senders but never adds `all` does not fail unmatched senders on its own; it simply returns neutral for them.

### The include mechanism only counts a pass

The `include` mechanism runs a full, recursive evaluation of another domain's SPF record. Only a `pass` from that nested check makes `include` itself match. A `fail`, `softfail`, or `neutral` result from the included domain does not match at all; evaluation just moves to the next mechanism. A `temperror` from the included domain propagates up, and a `permerror` or `none` result turns the whole check into `permerror`.

### The 10-lookup limit

Implementations must limit the mechanisms and modifiers that require a DNS query, meaning `include`, `a`, `mx`, `ptr`, `exists`, and the `redirect` modifier, to 10 total per evaluation, and must return `permerror` once that limit is exceeded. `ip4`, `ip6`, `all`, and `exp` do not count toward the limit because they need no additional lookup. A single `mx` mechanism has its own sublimit too: it must not query more than 10 address records, or the check also returns `permerror`. Implementations should also cap "void" lookups, meaning a query that returns no answer or NXDOMAIN, at two; exceeding that is another route to `permerror`. The `ptr` mechanism should not be published in a record at all, per [RFC 7208, Section 5.5](https://www.rfc-editor.org/rfc/rfc7208).

### SPF pass is not DMARC alignment

A `pass` result authenticates the RFC5321.MailFrom domain, the envelope sender, not the RFC5322.From domain a person reads. DMARC only credits that pass when the two domains align: in relaxed mode they need only share the same organizational domain (for example, `bounces.yourdomain.com` aligns with `yourdomain.com`); in strict mode they must match exactly, per [RFC 7489, Sections 3.1 and 3.1.2](https://www.rfc-editor.org/rfc/rfc7489). A message can pass SPF outright and still fail DMARC if the envelope sender domain and the visible From domain do not align.

## A worked SPF record

A record combining several common mechanisms looks like this:

```text
yourdomain.com.  IN  TXT  "v=spf1 ip4:203.0.113.0/24 include:_spf.provider.example -all"
```

This is an illustrative example only; do not publish it as-is. Read left to right:

- `v=spf1` identifies the record as SPF version 1; nothing else in the TXT value is evaluated unless this exact prefix is present.
- `ip4:203.0.113.0/24` matches, with the default `+` (pass) qualifier, any connecting IP inside that block, the domain's own mail servers.
- `include:_spf.provider.example` runs a nested check against an email provider's own record and matches only if that check returns pass.
- `-all` is the final mechanism, and it always matches. With a `-` qualifier, any sender not already matched by an earlier mechanism gets an explicit fail.

Changing that last mechanism changes the record's strictness without touching anything else: `~all` returns softfail instead of fail for unlisted senders, and `?all` returns neutral. Because evaluation stops at the first match, mechanism order matters. Putting `-all` before `include:_spf.provider.example` would fail that provider's mail before its own record is ever checked.

## Check your own record before changing it

A record that looks correct in isolation can still leave real senders unauthenticated. Before editing a live SPF record, build an inventory of everything that currently sends as the domain, including any transactional or marketing platform, help desk tool, or internal relay, then confirm each one is covered by an `ip4`, `ip6`, `a`, `mx`, or `include` mechanism.

Google's sender guidelines require SPF or DKIM from every sender and, for anyone sending 5,000 or more messages a day to Google, both SPF and DKIM with DMARC layered on top; unauthenticated mail at those volumes might be marked as spam or rejected with a 5.7.26 error, and the sending domain or IP still needs valid forward and reverse (PTR) DNS, per [Google's email sender guidelines](https://support.google.com/a/answer/81126). That threshold is a useful floor for checking whether a record actually covers production mail, not just what was true when it was first written.

A DNS lookup only shows what a domain publishes. It cannot confirm that every application on the network actually sends through an authorized path, and it cannot show DMARC alignment by itself. Pair the SPF result with the domain's DKIM and DMARC configuration, covered in the broader [email authentication](/learning/email-authentication) stack. For a real-world example of a receiver treating SPF and DKIM as a hard requirement rather than a suggestion, see [will La Poste require SPF, DKIM and DMARC for all senders?](/learning/will-la-poste-require-spf-dkim-dmarc)

## Check the record before you rely on it

Reading the RFC does not tell you what a specific domain currently publishes, and a record edited months ago can drift from what actually sends mail today.

Run the domain through the [SPF checker](/tools/spf) to see the published record, how its mechanisms parse, and whether it stays within the 10-lookup limit before changing anything.

A checker result confirms what DNS currently publishes. It does not confirm that every sending application uses an authorized path, and it does not replace a DMARC aggregate report for seeing which sources actually pass or fail in production.

## Sources and further reading

- [RFC 7208: Sender Policy Framework (SPF) for Authorizing Use of Domains in Email](https://www.rfc-editor.org/rfc/rfc7208)
- [RFC 7489: Domain-based Message Authentication, Reporting, and Conformance (DMARC)](https://www.rfc-editor.org/rfc/rfc7489)
- [Google email sender guidelines](https://support.google.com/a/answer/81126)
- [Palisade SPF checker](/tools/spf)

## Frequently asked questions

### How does the SPF Sender Policy Framework work?

A domain owner publishes a DNS TXT record starting with `v=spf1` that lists authorized mail servers using mechanisms like `ip4`, `ip6`, `a`, `mx`, and `include`. When a message arrives, the receiving server checks the connecting IP against that record, evaluating mechanisms in order until one matches, and returns a result: pass, fail, softfail, neutral, none, temperror, or permerror, per [RFC 7208](https://www.rfc-editor.org/rfc/rfc7208).

### What is an example of a Sender Policy Framework?

An example SPF record is `v=spf1 ip4:203.0.113.0/24 include:_spf.provider.example -all`, which authorizes a specific IP range plus everything the referenced provider's own record authorizes, and fails any other sender. This is an illustrative shape only; a real domain's record must list its own actual sending sources.

### How to implement Sender Policy Framework SPF?

Start by inventorying every service and server that sends mail as the domain. Build a single TXT record beginning with `v=spf1`, add one mechanism per legitimate source (`ip4`, `ip6`, `a`, `mx`, or `include` for a third-party sender's own record), and end with an `all` mechanism carrying the qualifier that matches the domain's intended strictness, usually `-all` once every source is confirmed. Publish only one SPF-formatted TXT record at the domain, since a second one causes a permerror, and stay within the 10-lookup limit for DNS-querying mechanisms, per [RFC 7208](https://www.rfc-editor.org/rfc/rfc7208).

### What is the RFC 7208 Sender Policy Framework?

RFC 7208 is the IETF specification that defines SPF version 1: the DNS TXT record format, how a receiving mail system evaluates the MAIL FROM and HELO identities against it, the seven possible results, and the limits implementations must enforce, including the cap on DNS-querying mechanisms per check.
