DMARC Explained: Complete Guide to Email Authentication and Aggregate Reports

Everything a domain owner needs to understand, deploy, monitor, and enforce DMARC — from the first TXT record to reading the XML aggregate reports that receivers send back.

This reference is provided in English. DMARC is specified in English-language RFCs; we keep the body in the source language so technical terms are consistent with the specifications.

1. Introduction — what DMARC is and why it exists

Email was designed in the 1980s on the assumption that mail servers trusted each other. Anyone could send a message with any From: address they wanted. That simple design has become the foundation of modern phishing, business-email compromise, and brand impersonation.

Three complementary standards tightened this up:

  • SPF (RFC 7208) — lists the IP addresses allowed to send mail for a domain.
  • DKIM (RFC 6376) — cryptographically signs each message so receivers can prove it was produced by an authorised server and has not been modified in transit.
  • DMARC (RFC 7489) — ties SPF and DKIM to the visible From: address, publishes a policy ("what to do with non-aligned mail"), and provides a feedback loop via aggregate reports.

DMARC is now mandatory for bulk senders targeting Gmail or Yahoo (announced February 2024) and is strongly recommended for every domain that ever sends email — even non-sending domains benefit from p=reject because attackers can no longer spoof them to third parties.

2. DMARC in 60 seconds

You publish a DNS TXT record at _dmarc.yourdomain.tld. It tells every receiving mail server three things:

  1. What to do if a message from your domain fails authentication: p=none (just report), p=quarantine (send to spam), or p=reject (bounce outright).
  2. Where to send a daily XML report summarising every authentication outcome: rua=mailto:….
  3. Optionally, where to send per-message failure reports: ruf=mailto:….

A minimal monitoring-only record looks like this:

_dmarc.example.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com; adkim=r; aspf=r"

Within 24 hours of publishing this record you will start receiving aggregate reports from Google, Microsoft, Yahoo, and every other major receiver. This dashboard imports those reports and turns them into actionable data: which IPs send mail for you, which are aligned, which are failing, and which are forgeries.

3. How DMARC works, step by step

3.1 Identifier alignment

SPF and DKIM each produce a pass/fail result against their own identifier — SPF authenticates the SMTP envelope (MAIL FROM / bounce address) and DKIM authenticates the signing domain (d= tag). Before DMARC, an attacker could pass SPF against their own bounce.attacker.example bounce address while still showing billing@yourbank.com in the From: header — a successful SPF "pass" that is useless to the recipient.

DMARC closes this gap with identifier alignment: SPF (or DKIM) must pass and its authenticated domain must align with the domain in the From: header. Alignment can be strict (adkim=s / aspf=s, exact domain match) or relaxed (adkim=r / aspf=r, organizational-domain match).

DMARC passes when at least one of SPF-aligned or DKIM-aligned passes. Because legitimate forwarding routinely breaks SPF (forwarder changes the envelope but not the message body), DKIM alignment is what typically survives — which is why you want DKIM signing on every sending source, not just SPF.

3.2 Policy application

The receiver consults the p= policy only after computing the DMARC result. On failure it applies one of three outcomes — but crucially the receiver is not required to honour the policy exactly: Google, for example, honours p=reject but may still deliver a tiny sample for its own learning.

3.3 Reporting

Once a day (some receivers more often) the receiver compiles every DMARC result for your domain, produces an XML aggregate report, gzip-compresses it, and emails it to the rua= address. DMARC Analyzer ingests these messages over IMAP or Microsoft Graph, decodes the XML, and turns the raw data into dashboards.

4. What's inside a DMARC aggregate report XML

Every aggregate report conforms to the schema published alongside RFC 7489. The root element <feedback> contains three top-level blocks:

  • <report_metadata> — who sent it and when.
  • <policy_published> — the DMARC record the receiver observed for your domain at report time.
  • One or more <record> elements — each is an aggregation of messages grouped by source IP, header-from, and policy outcome.

Here is the full annotated schema:

<feedback>
  <report_metadata>
    <org_name />          <!-- Reporting organisation (e.g. Google, Microsoft) -->
    <email />             <!-- Reporter contact email -->
    <report_id />         <!-- Unique report ID -->
    <date_range>
      <begin />           <!-- UNIX timestamp -->
      <end />             <!-- UNIX timestamp -->
    </date_range>
  </report_metadata>

  <policy_published>
    <domain />            <!-- Your domain -->
    <adkim />             <!-- DKIM alignment: r (relaxed) | s (strict) -->
    <aspf />              <!-- SPF alignment: r (relaxed) | s (strict) -->
    <p />                 <!-- Policy: none | quarantine | reject -->
    <sp />                <!-- Subdomain policy -->
    <pct />               <!-- Percentage of mail subject to policy -->
    <fo />                <!-- Failure reporting options -->
  </policy_published>

  <record>
    <row>
      <source_ip />                    <!-- Sending IP (v4 or v6) -->
      <count />                        <!-- Message count -->
      <policy_evaluated>
        <disposition />                <!-- none | quarantine | reject -->
        <dkim />                       <!-- pass | fail -->
        <spf />                        <!-- pass | fail -->
        <reason>
          <type />                     <!-- forwarded | sampled_out |
                                              trusted_forwarder |
                                              mailing_list | local_policy |
                                              other -->
          <comment />
        </reason>
      </policy_evaluated>
    </row>
    <identifiers>
      <header_from />                  <!-- From: header domain -->
      <envelope_from />                <!-- MAIL FROM / bounce address domain -->
      <envelope_to />                  <!-- Recipient domain (sometimes present) -->
    </identifiers>
    <auth_results>
      <dkim>
        <domain />                     <!-- Signing domain -->
        <selector />                   <!-- DKIM selector used -->
        <result />                     <!-- none | pass | fail | policy |
                                              neutral | temperror | permerror -->
        <human_result />               <!-- Optional human-readable detail -->
      </dkim>
      <spf>
        <domain />                     <!-- SPF-checked domain -->
        <scope />                      <!-- mfrom | helo -->
        <result />                     <!-- none | neutral | pass | fail |
                                              softfail | temperror | permerror -->
      </spf>
    </auth_results>
  </record>
</feedback>

Reports arrive as gzip-compressed XML (.xml.gz) or inside a ZIP archive. DMARC Analyzer's parser (includes/DmarcParser.php) accepts raw .xml, .gz, .zip, or .tar.gz uploads, extracts every contained report, stores the rows in MariaDB, and caches per-dashboard aggregations for fast display.

5. Policy levels and rollout strategy

p=none (monitor)

p=none asks receivers to report on outcomes but take no enforcement action. Use this for 4–8 weeks while you discover and align every legitimate sender (marketing platforms, transactional providers, help desk, CI/CD systems, forwarded mailboxes).

p=quarantine (soft enforcement)

Move to p=quarantine; pct=10 once you see your known-good traffic reach ~95 % alignment. Gradually raise pct to 100, watching aggregate reports for any remaining legitimate sender that has slipped through.

p=reject (full enforcement)

p=reject is the only policy that actually stops spoofing. Move here once quarantine at pct=100 has been stable for two weeks. A domain that never sends mail should publish p=reject immediately — there is no legitimate traffic to misclassify.

Subdomain policy (sp=)

sp=reject on an organisational domain inherits protection to every subdomain that has no DMARC record of its own. This is the single most valuable setting to deploy on a corporate root domain.

6. Common issues and troubleshooting

My SaaS provider fails alignment
Most SaaS platforms (SendGrid, Mailgun, Intercom, etc.) offer custom-domain DKIM setup. Enabling it lets messages DKIM-align with your From: domain even though the envelope sender remains the provider's bounce address.
Mailing lists break DMARC
Lists typically rewrite the Subject and sometimes the body, breaking DKIM. Well-behaved lists rewrite From: to their own domain (ARC or from: munging) so DMARC does not trigger on your domain at all.
Forwarded mail shows SPF fail
Expected. Forwarders change the envelope sender. DKIM usually survives forwarding, which is why DKIM-signing every outbound source is the real protection.
Aggregate reports are not arriving
Check three things: (1) the rua= address in your DMARC record is reachable, (2) the mailbox accepts messages up to ~10 MB, (3) if the reporting domain differs from your DMARC domain you must publish an authorisation record at yourdomain._report._dmarc.reporter.tld TXT "v=DMARC1" (see RFC 7489 §7.1).

7. Frequently Asked Questions

What is DMARC?
Domain-based Message Authentication, Reporting and Conformance — RFC 7489. A DNS-published policy + reporting standard that ties SPF and DKIM to the visible From: header.
What is the difference between SPF, DKIM and DMARC?
SPF authorises sending IPs. DKIM signs messages. DMARC ties both to the From: header, publishes a policy, and closes the feedback loop with aggregate reports.
What do p=none, p=quarantine and p=reject mean?
Monitor-only, send failing mail to spam, or bounce failing mail outright — respectively.
What is a DMARC aggregate report?
A daily XML summary of every authentication outcome observed for your domain, sent by major receivers to the rua= address.
Do I need to log in to read DMARC aggregate reports?
Technically no — but they are gzip-compressed XML. DMARC Analyzer parses them automatically and presents them as dashboards.

9. Get started with DMARC Analyzer

DMARC Analyzer imports XML / ZIP / GZ / TAR.GZ aggregate reports (manually or via IMAP / Microsoft Graph), parses them against the full RFC 7489 schema, and turns the data into a dashboard with compliance grading, source-IP analysis, geo-distribution, and per-report drilldowns.

The free plan covers 10 reports per month and is enough for a single-domain deployment. Paid plans add IMAP/Graph ingestion, longer retention, DNS record generators (SPF / DKIM / TLS-RPT / MTA-STS / BIMI), domain-security checks, and higher upload limits.

Sign up — Free plan Login