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.
## 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).