DMARC Analyzer
Upload DMARC aggregate XML reports (or pipe them in via a DMARC mailbox) and see a pass/fail digest per source IP for the last 7-30 days.
DMARC Analyzer
Sendry ingests DMARC aggregate reports and renders a digest of which source IPs are passing DKIM / SPF alignment for each of your domains. Use this to spot misconfigured forwarders, third-party senders missing DKIM, or unauthorized senders pretending to be you.
Publishing a DMARC record
Before receivers will mail you reports, you need a DMARC record on your sending domain:
_dmarc.example.com TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com"
p=none— monitoring mode, no action taken on failing mail. Start here.rua=mailto:— the address that should receive aggregate XML reports.
Once published, Google, Microsoft, Yahoo, and other large receivers will start mailing
daily aggregate reports to the rua address. Forward them into Sendry via either of the
two flows below.
Option 1 — Upload reports manually
- In the Sendry dashboard, go to Deliverability → DMARC.
- Click Upload report and pick the
.xmlor.xml.gzattachment from the receiver's email. - The page refreshes with the new source-IP breakdown.
The dashboard upload uses POST /v1/dmarc/reports under the hood. You can call this
directly from any script:
curl -X POST https://api.sendry.online/v1/dmarc/reports \
-H "Authorization: Bearer $SENDRY_API_KEY" \
-F "file=@google.com!example.com!1715731200!1715817600.xml.gz"
The response identifies the parsed report and indicates whether it was a duplicate of one
already ingested (matched on reporter + report_id):
{
"report_id": "dmarc_report_5n3Q…",
"reporter": "google.com",
"domain": "example.com",
"date_begin": "2026-05-14T00:00:00.000Z",
"date_end": "2026-05-15T00:00:00.000Z",
"record_count": 12,
"duplicate": false
}
Both raw XML and gzipped XML (.xml.gz) are accepted — Sendry detects the gzip magic
header and decompresses transparently. The upload size limit is 10 MB.
Option 2 — Pipe reports from inbound email
If you've configured Sendry's inbound email routing, you can point the rua= address at
a Sendry-managed mailbox and reports will be ingested automatically as they arrive. The
dmarc-ingest BullMQ worker picks up each .xml.gz attachment, decompresses it, parses
it, and inserts the records.
This path is asynchronous, so duplicates are still de-duplicated server-side on
(org_id, reporter, report_id).
Endpoints
| Method | Path | Description |
|---|---|---|
POST | /v1/dmarc/reports | Multipart upload — accepts .xml or .xml.gz (10 MB max). |
GET | /v1/dmarc/reports | List ingested reports (cursor-based, ?domain=&limit=). |
GET | /v1/dmarc/summary | Pass/fail digest per source IP (?domain=&days= — default 7, max 90 days). |
All three endpoints require full_access scope for the upload and read_only scope for
the GETs.
What the summary shows
For each (source_ip, domain) bucket, Sendry returns:
- Total — number of messages reported in the window.
- Pass / Fail — counts where DKIM or SPF aligned, following the DMARC RFC's any-aligned semantics for treating a message as authenticated.
- DKIM pass / SPF pass — per-mechanism pass counts.
- Disposition — the receiver's chosen action (
none,quarantine,reject). - Last seen — the most recent report's date range end.
The dashboard caps the displayed bucket list at the top 200 source IPs by message volume, so the page stays snappy even for very high-volume senders.
What it doesn't do
- No automated remediation — DMARC findings are read-only. Use the data to harden DKIM / SPF, then re-run the analysis after a few days of fresh reports.
- No forensic (RUF) report parsing yet — only RUA aggregate reports. Most receivers have deprecated RUF anyway.