SPF.Guru Sign in

SPF and PermError FAQ

Everything worth knowing about SPF records, the ten DNS lookup limit, PermError, and where SPF Guru does and does not help.

SPF and SPF records

What is SPF?

Sender Policy Framework lets a domain owner declare which mail servers may send on the domain's behalf. Receiving servers check the connecting IP against that list, which makes casual spoofing harder.

What is an SPF record?

A DNS TXT record beginning v=spf1 that lists the authorised senders. It lives at the domain itself, not at a special name.

Why does SPF matter?

It is one of the two ways DMARC can pass, the other being DKIM. Without a working SPF record, mail is more likely to be rejected or filtered.

What does an SPF record look like?

A short one might be v=spf1 include:_spf.google.com include:spf.protection.outlook.com ~all.

What does -all mean?

Hard fail. Any server not matched by an earlier mechanism is explicitly not authorised, and receivers may reject it outright, potentially during the SMTP conversation before DKIM or DMARC are considered at all. It is the right setting for a domain that sends no mail. It is not the goal for a domain that does. ~all or -all, explained in full covers why.

What does ~all mean?

Soft fail. Unauthorised servers are flagged but not rejected on SPF alone, which leaves the decision to DMARC. For a domain that sends mail and publishes DMARC, this is the recommended end state, not a temporary step on the way to -all.

How do I check my SPF record?

Enter your domain to see the record and what it costs in lookups, expand its include tree to see where those lookups go, or use the SPF checker to test a specific sending IP. dig TXT example.com works too.

Can a domain have more than one SPF record?

No. Exactly one. Two or more v=spf1 records is a permerror on its own, because a receiving server has no way to choose between them, and it fails that way whatever the records themselves contain. Merge them into a single record. Other TXT records on the same name are fine and do not count; only the ones beginning v=spf1 matter. Checking your domain reports this case specifically rather than a lookup count, because there is no sensible count to report until it is fixed. How to merge two SPF records covers the pitfalls.

What are the SPF mechanisms?

include, a, mx, ptr, exists and redirect= all cost a DNS lookup. ip4, ip6 and all cost nothing.

How often should I update my record?

Whenever a sending service is added or removed. Stale includes are a common cause of both wasted lookups and void lookups.

PermError and the lookup limit

What is SPF PermError?

A permanent error: the record could not be evaluated at all. Receivers treat it as though there were no SPF result, so SPF contributes nothing to DMARC.

What causes PermError?

Most often exceeding the ten DNS lookup limit. Also syntax errors, more than one SPF record, or more than two void lookups. What PermError means and how to fix it covers each cause in turn.

What is the ten DNS lookup limit?

RFC 7208 allows at most ten DNS-resolving terms per evaluation. The limit exists so a single message cannot trigger unbounded DNS traffic. How the count works, and why records exceed it goes through it properly.

How is the count worked out?

Each include, a, mx, ptr, exists and redirect= costs one, and the count carries down into every nested include. One vendor include can easily cost five on its own.

Does an mx mechanism count once or once per host?

Once. The mx term itself costs one of your ten. The A or AAAA lookups for each mail host are not charged to that budget, but they have a separate cap: more than ten address records under a single mx is a permerror in its own right. A domain with a large mail cluster can therefore fail at three terms.

What happens when I go over?

Evaluation returns permerror at the point it runs out of budget, which means the damage is partial and order-dependent. A sender matched within the first ten lookups still passes. A sender whose authorising mechanism sits beyond the tenth gets permerror, as does any IP that matches nothing, so your all policy is never reached. This is why the symptom is usually one vendor's mail failing rather than everything breaking at once.

How do I know if I am over?

Enter your domain. SPF Guru walks the whole record, including nested includes, and reports the true number even when it is above the limit. The include tree then shows which branch is spending it, which is the part that tells you what to change.

Why is this so common?

Because the limit counts nested lookups. Four or five vendors, each with an include of their own, is enough, and nothing warns you when you cross it. We measure what each vendor costs against live DNS: one of them spends nine of your ten on its own.

What is the difference between SPF fail and PermError?

Fail means the record was evaluated and the sending IP was not authorised. PermError means the record could not be evaluated at all.

Does PermError affect DMARC?

Yes. DMARC needs SPF or DKIM to pass and align. A PermError means SPF cannot pass, so DKIM is carrying DMARC alone.

What are void lookups?

Lookups that return nothing. More than two is a permerror by itself, independent of the ten lookup limit. An include pointing at a domain with no SPF record is a stale one worth removing. A macro exists: producing NXDOMAIN is not: that is how a vendor answers 'not this IP', it happens on nearly every check, and removing it would break that sender. It does mean such a domain permanently spends one of its two permitted voids.

Using SPF Guru

What is SPF Guru?

A free service that answers macro-based DNS queries on your behalf, so a receiving server performs one lookup instead of however many your record would otherwise need.

How does it fix PermError?

One term is placed at the front of your record, followed by your own policy. A receiving server resolves it, gets a definitive answer, and stops before it reaches the rest, so the ten lookup limit is never approached. How SPF Guru works sets out the mechanism in full.

What do I add to my record?

One term and your own policy, immediately after v=spf1: exists:i.%{ir}._d.%{d}.my.spf.guru followed by the all your record already ended with. Everything you publish today stays after it, untouched. The home page generates the exact record for your domain.

Why does the all move to the front?

Because an include only matches when the included record returns pass. An authorised sender matches the guru include and passes; everything else falls straight through to the next term, which is now your all. That is one lookup for both outcomes, and it keeps your own policy: -all still hard fails, ?all is still neutral.

Why is my old record still in there after the all?

Because it is the input SPF Guru evaluates on your behalf. Receivers ignore everything after an all, so it costs them nothing, but SPF Guru reads it from your TXT record. Delete it and there is nothing left to authorise anyone. To roll back, remove the guru include and move the all back to the end.

Do I remove my existing includes?

No, and this is the most important thing on this page. They move to after the all, where receivers ignore them, but they are what SPF Guru reads when it answers. Delete them and there is nothing left to evaluate, so every sender starts failing.

Can I use it for just one vendor?

Yes. Append ._i.%{ir}.my.spf.guru to a vendor's domain inside the existing include, and that vendor's whole record costs you one lookup instead of five or six. The rest of your record is untouched, and because an include only matches on pass, evaluation carries on normally if the sender is not theirs. Offloading a single vendor walks through it, and the vendor costs we measure will tell you which one is worth offloading.

Why exists: rather than include:?

Because of what each does when the name cannot be resolved. An include: pointing at a name that does not resolve is a permerror under RFC 7208, so a bad day for our DNS would have broken your record for every sender. An exists: that cannot be answered is simply 'no match', so evaluation moves on to your own all and your policy still decides. The cost is that every unauthorised check spends one of the two void lookups the RFC allows, because an empty answer is how the mechanism says no.

What if SPF Guru is unreachable?

The guru term does not match and your own all decides, so unauthorised mail is still handled as you intended. What you lose is recognition of your authorised senders, which soft-fail rather than pass until the lookup works again, with DKIM carrying DMARC in the meantime. If one sender matters more than the rest, put its include directly after the guru term and before the all: it is reached whenever SPF Guru does not answer and skipped entirely whenever it does.

Why do other checkers still say I am over the limit?

Because most of them count the terms in your record without evaluating it. Your record still contains every original mechanism, so a static count is still high. The number that affects delivery is what a receiving server actually performs, which is one. Both numbers are correct; the explanation covers why they differ.

Is it free?

Yes, and community supported. There is no account and nothing to install. Who runs it, and who pays for it is a fair question and answered plainly.

What does SPF Guru see about my mail?

No mail passes through SPF Guru; it only answers DNS queries. Those queries necessarily carry the sending IP and your domain, encoded in the query name, and aggregate pass and fail counts are recorded from them. Message content, recipients and headers are never involved. How to report a security issue if you find anything that contradicts this.

Can I use it in production?

Many people do. Test it first, keep DKIM configured so DMARC has a second way to pass, and read the disclaimer: this is a best-effort free service.

Good practice

Is SPF enough on its own?

No. Configure DKIM as well. DMARC passes if either SPF or DKIM passes and aligns, so DKIM covers you when SPF cannot, particularly on forwarded mail.

Should I use -all or ~all?

If the domain sends mail and publishes DMARC, use ~all. If it sends no mail at all, use v=spf1 -all. M3AAWG's Email Authentication Best Practices holds that a DMARC pass should override an SPF fail, except where a domain declares it sends nothing, and the DMARCbis draft references that same recommendation.

Is -all the goal?

No, and this is the most common misconception about SPF. Hardfail was the only enforcement SPF had before DMARC existed, so it came to be treated as the finish line. With DMARC at quarantine or reject, ~all gives the same security outcome, because DMARC is doing the enforcing. What it avoids is a receiver rejecting during SMTP on the SPF result alone, before DKIM has been checked, which is how forwarded and relayed mail gets lost. A hardfail rejection is also invisible in your DMARC reports, so you lose the evidence you would need to diagnose it.

Does anyone disagree?

Microsoft's guidance prefers -all in some configurations, on the grounds that DMARC policy is effectively ignored for ~all failures when a message carries no DKIM signature at all. That is a real gap, and it closes as soon as every sending source signs with DKIM. Configure DKIM everywhere and the objection does not apply to you.

What is SPF flattening?

Replacing includes with the literal IP addresses they currently resolve to. It reduces lookups, and it goes stale the moment a vendor renumbers, without telling you. Why SPF Guru resolves at query time instead explains the difference.

How is SPF Guru different from flattening?

Nothing is expanded or frozen. Your record keeps its includes and they are resolved at query time, so adding a vendor works immediately with no regeneration step.

Should I use subdomains instead?

If you can, yes. Sending different classes of mail from different subdomains, each with its own short record, is the cleanest fix, and moving one expensive vendor to a subdomain is often enough on its own. SPF Guru is for when a vendor insists on your root domain.

How long can an SPF record be?

Each TXT string is capped at 255 characters, and a record can be split across several strings. Keeping the whole response inside a single UDP packet, roughly 450 characters, avoids relying on TCP fallback.

Does SPF stop spoofing?

Only of the envelope sender, which recipients never see. Display-name and From-header spoofing needs DKIM and DMARC.

What is the difference between SPF and DKIM?

SPF authorises the sending IP. DKIM cryptographically signs the message, so it survives forwarding where SPF usually does not.

How should I monitor this?

Read your DMARC aggregate reports. They show SPF results across real traffic, which is the only way to catch a sender you forgot about.

Can I test before going live?

Yes. Use a subdomain, or use the SPF checker to evaluate a specific sending IP against a domain before you change anything. It also accepts a record to test, so a proposed record can be evaluated before it is published; the includes inside it still resolve for real, which is what makes the preview truthful.

Troubleshooting

My record is not being recognised

Check for a second SPF record, a syntax error, or a change that has not propagated. The SPF checker shows every step of evaluation, including which record was actually selected, which is the quickest way to see a name carrying two v=spf1 records.

What is redirect= ?

It hands evaluation to another domain's record entirely. It costs a lookup, and any all mechanism in your own record is ignored when it is used.

Why does forwarding break SPF?

The forwarding server is not in the original domain's record, so SPF fails on the second hop. DKIM survives forwarding, which is why you need both. Why forwarding breaks SPF covers SRS and ARC too.

My DMARC reports show SPF failures

Check alignment as well as the result. SPF can pass for the envelope domain while failing DMARC because that domain does not align with the From header.

Does IPv6 matter?

Yes. If you send over IPv6 and only publish ip4 mechanisms, those messages fail. Publish ip6 alongside.

Can I use this on a subdomain?

Yes. The %{d} macro expands to whichever domain is being evaluated, so the same record works on a subdomain. It can also be hardcoded if you want a subdomain to be evaluated against the parent.

What is the quickest fix for PermError?

Enter your domain, copy the generated record, and publish it as your SPF TXT record. Leave everything after the all in place.

Still stuck? Check your domain to see what your record actually costs, or raise an issue at github.com/smck83/spf.guru/issues.