Siftsmith Run on Apify
← All email error fixes

Fix SPF softfail: “domain does not designate IP as permitted sender”

The receiving server looked up the SPF record of the envelope sender’s domain and the sending IP wasn’t in it. Softfail means the record ends in ~all; fail means -all. Paste the header to run the same check for that IP: you see which term decided, whether the IP is in a common sending service’s SPF record, and its reverse DNS name, which often points to a forwarder.

Last verified 9 October 2026.

Check why the IP isn’t a permitted sender

Paste the message headers (in Gmail: More > Show original), or just the Received-SPF: or spf= line. Or type the envelope sender domain and the IP. The check runs in your browser against public DNS.

Or type them:

What this can and can’t tell you: it runs RFC 7208’s check_host() for the IP and domain through Cloudflare’s public resolver (Google’s when Cloudflare’s fails): ip4, ip6, a and mx with prefix lengths, include, redirect=, exists with macros, ptr, the 10-lookup and 2-void-lookup limits, and syntax errors. It then checks the IP against the SPF records of common sending services and looks up its reverse DNS name. A lookup that fails shows as temperror, and a macro it can’t fill in (such as %{p}, or %{h} without the HELO name) as “can’t tell here”: never as fail.

What the message means

When a server receives mail, it runs an SPF check on the domain in the envelope sender (the SMTP MAIL FROM, copied into Return-Path:) and the IP address that connected. It records the answer in the headers. Gmail writes:

Received-SPF: softfail (google.com: domain of transitioning bob@example.com does not designate 192.0.2.1 as permitted sender) client-ip=192.0.2.1;
Authentication-Results: mx.google.com;
       spf=softfail (google.com: domain of transitioning bob@example.com does not designate 192.0.2.1 as permitted sender) smtp.mailfrom=bob@example.com

Microsoft writes Received-SPF: SoftFail (protection.outlook.com: domain of transitioning example.com discourages use of 192.0.2.1 as permitted sender), and spf=softfail (sender IP is 192.0.2.1) smtp.mailfrom=example.com in Authentication-Results:. Some receivers leave the IP out of the SPF line; it’s then in the Received: line the receiver added. All of them say the same thing: example.com’s SPF record doesn’t authorize 192.0.2.1.

Softfail vs fail

The last term of the record decides what an unlisted IP gets:

Record ends inResultWhat RFC 7208 says
~allsoftfail“a weak statement by the publishing ADMD that the host is probably not authorized”; receivers “SHOULD NOT reject the message based solely on this result” (§2.6.5, §8.5).
-allfail“an explicit statement that the client is not authorized to use the domain in the given identity” (§2.6.4).
?all, or no all and no redirect=neutralNo statement either way.

For delivery, DMARC usually matters more than the SPF result alone: a message passes DMARC when SPF or DKIM passes for a domain aligned with the From: address. So a softfail or fail next to an aligned DKIM pass still passes DMARC. A softfail with no passing DKIM fails DMARC, and the domain’s p= policy applies.

Sources: RFC 7208 §2.6.4, §2.6.5, §4.6.4, §5.2, §6.1 and §8.5 (checked 9 October 2026).

Causes and fixes

A sending service isn’t in your SPF record

The most common cause: you started sending through a new service (a newsletter tool, CRM, help desk, invoicing app, a new mail host) and its servers aren’t listed. Add the include its setup guide gives, before the all term. The checker above tells you when the IP is in one of these services’ records:

ServiceAdd
Google Workspaceinclude:_spf.google.com
Microsoft 365include:spf.protection.outlook.com
Amazon SESinclude:amazonses.com
SendGridinclude:sendgrid.net
Mailguninclude:mailgun.org
Mailchimpinclude:servers.mcsv.net
Mailchimp Transactional (Mandrill)No include: a return-path subdomain with a CNAME to mandrillapp.com
Brevoinclude:spf.brevo.com
Zoho Mailinclude:zohomail.com
Salesforceinclude:_spf.salesforce.com
Zendeskinclude:mail.zendesk.com
Fastmailinclude:spf.messagingengine.com

Amazon SES and Mailchimp Transactional (Mandrill) send with a Return-Path on their own domain by default, so SPF checks their record, not yours. For SES, a custom MAIL FROM subdomain gets its own record, v=spf1 include:amazonses.com ~all, as the SES setup shows. Mandrill’s custom return-path is a subdomain with a CNAME to mandrillapp.com, so it uses Mandrill’s record and needs no include on yours. Each name above publishes an SPF record (checked in DNS on 9 October 2026). Your record stays one TXT record: v=spf1 include:_spf.google.com include:sendgrid.net ~all, never a second v=spf1 record (two records are a permerror).

The wrong domain was checked

SPF checks the envelope sender, not the From: address. Look at smtp.mailfrom= or envelope-from= in the header: many services send with a Return-Path on their own domain, or on a subdomain of yours such as bounce.example.com, and that domain’s record is the one checked. Fix the record of the domain the header names, or set up the service’s custom return-path so it uses your domain. For DMARC, the envelope domain also has to align with From:; see DMARC alignment failed.

The message was forwarded

When an alias, a mailing list or a mailbox forward passes your message on, the forwarder’s server connects to the final receiver with its own IP. Your record can’t list every forwarder, so SPF fails or softfails there, and that’s expected. The fix is DKIM: a signature on your domain survives forwarding as long as the message isn’t modified, and an aligned DKIM pass makes DMARC pass. The checker shows the IP’s reverse DNS name, which often names the forwarder’s network; it can’t prove forwarding on its own.

The record is over the 10-lookup limit

RFC 7208 §4.6.4 limits include, a, mx, ptr, exists and redirect to 10 DNS lookups per check, and allows at most 2 lookups that find nothing (void lookups). Past either limit the result is permerror, so includes after that point never count. The checker reports the lookup that goes over. See SPF PermError and too many DNS lookups.

An include has no SPF record

An include: of a name without an SPF record doesn’t just fail to match: RFC 7208 §5.2 makes it a permerror, and the same goes for redirect= (§6.1). This happens when a service retires the include name you copied years ago. Replace it with the one the service documents today.

FAQ

Is SPF softfail bad?

It means the sending IP isn’t in the domain’s SPF record and the record ends in ~all. On its own a softfail rarely gets mail rejected: RFC 7208 says receivers “SHOULD NOT reject the message based solely on this result”. But SPF didn’t pass, so DMARC now depends on DKIM. If DKIM also fails or isn’t aligned, the message fails DMARC and the domain’s policy decides whether it’s junked or rejected.

Should I change ~all to -all?

Only after every service that sends as your domain is in the record. -all asks receivers to treat unlisted IPs as unauthorized, so a service you forgot fails harder. With DMARC at p=quarantine or p=reject, the DMARC policy already decides what happens to unauthenticated mail, so ~all and -all usually make little difference to delivery. One exception: RFC 7489 §10.1 warns that a receiver that checks SPF before DMARC can reject on -all before DMARC is evaluated, even when DKIM would have passed.

Why does SPF check a different domain than my From: address?

SPF checks the envelope sender: the address in MAIL FROM, which ends up in the Return-Path: header. Sending services often set it to their own domain (bounces.example-esp.com), so the header’s smtp.mailfrom= names their domain, not yours. Fixing SPF on your From: domain doesn’t change that result; a custom return-path on your domain, or an aligned DKIM signature, does.

My SPF record includes the service. Why does the IP still fail?

Three usual reasons: the message went out from an IP the service doesn’t list in its own SPF record (a different region or a dedicated IP), the record is over the 10 DNS-lookup limit so receivers return permerror before reaching the include, or a forwarder relayed the message. Paste the header into the checker on this page: it shows each term evaluated for that IP and which one decided.

Checking many domains?

If you manage domains for clients or brands, Email Security Signals reads each domain’s SPF record with its DNS-lookup count and its all term, alongside DKIM, DMARC, MTA-STS and an A–F grade, one row per domain. $0.02 per graded domain ($20 per 1,000); invalid inputs, domains that don’t exist, DNS lookup failures and duplicates are free.

Check a list on the Apify Store →

Related: 550 5.7.23 SPF validation failed, DMARC alignment failed, SPF PermError and the free DMARC, SPF and DKIM checker.