Parse Dmarc — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Parse Dmarc (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Monitor who's sending email on behalf of your domain. Catch spoofing. Stop phishing.
Deploy Parse DMARC to your favorite cloud provider with one click:
| Provider | Deploy | Notes |
|---|---|---|
| CapRover | Self-hosted PaaS | |
| Coolify | Open-source Heroku alternative | |
| Dokploy | Self-hosted deployment platform | |
| Docker | Run anywhere |
Note: All deployments require IMAP credentials. See Configuration for details on setting up Gmail, Outlook, or other email providers.
DMARC (Domain-based Message Authentication, Reporting & Conformance) helps protect your domain from email spoofing and phishing. When you enable DMARC on your domain, email providers like Gmail, Outlook, and Yahoo send you aggregate reports showing:
The Problem: These reports arrive as compressed XML attachments in your inbox - nearly impossible to read or analyze manually.
The Solution: Parse DMARC automatically fetches these reports from your inbox, parses them, and displays everything in a beautiful dashboard. All in a single 14MB Docker image.
brew tap meysam81/tap
brew install parse-dmarcdocker pull meysam81/parse-dmarcDownload pre-built binaries from the Releases page.
This is the most important step! Without this, you won't receive any reports to analyze.
Add a DMARC TXT record to your domain's DNS:
Name: _dmarc.yourdomain.com
Type: TXT
Value: v=DMARC1; p=none; rua=mailto:[email protected]What this means:
p=none - Monitor only (don't block emails yet)rua=mailto:[email protected] - Send aggregate reports to this email addressImportant: Replace [email protected] with an actual email inbox you control. This is where Gmail, Outlook, Yahoo, etc. will send your DMARC reports.
DNS Examples:
_dmarc, Content: v=DMARC1; p=none; rua=mailto:[email protected]_dmarc, Data: v=DMARC1; p=none; rua=mailto:[email protected]_dmarc.yourdomain.com, Value: "v=DMARC1; p=none; rua=mailto:[email protected]"Reports typically start arriving within 24-48 hours.
Run the container:
docker run -d \
--name parse-dmarc \
-p 8080:8080 \
-e IMAP_HOST=imap.gmail.com \
-e IMAP_PORT=993 \
-e [email protected] \
-e IMAP_PASSWORD=your-app-password \
-v parse-dmarc:/data \
meysam81/parse-dmarcFor Gmail users: You'll need an App Password, not your regular Gmail password.
Access the dashboard: Open http://localhost:8080 in your browser.
Once DMARC reports start arriving and Parse DMARC processes them, your dashboard will show:
This helps you:
p=none) to enforcement (p=quarantine or p=reject)Gmail:
{
"host": "imap.gmail.com",
"port": 993,
"username": "[email protected]",
"password": "your-app-password",
"use_tls": true
}Requires App Password
Outlook/Office 365:
{
"host": "outlook.office365.com",
"port": 993,
"username": "[email protected]",
"password": "your-password",
"use_tls": true
}Generic IMAP: Most providers use port 993 with TLS. Check your provider's documentation.
# Fetch once and exit (useful for cron jobs)
docker exec parse-dmarc ./parse-dmarc -fetch-once
# Serve dashboard only (no fetching)
docker exec parse-dmarc ./parse-dmarc -serve-only
# Custom fetch interval (in seconds, default 300)
docker exec parse-dmarc ./parse-dmarc -fetch-interval=600Q: I'm not receiving any reports. What's wrong?
A: Check these things in order:
_dmarc TXT record to your DNS? (Use a DNS checker like dig _dmarc.yourdomain.com TXT)config.jsonQ: Do I need SPF and DKIM set up first?
A: No! DMARC reports will show you whether SPF and DKIM are passing or failing, which helps you configure them correctly.
Q: What should my DMARC policy be?
A: Start with p=none (monitoring only). After reviewing reports and fixing any issues, gradually move to p=quarantine and then p=reject.
Q: How much email traffic do I need?
A: Any amount works. Even small domains with a few emails per day will receive useful reports.
Q: Can I use a Gmail account to receive reports?
A: Yes! Create a dedicated Gmail like [email protected], forward it to your personal Gmail if needed, and use Gmail's IMAP settings.
git clone https://github.com/meysam81/parse-dmarc.git
cd parse-dmarc
just install-deps
just build
./bin/parse-dmarc -config=config.jsonSee compose.yml for Docker Compose configuration.
GET /api/statistics - Dashboard statisticsGET /api/reports - List of reports (paginated)GET /api/reports/:id - Detailed report viewGET /api/top-sources - Top sending source IPsGET /metrics - Prometheus metrics endpointParse DMARC includes production-ready Prometheus metrics for monitoring and alerting. Metrics are enabled by default and exposed at /metrics.
#### Build Information
| Metric | Type | Description |
|---|---|---|
parse_dmarc_build_info | Gauge | Build information (version, commit, build_date) |
#### Report Processing
| Metric | Type | Description |
|---|---|---|
parse_dmarc_reports_fetched_total | Counter | Total DMARC report emails fetched from IMAP |
parse_dmarc_reports_parsed_total | Counter | Total DMARC reports successfully parsed |
parse_dmarc_reports_stored_total | Counter | Total DMARC reports stored in database |
parse_dmarc_reports_parse_errors_total | Counter | Total parse errors |
parse_dmarc_reports_store_errors_total | Counter | Total storage errors |
parse_dmarc_reports_attachments_total | Counter | Total attachments processed |
parse_dmarc_reports_fetch_duration_seconds | Histogram | Duration of fetch operations |
parse_dmarc_reports_last_fetch_timestamp_seconds | Gauge | Unix timestamp of last successful fetch |
parse_dmarc_reports_fetch_cycles_total | Counter | Total fetch cycles executed |
parse_dmarc_reports_fetch_errors_total | Counter | Total fetch cycle errors |
#### IMAP Connection
| Metric | Type | Labels | Description |
|---|---|---|---|
parse_dmarc_imap_connections_total | Counter | status | IMAP connection attempts (success/error) |
parse_dmarc_imap_connection_duration_seconds | Histogram | IMAP connection establishment duration |
#### DMARC Statistics
| Metric | Type | Description |
|---|---|---|
parse_dmarc_dmarc_reports_total | Gauge | Total reports in database |
parse_dmarc_dmarc_messages_total | Gauge | Total messages across all reports |
parse_dmarc_dmarc_compliant_messages_total | Gauge | Total DMARC-compliant messages |
parse_dmarc_dmarc_compliance_rate | Gauge | Overall compliance rate (0-100) |
parse_dmarc_dmarc_unique_source_ips | Gauge | Number of unique source IPs |
parse_dmarc_dmarc_unique_domains | Gauge | Number of unique domains |
#### Per-Domain/Org Metrics
| Metric | Type | Labels | Description |
|---|---|---|---|
parse_dmarc_dmarc_messages_by_domain | Gauge | domain | Messages per domain |
parse_dmarc_dmarc_compliance_rate_by_domain | Gauge | domain | Compliance rate per domain |
parse_dmarc_dmarc_reports_by_org | Gauge | org_name | Reports per organization |
parse_dmarc_dmarc_messages_by_disposition | Gauge | disposition | Messages by disposition type |
#### Authentication Results
| Metric | Type | Labels | Description |
|---|---|---|---|
parse_dmarc_dmarc_spf_results | Gauge | result | SPF authentication result counts |
parse_dmarc_dmarc_dkim_results | Gauge | result | DKIM authentication result counts |
#### HTTP Server
| Metric | Type | Labels | Description |
|---|---|---|---|
parse_dmarc_http_requests_total | Counter | method, path, status | Total HTTP requests |
parse_dmarc_http_request_duration_seconds | Histogram | method, path | HTTP request duration |
parse_dmarc_http_requests_in_flight | Gauge | Current in-flight requests |
#### Go Runtime (Built-in)
Standard Go runtime metrics are also exposed:
go_goroutines - Number of goroutinesgo_memstats_* - Memory statisticsgo_gc_* - Garbage collection metricsprocess_* - Process metrics (CPU, memory, file descriptors)To disable the metrics endpoint:
# Command line
./parse-dmarc --metrics=false
# Environment variable
export PARSE_DMARC_METRICS=false
# Docker
docker run -e PARSE_DMARC_METRICS=false meysam81/parse-dmarcAdd Parse DMARC to your prometheus.yml:
scrape_configs:
- job_name: "parse-dmarc"
static_configs:
- targets: ["parse-dmarc:8080"]
scrape_interval: 30s
metrics_path: /metricsFor Kubernetes with ServiceMonitor (Prometheus Operator):
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: parse-dmarc
labels:
app: parse-dmarc
spec:
selector:
matchLabels:
app: parse-dmarc
endpoints:
- port: http
path: /metrics
interval: 30sA production-ready Grafana dashboard is included in grafana/dashboard.json.
#### Import Manually
grafana/dashboard.json or paste its contents#### Provision Automatically (Recommended for Production)
# Copy dashboard to Grafana dashboards directory
cp grafana/dashboard.json /var/lib/grafana/dashboards/parse-dmarc/
# Copy provisioning config
cp grafana/provisioning.yaml /etc/grafana/provisioning/dashboards/parse-dmarc.yaml
# Restart Grafana or wait for it to pick up changes
systemctl restart grafana-server#### Dashboard Variables
| Variable | Purpose |
|---|---|
datasource | Prometheus datasource to query |
job | Filter by Prometheus job label |
instance | Filter by instance(s) |
domain | Filter by monitored domain(s) |
#### Dashboard Sections
| Section | What It Shows |
|---|---|
| Overview - Golden Signals | Compliance rate, total messages, reports count, time since last fetch |
| DMARC Authentication Results | SPF/DKIM pass rates, disposition breakdown, per-domain compliance |
| Report Sources & Organizations | Top reporting organizations (Google, Microsoft, etc.), messages by domain |
| IMAP & Fetch Operations | Connection health, fetch cycle monitoring, latency heatmaps |
| Error Tracking | Parse errors, storage errors, fetch failures |
| HTTP Server | Request rates, latency percentiles, error rates |
| Go Runtime | Goroutines, memory usage, GC stats, CPU usage |
#### Example Grafana Panels
Compliance Rate Gauge:
parse_dmarc_dmarc_compliance_rateMessages Over Time:
rate(parse_dmarc_dmarc_messages_total[5m])Compliance Rate by Domain:
parse_dmarc_dmarc_compliance_rate_by_domainSPF/DKIM Pass Rate:
# SPF Pass Rate
parse_dmarc_dmarc_spf_results{result="pass"} / ignoring(result) sum(parse_dmarc_dmarc_spf_results) * 100
# DKIM Pass Rate
parse_dmarc_dmarc_dkim_results{result="pass"} / ignoring(result) sum(parse_dmarc_dmarc_dkim_results) * 100Fetch Success Rate:
1 - (rate(parse_dmarc_reports_fetch_errors_total[1h]) / rate(parse_dmarc_reports_fetch_cycles_total[1h]))IMAP Connection Health:
rate(parse_dmarc_imap_connections_total{status="success"}[5m]) /
(rate(parse_dmarc_imap_connections_total{status="success"}[5m]) + rate(parse_dmarc_imap_connections_total{status="error"}[5m]))HTTP Request Latency (p95):
histogram_quantile(0.95, rate(parse_dmarc_http_request_duration_seconds_bucket[5m]))Reports by Organization:
topk(10, parse_dmarc_dmarc_reports_by_org)#### Alerting Rules
Example Prometheus alerting rules:
groups:
- name: parse-dmarc
rules:
- alert: DMARCComplianceLow
expr: parse_dmarc_dmarc_compliance_rate < 90
for: 1h
labels:
severity: warning
annotations:
summary: "DMARC compliance rate is below 90%"
description: "Current compliance rate: {{ $value }}%"
- alert: DMARCFetchFailures
expr: rate(parse_dmarc_reports_fetch_errors_total[15m]) > 0
for: 30m
labels:
severity: critical
annotations:
summary: "Parse DMARC fetch failures detected"
description: "IMAP fetch operations are failing"
- alert: IMAPConnectionErrors
expr: rate(parse_dmarc_imap_connections_total{status="error"}[5m]) > 0
for: 10m
labels:
severity: warning
annotations:
summary: "IMAP connection errors detected"
description: "Check IMAP credentials and server connectivity"
- alert: NoRecentFetch
expr: time() - parse_dmarc_reports_last_fetch_timestamp_seconds > 600
for: 5m
labels:
severity: warning
annotations:
summary: "No recent DMARC report fetch"
description: "Last fetch was {{ humanizeDuration $value }} ago"Complete monitoring stack:
version: "3.8"
services:
parse-dmarc:
image: meysam81/parse-dmarc
ports:
- "8080:8080"
volumes:
- ./config.json:/app/config.json
- ./data:/data
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- "--config.file=/etc/prometheus/prometheus.yml"
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
volumes:
grafana-data:With prometheus.yml:
global:
scrape_interval: 15s
scrape_configs:
- job_name: "parse-dmarc"
static_configs:
- targets: ["parse-dmarc:8080"]Access:
This project is inspired by ParseDMARC but built for simplicity:
Issues and pull requests are welcome! Please check the issues page.
Apache-2.0 - see LICENSE for details.
Found this useful? Star the repo! ⭐
[koyeb-1click]: https://app.koyeb.com/deploy?name=parse-dmarc&type=docker&image=docker.io%2Fmeysam81%2Fparse-dmarc%3Alatest®ions=fra&env%5BDATABASE_PATH%5D=%2Fdata%2Fdb.sqlite&env%5BIMAP_HOST%5D=&env%5BIMAP_MAILBOX%5D=INBOX&env%5BIMAP_PASSWORD%5D=&env%5BIMAP_PORT%5D=993&env%5BIMAP_USERNAME%5D=&env%5BIMAP_USE_TLS%5D=true&env%5BSERVER_PORT%5D=8080&ports=8080%3Bhttp%3B%2F&hc_protocol%5B8080%5D=http&hc_grace_period%5B8080%5D=5&hc_interval%5B8080%5D=30&hc_restart_limit%5B8080%5D=3&hc_timeout%5B8080%5D=5&hc_path%5B8080%5D=%2Fapi%2Fstatistics&hc_method%5B8080%5D=get
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.