Sender authentication has an unusual failure mode: the records are right, the online checkers agree they are right, and the mail is still treated as unauthenticated. That happens because the checkers verify the thing you published, and the receiver verifies a relationship between that thing and the message. Those are different questions. Below are four ways we have seen the second one answered no while the first one was answered yes, taken from setting this up on domains we do not own.
01Alignment is what gets checked, not the record
A published SPF record proves that some server may send for some domain. A valid DKIM signature proves that some key signed the message. Neither says the domain in question is the one the recipient can see in the From header, and that is the only thing DMARC evaluates.
So there are two domains in every message and most tooling only shows you one. The visible From domain is what the recipient reads. The Return-Path domain, which SPF is actually checked against, is set by whoever is doing the sending, and by default that is your provider. A message can pass SPF perfectly against a provider hostname while DMARC records a failure, because SPF passed for a domain that is not yours.
DMARC needs only one of the two to align, which is the part worth internalising. SPF alignment through a custom Return-Path, or DKIM alignment through a signature carrying your domain, either is sufficient. This is why a domain can show a green SPF check and still fail, and why fixing DKIM often fixes a problem that looked like an SPF problem.
02The proxied CNAME that answers with the wrong address
This is the one that has cost us the most time, and it produces the most convincing false success of the four. Authentication records are usually CNAMEs into a vendor zone. On a proxied DNS provider, a CNAME can be flagged to route traffic through the proxy, and a proxied record does not answer with the target. It answers with the proxy edge addresses, because that is its entire purpose.
For a website that is correct behaviour and the reason people use it. For a DKIM selector it is fatal in a specific way: the lookup succeeds. The name resolves, something answers, nothing reports an error. What comes back is an address record where a key was expected, so the verifier finds no key and treats the message as unsigned. Nothing in that sequence looks like a misconfiguration from the outside.
The reason it keeps happening is that the default is set for the common case. Most records people add to a zone are for a site, and the interface offers proxying because that is usually wanted. Authentication records are the exception, and they are added by someone following instructions that say nothing about a toggle their DNS host invented.
03The selector you were given is already in use
A DKIM selector is a label that lets one domain hold several keys at once. Providers pick a default and reuse it across every account they have ever issued, which is fine until one domain has two relationships with the same provider.
One of the domains we authenticate is a live example. Its provider issues s1 and s2 by default, and both are already published there from an account that predates us. Had we accepted the default, our records would have collided with working ones on a domain we do not control, and the failure would have arrived as broken mail for somebody else. We use a distinct selector for exactly this reason.
There is a second trap inside the first, and it only shows up when the second key is issued. Providers commonly derive the second selector by appending a digit to the first. Choose a selector already ending in a digit and the pair you get is not the pair you expected. We chose a name with no trailing digit after confirming that behaviour against the live API rather than the documentation.
- Look up the provider default selectors on the domain before you add anything. Existing records mean an existing relationship you were not told about.
- Never assume one domain has one mail provider. Marketing, transactional, support and a legacy contract are four relationships and often four vendors.
- Pick a selector that identifies the sender, not the year or the sequence. It becomes readable in DNS by anyone auditing that zone later.
04Pointing at a vendor hostname makes it their record, not yours
This one is not a failure on the day, it is a failure eighteen months later, and it is the reason our records look different from the ones most services hand out.
A provider gives you CNAMEs into its own zone, and the obvious move is to pass those to the customer unchanged. It works immediately. What it also does is place a vendor hostname inside a zone you do not control, once per customer. Changing provider then means asking every customer to edit DNS, which in practice means a portion of them never do and quietly stop authenticating.
So we point customer records at our own hostnames, and those hostnames point at the provider. The extra hop costs one lookup and turns a migration from a mass email into three records in a zone we own. A live chain reads as the customer selector, then our alias, then the provider target, which is the same thing every vendor CNAME does with one indirection added at the only point where it helps.
The cost of that design is a new way to be wrong, and it is worth naming rather than hiding. Provider targets contain identifiers that are assigned rather than promised, including a pool identifier that can change. If it changes, our aliases point at nothing useful and every customer stops authenticating at once, silently, because the records still resolve. We check for that drift on a schedule for the same reason we check anything: the failure is invisible from the inside.
05One click is a provider decision, not a standard
Asking a customer to add three records is where onboarding stalls, and the standard answer is Domain Connect: the customer is sent to their own DNS provider, that provider authenticates them, shows them the records, and writes them if they agree. Nobody hands anybody a credential.
The part that is easy to misread is what publishing a template gets you. Getting it merged into the public template repository is necessary and it is not sufficient, because providers onboard templates individually. A template can be public and correct for years while a given DNS host has never served it.
A well known ESP has had its template merged upstream since 2022. Querying a major DNS provider for it today returns a 404, which means every customer of that provider is still adding those records by hand. We checked before assuming, because assuming would have meant showing customers a button that leads nowhere.
Which is the general shape of all five of these. Ask the provider whether it serves the template before offering the button. Resolve the record and read its type before believing the interface. Query the selector on the domain before accepting a default. In each case the check is one lookup, and skipping it produces a system that reports success while delivering nothing.
The summary is that authentication is a relationship between a message and a domain, and every failure above is a break in that relationship rather than a mistake in a record. That is why the records look right. They are right. They are just not connected to the thing being checked, and the only reliable way to find that out is to resolve what you published and read what actually comes back.