Skip to content

richardevs/dmarc-dashboard-kit

Repository files navigation

DMARC Dashboard

DMARC Dashboard Kit

This project is born out of the frustration against expensive DMARC analytics services that individuals can't afford.

A self-hosted DMARC report analyzer on Cloudflare's free tier. One deploy script sets up everything: email ingestion, database, dashboard, and access control.

Email Sender → Cloudflare Email Routing → Worker email() → D1 (SQLite)
                                          Worker fetch()  → Dashboard (Svelte)
                                          Cloudflare Access (login wall)

A single Cloudflare Worker handles both DMARC report ingestion (via email) and serves the dashboard + API. Cloudflare Access protects the entire application.

Prerequisites

  • Node.js (v18+)
  • pnpm
  • A Cloudflare account with a domain (free plan works)
  • A Cloudflare API token with permissions:
    • Workers Scripts: Edit
    • D1: Edit
    • DNS: Edit
    • Email Routing Rules: Edit
    • Access: Apps and Policies: Edit
    • Access: Groups: Edit (only required if ACCESS_ALLOWED_IPS is set)

Manual Prerequisites (One-Time)

  1. Enable Email Routing for your receiving domain:

    Cloudflare Dashboard → your domain → Email → Email Routing → Enable

    Note: Cloudflare Email Routing requires your receiving domain's MX records to point to Cloudflare's mail servers. If your domain is already using another email provider, you cannot use Cloudflare Email Routing on the same domain without replacing the current MX records, which would break your existing email setup. A cheap dedicated domain is the recommended solution.

  2. Enable Cloudflare Access on your account:

    Cloudflare Dashboard → Access → Get started

Both are one-time settings best configured through the dashboard.

Quick Start

git clone <this-repo>
cd dmarc-dashboard-kit
pnpm install
pnpm run deploy

On first run, pnpm run deploy creates a .env file for you to fill in:

CLOUDFLARE_API_TOKEN=
CLOUDFLARE_ACCOUNT_ID=
CLOUDFLARE_ZONE_ID=
DMARC_EMAIL=dmarc
REPORT_AUTHORIZED_DOMAINS=
ACCESS_ALLOWED_EMAILS=
ACCESS_ALLOWED_EMAIL_DOMAINS=
ACCESS_ALLOWED_IPS=

Then run pnpm run deploy again.

What Deploy Automates

Step What
0 Auto-detects domain from zone ID
1 Creates D1 database (dmarc-reports)
2 Generates wrangler.toml with D1 database ID
3 Runs D1 schema migrations (all migrations/*.sql in order)
4 Builds Svelte dashboard
5 Deploys worker (API + dashboard + email handler)
6 Creates email routing rule + _report._dmarc DNS TXT records
7 Creates Cloudflare Access application + policy

Multi-Domain Support

To monitor a domain, two DNS records are needed:

1. On the monitored domain:

_dmarc.otherdomain.com  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"

2. On your receiving domain (authorizes accepting reports):

otherdomain.com._report._dmarc.yourdomain.com  TXT  "v=DMARC1;"

The deploy script handles step 2 automatically:

  • Set REPORT_AUTHORIZED_DOMAINS=otherdomain.com,another.org in .env for specific domains
  • Or leave it empty to create a wildcard *._report._dmarc that accepts reports from any domain

Warning: p=none only monitors — it does not block spoofed emails. Once you've reviewed your DMARC reports and confirmed all legitimate senders pass DKIM/SPF, move to p=quarantine and then p=reject as soon as possible.

Local Development

# Run D1 migrations locally
pnpm run migrate:local

# Start worker dev server (API + email handler)
pnpm run dev

# In another terminal — start dashboard dev server
cd dashboard
pnpm install
pnpm run dev

The dashboard dev server (Vite) runs separately during development. In production, the built dashboard is served as static assets by the worker.

Project Structure

├── src/                    # Cloudflare Worker
│   ├── index.ts            # Entry: email() + fetch() handlers
│   ├── email-handler.ts    # Email → parse XML → D1
│   ├── api.ts              # /api/* routes
│   ├── db.ts               # D1 queries
│   └── types.ts            # TypeScript types + DMARC enums
├── dashboard/              # Svelte SPA
│   └── src/
│       ├── App.svelte
│       ├── components/     # SummaryCards, Charts, Tables
│       └── lib/api.ts      # API client
├── migrations/
│   ├── 0001_init.sql       # D1 schema (reports + record_rows tables)
│   └── 0002_record_rows_unique.sql  # unique index on record_rows
├── deploy.sh               # One-command deploy
└── wrangler.toml           # Generated by deploy.sh (gitignored)

License

MIT — see LICENSE. Portions adapted from Cloudflare's dmarc-email-worker.

About

Receive, store, and visualize DMARC reports using Cloudflare Workers, D1, and Email Routing.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors