SPF.Guru

How SPF Guru works

SPF Guru does not shorten your record. It puts two macro-based includes at the front of it, and answers those two queries by evaluating the rest of the record on your behalf, where the ten-lookup limit does not apply.

The problem: ten DNS lookups

SPF lets a domain owner declare which servers may send on its behalf, with a hard limit of ten DNS-resolving terms. Each include:, a, mx, ptr, exists and redirect= counts against it.

Exceed the limit and evaluation returns permerror. Receiving servers treat that as no usable SPF result, DMARC alignment fails on the SPF side, and mail that should have been authenticated is not.

Why it happens so often

A typical organisation sends from several platforms: Microsoft 365, Google Workspace, a CRM, a helpdesk, a marketing tool. Each contributes an include:, and those includes contain includes of their own. Four or five vendors is usually enough to go over.

Best practice first: use subdomains

The cleanest long-term fix is to send different classes of mail from different subdomains, each with its own short record:

If you can do that, do it. SPF Guru exists for the cases where you cannot, because a vendor insists on your root domain or a system is too old to change.

What SPF Guru adds to your record

One exists term, and your own policy moved up behind it:

v=spf1 exists:i.%{ir}._d.%{d}.my.spf.guru ~all <your existing mechanisms>

The include uses SPF macros. %{ir} expands to the connecting IP address in reverse order, and %{d} to your domain. For 1.2.3.4 sending as example.com, a receiving server resolves exactly one name:

i.4.3.2.1._d.example.com.my.spf.guru

The all keeps whatever qualifier your record already had. If you published -all you still hard fail, and ?all is still neutral. We are reducing lookups, not changing your policy.

What happens when that query arrives

  1. SPF Guru reads the IP and the domain out of the query name, fetches your published record, and evaluates the mechanisms that sit after the all.
  2. If that IP is authorised, it answers. An exists mechanism matches when the name resolves, so your record matches there and evaluation stops with a pass. One lookup.
  3. If it is not authorised, there is no answer, the mechanism does not match, and the very next term is your own all, which decides the outcome. Still one lookup.

Each unauthorised check spends one of the two void lookups RFC 7208 allows, because an empty answer is how the mechanism says no. That is the one cost this design carries, and it leaves a margin of one.

Do not delete the rest of your record. The mechanisms after the all are not leftovers. Receivers ignore them, which is the point, but they are the input SPF Guru reads when answering. Remove them and there is nothing to evaluate, so every sender fails. To roll back, delete the guru include and move the all back to the end.

If SPF Guru is unreachable

This is the reason the record uses exists rather than include. An include pointing at a name that does not resolve is a permerror under RFC 7208, which would break the record for every sender the moment our DNS had a bad day. An exists that cannot be answered is simply "no match", so evaluation moves to the next term and your own all still decides.

Unauthorised mail is therefore still handled exactly as you intended. What you lose during an outage is recognition of your authorised senders, so they soft-fail rather than pass, and DKIM carries DMARC until the lookup works again.

You can protect one sender against even that by putting its include directly after the guru term, before the all:

v=spf1 exists:i.%{ir}._d.%{d}.my.spf.guru include:spf.protection.outlook.com ~all <the rest>

Because a non-matching exists falls through, that include is reached whenever SPF Guru does not answer, and skipped entirely whenever it does. Unlike the older design there is no ordering trap and no cost in the normal case.

Choose the vendor for cost anyway, since it is paid on every check that SPF Guru does not match. Microsoft's spf.protection.outlook.com is a flat list of addresses and costs one lookup. Google's _spf.google.com nests three more records behind it and costs four. This protects only the senders you list.

Already publishing the include form?

Earlier records used include:i.%{ir}._d.%{d}.my.spf.guru instead of an exists, and those keep working. SPF Guru still answers them, they still cost one lookup, and this site still recognises a domain using one as already configured. Nothing breaks and there is no deadline.

The difference only shows up when SPF Guru cannot answer. An include pointing at a name that does not resolve is a permerror, so an outage would break the record for every sender, where the exists form falls through to your own all. That is why the tool now generates exists, and it is the only reason to switch.

Why this is not flattening

SPF flattening tools expand your vendors into a literal list of IP addresses. That list is correct on the day it is generated and starts rotting immediately, because vendors add and renumber servers without telling you. SPF Guru resolves your record at query time, so adding a vendor to it works straight away with no regeneration step.

What other checkers will tell you

Your record still contains all its original mechanisms, so a checker that counts terms without evaluating them will still report more than ten lookups. That is expected. The number that affects delivery is the number a receiving server actually performs, which is two.

Trade-offs worth knowing

SPF Guru does not replace best practice. It buys you deliverability where best practice cannot be applied.