Start with the records
Check the DMARC record of your domain:
Then the DKIM key with the DKIM checker and the sender list with the SPF checker.
Read the failure in the headers
Open a failing message's full headers and find Authentication-Results:
Authentication-Results: mx.receiver.example;
dkim=fail (body hash did not verify) header.d=example.com header.s=selector1;
spf=pass smtp.mailfrom=bounce.vendor.example;
dmarc=fail (p=NONE) header.from=example.com
Here SPF passed, but for bounce.vendor.example and not for example.com, and DKIM broke. So DMARC fails.
Causes and fixes
| What you see | Likely cause | Fix |
|---|---|---|
dmarc=none or "no DMARC record found" | No TXT record at _dmarc.yourdomain, or a typo in the name or in v=DMARC1 | Publish it at exactly that name. Some DNS hosts add your domain automatically, producing _dmarc.example.com.example.com; enter only _dmarc. |
dkim=none | The sender doesn't sign mail with a key for your domain | Turn on DKIM for that service and publish the records it gives you. See DKIM selector. |
dkim=fail (no key for signature) | Wrong selector, or the key record doesn't exist | Compare s= in the header with the DNS name. Publish the key at selector._domainkey.domain. |
dkim=fail (body hash did not verify) | Something changed the message after signing: a footer, disclaimer, link rewriting or a mailing list | Sign after the last system that edits the message, or exclude it. Mailing lists often break DKIM. |
dkim=permerror or key unreadable | The public key was cut off or has stray characters, often from a long key split across lines | Re-copy the whole value. Keys over 255 characters must be stored as several quoted strings that join. |
| SPF and DKIM pass, DMARC fails | Neither is aligned with the From domain | Make the service sign with d=yourdomain or send with a MAIL FROM on your domain. |
spf=fail after forwarding | The forwarder isn't in your SPF record, and can't be | Rely on DKIM for forwarded mail. Keep DKIM signing on for every sender. |
Alignment in one minute
DMARC doesn't just ask whether SPF or DKIM passed. It asks whether they passed for the domain in the visible From address. SPF is checked against the hidden return-path domain, and DKIM against d= in the signature. A marketing service that signs with its own domain passes DKIM, but not for yours, so DMARC fails. Either one aligned is enough. Details are in what is DMARC.
Fix order that avoids blocking real mail
- Publish DMARC with
p=noneand aruaaddress, then read the reports. - For each legitimate sender that fails, set up DKIM for your domain (and add SPF where the sender supports it).
- When the reports are clean for a few weeks, move to
p=quarantine, thenp=reject.
Never jump straight to reject: any forgotten sender, such as invoicing software or a CRM, will have its mail refused.
Provider-specific steps
If the failing sender is one of these, follow its page: Google Workspace, Microsoft 365, GoDaddy or Salesforce. The overview is in SPF, DKIM and DMARC explained.