DMARC Aggregate Report Analyzer avatar

DMARC Aggregate Report Analyzer

Pricing

from $8.16 / 1,000 item extracteds

Go to Apify Store
DMARC Aggregate Report Analyzer

DMARC Aggregate Report Analyzer

Parse DMARC aggregate XML into normalized sender, authentication, disposition, policy, and failure records for recurring email-security monitoring.

Pricing

from $8.16 / 1,000 item extracteds

Rating

0.0

(0)

Developer

Automation Lab

Automation Lab

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Categories

Share

Turn DMARC aggregate XML reports into normalized source-IP, message-volume, policy, disposition, DKIM, SPF, and failure records. This DMARC aggregate report analyzer accepts pasted XML, downloadable report files, and base64 attachments, making recurring email-authentication evidence ready for Apify Datasets, spreadsheets, alerts, and security pipelines.

The Actor analyzes aggregate (rua) feedback. It does not collect mailbox messages, change DNS records, or parse forensic (ruf) reports.

What does this Actor do?

DMARC receivers such as Google, Yahoo, and Microsoft send machine-readable XML. Each file may contain many source rows and nested authentication results. The Actor:

  1. loads XML from input, an HTTP(S) URL, or base64;
  2. decompresses GZIP and ZIP attachments when necessary;
  3. validates the XML and required DMARC feedback sections;
  4. emits one stable dataset row per reported source record;
  5. derives a DMARC pass flag and concise failure signals;
  6. optionally combines matching source-IP rows across recurring reports.

The original message count is preserved. One output item can represent many emails, so messageCount is the metric to sum for volume analysis.

Who is it for

  • Email administrators investigating unauthorized or misconfigured senders.
  • Security teams tracking reject, quarantine, and authentication-failure volume.
  • Deliverability teams comparing SPF and DKIM alignment over time.
  • Managed service providers processing daily reports for multiple domains.
  • Data engineers feeding normalized DMARC evidence into a warehouse or SIEM.
  • Developers who need a repeatable parser without maintaining XML edge cases.

Use Bulk DMARC Record Checker when you need to inspect the current DNS policy for domains. Use this Actor when you already have aggregate report files and need to understand observed traffic.

What is a DMARC aggregate report?

A DMARC aggregate report is XML feedback from a receiving mail provider. It summarizes messages claiming to be from a domain during a reporting period. Rows contain a sender IP, message count, receiver disposition, aligned DKIM/SPF results, identifiers, and detailed authentication evidence.

Reports do not contain message bodies. They can still reveal infrastructure, domains, addresses, and operational patterns, so store and share them according to your organization's security policy.

How to read a DMARC aggregate report

Start with these fields:

QuestionOutput field
Which domain was evaluated?domain, headerFrom
Which host sent the mail?sourceIp
How much traffic did it send?messageCount
What action did the receiver apply?disposition
Did aligned DKIM pass?dkimEvaluation
Did aligned SPF pass?spfEvaluation
Did DMARC pass through either mechanism?dmarcPass
Why should this row be reviewed?failureReasons
Which policy was published?policyDisposition, policyPercentage

A DMARC pass requires aligned DKIM or aligned SPF. A detailed SPF result may say pass while spfEvaluation says fail if the authenticated envelope domain does not align with the visible From domain.

Input

reports is required and accepts 1–100 objects. Each object requires a name and exactly one source:

  • xml: the complete XML string;
  • url: an HTTP(S) URL returning XML, GZIP, or ZIP;
  • base64: base64-encoded XML, GZIP, or ZIP bytes.
ParameterTypeDefaultPurpose
reportsarrayrequiredNamed report sources to analyze
aggregateBySourceIpbooleanfalseCombine matching source/authentication rows
failOnInvalidbooleantrueFail closed, or skip bad files in a mixed batch
maxItemsinteger10000Limit normalized output rows to 1–100,000

A URL is fetched once with redirects, a 30-second timeout, status validation, and a 10 MB compressed/download limit. Unpacked content is also limited to 10 MB. The Actor does not use a proxy and cannot access private intranet URLs unless they are reachable from the Apify run.

Example input: pasted XML

{
"reports": [
{
"name": "Google daily report",
"xml": "<feedback>...</feedback>"
}
],
"aggregateBySourceIp": false,
"failOnInvalid": true,
"maxItems": 10000
}

For automation, base64 avoids JSON escaping issues. Keep the source label stable so downstream users can identify the originating file.

Example output

{
"reportName": "Google report for sendgrid.net",
"reporter": "google.com",
"reportId": "2026-09-01-google-sendgrid",
"reportIds": ["2026-09-01-google-sendgrid"],
"reportsCount": 1,
"periodBegin": "2026-09-01T00:00:00.000Z",
"periodEnd": "2026-09-01T23:59:59.000Z",
"domain": "sendgrid.net",
"policyDisposition": "reject",
"policyDkimAlignment": "r",
"policySpfAlignment": "r",
"policyPercentage": 100,
"policySubdomainDisposition": "reject",
"sourceIp": "209.85.220.41",
"messageCount": 24,
"disposition": "none",
"dkimEvaluation": "pass",
"spfEvaluation": "pass",
"dmarcPass": true,
"headerFrom": "sendgrid.net",
"envelopeFrom": "sendgrid.net",
"envelopeTo": null,
"dkimResults": [{"domain":"sendgrid.net","result":"pass","selector":"s1"}],
"spfResults": [{"domain":"sendgrid.net","result":"pass","scope":"mfrom"}],
"policyOverrideReasons": [],
"failureReasons": [],
"analyzedAt": "2026-09-02T00:05:00.000Z"
}

Provider-optional values are nullable. Arrays remain arrays even when the XML contains one result, which keeps warehouse and TypeScript contracts stable.

Aggregating recurring reports

Set aggregateBySourceIp to true when scheduled runs ingest multiple report periods. Rows combine only when source IP, header-from domain, disposition, DKIM evaluation, and SPF evaluation all match. This avoids hiding a change from pass to fail or from none to reject.

Aggregated rows sum messageCount, list unique reportIds, expand the reporting period, and set reportId to null. reportsCount records how many original rows contributed. Schedule one run after new files land, or call the Actor from an email-ingestion or object-storage workflow.

Failure and disposition analysis

failureReasons is designed for filters and alerts:

  • dkim:fail or dkim:missing indicates no aligned DKIM pass;
  • spf:fail or spf:missing indicates no aligned SPF pass;
  • disposition:quarantine or disposition:reject records enforcement;
  • override:<type> preserves a receiver policy override.

Do not classify every listed reason as malicious activity. Forwarding, mailing lists, third-party senders, and temporary configuration changes can produce legitimate failures. Correlate source IP ownership and approved sender inventory before blocking traffic.

How much does it cost to analyze DMARC report source rows?

Pay-per-event billing has a $0.005 Actor start plus one item event for each saved normalized or aggregated source row. The provisional market-led BRONZE item price is $0.0136 per row; higher Apify tiers receive lower item prices. The final live price shown in Apify Console is authoritative.

Example BRONZE costs at the provisional curve:

Saved rowsEstimated charge
1$0.0186
10$0.1410
25$0.3450
100$1.3650

Invalid reports, skipped files, and XML records beyond maxItems do not produce item events. One item can summarize many messages; billing is not per email.

Getting started

  1. Open the Actor input page.
  2. Add a report name and paste XML, a URL, or base64 content.
  3. Keep Fail on an invalid report enabled for strict pipelines.
  4. Enable source-IP aggregation only when combining periods is desired.
  5. Set a practical maxItems safety limit.
  6. Run the Actor and open the DMARC source results dataset view.
  7. Filter dmarcPass = false or non-empty failureReasons for investigation.
  8. Export CSV, JSON, Excel, or connect the dataset to another service.

API usage with cURL

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~dmarc-aggregate-report-analyzer/runs?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"reports": [{"name":"daily-report","url":"https://your-authorized-host/reports/dmarc.xml.gz"}],
"aggregateBySourceIp": false,
"maxItems": 10000
}'

Poll the returned run or use run-sync-get-dataset-items for small synchronous jobs. Do not put tokens or confidential XML into logs or public Task inputs.

JavaScript API client

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/dmarc-aggregate-report-analyzer').call({
reports: [{ name: 'daily-report', base64: process.env.DMARC_REPORT_BASE64 }],
aggregateBySourceIp: true,
maxItems: 10000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((row) => !row.dmarcPass));

Python API client

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/dmarc-aggregate-report-analyzer').call(run_input={
'reports': [{'name': 'daily-report', 'url': 'https://your-authorized-host/reports/dmarc.xml'}],
'failOnInvalid': True,
'maxItems': 10000,
})
rows = client.dataset(run['defaultDatasetId']).list_items().items
failures = [row for row in rows if not row['dmarcPass']]
print(failures)

MCP

Expose this Actor as a tool in Claude Code:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/dmarc-aggregate-report-analyzer"

For Claude Desktop, Cursor, and VS Code, add this MCP JSON block to the client's MCP configuration:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/dmarc-aggregate-report-analyzer"
}
}
}

Example prompts:

  • “Analyze this base64 DMARC aggregate report and list failing source IPs.”
  • “Combine these three authorized report URLs and rank senders by message count.”
  • “Return rejected rows where neither aligned DKIM nor aligned SPF passed.”

Integrations and monitoring patterns

  • Google Sheets or Excel: export source rows for a weekly deliverability review.
  • Make or Zapier: launch a run when an attachment reaches object storage.
  • Webhooks: notify a security workflow after a successful scheduled run.
  • SIEM: ingest rows and alert on new IPs or rising reject counts.
  • Data warehouse: partition by periodEnd, domain, and sourceIp.
  • Apify schedules: rerun after daily aggregate-report collection completes.

The Actor analyzes supplied reports; it does not monitor an inbox or remember prior runs. Retain datasets or compare them downstream for change detection.

Limits and data handling

  • Aggregate DMARC XML is supported; forensic message reports are not.
  • One run accepts at most 100 report inputs.
  • Each downloaded and unpacked report is limited to 10 MB.
  • ZIP archives must contain at least one .xml member; the first is parsed.
  • XML external entities are not resolved or fetched.
  • Unknown provider extension fields are ignored.
  • Results stop at maxItems; reports are parsed in input order.
  • The Actor performs no reverse-DNS, ASN, geolocation, or reputation lookup.
  • URL availability and authorization remain the user's responsibility.

Troubleshooting

“XML is not a DMARC aggregate feedback report” means the root does not contain both report_metadata and policy_published. Confirm that the file is an aggregate XML report rather than an email body or forensic report.

“Provide exactly one of xml, url, or base64” means a report object has no source or several source fields. Keep one source and preserve the required name.

A ZIP archive fails when it contains no .xml member. Extract or rebuild the archive, or submit the XML member as base64.

Some reports succeed and one fails. Keep failOnInvalid: true for atomic processing. Set it to false only when skipped-file warnings are acceptable.

SPF details pass while spfEvaluation fails. The detailed domain likely did not align with headerFrom; this is valid DMARC behavior.

Legality and responsible use

Process only reports you are authorized to access. Treat report URLs as secrets when they contain signed query parameters. DMARC data can reveal internal or third-party email infrastructure, sender IPs, domains, and operational volume. Apply suitable access controls, retention limits, and regional privacy rules.

This tool provides technical normalization, not a legal conclusion, abuse verdict, or guarantee that a sender is authorized. Validate findings against business and infrastructure ownership records before enforcement.

FAQ

Does the Actor send or receive email?

No. It only processes report content supplied in Actor input.

Can it parse .xml.gz and .zip attachments?

Yes. Submit the bytes as base64 or provide an accessible HTTP(S) URL. ZIP processing selects the first .xml member.

Does messageCount equal the number of dataset rows?

No. A dataset row represents one DMARC source record. messageCount is the number of messages summarized by that record.

Can it identify unauthorized senders automatically?

It identifies authentication and disposition signals. Authorization depends on your sender inventory, forwarding rules, vendors, and business context.

Why is reportId null in an aggregated row?

An aggregate can include several reports. Use reportIds and reportsCount to trace the contributing evidence.

Can I schedule recurring analysis?

Yes. Use Apify schedules after your report-collection workflow makes new XML or compressed files available. Store prior datasets if you need trend comparison.