🛡️ DMARC Monitor

Automated DMARC aggregate report collection and analysis for cPanel servers

v1.0.3 Python 3.6+ PHP 8.0+ cPanel / WHM WB3ISP

What It Does

DMARC Monitor is a self-hosted suite of scripts that connects to a cPanel mailbox via IMAP, fetches DMARC aggregate report emails, parses the embedded XML, and displays the results in a clean PHP dashboard. It shows per-domain SPF and DKIM pass rates, identifies unauthorized sending sources, and provides plain-English recommended actions for every issue found. A cron job runs automatically every 4 hours — no manual intervention needed once it's set up.

DMARC (Domain-based Message Authentication, Reporting & Conformance) works by having receiving mail servers — Google, Microsoft, Yahoo, and others — send daily reports back to your domain telling you who sent mail on your behalf and whether it passed SPF and DKIM checks. Without a tool to collect and parse these reports, they pile up unread in your mailbox as compressed XML attachments. This script does all the heavy lifting automatically.

Key Features

📨

Automatic IMAP Fetching

Connects directly to your cPanel mailbox via localhost using SSL/TLS or STARTTLS. Searches by subject line, sender address, and unseen flag to catch reports from all major receivers — Google, Microsoft, Yahoo, and others.

📦

Attachment Parsing

DMARC reports arrive as ZIP or GZ compressed XML attachments. The script decompresses both formats automatically and parses the XML — no manual extraction or third-party libraries needed.

🌐

Multi-Domain Dashboard

Groups all reports by domain and shows SPF/DKIM pass rates, DMARC policy enforcement status, and a per-source IP breakdown for every domain on your server — all in one view.

⚠️

Actionable Findings

Every domain card analyzes its records and surfaces specific findings — SPF failures, DKIM failures, unknown sending sources, quarantined messages, and rejected mail — each with a plain-English recommended fix.

🔁

Fingerprint Deduplication

Each parsed report is fingerprinted using an MD5 hash of its report ID, organization, domain, and date range. The script never double-counts a report even if the same email is encountered on multiple runs.

⏱️

Cron Run Tracking

After every run the script writes a last_run.json file recording the timestamp, number of emails checked, and new reports added. The dashboard status bar shows this information at a glance.

🔒

Session-Based Login

The dashboard is protected by its own PHP session login — no Apache .htpasswd required. Username and password are stored using PHP's password_hash() and can be changed from within the Settings page.

🖥️

Sidebar Navigation

Clean sidebar layout with Overview, By Domain, Run Log, and Settings pages. Domain cards are sorted by severity — domains with active failures appear at the top. Full dark mode support via CSS prefers-color-scheme.

🛠️

DNS Bulk Tools

Shell scripts to add, audit, fix, and verify _dmarc TXT records across all domains on the server in one command. Handles duplicate detection, broken records, and color-coded verification reporting.

How It Works

Send mailYour domains send email normally through cPanel/Exim. Receiving servers check SPF and DKIM alignment against your DNS records.
Reports generatedReceivers (Google, Microsoft, Yahoo, etc.) compile daily aggregate reports and email them to dmarc@yourdomain.com as compressed XML attachments.
Cron fetchesEvery 4 hours the Python script connects to your IMAP mailbox, finds DMARC report emails, decompresses the attachments, and parses the XML.
Data storedParsed reports are fingerprinted and written to a JSON data file. Duplicate reports from previous runs are skipped automatically.
Dashboard displaysThe PHP dashboard reads the JSON file and shows per-domain pass rates, source breakdowns, and findings with recommended actions.
You actFix any SPF or DKIM issues identified in the findings. Once all domains are clean, tighten your DMARC policy from p=none to p=quarantine then p=reject.

Files Included

All files are plain text — no compiled binaries, no external package managers, no dependencies beyond what's already on a standard cPanel server.

fetch_dmarc.py

The core fetch and parse script. Connects to IMAP, finds DMARC report emails, decompresses ZIP and GZ attachments, parses the XML, fingerprints each report, and writes results to the JSON data file. Reads all configuration from config.ini. Run manually or via cron.

config.ini

Configuration file for IMAP host, port, security mode, username, password, mailbox folder, maximum emails per run, data file path, log file path, and post-processing options (mark-as-read, delete-after-processing).

index.php

The PHP dashboard. Reads the JSON data file and renders the full UI — login page, overview metrics, per-domain expandable cards with findings, run log tab, and settings page. No database required — everything runs off the JSON file written by the fetch script.

setup.sh

One-time setup script. Creates the required directory structure, deploys the dashboard and fetch script to their target paths, prompts for an HTTP password (optional), and installs the cron job to run every 4 hours.

add_dmarc_records.sh

Bulk-adds _dmarc TXT records for all specified domains via the WHM API (whmapi1 / uapi). Checks for existing records before adding to avoid duplicates. Requires root or WHM API access.

audit_dmarc.sh

Audits all domains for DMARC record issues. Reports missing records, duplicate records, and records that are missing the rua= or ruf= reporting addresses. Color-coded pass/fail output per domain.

fix_dmarc_records.sh

Auto-fixes duplicate and misconfigured DMARC records. Removes all existing _dmarc records for any problem domain and replaces them with a single correct record. Domains that are already correct are skipped.

verify_dmarc.sh

Full verification report showing record count, policy, RUA presence, RUF presence, and pass/fail status for every domain. Color-coded terminal output. Run after any DNS changes to confirm everything is correct.

Dashboard Pages

Overview

Global summary across all monitored domains. Metric cards show domain count, total reports parsed, total messages analyzed, and global SPF and DKIM pass rates with color-coded thresholds (green above 90%, amber above 60%, red below 60%). A sortable summary table lists every domain with its message count, SPF rate, DKIM rate, current policy, and status badge — domains with failures appear at the top.

By Domain

Expandable card for each domain. Each card shows sub-metrics (message count, SPF pass rate, DKIM pass rate, policy and percentage, alignment mode, and reporting organizations), a source IP table with per-row SPF/DKIM/DMARC result badges, and a findings section. Each finding has a colored icon, title, sub-detail, and a blue action box with a specific recommended fix — whether that's updating an SPF record, repairing a DKIM key in cPanel, authorizing a third-party sender, or tightening the DMARC policy.

Run Log

Shows the last 40 lines of the fetch script's log file directly in the browser. Useful for confirming the cron job is running, checking how many emails were found, and diagnosing any IMAP connection or parsing errors without needing SSH access.

Settings

Change the dashboard login username and password from within the browser. Current password verification required. Credentials are stored in a PHP file using password_hash() — never in plain text. Default credentials on first install are admin / dmarc1234 — change these immediately after setup.

DMARC Policy Progression

DMARC enforcement is applied gradually. Start at p=none to collect data without affecting mail delivery, then tighten once you're confident all legitimate senders are passing.

📊 p=none

Monitor only. Receivers send reports but deliver all mail normally regardless of SPF/DKIM result. Start here for every domain and run for at least 2–4 weeks before tightening.

📥 p=quarantine

Failing messages are sent to the recipient's spam folder. Legitimate mail that passes SPF or DKIM is unaffected. Move here once the dashboard shows all known senders passing.

🚫 p=reject

Failing messages are dropped entirely by the receiving server. Maximum protection against spoofing. Only apply once you're fully confident all legitimate mail is authorized.

📈 pct=

Percentage of messages the policy applies to. Set to 100 for full enforcement. Can be reduced (e.g. pct=10) during a gradual rollout to quarantine or reject.

Requirements

🖥️
ServercPanel / WHM
🐍
Python3.6 or higher
🐘
PHP8.0 or higher
📬
MailboxDedicated DMARC address (e.g. dmarc@yourdomain.com)
🔑
AccessSSH / terminal access for setup
📦
DependenciesNone — stdlib only (imaplib, email, zipfile, gzip, xml, json)
💡 The fetch script connects to IMAP via localhost when the mailbox is on the same cPanel server. This is faster and more reliable than connecting via the public hostname, and avoids any firewall issues.

Installation

1. Create a DMARC mailbox

In cPanel → Email Accounts, create a dedicated address such as dmarc@yourdomain.com. This is where all aggregate reports will be delivered.

2. Add DMARC DNS records

For each domain you want to monitor, add a _dmarc TXT record in DNS. Use add_dmarc_records.sh to do this in bulk across all server domains, or add them manually in cPanel → Zone Editor. Start with p=none:

v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com; ruf=mailto:dmarc@yourdomain.com; pct=100; fo=1

3. Run setup

Upload the zip, extract it, edit setup.sh to match your server paths, then run it via SSH. It creates the required directories, deploys all files, and installs the cron job.

4. Edit config.ini

Set your IMAP password and confirm the file paths. The host defaults to localhost which is correct for same-server mailboxes.

5. Test manually

Run the fetch script once by hand and check the log to confirm it connects and processes any existing emails:

python3 ~/scripts/dmarc/fetch_dmarc.py

6. Open the dashboard

Navigate to https://yourdomain.com/dmarc/, sign in with the default credentials, and immediately change the password under Settings. Reports will begin appearing within 24 hours as receivers send their first aggregate reports.

📝 DMARC aggregate reports are sent by receivers once every 24 hours and only after they have seen mail from your domain. The first reports typically arrive from Google and Microsoft within 24–48 hours of adding the DNS records.

Version History

1.0.3 May 2026 Cron run tracking — fetch_dmarc.py now writes last_run.json after every run, recording timestamp, emails checked, and new reports added. Dashboard status bar shows last run time and results. Graceful fallback if file does not exist yet.
1.0.2 May 2026 Settings page added to the dashboard. Username and password can now be changed from within the browser. Credentials stored using PHP password_hash() — never plain text. Auth file auto-created on first load with default credentials. Signed-in username shown in sidebar footer.
1.0.1 May 2026 Dashboard redesigned with full sidebar navigation — Overview, By Domain, Run Log, and Settings. Color-coded metric cards with green/amber/red pass rate thresholds. Issue icons now have colored backgrounds. Login page redesigned with shield logo. Domains sorted by severity in overview table. Improved dark mode coverage.
1.0.0 May 2026 Initial release. IMAP fetcher with SSL/TLS and STARTTLS support, ZIP and GZ decompression, DMARC XML parsing with SPF/DKIM auth results and selectors, MD5 fingerprint deduplication, configurable mark-as-read and delete-after-processing, activity log, config.ini support, multi-domain PHP dashboard with session login, per-domain findings and recommended actions, and DNS bulk tools (add, audit, fix, verify).