Open source

The open-source email server from MailKite

MailKite Server is an open-source (AGPL-3.0) email server for apps and AI agents: Haraka SMTP MX + submission edges, an IMAP server, a zero-dependency SQLite backend, and a web console. Run the whole stack on a $5 VPS — or point the same components at MailKite Cloud and never think about port 25.

Not a code drop — the SMTP and IMAP edges are the same code serving MailKite production today.

quick start
git clone https://github.com/mailkite/server
cd server
docker compose up -d
# backend + web console → http://localhost:8787
# --profile edges adds the MX edge on :25
What's in the box

Five components. One repo.

Take all five, or just the piece you're missing — every part is a stateless protocol head talking to the same small HTTP contract, so they run alone or together.

mta/

Inbound MX edge

Haraka on :25. Accepts mail with live anti-open-relay recipient checks, then POSTs the raw message to your backend as a signed webhook.

mta-submit/

Submission edge

SMTP AUTH on :587/:465 with DKIM signing — for every app and library that only speaks SMTP.

imap/

IMAP server

IMAP4 on :993 (implicit TLS). Read received mail from Thunderbird, Apple Mail, or your agent's IMAP library.

api-local/

Reference backend

One Node process, node:sqlite, zero npm dependencies. Signed inbound webhooks with retries, plus smarthost outbound through any SMTP relay.

ui/

Web console

Domains, DNS records, message log, webhooks, and credentials — magic-link sign-in, no password table to run.

docs/contract.md

The backend contract

The adapter boundary that ties it all together — with a conformance suite as its executable form.

Set it up

Want to run your own mail server? Here's the whole setup.

Running a mail server has a reputation. Most of that reputation belongs to deliverability — which is exactly the part you can rent. The server itself is four steps.

  1. 1

    Start the stack

    git clone the repo and docker compose up -d. The backend and web console come up on localhost:8787, and the first visit bootstraps your admin account — you sign in with an emailed magic link, no password table to manage.

  2. 2

    Add your domain

    Do it in the console — it generates your DKIM key and shows you the exact DNS records to set: MX pointing at your box, SPF, and the DKIM public key. Paste them into your DNS provider and you're verified.

  3. 3

    Open the mail ports

    docker compose --profile edges up -d adds the MX edge on :25. On a bare VPS, the self-hosting guide walks through submission (:587), IMAP (:993), TLS certs, and the systemd units — one VPS, three daemons, your backend URL in one env var. Can't get port 25 unblocked? Point our hosted MX at your box and skip it entirely.

  4. 4

    Prove it works

    Email yourself from anywhere. Watch it clear the recipient check, land in the message log, and hit your webhook — signed, with retries if your endpoint is down.

That's genuinely it. The full walkthrough — DNS records, TLS provisioning, systemd units, Fly.io and Railway deploys — lives in the docs:

Already running Haraka? You don't need to adopt the repo — npm install haraka-plugin-mailkite teaches your existing MX or submission server the same backend contract.

The design

Dumb edges, one small contract

Every component is a protocol head with no storage of its own. State sits behind a handful of HMAC-authenticated HTTP endpoints — implement them over any store and every edge here works unchanged.

That's the whole trick: the bundled SQLite backend and MailKite Cloud are just two implementations of the same contract. One MX edge can even serve several backends at once, routing each recipient domain to its owner.

Read the contract — the conformance suite is its executable form.

the backend contract
POST /api/imap/auth     # verify a mailbox credential
GET /api/imap/status # message counts, uidvalidity
GET /api/imap/list # list messages in a mailbox
POST /api/imap/flags # read / unread / deleted
GET /api/imap/raw # fetch a raw RFC822 message

POST <ingest hook> # signed inbound delivery
POST <inject endpoint> # authenticated submission relay
Self-host or Cloud?

Same stack. Two ways to run it.

The edges and the console run unchanged against either backend. Switching is a credential swap, not a migration.

Run MailKite Server

  • Your mail never leaves hardware you control
  • Any Node ≥ 22.5 host — a $5 VPS, Docker, Fly.io, Railway
  • One VPS, three daemons, your backend URL in one env var
  • AGPL-3.0 — read it, patch it, contribute back
Self-hosting guide →

Point it at MailKite Cloud

  • Nobody babysits port 25 — deliverability and IP reputation handled
  • Inbound as a webhook, unlimited domains, free to start
  • Retention, search, and agent features ship here first
  • A human answers when something breaks
Get your API key →

Start self-hosted and move to Cloud when a product takes off — or the other way around. The contract doesn't care.

LICENSE

Free to run, read, and fork

AGPL-3.0 — use it, change it, redistribute it. If you offer a modified copy as a service, you publish those changes too, so improvements flow back. The same license Grafana and Mastodon use.

TRADEMARK.md

Forks use their own name

The license covers the code, not the MailKite name and logo — so if you take a fork in your own direction, it ships under your own brand. The same approach Mozilla and Plausible take.

CONTRIBUTING.md

Merged PRs run in production

The public repo is the upstream — MailKite Cloud pins it as a dependency, so your merged PR ships to real traffic, not a read-only mirror. A bot collects a one-time CLA on your first PR.

MailKite Server, in plain terms

What is MailKite Server?

MailKite Server is an open-source, programmable mail server for apps and AI agents: a Haraka-based SMTP MX edge, a submission edge (587/465) with DKIM signing, an IMAP4 server, a zero-dependency SQLite reference backend, and a web console. It is licensed AGPL-3.0 and runs on any Node.js ≥ 22.5 host.

Is MailKite open source?

The mail server is — the SMTP MX, submission, and IMAP edges, the reference backend, and the web console are AGPL-3.0 on GitHub, and they are the same code serving MailKite production. The hosted control plane (billing, deliverability tooling, retention tiers) is the commercial product and stays closed.

Can I self-host MailKite?

Yes. docker compose up -d starts the backend and web console; the repo ships guides for a bare VPS (systemd units, DNS records, TLS), Fly.io, and Railway. The short version is one VPS, three daemons, and your backend URL in one environment variable. Serverless runtimes are out of scope — they can't hold SQLite state or raw TCP mail ports.

What license is MailKite Server under?

AGPL-3.0-only for the code. The MailKite name and logo are trademarks and are not covered by the code license, so forks must use their own branding. Contributions require a signed CLA.

Do I have to run port 25 myself?

No. The MX edge routes per recipient domain across multiple backends, and MailKite's hosted MX runs the same code — so you can point our hosted MX at your self-hosted backend and receive mail without exposing port 25 at all. Outbound works the same way: set SMARTHOST=cloud to send through MailKite Cloud's deliverability while keeping storage on your box.

What is the difference between MailKite Server and MailKite Cloud?

They implement the same backend contract. MailKite Server is the self-hosted stack you run and operate yourself. MailKite Cloud is the hosted backend and dashboard, with deliverability, IP reputation, retention, and human support handled for you. The edges and the console run unchanged against either — switching is a credential swap, not a migration.

Clone it, or skip the ops

The repo is one docker compose up from a running mail stack. Cloud is one API key from the same thing, hosted.