What is SPF?

SPF (Sender Policy Framework) is a DNS-based authorization system that lets domain owners declare which servers are allowed to send mail on their behalf.

How SPF works

When a receiving mail server gets an email claiming to be from user@example.com, it performs a simple check:

  1. Look up the SPF TXT record for example.com
  2. Parse the record to extract authorization rules (mechanisms)
  3. Test if the sending server's IP address matches any of those rules
  4. Accept, reject, or quarantine the message based on the result

The SPF record is just a TXT record on your domain. Here's a minimal example:

v=spf1 ip4:192.0.2.0 ip4:198.51.100.0 -all

This says: "Version 1 of SPF. Servers at 192.0.2.0 and 198.51.100.0 are authorized to send mail for this domain. Everything else is not." The -all at the end is the "fail" rule—any sender not in the list gets rejected.

SPF mechanisms

An SPF record is built from mechanisms—directives that describe which IPs or servers are authorized. The common ones:

ip4 / ip6

Explicitly list IPv4 or IPv6 addresses (or CIDR ranges). Use this for your own mail servers or static IPs from a vendor.

ip4:192.0.2.10/24 # authorizes any IP in the 192.0.2.x range

include:

Pull in SPF rules from another domain. This is how you reference a vendor's SPF policy. When a receiver sees an include:, they recursively look up that domain's SPF record.

include:sendgrid.net # sendgrid publishes their authorized IPs on sendgrid.net

Each include: counts as one DNS lookup. This is why the 10-lookup limit exists. Adding 5 ESPs (Google Workspace, Microsoft 365, SendGrid, Mailgun, Constant Contact) easily hits the limit.

a / mx

The a mechanism authorizes the A/AAAA record of your domain (your mail server). The mx mechanism authorizes the mail exchange servers in your MX records.

a # mail from mail.example.com is okay
mx # mail from any of our MX servers is okay

These are convenient for small deployments but can add lookups if your MX or A records resolve to many addresses.

ptr

The ptr mechanism checks the reverse DNS (PTR record) of the sender's IP. It's the least secure mechanism (PTR records are not authoritative) and is deprecated. Avoid it.

exists:

A macro-based mechanism that allows dynamic lookups. Rarely used in simple deployments, but essential for sophisticated policies. Each exists: counts as a lookup.

Qualifiers: pass, soft fail, neutral, fail

Every mechanism can be prefixed with a qualifier that determines the result if the mechanism matches:

Qualifier Symbol Meaning Common use
Pass + IP is authorized (default if no qualifier) Most mechanisms
Soft fail ~ IP is probably not authorized, but don't reject Testing, temporary issues
Neutral ? No statement about authorization (NXDOMAIN-like) Rarely used
Fail - IP is explicitly not authorized; receiver should reject The all mechanism: `-all`

The -all rule at the end of most records is the "fail all" rule—anything not explicitly authorized is rejected. Some organizations use ~all (soft fail) during rollout.

Example SPF records

Simple: single mail provider

v=spf1 include:google.com -all

This says: "Only Google's mail servers (via their published SPF) are authorized to send mail for this domain."

Multiple vendors

v=spf1 include:google.com include:sendgrid.net include:mailgun.org a mx -all

This authorizes Google Workspace, SendGrid, and Mailgun, plus your own A and MX records. That's 3 includes + 2 mechanisms = 5 lookups. Still under the 10-lookup limit, but adding more vendors will push you over.

Using macros for per-IP synthesis

v=spf1 include:%{ir}.%{v}.%{d}.spf.uglydmarc.com -all

This is UglyDMARC's synthetic approach. The macros expand so that each sender's IP is embedded in the query, and our authoritative DNS service answers with a pre-flattened CIDR set. No matter how many vendors you add, it's always one include and a single-IP response.

SPF alignment

SPF passes if the sending server's IP is in the authorized list. But for DMARC (which we'll cover later), there's an additional concept: alignment.

A mail server's Return-Path (the "envelope from" address) might be different from the From header (what users see). SPF alignment asks: does the Return-Path domain match the From domain, or at least share the same organizational domain?

For example, if the From header says alice@example.com but the Return-Path is bounce@mail.example.com, alignment fails unless the SPF record explicitly authorizes mail from mail.example.com or the subdomain relaxes the check.

Common SPF mistakes

Multiple SPF records (only one is used)

DNS TXT records are flat. If you accidentally create multiple TXT records with SPF syntax, only the first one is used. All mechanisms must go in a single record.

Warning

Never create multiple v=spf1 records. Merge all mechanisms into one.

Hitting the 10-lookup limit

Each include:`, `a`, `mx`, and `exists:` mechanism triggers a DNS lookup. The RFC 7208 limit is hard: more than 10 lookups causes a permerror, and SPF evaluation fails. This is the single biggest pain point with SPF and why solutions like UglyDMARC exist.

Using ptr (deprecated and insecure)

PTR records are not authoritative, and attackers can set PTR records pointing to domains they don't own. Never rely on ptr: for authorization.

Forgetting to publish an SPF record

If your domain has no SPF record, receivers treat it as a "neutral" result—mail might still be accepted, but there's no proof of authorization. For critical domains, an explicit policy is essential.

When SPF fails

SPF evaluation can result in several outcomes:

  • Pass: The sender's IP matches an authorized mechanism. Mail should be accepted.
  • Fail: The sender's IP matches the `-all` rule or a fail mechanism. Receiver should reject.
  • Soft fail: The sender's IP matches a `~all` rule. Receiver should accept but flag as suspicious.
  • Neutral: No SPF record found, or the result is `?all`. Receiver has no guidance.
  • Permerror: The SPF record is malformed or requires more than 10 DNS lookups. Mail is treated as failing.
  • Temperror: A temporary DNS lookup failure. Receiver should retry later.

The permerror (too many lookups) is the most insidious: your legitimate mail fails silently, and you won't know why unless you run a manual SPF check.

Going further

SPF is foundational, but it's not bulletproof. It can't prevent a compromised authorized server from sending phishing mail, and the 10-lookup limit breaks at scale. That's where DKIM and DMARC come in.

If you're hitting the lookup limit or managing many vendors, read about the 10-lookup problem and how to solve it. Or jump to DKIM to add cryptographic signing.