MillionSend

The open-source email platform. Send one. Send a million.

Self-host on your own AWS SES, or use the hosted cloud. Resend-compatible API — migrating means changing two environment variables, not rewriting your integration.

The MillionSend dashboard: the Emails page, with each send's delivery status

## Features | Feature | Status | Notes | | --- | --- | --- | | Emails API (Resend-compatible) | ✅ | Send, batch, get, cancel — same request/response shapes as Resend. | | Idempotency | ✅ | `Idempotency-Key` header dedupes retried sends. | | API keys | ✅ | Create and revoke `ms_` keys from the dashboard, with last-used tracking. | | Suppression list | ✅ | Hard bounces and complaints suppressed automatically; review and remove per address, or manage via `/suppressions` (batch add/remove up to 1000). | | Metrics | ✅ | Daily sends with bounce and complaint rates tracked against SES thresholds. | | Webhooks (Standard Webhooks) | ✅ | Signed event deliveries (`webhook-*` and `svix-*` headers) with per-endpoint event selection, a delivery log, and bring-your-own `whsec_` secret. | | Domains + BYODKIM | ✅ | Guided DNS verification; bring your own DKIM key or let SES manage it. | | Contacts | ✅ | Team-wide contacts with subscribe state, segments, topics, CSV import, and bulk `POST /contacts/batch`. | | One-click unsubscribe (RFC 8058) | ✅ | `List-Unsubscribe` headers plus a hosted unsubscribe page. | | Broadcasts | ✅ | Compose, schedule, and send to all contacts, a segment, or a topic; cancel while scheduled. | | Templates + merge fields | ✅ | Reusable templates with per-contact merge fields; `/templates` API with per-team aliases. | | API request logs | ✅ | Every API request recorded with request/response bodies, secrets redacted. | | SMTP relay | ✅ | Drop-in SMTP on port 2587; authenticate with an API key. | | Receiving | Beta | Mail to any address on a verified domain, through an MX the instance runs (`PROCESS=mx`); Resend's `emails.receiving` API, `forward()` included, and the `email.received` webhook. | | Dashboard (en/pt-BR) | ✅ | Full dashboard in English and Brazilian Portuguese. | | Self-host (Docker) | ✅ | Compose file plus a setup wizard; sends through your own AWS SES. | | Migrate from Resend | ✅ | `npx @millionsend/cli migrate --from resend` moves contacts, segments, topics, templates, webhooks, domains and suppressions; read-only against Resend, safe to re-run before cutover. | | Content monitoring | ✅ | Optional outbound judge via [TypeSafe Jev](https://typesafe.ai). Off by default on self-host. | The hosted monitor uses [TypeSafe](https://typesafe.ai)'s Jev, a System One model built for typed decisions in software. A new team's mail in its first window and its broadcasts, and any team's mail to a destination it has never used, are scored before SES takes them and wait for the verdict, about half a second; everything else is sampled after it is sent, and sending never waits on it. Self-hosters leave it off unless they set `ABUSE_JUDGE=typesafe`. ## Run it locally One command, in an empty directory — no clone needed: ```sh npx @millionsend/setup ``` The wizard creates `.env` (secrets generated for you), optionally provisions the AWS resources (IAM user, SNS event topic, SES configuration set), and starts the prebuilt image with `docker compose up -d`. Every step is offered, skippable, and safe to re-run. Prefer doing it by hand? The manual curl path and everything else — from-source build, SES/SNS event pipeline, Docker-less development — is in [SELF_HOSTING.md](SELF_HOSTING.md). Dashboard at http://localhost:3000, API at http://localhost:3001. ## License Code is licensed under [AGPL-3.0](LICENSE). SDKs ship separately under MIT (npm/PyPI package: `millionsend`). The MillionSend name, wordmark, and logos are trademarks of the MillionSend project and are not licensed under the AGPL. ## Community Questions, ideas and roadmap talk live in the [Discussions](https://github.com/orgs/MillionSend/discussions).