If you are here because your emails suddenly started bouncing, landing in spam, or your ESP dashboard is screaming SPF PermError, yeah. Been there.
The annoying part is that SPF is supposed to be simple.
The even more annoying part is that modern outbound stacks are not simple anymore. You have Google Workspace or Microsoft 365, a sending tool, a tracking domain, maybe a warm up tool, maybe a CRM, maybe a helpdesk, maybe a newsletter tool you forgot you connected last year.
And SPF has a hard limit. Not a best practice. A limit.
So this post is basically a fast rescue guide. What “SPF flattening” actually is, why PermError happens, and how to fix it quickly without breaking your mail flow.
You can do this in under 15 minutes if you follow the steps and you do not overthink it.
What SPF PermError actually means (in plain English)
SPF is a DNS record that lists which servers are allowed to send email for a domain.
When a receiving mail server checks your SPF record, it needs to do DNS lookups to verify the chain of includes and mechanisms.
SPF has a strict rule:
Maximum 10 DNS lookups during evaluation.
If your SPF evaluation needs more than 10 lookups, many receivers stop and return PermError.
PermError is basically: “I tried to validate your SPF but it is too complex, so I treat it as broken.”
Some receivers will fail it hard. Some will soft fail. Either way, deliverability takes a hit.
The most common reason you hit PermError
This is the classic pattern:
- You started with something clean like
v=spf1 include:_spf.google.com ~all - Then you added a cold outreach tool that told you to add another include
- Then you added a warm up tool
- Then you added HubSpot or Salesforce
- Then you added Zendesk or Intercom
- Then you added a transactional provider you barely use
- Then someone added yet another include for “just testing” and forgot
And now your SPF record has like 7 includes. Each include expands into more lookups. Boom. You cross 10.
This is why people say SPF “breaks” at scale. It does not break. It just has a lookup ceiling.
Quick self check: are you actually in PermError right now?
Before you change anything, confirm it.
Option A: Use a free SPF checker
Search “SPF lookup checker” and run your domain. It will usually show:
- the SPF record string
- total DNS lookups
- whether it exceeds 10
- expanded includes
Option B: Use dig (fast, no tools)
Run:
bash dig txt yourdomain.com +short
Look for the SPF record. It starts with:
"v=spf1 ..."
Then you still need an evaluator to count lookups, but at least you see what is currently published.
Option C: Check headers from a real email
Send an email to a Gmail inbox you control. Open the message, view “Original” and look for spf= results.
You might see spf=permerror or something similar.
What “SPF flattening” means
SPF flattening is basically:
- Take your SPF record with includes
- Expand those includes into the actual IP ranges they resolve to
- Replace
include:mechanisms withip4:andip6:blocks - Reduce DNS lookups so you stay under 10
So instead of:
v=spf1 include:_spf.google.com include:somevendor.com ~all
You end up with something like:
v=spf1 ip4:203.0.113.0/24 ip4:198.51.100.0/24 ... ~all
The upside: lookup count drops.
The downside: vendor IPs can change, and your flattened SPF can become stale unless you maintain it.
So flattening is not “set and forget” unless you have a plan to keep it updated.
Important: flattening is not always the best fix
Sometimes flattening is the fastest emergency fix. But longer term, you might not want a giant IP list in SPF.
Other options:
- Remove vendors you do not use anymore
- Move some tools to subdomains (separate SPF)
- Consolidate sending through fewer providers
- Use a sending platform that does not require extra SPF includes beyond your mailbox provider
But ok. Right now you want PermError gone quickly. So we will do the fast path first, then talk about the “clean architecture” after.
The 15 minute fix plan (high level)
Here is the exact flow:
- Find your current SPF record
- List every include / mechanism
- Remove anything you do not use (quick wins)
- Flatten the remaining includes (reduce lookups under 10)
- Publish the updated SPF record
- Recheck with an SPF validator
- Wait for DNS propagation (usually minutes, sometimes longer)
That is it.
For detailed guidance on how to set up your SPF correctly, let’s do it in a way that does not accidentally break your Google or Microsoft sending.
Step 1: Copy your current SPF record into a scratchpad
Example SPF record (typical messy one):
v=spf1 include:_spf.google.com include:mailgun.org include:sendgrid.net include:servers.mcsv.net include:_spf.salesforce.com include:spf.protection.outlook.com ~all
Now, do not touch anything yet. Just copy it.
Step 2: Count “lookup causing” mechanisms
SPF mechanisms that usually trigger DNS lookups:
include:amxptr(avoid it)exists:redirect=
Mechanisms that do NOT cause lookups:
ip4:ip6:all
So if you see multiple include: plus mx plus a, you are already in danger.
Image suggestion: a simple screenshot style diagram of SPF evaluation and the 10 lookup limit.
(If you do not have this image yet, create a simple graphic. It will perform well in the article.)
Step 3: Do the easiest fix first. Remove stuff you do not use.
This step alone solves PermError surprisingly often.
Ask:
- Do we still use Mailchimp?
- Do we still use SendGrid?
- Do we still use that old ticketing tool?
- Do we still send any email through that vendor at all?
If you are not sure, do not remove it blindly. But if you are sure it is dead, remove its include.
Common “leftover” includes people forget
include:servers.mcsv.net(Mailchimp)include:sendgrid.net(SendGrid)include:mailgun.org(Mailgun)include:_spf.salesforce.com(Salesforce)include:spf.zendesk.com(Zendesk)include:_spf.intercom.io(Intercom)include:spf.protection.outlook.com(Microsoft 365, but only if you actually send via it)include:_spf.google.com(Google Workspace, usually needed)
If you are doing cold outreach from Google Workspace accounts, _spf.google.com stays.
If you are doing cold outreach from Microsoft 365, spf.protection.outlook.com stays.
A lot of domains mistakenly have both.
Step 4: Flatten the remaining includes (the actual PermError fix)
There are two ways to flatten:
- Manual flattening (fast if you only have 1 to 3 includes)
- Automated flattening (recommended, fewer mistakes)
Manual flattening (quick method)
Let’s say your record is:
v=spf1 include:_spf.google.com include:mailgun.org ~all
You need to expand each include to the ip4 and ip6 it ultimately allows.
That means:
- look up
_spf.google.comTXT record(s) - follow its includes
- gather the IP blocks
- do same for Mailgun
- paste those IP blocks into your SPF
This can get messy fast because Google’s SPF includes multiple layers.
So manual is only reasonable when you are flattening a small, stable include that resolves to a known set of IPs.
Automated flattening (the “under 15 minutes” way)
Use an SPF flattening tool that:
- expands includes
- counts lookups
- outputs a flattened SPF string
- ideally provides a way to keep it updated
Most online SPF flatteners do the first three, but the “keep updated” part is where people fail long term.
If you flatten once and never revisit, you can drift over time. IPs change. Vendors add new sending infrastructure. Then you get random SPF fails months later.
So. If you are flattening, either:
- set a calendar reminder to re-flatten every month or quarter, or
- use a platform/workflow that monitors and updates it
The one mistake to avoid while flattening
Do not create multiple SPF records.
You only get one SPF TXT record per hostname. This is a classic error:
- Someone adds a new TXT record like
v=spf1 include:vendor.com ~all - But you already had one like
v=spf1 include:_spf.google.com ~all
Now receivers see two SPF records and treat it as invalid. Different error, same pain.
So when you publish, make sure you are editing the existing SPF record, not adding a second one.
For more detailed guidance on how to properly manage your email SPF record, it's essential to follow best practices to avoid common pitfalls.
Step 5: Publish the new SPF record (and keep it clean)
A good “fixed” SPF record is:
- one TXT record
- fewer than 10 lookups (ideally 0 to 2)
- ends with
~allor-alldepending on policy
Which should you use, ~all or -all?
~allis SoftFail. Common for teams still changing vendors.-allis Fail. Stronger, but punishing if you forgot a sender.
If you are doing outbound and you are not 100 percent sure you listed everything, use ~all for now. You can tighten later.
A realistic example: fixing a broken SPF record
Here is a domain with PermError:
v=spf1 a mx include:_spf.google.com include:spf.protection.outlook.com include:mailgun.org include:sendgrid.net include:servers.mcsv.net ~all
Problems:
aandmxcause lookups, and often are unnecessary- both Google and Microsoft includes, likely not needed
- multiple vendor includes
Quick cleanup (before flattening)
- If you do not need
aandmx, remove them. Most SaaS companies do not need them unless their own server sends mail. - Decide: Google or Microsoft. Not both, unless you genuinely send from both.
Let’s assume you send from Google only, and you use Mailgun for transactional. You no longer use SendGrid or Mailchimp.
Now it becomes:
v=spf1 include:_spf.google.com include:mailgun.org ~all
Now you might still be close to 10 lookups because _spf.google.com expands.
So we flatten Mailgun first, maybe keep Google as include, because Google is stable and widely supported.
In many cases, just removing extras gets you under 10. If not, flatten the smaller vendor.
A practical compromise that usually works
- Keep your mailbox provider as an include (
_spf.google.comorspf.protection.outlook.com) - Flatten the rest
This is often enough to get under 10 without creating an enormous SPF record.
Step 6: Recheck until the validator shows no PermError
After publishing, re run the SPF check.
You are looking for:
- Lookup count under 10
- SPF syntax valid
- Only one SPF record published
If it still shows PermError, it means:
- you still exceed 10 lookups, or
- you still have multiple SPF records, or
- you have a redirect loop, or
- you used
ptr(please do not)
Step 7: Wait for DNS propagation (but do not wait blindly)
DNS propagation is usually quick, but TTL matters.
If your TTL is set to 3600 seconds, that is up to 1 hour. Sometimes longer with caching.
You can check what different resolvers see:
bash dig txt yourdomain.com @8.8.8.8 +short dig txt yourdomain.com @1.1.1.1 +short
If both show the new record, you are basically done.
Where SPF flattening goes wrong (so you can avoid it)
1) You flatten and exceed the SPF TXT character limit
A single TXT string has a 255 character segment limit, though DNS supports splitting across multiple quoted strings in one record.
Most DNS providers handle this automatically when you paste a long SPF, but some require manual quoting.
So if your flattened SPF is huge, make sure your DNS UI supports long TXT values and correctly formats them.
2) You flatten but forget to include your actual mailbox provider
Then your day-to-day sending fails SPF.
This is why I like the “keep Google include, flatten the rest” approach. Less risk.
3) You flatten once, then vendor IPs change
This is the long-term risk. You need a maintenance plan.
4) You try to solve SPF with DKIM or DMARC
Different layers. DKIM and DMARC help, but they do not remove the SPF 10 lookup limit.
The better long-term fix: split sending by subdomain
If you are doing cold outreach, a common best practice is to separate domains anyway:
@yourdomain.comfor core company email@getyourdomain.comor@tryyourdomain.comfor outbound- Or at least a subdomain like
mail.yourdomain.com
Then SPF for outbound can be simpler, and if something goes sideways, you isolate risk.
This also makes DMARC alignment and reputation management cleaner.
And yeah, it is more setup. But it is calmer long term.
How this ties into cold outreach deliverability (the part people skip)
PermError does not just mean “some receiving server can’t validate SPF.”
It can also:
- reduce trust signals across inbox providers
- increase spam placement
- cause bounces in stricter environments (security gateways)
- break DMARC alignment in some scenarios if DKIM is not aligned properly
So even if your emails are still delivering, PermError is like dragging a rope behind the car. Eventually you feel it.
If you are running outbound at any real volume, you want SPF to be boring.
For more information on the technical setup necessary for cold emailing including SPF, DKIM, and DMARC, consider exploring those resources.
A quick checklist you can paste into your SOP
Here:
- Only one SPF TXT record exists
- SPF starts with
v=spf1 - No
ptr - Avoid
aandmxunless needed - Under 10 DNS lookups
- Mailbox provider include is present (Google or Microsoft)
- Ends with
~all(or-allwhen confident) - Flattened vendors have a maintenance plan
Image suggestion: a clean checklist graphic for “SPF PermError fix”.
What to do if you are using Google Workspace for cold outreach
Typical SPF:
v=spf1 include:_spf.google.com ~all
That alone is usually fine. Lookup count is not huge, and Google manages their structure carefully.
PermError usually appears when you add extra includes on top of Google.
So your fix is usually:
- keep Google include
- remove unused vendors
- flatten the rest
What to do if you are using Microsoft 365 for cold outreach
Typical SPF:
v=spf1 include:spf.protection.outlook.com ~all
Same story. Keep Microsoft include. Flatten other vendors.
Tools that add SPF complexity in outbound stacks (so you can anticipate it)
A bunch of outbound and marketing tools do not actually require SPF includes if you are sending via your mailbox provider (they might only need tracking domain CNAME and DKIM for their own domain).
But some providers still ask you to add SPF includes, especially transactional services.
So, if you keep adding tools, you need a rule:
Every time someone adds an SPF include, they must remove one or flatten.
Otherwise PermError returns later.
Where PlusVibe fits (subtle but real)
If you are doing cold outreach at scale, the technical setup is only half the game. The other half is keeping reputation stable once you start sending.
This is where platforms like PlusVibe are useful, because deliverability is not treated like a one time DNS chore. It is part of the workflow.
Stuff like:
- warm up that does not torch your domain
- inbox rotation and throttling so you do not spike volume
- deliverability optimization and monitoring
- bulk verification so you stop hitting dead addresses
SPF PermError is a DNS problem. But it usually shows up because the outbound system around it got messy. Fix the record, then fix the process.
FAQ (the fast ones)
Does SPF flattening hurt deliverability?
Not by itself. It can actually help because PermError disappears. The risk is maintenance. Stale flattened IPs can cause SPF fail later.
Can I just use redirect= instead of includes?
redirect= still causes lookups and can still exceed 10 if the redirected record is complex.
Can DMARC pass if SPF is PermError?
Sometimes, if DKIM passes and aligns. But relying on that is shaky, and some receivers penalize SPF PermError anyway.
Why not just add another SPF record for the vendor?
Because multiple SPF records breaks SPF evaluation. You must merge into one.
How often should I re flatten?
Depends on vendors. Monthly is safe if you rely on flattened third party infrastructure. Quarterly if you only flattened one stable vendor and you monitor.
Wrap up (the actual quick answer)
If you want the simplest way to fix SPF PermError fast:
- Find your SPF record
- Remove unused includes
- Keep only what you truly send from
- Flatten the remaining third party includes until lookups are under 10
- Publish as a single SPF TXT record
- Recheck with a validator
That is it. PermError gone.
And if you are doing cold outreach and you want fewer deliverability fires long term, simplify your sending stack, segment outbound domains, and use a platform that treats deliverability as a system, not a checkbox. That is basically the whole pitch behind PlusVibe.
Now go make SPF boring again.
FAQs (Frequently Asked Questions)
What does SPF PermError mean and why does it happen?
SPF PermError occurs when your domain's SPF record requires more than 10 DNS lookups during validation. Since SPF has a strict limit of 10 DNS lookups, exceeding this causes receiving mail servers to treat the SPF record as broken, leading to delivery issues like emails bouncing or landing in spam.
Why do my emails suddenly start bouncing or land in spam related to SPF?
Emails may bounce or land in spam if your SPF record becomes too complex due to multiple includes from various sending tools and services. This complexity can cause the SPF evaluation to exceed the 10 DNS lookup limit, triggering a PermError and negatively impacting email deliverability.
How can I check if my domain is currently experiencing an SPF PermError?
You can verify SPF PermError by using free online SPF lookup checkers that show your total DNS lookups and if it exceeds 10. Alternatively, use the 'dig' command (e.g., dig txt yourdomain.com +short) to view your SPF record or inspect email headers in Gmail for 'spf=permerror' results.
What is SPF flattening and how does it help fix PermError?
SPF flattening involves expanding all 'include:' mechanisms in your SPF record into their actual IP addresses (ip4/ip6), replacing includes with direct IP ranges. This reduces DNS lookups below the 10-lookup limit, quickly resolving PermError issues. However, flattened records require maintenance as vendor IPs change over time.
Is SPF flattening always the best solution for fixing PermError?
No, while SPF flattening is a quick emergency fix, it's not always ideal long-term due to maintenance overhead. Other strategies include removing unused vendors from your SPF, consolidating sending providers, moving some tools to subdomains with separate SPF records, or using platforms that minimize extra includes.
What are the steps for a quick 15-minute fix to resolve SPF PermError?
The quick fix involves: 1) Finding your current SPF record; 2) Listing all includes and mechanisms causing lookups; 3) Removing any unused services; 4) Flattening remaining includes to reduce DNS lookups under 10; 5) Publishing the updated SPF record; 6) Validating it with an SPF checker; and 7) Waiting for DNS propagation before testing email deliverability again.


























































