Quick Answer

Debug SPF failures by checking your record exists (dig TXT domain.com), verifying syntax and lookup count (MXToolbox), confirming the sending IP is covered by your mechanisms, and checking email headers for the specific failure reason. Common failures: permerror (too many lookups or syntax error), softfail (~all and IP not listed), fail (-all and IP not listed).

Debugging SPF Failures with dig, nslookup, and Online Tools

By Braedon·Mailflow Authority·Email Authentication·Updated 2026-03-31

Step 1: Verify Your SPF Record Exists

Using dig (Linux/Mac)

dig TXT yourdomain.com +short

Expected output:

"v=spf1 include:_spf.google.com include:sendgrid.net ~all"

If no output contains v=spf1, you don't have an SPF record.

Using nslookup (Windows)

nslookup -type=TXT yourdomain.com

Checking Specific DNS Servers

During propagation, check authoritative servers:

# Google DNS
dig TXT yourdomain.com @8.8.8.8 +short

# Cloudflare DNS
dig TXT yourdomain.com @1.1.1.1 +short

# Your domain's authoritative server
dig NS yourdomain.com +short
dig TXT yourdomain.com @ns1.yourdns.com +short

Step 2: Validate Syntax and Lookup Count

Using MXToolbox

  1. Go to MXToolbox SPF Record Lookup
  2. Enter your domain
  3. Check for:
    • Syntax errors (highlighted in red)
    • DNS lookup count (must be ≤10)
    • Void lookups (must be ≤2)
    • Multiple SPF records (must have exactly 1)

Using dmarcian SPF Surveyor

  1. Go to dmarcian.com/spf-survey
  2. Enter your domain
  3. View the visual tree of all includes
  4. See total lookup count at each level

Practitioner note: MXToolbox is my first stop for SPF debugging. It catches 90% of issues in 10 seconds—multiple records, lookup limits, syntax problems—all flagged clearly.

Step 3: Find the Failing IP

The sending IP is what SPF checks. To debug, you need to know which IP tried to send.

From Email Headers

Open the failed email and find headers. Look for:

Authentication-Results: mx.google.com;
    spf=softfail (google.com: domain of [email protected] does not designate 192.0.2.50 as permitted sender) [email protected]

The IP address in the SPF result (192.0.2.50) is what failed.

From Received Headers

Received: from mail.example.com (192.0.2.50) by mx.google.com ...

The IP in parentheses is the connecting server.

Step 4: Check If IP Is Covered

Now verify if your SPF record authorizes that IP.

For include Mechanisms

Trace the include chain:

# Your record
dig TXT yourdomain.com +short
# "v=spf1 include:sendgrid.net ~all"

# SendGrid's record
dig TXT sendgrid.net +short
# "v=spf1 ip4:167.89.0.0/17 ip4:208.117.48.0/20 ..."

Is 192.0.2.50 within those IP ranges? If not, SPF correctly fails.

For ip4 Mechanisms

Check if the IP falls within your listed ranges:

ip4:192.0.2.0/24

This covers 192.0.2.0 through 192.0.2.255. Check with an IP calculator if needed.

Step 5: Common Failure Patterns

Pattern 1: permerror

Header shows:

spf=permerror

Causes:

  • Too many DNS lookups (>10) — see the 10 DNS lookup limit guide
  • Syntax error in record
  • Multiple SPF records
  • Void lookup limit exceeded (>2)

Debug:

# Check for multiple records
dig TXT yourdomain.com +short | grep -c spf
# Should return 1

# Check lookup count with MXToolbox

Pattern 2: softfail

Header shows:

spf=softfail (domain does not designate IP as permitted sender)

Causes:

  • Record ends with ~all
  • Sending IP not covered by any mechanism
  • Forwarded email (forwarder IP not authorized)

Debug:

  • Identify the IP from headers
  • Trace include chain to see if IP should be covered
  • If legitimate sender, add their include or IP

Pattern 3: fail

Header shows:

spf=fail

Causes:

  • Record ends with -all
  • Sending IP definitely not authorized
  • Spoofing attempt (expected behavior)

Debug: Same as softfail—verify if the IP should be authorized.

Pattern 4: neutral

Header shows:

spf=neutral

Causes:

  • Record ends with ?all
  • IP matched a mechanism with ? qualifier

Debug: Check your record—you probably have ?all instead of ~all or -all.

Pattern 5: temperror

Header shows:

spf=temperror

Causes:

  • DNS timeout during SPF lookup
  • Temporary DNS server issue
  • Network problem

Debug: Usually resolves on retry. If persistent, check DNS server health.

Step 6: Test Specific Scenarios

Test from Your ESP

Most ESPs provide test tools:

  • SendGrid: Settings → Sender Authentication → Verify
  • Mailgun: Sending → Domains → Check DNS Records
  • Google Workspace: Admin → Apps → Google Workspace → Gmail → Authenticate Email

Send Test Email

  1. Send from the suspected service/IP
  2. Send to a Gmail account
  3. Open email → Three dots → Show original
  4. Check Authentication-Results for SPF
spf=pass (google.com: domain of [email protected] designates 167.89.123.45 as permitted sender)

Practitioner note: When clients report "SPF is failing," I always ask for the actual email headers first. Half the time, the issue isn't SPF at all—it's DKIM or DMARC, and they've misread the authentication results.

Quick Reference Commands

# Check SPF record
dig TXT yourdomain.com +short | grep spf

# Check specific include
dig TXT _spf.google.com +short

# Check with specific DNS server
dig TXT yourdomain.com @8.8.8.8 +short

# Count SPF records (should be 1)
dig TXT yourdomain.com +short | grep -c "v=spf1"

# Trace full include chain
dig TXT yourdomain.com +short
dig TXT _spf.google.com +short
dig TXT _netblocks.google.com +short

When to Get Help

If you've traced the include chain, verified the IP, checked lookup counts, and still can't identify the issue, schedule a consultation. Some SPF problems require deep DNS analysis or involve complex multi-sender configurations.

Sources


v1.0 · March 2026

Frequently Asked Questions

How do I check my SPF record with dig?

Run: dig TXT yourdomain.com +short | grep spf. This returns your SPF record. If nothing returns, you don't have an SPF record published.

How do I find the sending IP that failed SPF?

Check the email headers. Look for 'Received: from' lines or the 'Authentication-Results' header. The IP that connected to the receiving server is what SPF checks.

What does 'SPF permerror' mean in headers?

Permerror means your SPF record has a permanent error—usually too many DNS lookups (over 10), syntax errors, or multiple SPF records. The receiving server couldn't evaluate your record.

Why is SPF failing when my record looks correct?

Common causes: sending IP isn't covered by your includes, nested includes exceed lookup limit, you have multiple SPF records, or there's a propagation delay after recent DNS changes.

How long does DNS propagation take for SPF changes?

Typically 15-30 minutes, but can take up to 48 hours depending on TTL settings. Use dig with @8.8.8.8 to check Google's DNS or @1.1.1.1 for Cloudflare during propagation.

Want this handled for you?

Free 30-minute strategy call. Walk away with a plan either way.