Corsair

Open source mail server + control panel

Run your own mail. On your own machine.

Corsair is the mail server and the panel that manages it. Add a domain, publish the records it prints, create a mailbox, and point any client at it. One process, PostgreSQL, and a bucket.

What actually happens

A message arrives and four protocols can already see it

Corsair checks SPF, verifies the DKIM signature, applies the sender's DMARC policy, scores the message, runs the recipient's filter, and files it. There is one copy of the mail and no synchronisation step, so IMAP, JMAP, POP3, and the webmail are all looking at the same row a moment later.

How the pieces fit together →

220 mail.example.com Corsair ESMTP ready
EHLO sender.example.net
250-mail.example.com
250-STARTTLS
250-8BITMIME
250 SIZE 52428800
MAIL FROM:<sam@sender.example.net>
250 2.1.0 Sender OK
RCPT TO:<you+receipts@example.com>
250 2.1.5 Recipient OK
DATA
354 Start mail input; end with <CRLF>.<CRLF>
...
250 2.0.0 Message accepted
     spf=pass dkim=pass dmarc=pass
     filed → Receipts (uid 4192)

Specification

Everything a mail host does, in one binary

No per-seat pricing, because the cost of a mailbox is disk and bandwidth.

Receiving

MX on port 25

SPF, DKIM verification, DMARC, spam scoring, and Sieve filtering on the delivery path. Unmatched recipients fall through to sub-addressing, then a catch-all, then a fallback domain.

Sending

Submission on 587 and 465

The From address is proven to belong to the caller, the message is DKIM-signed, a copy is filed in Sent, and delivery retries with backoff for five days.

Reading

IMAP, JMAP, POP3, webmail

IMAP4rev1 with IDLE, MOVE, SORT, and UIDPLUS. JMAP per RFC 8620 and 8621. POP3 for the clients that still want it. A three-pane webmail client at /webmail.

Addresses

Four kinds, one domain

Mailboxes with a password, aliases that forward, groups that fan out, and a catch-all. Forwarded mail is SRS-rewritten so it survives the next hop's SPF check.

DNS

Published for you

Corsair detects your provider from the NS records and, given a token, writes all ten records itself. The token is used once and never stored. Manual setup, a live checker, and a zone-file export are always there too.

Events

Signed webhooks

A POST to your endpoint when mail arrives, bounces, or is filed as spam. Standard Webhooks signing, so the verification library you already have works unchanged.

By the numbers

Small on purpose

1Process
5Protocols
11DNS records
2Dependencies
0Telemetry calls

Read this part first

Running mail is four things that are not code

Corsair will not pretend otherwise. Before any of this is reachable mail you need a static IP whose PTR record matches your hostname, port 25 unblocked outbound, a real TLS certificate, and permission to bind the privileged ports.

If you cannot get port 25, that is fine — point Corsair at a smarthost and it relays instead. Everything else works the same.

The prerequisites, in detail →

Ten minutes

Try it on your laptop first

sh
git clone https://github.com/wess/corsair
cd corsair
bun install && cp .env.example .env
bun run db:up && bun run migrate && bun run seed
bun run dev

Unprivileged ports, mail printed to the console instead of sent, and a panel at localhost:3000/app. Nothing leaves the machine.

Documentation

Learn it end to end

Setup, operation, and every protocol surface — written to be read in order or searched.

Tutorials

Follow a build

Your first production server takes a blank VPS to delivered mail. Then migrate a domain off Google, wire up webhooks, or set up a household.