SPF Record Publication
A name can answer with an SPF record that isn't the one you wrote. The panel does four things to your SPF records on the way to the name servers, all automatic, and none of them changes what you wrote.
Sender verification explains what SPF is and which policy to choose. This page covers what happens to the record after that.
What you do
Add the SPF record a mail service gives you, word for word, as a custom TXT record on the name. Do this for each service that sends mail for you, e.g. a newsletter service, a shop, or a CRM. Then stop.
You don't join one service's record to another's, count DNS lookups, or shorten anything. The panel does all of that every time a record changes, and your own records stay as you wrote them.
| Step | What it does |
|---|---|
| Merging | Joins all SPF records at one name into a single record. |
| Examination | Counts the DNS lookups and the bytes, and reports every problem in the record. |
| Flattening | Resolves the senders into addresses, but only when the record needs more than ten lookups. |
| Division | Moves the remainder of a long record to additional names. |
To see all four for one name, open the zone's DNS Records page and select SPF Check on the row of an SPF record. The SPF Records for <name> screen shows each step, a badge saying what became of it, and the reason when it didn't run.
The work happens below the record layer, on the way to the name servers. DNS Records shows what you wrote, because that's still there; the name servers answer with the result of the four steps.
Why the panel does this for you
SPF has rules that break a domain silently: a record that breaks one looks correct in your DNS while mail servers stop believing your mail, and the first report comes from someone whose email didn't arrive.
Three such rules, and the step that answers each:
| The rule | What happens without the panel | The step |
|---|---|---|
| A name can answer with only one SPF record. | You add a second service's record beside the first. A mail server finds two, gives a permanent error, and applies neither. | Merging |
| One evaluation can use only ten DNS lookups. | Each service you add costs one or more lookups, and the total passes ten on an ordinary day. Above ten, a mail server gives a permanent error and applies none of your policy. | Examination and Flattening |
| A DNS answer over 512 bytes doesn't fit in one UDP packet. | The flattened record holds every address of every sender, so it gets long. | Division |
Two more reasons make the work automatic rather than a button:
- A sender's addresses change, and the sender doesn't tell you. A flattened record holds somebody else's addresses. The panel reads them again every day, so the record follows the sender.
- A record that's correct today can break next month. A service can grow its own record, and your total passes ten lookups with no change on your side. The panel re-examines each name on a schedule and corrects the published record.
It can't remove a sender you no longer use. Each sender costs lookups and bytes, and a very long list passes a limit no automatic step can correct. Delete a service's record when you stop using the service.
Merging
The panel joins all SPF records at one name into one, because a mail server that finds two gives a permanent error and applies neither.
Your own record and a service's record merge the same way:
- A mechanism that's in two records goes into the result once.
- When two records give the same mechanism different qualifiers, the
most restrictive wins:
-, then~, then?, then+. - The
allmechanism goes last. - For a modifier such as
redirect=orexp=, the first one wins.
The merge is arithmetic on the text; it makes no DNS query.
On the DNS Records page, a record merged with a sibling carries the Merged badge. So you can add one record per sender, or list every sender in one record; the published result is the same.
Examination
The standard sets two limits on the merged record, and only one of them is a rule.
| Limit | Value | What it is |
|---|---|---|
| DNS lookups for the whole evaluation | 10 | A rule. Above it, a mail server gives a permanent error and applies no part of your policy. |
| Length of the record | 450 bytes | A recommendation. A DNS answer over 512 bytes doesn't fit in one UDP packet. Almost all mail servers read a longer answer correctly. |
The include:, a, mx, ptr, exists:, and redirect= terms each
cost at least one lookup; ip4: and ip6: cost none. A lookup inside a
sender's record counts against your ten.
The Cost of Each Term table gives each term's total cost, its own lookup plus every lookup it causes, which tells you which term to remove when the total is too high. Every Lookup in Order below it shows the complete tree, with the record each lookup found.
The examination also reports every problem it finds, with a severity of Fatal, Warning, or Notice.
When a sender's name server doesn't answer, the panel can't see inside that record, and the total on the page is lower than the true total. That's why the panel doesn't decide from the count alone: it tries to flatten the record and lets the result decide.
Flattening
Flattening a record means doing its DNS lookups now and writing the senders' addresses into the record. A mail server reading the result does no lookups at all.
The panel flattens a record only when it must. A record under ten lookups is published as you wrote it. There's no setting for this, because the alternative for a record over the limit is a policy mail servers refuse to apply.
The panel resolves the senders in the background, a few minutes after you change a record, and then re-reads a flattened record's senders every day, because the sender can change its addresses.
What flattening never does
A flatten that can't resolve one sender refuses completely. The panel then publishes your record as you wrote it, and the Flattening step reports Not possible with the reason. A partial result would be a smaller policy than you wrote, refusing mail that must pass.
The panel also refuses to flatten in these cases:
| Case | Reason |
|---|---|
The target of an include: or redirect= publishes no SPF record. | Nothing to resolve. |
A mechanism has a qualifier other than pass and isn't the last all. | SPF applies the first mechanism that matches, so such a record depends on the order of its terms. A flatten sorts the addresses and can't keep that order. |
A term is behind the all mechanism. | A mail server never reads it. |
| The senders point at each other, or the tree is too deep. | The panel can't resolve a loop. |
ptr, exists:, and any term with a macro can't be resolved in advance;
the panel keeps them in the record word for word, and each still costs
its lookup.
The second record beside a flattened record
The panel publishes one more TXT record at the same name:
elpan-note=this SPF record is flattened and/or divided automatically from the provided record
It isn't an SPF record, and no mail server reads it as one. It's for the
person who reads your DNS with a tool such as dig and finds addresses
nobody typed.
The panel publishes your senders' addresses as they were at the last successful read. If a sender's name server stays silent, the panel keeps the addresses it has and tries again every hour. The Flattening step shows the date of the last successful read, in red after one day.
Division
A flattened record gets long. A second SPF record at the same name isn't
possible, so the remainder goes to additional names under _spf, and the
main record points at the first of them with an include:.
example.com TXT "v=spf1 ip4:... include:1._spf.example.com -all"
1._spf.example.com TXT "v=spf1 ip4:... include:2._spf.example.com ?all"
2._spf.example.com TXT "v=spf1 ip4:... ?all"
Four facts about those names:
- The panel writes and removes them; you don't edit them, and they don't appear on the DNS Records page.
- Each holds addresses only. A term that isn't an address means something different under a different name, so it stays in your record.
- They form a chain, each name pointing at the next, which keeps the main record short for the same cost in lookups.
- Each ends with
?all, because a mail server reads it only through theinclude:that points at it.
Each additional name costs one lookup, so the panel divides a record only while enough lookups remain. The rule comes before the recommendation: if division needs more lookups than the record has left, the panel keeps the long record, the Division step reports Not possible, and the one remedy is yours: remove a sender.
Under a wildcard name such as *.example.com, additional names aren't
possible, and the flattened record is published at its full length.
What each badge means
Each of the four steps carries one badge.
| Badge | Meaning |
|---|---|
| Done | The panel did this step; the step shows the result. |
| Not needed | The record is already correct for this step. The healthiest result. |
| Waiting | Not examined yet. This takes a few minutes after you change a record. |
| Not possible | The panel tried and stopped. The step gives the reason. |
| Does not apply | An earlier step didn't run, so this one can't arise. |
Where you see the published record
| Where you look | What you see |
|---|---|
| The DNS Records page | The records you and your services wrote. |
| The SPF Check screen | Each of the four steps, and the value after each one. |
dig TXT example.com | The published record, the note, and the additional names under _spf. |
| The zone file you download | The published record, the same as the name servers answer with. |
The published field of an RRset in the API | The published record. The answer to "I wrote that, why does dig show this?" |