p=reject, its mail starts bouncing. The usual cause is that the tool authenticates as its own domain, not yours. DMARC only counts authentication that lines up with the domain in the From header.
This guide focuses on checks you can run yourself from a terminal, before the tool goes live and again after the vendor says setup is complete.
Why SPF and DKIM can pass while DMARC fails
d= tag that names the domain doing the signing. Until you set up custom DKIM, many platforms sign with d= set to their own domain. The signature is valid. It just vouches for the wrong domain.
DMARC asks a stricter question. At least one of SPF or DKIM must pass, and the domain it passed for must align with the From header domain. Alignment has two modes:
- Relaxed, the default, accepts the same organizational domain. A signature with
d=mail.example.comaligns withFrom: [email protected]. - Strict requires an exact match, so
d=mail.example.comwould not align withexample.com.
d= works regardless of where bounces go.
This also explains a common point of confusion at the support desk. A customer shows a vendor dashboard that says verified and assumes the job is done. That checkmark often means the vendor can see your DNS records. It does not prove that delivered messages carry an aligned signature. Two places hold the real answer: public DNS and the headers of a message that actually arrived.
Confirm the selector record is published in public DNS
_domainkey. The part before ._domainkey is the selector, a label that tells receivers which key to fetch. Vendors publish keys in one of two ways:
- A CNAME that points to a key the vendor hosts and can rotate.
- A TXT record that contains the public key directly.
BASH
# Replace crm1 and example.com with the exact selector and domain from the vendor
dig +short CNAME crm1._domainkey.example.com
# Querying TXT follows a CNAME and returns the key the receiver will actually use
dig +short TXT crm1._domainkey.example.com
# Ask a public resolver too, so a stale local cache does not mislead you
dig @1.1.1.1 +short TXT crm1._domainkey.example.com
# Check for a doubled name in case the DNS panel appended the zone a second time
dig +short TXT crm1._domainkey.example.com.example.comv=DKIM1 and includes a p= tag with a long base64 value. Long keys are often split into several quoted chunks. That is normal, because receivers join the chunks back together.
Three results deserve a closer look:
- Empty output means the record is not published, has not propagated, or sits at the wrong name.
- Output from the doubled-name query means the record exists at the wrong name. This happens when someone types the full host name into a panel that appends the zone automatically. The fix is to re-enter it as
crm1._domainkeyonly. - A present but empty
p=means the key is revoked. Receivers treat signatures under that selector as failing.
Check the alignment mode in your DMARC record
BASH
dig +short TXT _dmarc.example.com
# Illustrative output format:
# 'v=DMARC1; p=none; rua=mailto:[email protected]; adkim=s; aspf=r'adkim is absent, DKIM alignment is relaxed. If it reads adkim=s, the vendor's d= value must match your From domain exactly. That matters when the vendor asks you to sign as a subdomain while the tool sends from the apex domain. Choose one of two fixes: change the From address to the subdomain, or relax DKIM alignment. Make that decision on purpose.
Keep subdomains in mind as well. If the tool sends from something like help.example.com, the apex policy may still apply to that subdomain through the sp= tag or inheritance. Check which policy actually covers the From domain the tool uses.
Read the signature on a message that actually arrived
BASH
# message.eml is the saved raw source, headers included
grep -i '^From:' message.eml
# List the d= value of every DKIM signature; headers are folded, so look a few lines down
grep -i -A4 '^DKIM-Signature:' message.eml | grep -oE '[[:space:];]d=[^;]+'
# The receiver's own verdict on SPF, DKIM, and DMARC
grep -i -A8 '^Authentication-Results:' message.emldkim=pass with header.d= set to your domain or one of its subdomains, along with dmarc=pass. It is fine to see more than one DKIM signature. Many platforms keep signing with their own domain and add yours. DMARC passes as long as one aligned signature verifies. For a closer walkthrough of these fields, see Reading Authentication-Results Headers to Fix DMARC Alignment.
If the only passing signature is header.d= on the vendor's domain while your selector resolves correctly in DNS, the vendor has not switched to signing with your key yet. On many platforms, signing changes only after you complete a verify or enable step in their dashboard. Records alone are not enough. Check the vendor's documentation for that step instead of waiting for DNS to fix it.
SPF in the same header will probably show a pass for the vendor's bounce domain. That is expected and does not hurt when DKIM aligns. This is also why adding the vendor's include: to your SPF record seldom fixes DMARC for these tools. If the envelope sender is their domain, your SPF record is never consulted for that message. The extra include still counts toward SPF's limit of 10 DNS lookups. Only add it if the vendor's documentation says mail actually leaves with your domain as the envelope sender.
Confirm it in aggregate reports before you enforce
p=quarantine or p=reject, do this before the tool goes live, not after users report missing mail. A broader pre-enforcement checklist is in What to Audit Before Switching DMARC Policy from None to Reject.
The practical habit is short. Whenever a new tool starts sending as your domain, check three things. First, the selector resolves from a public resolver with a non-empty key. Second, your DMARC alignment mode fits the domain the vendor signs with. Third, a real message from the tool shows dkim=pass with your domain in header.d=. A vendor dashboard checkmark is a useful starting point, but the delivered headers are what confirm the setup.