Last updated: July 2026
In short: After this guide your domain publishes a DMARC record that tells receiving servers what to do with unauthenticated mail — and shows you via reports who sends in your name.
Prerequisites
- A running Mailcow server
- SPF and DKIM must be set up first — the Mailcow docs explicitly call DMARC “the last step”, after SPF and DKIM
- Access to your domain’s DNS management
What is DMARC?
DMARC (Domain-based Message Authentication, Reporting & Conformance) combines SPF and DKIM into an enforceable policy. It’s a TXT record under the subdomain _dmarc. In it you define what a recipient should do with mail that fails the check (the p policy), and where it sends you reports (the rua address).
When self-hosting, DMARC closes the loop: SPF authorizes your server, DKIM signs the message, and DMARC turns both into a rule that receiving servers enforce.
The starting point at Mailcow
Mailcow itself doesn’t set the DMARC record — your DNS zone is at your DNS provider. But the Mailcow docs document exactly what belongs there, and point to a DMARC Assistant for creating it. Their example record is already at enforcing:
_dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:mailauth-reports@example.org"
For a cleanly configured self-hoster, p=reject is the right goal — but get there via the ramp, not immediately.
The safe path: none → quarantine → reject
p=none— observe, block nothing. You start here and collect reports:
v=DMARC1; p=none; rua=mailto:dmarc@beispiel.de
p=quarantine— suspicious mail lands in spam, optionally staggered withpct:
v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@beispiel.de
p=reject— enforcement, optionally with strict alignment and a subdomain policy:
v=DMARC1; p=reject; rua=mailto:dmarc@beispiel.de; sp=reject; adkim=s; aspf=s
Only move on when the reports show that all your legitimate sending sources pass SPF/DKIM.
Step-by-step guide
1. Set the report address
The rua address receives the aggregated reports. For analysis, a DMARC monitor like MARCo is worthwhile — it makes the daily XML reports readable and shows you which sources aren’t yet cleanly authenticated.
2. Create the _dmarc TXT record at the DNS provider
Create a TXT record on the host _dmarc. Where exactly depends on the DNS provider — see our guides for IONOS, Strato, Netcup, or Hetzner DNS (at Hetzner the TXT value must be in quotation marks).
3. Read reports and tighten the policy
Start with p=none, move via quarantine to reject once the reports are clean.
4. Wait until the change is live
DNS changes take a few hours depending on caching.
The most important tags
| Tag | Meaning |
|---|---|
v=DMARC1 | version, must be at the start |
p= | policy: none (observe), quarantine (spam), reject (reject) |
rua= | address for aggregated status reports |
ruf= | address for forensic failure reports |
sp= | separate policy for subdomains |
adkim= / aspf= | alignment (r relaxed, s strict) for DKIM and SPF respectively |
Verify the result
Check your configuration with the free MXAudit scanner — it shows you the DMARC policy, SPF, and DKIM at a glance.
Common mistakes
Copied Mailcow’s p=reject example verbatim. The docs example is at enforcing. If you adopt it before your sources authenticate cleanly, you block your own mail. First p=none, read reports, then tighten.
No rua set. Without a report address you never see which sources fail.
DMARC without SPF/DKIM. DMARC checks the results of SPF and DKIM. First SPF and DKIM, then DMARC.
Wrong hostname. The record belongs at _dmarc — not at @ or the bare domain.
Further reading
- Mailcow docs: DNS setup (retrieved: July 10, 2026)
- RFC 7489 — DMARC
