DMARC is a single TXT record at _dmarc.yourdomain.com. The only genuinely cPanel-specific thing about publishing it is the Name field, which behaves like a zone file rather than like every other hosting dashboard you have used. Get that right and the rest is choosing a policy you can live with.
Where is the Zone Editor?
From the cPanel home screen, find the Domains section and open Zone Editor. You get a list of every domain and addon domain on the account, each with a Manage button and often quick-add buttons for common record types. Click Manage on the domain you are publishing DMARC for, then Add Record.
Recent cPanel versions include helper buttons alongside Add Record for specific record types — some builds ship a DMARC helper that assembles the policy string from a form. If yours has one, use it: it produces the same TXT record and removes the chance of a syntax slip. If it does not, add a plain TXT record; that is what DMARC always is under the hood.
The cPanel name-field quirk: it appends your domain
cPanel's Zone Editor writes BIND zone-file syntax, and it exposes that directly. In zone-file syntax a name without a trailing dot is relative to the zone origin and the origin gets appended; a name with a trailing dot is absolute and is used as-is. cPanel applies exactly that rule to whatever you type.
| You type in Name | cPanel stores | Correct? |
|---|---|---|
_dmarc | _dmarc.example.com. | Yes — this is the normal way |
_dmarc.example.com. | _dmarc.example.com. | Yes — absolute, note the trailing dot |
_dmarc.example.com | _dmarc.example.com.example.com. | No — the classic doubled-domain mistake |
@ | example.com. | Apex — wrong name for DMARC |
That third row is the failure everyone hits. It is not a bug; it is zone-file semantics leaking through the UI. The fix is trivial once you know it: type _dmarc and nothing else, or type the fully-qualified name with the trailing dot. Never type the fully-qualified name without it.
The same rule applies to every name in the Zone Editor, which is why cPanel users also end up with mail.example.com.example.com CNAMEs and selector._domainkey.example.com.example.com DKIM records. After saving, the record list shows the fully-qualified stored name ending in a dot — read it. One glance at that column catches the mistake immediately.
What value should the record have?
Start with a monitoring policy. p=none tells receivers to apply no enforcement but to send you aggregate reports, so you learn which of your sending sources pass and which fail before anything gets quarantined. Publishing p=reject on day one is how organisations discover their invoicing system was sending unauthenticated mail all along.
# Monitoring — start here
v=DMARC1; p=none; rua=mailto:[email protected]; fo=1
# After reports look clean — partial enforcement
v=DMARC1; p=quarantine; pct=25; rua=mailto:[email protected]
# Full enforcement, subdomains included
v=DMARC1; p=reject; sp=reject; rua=mailto:[email protected]; adkim=s; aspf=sEnter the value unquoted. cPanel writes the quoting into the zone file itself, and a value that arrives with your own quotation marks embedded is a value no DMARC parser will read. Semicolons need no escaping. v=DMARC1 must come first and is case-sensitive; the tags after it are order-independent.
The rua mailbox must exist and be able to receive mail — reports are sent to it daily by every major receiver. If you point rua at an address on a *different* domain than the one publishing the record, that other domain has to authorise it with its own TXT record, or the reports are dropped:
# Publishing DMARC for example.com but sending reports to example.net?
# example.net must publish this TXT record:
# name: example.com._report._dmarc.example.net
# value: v=DMARC1How do you verify it published?
Query the name directly. A DMARC record either exists at _dmarc.example.com or it does not — there is no partial state, and the doubled-domain mistake shows up instantly as an empty answer.
# The record itself
dig +short TXT _dmarc.example.com
# Ask the authoritative server, bypassing every cache
dig +short NS example.com
dig @ns1.yourhost.com +short TXT _dmarc.example.com
# Did you accidentally create the doubled name?
dig +short TXT _dmarc.example.com.example.com
# Without dig
host -t TXT _dmarc.example.comA correct result looks like "v=DMARC1; p=none; rua=mailto:[email protected]; fo=1" on one line. Empty output from the first command plus a hit on the third command is a doubled name: delete the bad record in Zone Editor and re-add with _dmarc alone.
DMARC only works if SPF or DKIM aligns
This is the part that gets skipped on shared hosting. DMARC does not authenticate anything itself — it checks that a message passing SPF or DKIM did so on a domain that aligns with the From: header domain, and then applies your policy to messages that pass neither.
- SPF alignment compares the
From:domain with the domain in the SMTP envelope sender (Return-Path). On shared cPanel hosting the envelope sender is often the server's own hostname or a[email protected]address, which does not align even though SPF itself passes. - DKIM alignment compares the
From:domain with thed=value in the DKIM signature. cPanel can generate a DKIM key for the domain in the Email Deliverability interface — that is usually the easier of the two to get aligned on shared hosting. - Either one is enough. DMARC passes if SPF aligns *or* DKIM aligns. You do not need both, though both is more resilient to forwarding.
- Forwarding breaks SPF, not DKIM. A mailing list or a forwarded mailbox rewrites the envelope sender, so alignment survives on DKIM alone. That is a good reason to get DKIM working before raising the policy.
cPanel's Email Deliverability page (also under Domains) shows SPF and DKIM status per domain and can install both into the same zone. Check the resulting records with the SPF Checker and the DKIM Checker, or run the Email Deliverability Test to see SPF, DKIM, DMARC, MX, and PTR together.
Once reports are arriving and every legitimate source aligns, raise the policy in steps. DMARC p=none vs quarantine vs reject covers the rollout schedule, and DMARC Policy Not Enabled explains the warning you will see from checkers while you are still on p=none. If you are publishing on Cloudflare instead, see Add a DMARC Record on Cloudflare.