npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@beesolve/dmarc-reports

v0.1.1

Published

DMARC report ingestion pipeline — SES to S3 to EventBridge via Lambda

Readme

@beesolve/dmarc-reports

DMARC report ingestion pipeline — receives aggregate reports via SES, parses them, and emits structured events to EventBridge.

Architecture

                    ┌─────────┐
DMARC reports ──►  │   SES   │
(email)            └────┬────┘
                        │
                        ▼
                   ┌─────────┐
                   │   S3    │  (inbox/, 90-day lifecycle)
                   └────┬────┘
                        │ EventBridge (Object Created)
                        ▼
                   ┌─────────┐
                   │ Lambda  │  Parse MIME → extract XML → validate
                   └────┬────┘
                        │
                        ▼
                  ┌───────────┐
                  │EventBridge│  DmarcReportParsed events
                  └───────────┘

Installation

npm install @beesolve/dmarc-reports

SES Setup Guide

Use a dedicated subdomain for receiving DMARC reports (e.g. dmarc.example.com). This keeps it separate from your main email routing.

1. Verify the subdomain in SES

Add dmarc.example.com as a verified identity in SES. This tells SES to accept inbound email for this domain. You do not need Custom MAIL FROM, SPF, or DKIM for this identity — it is receive-only.

2. Set up MX record

Point the subdomain to SES inbound in Route 53 (or your DNS provider):

dmarc.example.com  MX  10 inbound-smtp.<region>.amazonaws.com

Replace <region> with your SES region (e.g. eu-central-1).

3. Update your DMARC DNS record

On each domain you want to collect reports for, update (or add) the DMARC TXT record to include the rua tag pointing to your new address:

_dmarc.example.com  TXT  "v=DMARC1; p=reject; rua=mailto:[email protected]; pct=100"

4. SES sandbox vs production

By default, SES accounts are in sandbox mode. Inbound receiving works in sandbox only for verified email addresses. To receive DMARC reports from external senders (Google, Microsoft, Yahoo, etc.), you must request production access via the AWS Console.

Notes

  • No SPF/DKIM/Custom MAIL FROM is needed on the receiving subdomain — those are only required for sending emails
  • The CDK construct automatically activates the SES receipt rule set
  • Reports typically start arriving within 24–48 hours after updating the DMARC rua tag
  • Use a subdomain (not your main domain) to avoid conflicts with existing email routing (e.g. Google Workspace catch-all rules)

CDK Usage

import { DmarcReports } from "@beesolve/dmarc-reports/cdk";

const dmarcReports = new DmarcReports(this, "DmarcReports", {
  recipient: "[email protected]",
  // Optional: custom event bus
  eventBusArn: "arn:aws:events:us-east-1:123456789012:event-bus/custom",
  // Optional: override Lambda props
  handlerProps: {
    memorySize: 512,
    timeout: Duration.seconds(60),
  },
});

Event Consumer Example

import { isDmarcReportParsedEvent, eventSource, detailType } from "@beesolve/dmarc-reports";

// In an EventBridge rule target (Lambda handler):
export async function handler(event: unknown): Promise<void> {
  if (!isDmarcReportParsedEvent(event)) {
    console.error("Invalid event received");
    return;
  }

  // event.detail is fully typed as DmarcReport
  const report = event.detail;
  console.log(`Report from ${report.reportMetadata.orgName} for ${report.policyPublished.domain}`);

  for (const record of report.records) {
    if (record.policyEvaluated.dkim === "fail" || record.policyEvaluated.spf === "fail") {
      console.warn(`Auth failure from ${record.sourceIp} (${record.count} messages)`);
    }
  }
}

Cost Estimate

At expected volume (~5–10 reports/day per domain):

| Service | Calculation | Cost/month | | ----------- | ------------------------------------------------------ | ---------- | | SES | $0.10/1000 emails → ~150–300 emails/month | ~$0.01 | | S3 | Reports are <10KB each, 90-day lifecycle | minimal | | Lambda | ~300 invocations × 256MB × <1s = well within free tier | $0.00 | | EventBridge | $1/million events → ~300 events/month | ~$0.00 | | Total | | <$0.10 |

Useful Links