SPF (Sender Policy Framework) authenticates email by letting domain owners declare in DNS which mail servers are allowed to send on their behalf. When a message is received, the receiving server performs a series of DNS lookups and mechanism checks in under a second to decide whether the sending IP is authorised. Understanding this process helps you write correct SPF records, debug failures, and appreciate why SPF must be paired with DKIM and DMARC.
The SPF Check: Step by Step
SPF evaluation begins the moment a sending server opens an SMTP connection and issues the MAIL FROM command. Here is exactly what happens:
- The sending server connects and issues
EHLO, thenMAIL FROM:<sender@example.com>. - The receiving server reads the domain from the envelope sender address (
example.com). - A DNS TXT lookup is performed for
example.comto find a record starting withv=spf1. - Mechanisms are evaluated left to right against the connecting IP address.
- The first matching mechanism determines the result. If no mechanism matches, the default result is Neutral.
- The result is passed to the receiving mail server's policy engine, which decides what to do with the message (deliver, quarantine, or reject).
MAIL FROM vs the From Header
This distinction is one of the most misunderstood aspects of SPF. There are two "from" fields in every email:
- MAIL FROM (envelope sender / Return-Path) — set during the SMTP session. This is what SPF checks. It is used for bounce messages and is often not the address your recipients see.
- From header — the address displayed in your email client. This is what you see in the "From:" field. SPF does not check this field.
An attacker can craft a message where the MAIL FROM passes SPF on a domain they control, while the From header shows ceo@yourcompany.com. Recipients see the spoofed address. This is why DMARC — which enforces alignment between the two — is essential.
SPF Mechanisms
Mechanisms are the building blocks of an SPF record. Each one describes a set of IP addresses or domains. The record is evaluated left to right, and the first matching mechanism wins.
| Mechanism | What It Matches | DNS Lookup? |
|---|---|---|
ip4:x.x.x.x | A specific IPv4 address or CIDR range. | No |
ip6:x:x::/nn | A specific IPv6 address or prefix. | No |
a | The A/AAAA records of the domain (or a specified domain). | Yes |
mx | The MX records of the domain (or a specified domain). | Yes |
include:domain | Delegates to the SPF record of another domain. | Yes |
exists:domain | Matches if the specified domain has an A record. | Yes |
ptr | PTR record of the sending IP (deprecated, avoid using). | Yes |
all | Always matches — used as the final catch-all. | No |
SPF Qualifiers
Each mechanism can be prefixed with a qualifier that determines the result when that mechanism matches. If no qualifier is specified, + (Pass) is assumed.
| Qualifier | Name | Result When Matched |
|---|---|---|
+ | Pass | The sender is authorised. Default if omitted. |
- | Fail | The sender is not authorised. Reject the message. |
~ | Softfail | Probably not authorised. Accept but mark suspicious. |
? | Neutral | No assertion about this sender. |
A Real-World SPF Record
Here is a typical SPF record for a company using Google Workspace for business email and Mailgun for transactional messages:
v=spf1 include:_spf.google.com include:mailgun.org ~allEvaluation for a message from a Google sending IP:
- The server checks
include:_spf.google.com— this triggers a lookup of Google's SPF record. - Google's record contains the sending IP, so the mechanism matches with a
+qualifier. - Result: Pass. Evaluation stops immediately.
For a message from an unknown IP not covered by either include:
- Neither
include:_spf.google.comnorinclude:mailgun.orgmatch. - The
~allcatch-all matches everything with a Softfail qualifier. - Result: Softfail. The message is accepted but flagged.
The 10 DNS Lookup Limit
RFC 7208 imposes a hard limit of 10 DNS lookups during SPF evaluation. The following mechanisms each consume one lookup: include:, a, mx, ptr, and exists:. Lookups triggered recursively inside an include: also count toward the total.
If evaluation exceeds 10 lookups, the result is PermError — the same as a malformed record. This silently breaks SPF for your domain, making it easy to miss in testing.
v=spf1 include:sendgrid.net include:mailchimp.com include:_spf.google.com include:salesforce.com ~all can easily exceed 10 lookups once the nested records of each provider are counted. Use an SPF lookup validator to count your total before publishing.SPF and Email Forwarding
SPF breaks with email forwarding because when a message is forwarded, the forwarding server sends the message with a new SMTP connection but preserves the original envelope sender domain. The forwarding server's IP is almost never listed in the original domain's SPF record, so SPF fails for a perfectly legitimate forwarded message.
The correct solution is to use SRS (Sender Rewriting Scheme) on the forwarding server, or to rely on DKIM and DMARC which are more resilient to forwarding scenarios.
How to Check SPF Results
Use the TXT Record Lookup tool to retrieve your current SPF record. For a full email authentication audit, the Security Headers Scanner gives you a quick overview of your domain's authentication posture.
Frequently Asked Questions
What happens if there is no SPF record for a domain?
If no SPF record is found, the result is None. Receiving servers treat this as unauthenticated mail. Depending on the receiving server's policy and whether DMARC is in place, the message may still be delivered, but it has a higher probability of being flagged as spam.
Why does my SPF record fail even though I included the right provider?
The most common reasons are exceeding the 10-lookup limit (causing PermError), a typo in theinclude: domain, or the sending IP not being covered by the provider's own SPF record. Use a TXT lookup tool to retrieve the full evaluated record and count your lookups.
Does SPF need to match the From address recipients see?
No. SPF only checks the envelope sender. However, DMARC requires that the domain used for SPF is aligned with the From header domain. Without DMARC, there is no enforcement of that alignment.
Can SPF be used without DKIM?
Yes, but it is strongly discouraged. SPF alone cannot verify message integrity, and it fails for forwarded email. DKIM signs the message body and headers with a cryptographic key, providing verification that is more robust than SPF alone. Using both together, under a DMARC policy, provides much stronger protection.
What is the redirect modifier in SPF?
The redirect= modifier tells a receiving server to use the SPF record of another domain entirely. Unlike include:, which checks that domain's record and then continues evaluation, redirect= replaces the entire evaluation with the target domain's record. It is useful when all sending for multiple domains is consolidated into one master SPF record.