1. Library
  2. Computer Networks
  3. Email Protocols
  4. Authentication

Updated 8 hours ago

SPF is a public declaration: "These servers speak for me. Everyone else is lying."

You publish a DNS record listing every IP address and service authorized to send email as your domain. When mail arrives claiming to be from you, receiving servers check your SPF record. If the sending server isn't on the list, the message fails authentication.

The concept is simple. The implementation has teeth.

Inventory Everything First

Before touching DNS, list every system that sends email using your domain:

  • Your mail server (or Google Workspace, Office 365)
  • Marketing platforms (Mailchimp, SendGrid, Constant Contact)
  • CRM systems (Salesforce, HubSpot)
  • Support tickets (Zendesk, Freshdesk)
  • Monitoring alerts
  • Web application notifications
  • Transactional email services

Miss one, and that service's emails start failing. This is the step most people rush through and later regret.

For each service, find either:

  • The IP addresses they send from
  • Their SPF include string (most SaaS providers publish one)

Check if you already have an SPF record:

$ dig yourdomain.com TXT | grep spf

If one exists, you'll modify it. Never create a second SPF record—DNS allows only one per domain.

Build the Record

Every SPF record starts the same way:

v=spf1

Then you add mechanisms that authorize senders.

Your own mail server:

v=spf1 mx

This authorizes whatever servers your MX records point to. Or specify IPs directly:

v=spf1 ip4:203.0.113.10
v=spf1 ip4:203.0.113.0/24

Cloud email providers:

Google Workspace:

include:_spf.google.com

Office 365:

include:spf.protection.outlook.com

Third-party services:

ServiceInclude String
Mailchimpinclude:servers.mcsv.net
SendGridinclude:sendgrid.net
Mailguninclude:mailgun.org
Salesforceinclude:_spf.salesforce.com

Combine them:

v=spf1 mx include:_spf.google.com include:servers.mcsv.net include:sendgrid.net -all

End with a policy:

  • ~all (softfail): Unauthorized servers are flagged but mail still delivers. Use during testing.
  • -all (fail): Unauthorized servers are rejected. Use in production.

Never use +all. It authorizes everyone and defeats the entire purpose.

The 10-Lookup Limit

SPF allows a maximum of 10 DNS lookups. Exceed this and SPF returns "permerror"—authentication fails entirely.

Mechanisms that cost lookups:

  • mx — 1 lookup
  • a — 1 lookup
  • include — 1 lookup, plus whatever that record contains
  • exists — 1 lookup

Mechanisms that are free:

  • ip4 and ip6 — no lookups
  • all — no lookups

This limit made sense in 2006. Today, with companies using a dozen SaaS tools that all send email, it's a constant headache.

When you hit the limit:

  1. Replace include statements with raw IP ranges where services publish them
  2. Consolidate email services (do you really need four marketing platforms?)
  3. Use SPF flattening tools that resolve includes to IPs automatically

Validate Before Publishing

Use these tools to check your record before it goes live:

  • MXToolbox SPF Record Checker
  • dmarcian SPF Surveyor
  • EasyDMARC SPF Checker

They verify syntax, count DNS lookups, and show exactly which IPs your record authorizes.

Publish the Record

Add a TXT record to your DNS:

FieldValue
TypeTXT
Name@ (root domain)
Valuev=spf1 mx include:_spf.google.com ~all
TTL3600

Subdomains need separate records. If you send mail from newsletter.yourdomain.com, it needs its own SPF:

newsletter.yourdomain.com.  IN  TXT  "v=spf1 include:sendgrid.net -all"

Subdomains don't inherit the root domain's SPF.

Wait for Propagation

DNS changes take time to spread globally:

  • Minimum: 5-10 minutes
  • Typical: 1-4 hours
  • Maximum: 24-48 hours

Verify propagation:

$ dig yourdomain.com TXT +short
$ dig @8.8.8.8 yourdomain.com TXT
$ dig @1.1.1.1 yourdomain.com TXT

Test It

Send email from your authorized sources to:

  • check-auth@verifier.port25.com
  • Your own Gmail or Outlook account

Check the headers in received messages:

Received-SPF: pass (domain of sender@yourdomain.com designates 203.0.113.10 as permitted sender)

"pass" means SPF worked. "fail" or "softfail" means the sending server wasn't authorized.

Monitor with DMARC

Even before enforcing DMARC, set it up in monitoring mode:

_dmarc.yourdomain.com.  IN  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"

You'll receive reports showing:

  • Which sources pass SPF
  • Which sources fail SPF
  • Potential spoofing attempts

These reports reveal the services you forgot to authorize.

Tighten the Policy

Once DMARC reports confirm all legitimate sources pass:

# Testing:
v=spf1 mx include:_spf.google.com ~all

# Production:
v=spf1 mx include:_spf.google.com -all

The -all policy means unauthorized senders get rejected outright.

Common Mistakes

Multiple SPF records:

Two TXT records starting with v=spf1 causes permerror. Combine everything into one record.

Forgetting a service:

That marketing platform you onboarded six months ago? Its emails are now failing. This is why the inventory step matters.

Not updating after migrations:

Switched from Mailchimp to Klaviyo? Update SPF or the new platform's emails fail.

Exceeding 10 lookups:

Your record worked fine until you added one more include. Now everything fails with permerror.

Maintenance

Quarterly: Review DMARC reports. Check for new services that need authorization.

When adding services: Update SPF immediately. Don't wait for complaints.

Document your record: Note what each mechanism authorizes and when it was added. Future-you will appreciate this.

Frequently Asked Questions About SPF Records

Was this page helpful?

😔
🤨
😃