
Every authentication failure names itself — you never have to guess. Open the affected message in Gmail, click the three-dot menu, choose Show original, and read the Authentication-Results header near the top. The receiving server records a verdict for each mechanism: spf, dkim, and dmarc, each marked pass, fail, permerror, or temperror, along with the exact domain and IP it evaluated. Diagnose from this header, never from a vague "it went to spam" report.
Notice the two different domains in that example. SPF is evaluated against the envelope-from domain (smtp.mailfrom — here relay.example.net), while DMARC is evaluated against the visible From: address (header.from — example.com). Half of all "impossible" failures come from checking the wrong one: you dig your own domain, the record looks perfect, and the receiver was never checking your domain for SPF at all. Read the verdicts, note which domain each one names, then jump to the matching fix below.
spf=permerror means the receiver could not even evaluate your record, and it almost always has one of two causes. First: two TXT records both starting with v=spf1 — usually left behind when someone added a new provider's record instead of merging it into the existing one. The standard requires exactly one, so evaluators simply give up. Second: more than ten DNS lookups. Every include:, a:, mx:, exists:, and redirect= costs a lookup, and includes count their nested includes too — stack Google Workspace, a marketing platform, a helpdesk, and a payment provider and you sail past the limit without noticing. Check for both in one command:
Under DMARC, a permerror is worse than a fail in practice: SPF contributes nothing at all, so every message rides on DKIM alone. If DKIM is also broken, an enforced DMARC policy (p=quarantine or p=reject) will junk or bounce your entire mail flow — password resets and invoices included. Fix permerrors before anything else: merge duplicate records into one, and replace lookup-heavy includes with direct ip4: entries for providers that publish stable IP ranges.
dkim=fail has three distinct causes, and the header's s= tag — the selector — is your first clue. Cause one: the selector does not exist in DNS. The message is signed with s=mail1, but nobody ever published mail1._domainkey as a TXT record, which is common right after switching mail providers since each provider uses its own selector names. Cause two: key mismatch. The server was rebuilt or the mail stack reinstalled, a fresh keypair was generated, and DNS still holds the old public key — every signature now verifies against the wrong key and fails. Cause three: the message was modified in transit. Mailing lists that append footers and forwarders that rewrite the body change the content after signing, so a signature that was valid at send time fails on delivery. Verify the exact selector the header names:
For a missing selector, publish the public key your mail server is actually signing with, at exactly the name in the s= tag. For a rebuild mismatch, export the current public key from the server and overwrite the DNS record — do not generate yet another keypair and create a second stale copy. dkim=temperror is different: the receiver's DNS query for your key timed out. It usually clears on its own; if it recurs, your authoritative nameservers are slow or rate-limiting, which is a DNS hosting problem, not a DKIM problem.
The most confusing verdict is dmarc=fail sitting next to spf=pass and dkim=pass, and the answer is always alignment: DMARC does not ask whether SPF or DKIM passed, it asks whether the domain that passed matches your header-from domain. This is the classic relay failure. SendGrid or Mailgun delivers your message using its own bounce domain, SPF passes for sendgrid.net, DKIM may pass for sendgrid.net too — but your From: says example.com, nothing aligned with it, and DMARC fails, applying your own policy to your own legitimate mail.
The fix lives in the relay's dashboard, not in your DMARC record. Enable the feature every major provider offers under a name like domain authentication or custom return-path: you publish a few CNAMEs, after which the relay signs DKIM as d=example.com and uses a bounce subdomain of example.com for SPF. Either aligned pass satisfies DMARC — DKIM alignment alone is enough, and it is the more durable of the two. Do not "fix" an alignment failure by deleting the DMARC record or parking at p=none forever; that trades a solvable configuration issue for an open door to spoofing.
Some failures are not yours to fix. When a recipient auto-forwards your mail — a university address relaying to Gmail, an old domain forwarding to a new one — the forwarding host becomes the sending IP, so SPF fails at the final hop by design. If the forwarder also rewrites the body, DKIM breaks too, and the message arrives with nothing intact. ARC (Authenticated Received Chain) exists precisely for this: the forwarder cryptographically seals the authentication results it saw on arrival, and a receiver like Gmail can trust that sealed chain and accept a message whose direct checks fail. You cannot force forwarders to implement ARC; what you can do is keep DKIM solid and aligned, because an unmodified forwarded message still carries your valid signature — the one mechanism that survives forwarding.
Most of these failures trace back to records typed by hand into a registrar panel. If your server runs on CloudStick, that whole class disappears: when you set up email, CloudStick generates the matching SPF, DKIM, and DMARC records for the server that will actually be sending, and with the Cloudflare integration connected, correcting a bad record is a dashboard edit that propagates in minutes — no registrar hunt, no drift between the key on disk and the key in DNS. Your next step takes ten minutes: send a test message to a Gmail address, open Show original, and read the three verdicts. Fix the first failing mechanism using the matching section above, wait out the DNS TTL, and send again — repeat until the header reads spf=pass, dkim=pass, dmarc=pass, then keep a copy of that header as your known-good baseline for the next time deliverability wobbles.

