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

  1. p=none — observe, block nothing. You start here and collect reports:
v=DMARC1; p=none; rua=mailto:dmarc@beispiel.de
  1. p=quarantine — suspicious mail lands in spam, optionally staggered with pct:
v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@beispiel.de
  1. 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

TagMeaning
v=DMARC1version, 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