new-site/infra/cron
justin 8e5590b492 mail: DMARC aggregate-report parser + dedicated dmarc@ mailbox ingestion
Tool 2 of the deliverability monitoring pair (Tool 1 = mail_reputation_monitor).
DMARC rua reports from dozens of operators (Google, Yahoo, Comcast, Cox, Bell,
Mimecast, Cisco ESA, GMX, mail.com, ...) were landing in ops@ (dmarc@ was a DL),
burying real mail and never parsed. Now ingested + queryable:

- dmarc@performancewest.net converted DL -> dedicated Carbonio mailbox; isolated
  IMAP creds in server .env, surfaced to workers in docker-compose.yml (mirrors
  OPS_IMAP_*). 29 historical reports moved ops@ -> dmarc@ via IMAP.
- scripts/dmarc_report_parser.py: IMAP fetch unseen -> decompress .gz/.zip/.xml
  (namespace-agnostic: classic + urn:ietf:params:xml:ns:dmarc-2.0 GMX/mail.com) ->
  parse aggregate XML -> upsert dmarc_report (keyed (org_name,report_id), no-op on
  re-parse) + dmarc_record per source IP. dmarc_pass = dkim_aligned OR spf_aligned.
  Marks \Seen. --dry-run/--all/--alert (7d per-IP summary + Telegram if one of OUR
  IPs <95% pass, or EXTERNAL IP sends >=20 failing msgs as us = spoofing under
  p=reject). psycopg2 imported lazily so --dry-run runs without the driver.
- api/migrations/102_dmarc_aggregate.sql: dmarc_report + dmarc_record tables.
- infra/cron/pw-dmarc-parser: 06:20 UTC daily --alert (after reputation, before scrub).
- docs/deliverability.md: DMARC section DONE; query examples.

Verified: dry-run --all parses all 28 reports (1 non-report test probe), 0 unknown
after the namespace fix.
2026-06-19 08:50:20 -05:00
..
pw-dmarc-parser mail: DMARC aggregate-report parser + dedicated dmarc@ mailbox ingestion 2026-06-19 08:50:20 -05:00
pw-fmcsa-refresh trucking: weekly FMCSA source refresh so new non-compliant carriers are caught 2026-06-17 20:44:54 -05:00
pw-hc-campaign hc: warmup must run DAILY for the full 21-day ramp (not weekdays-only) 2026-06-14 21:02:08 -05:00
pw-hc-nppes hc: warmup must run DAILY for the full 21-day ramp (not weekdays-only) 2026-06-14 21:02:08 -05:00
pw-hc-rampcap infra: codify the email-campaign pipeline in Ansible (new mail-pipeline role) 2026-06-17 20:26:01 -05:00
pw-hc-refresh infra: codify the email-campaign pipeline in Ansible (new mail-pipeline role) 2026-06-17 20:26:01 -05:00
pw-ifta-campaign infra: codify the email-campaign pipeline in Ansible (new mail-pipeline role) 2026-06-17 20:26:01 -05:00
pw-ip-rehab warmup: IP rehab for .91-.93 so they can be reallocated 2026-06-09 20:27:47 -05:00
pw-listmonk-rampcap infra: codify the email-campaign pipeline in Ansible (new mail-pipeline role) 2026-06-17 20:26:01 -05:00
pw-listmonk-scrub infra(cron): daily Listmonk consumer-domain reconciliation (pw-listmonk-scrub) 2026-06-19 00:00:46 -05:00
pw-mail-reputation infra(cron): nightly mail-reputation snapshot (pw-mail-reputation) 2026-06-19 08:38:35 -05:00
pw-mta-warmup infra: codify the email-campaign pipeline in Ansible (new mail-pipeline role) 2026-06-17 20:26:01 -05:00
pw-trucking-campaign-builder infra: codify the email-campaign pipeline in Ansible (new mail-pipeline role) 2026-06-17 20:26:01 -05:00
pw-ucr-campaign infra: codify the email-campaign pipeline in Ansible (new mail-pipeline role) 2026-06-17 20:26:01 -05:00
pw-warmup-tg-alert monitoring: daily warmup IP-reputation Telegram alert 2026-06-08 21:06:41 -05:00