Karti TripathiandClaude Opus 5 4b6f08e170 Drop mail-auth's 'generate' feature: removes RUSTSEC-2023-0071
cargo-deny's advisory check caught the rsa crate (RUSTSEC-2023-0071, the
Marvin Attack — private-key recovery through a timing sidechannel that is
observable over the network, with no fixed version available).

Root cause was ours: enabling mail-auth's 'generate' feature, which exists
to create DKIM keypairs and pulls in the pure-Rust rsa implementation. The
default aws-lc-rs backend signs and verifies in constant time, which is what
a service listening on :25 actually needs. Key generation is a one-time
operator action and belongs in tooling (openssl genpkey), not in the daemon.

Fixed by removing the feature rather than by adding an advisory exception —
the reason is recorded inline in Cargo.toml so nobody re-adds it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JkyvfNJGTshJNE9FtwPLk7
2026-09-02 14:01:15 -07:00
2026-09-02 13:08:05 -07:00

OpenMail

An agent-native, self-hosted mail server, written in Rust.

One binary that gives an AI agent its own real email address — receive, parse, thread, search and send actual SMTP mail on infrastructure you control — behind a clean REST API and an MCP server. Humans and agents are both first-class users.

License Status

Status: v0.1, work in progress, not yet released. The workspace compiles and the domain model is taking shape; it does not yet send or receive mail. Follow docs/adr/0004-milestones.md.


Why this exists

The hard part of an agent-mailbox product was never the API. It is the mail plumbing: receiving over SMTP/MX, sending with real deliverability (SPF/DKIM/DMARC, DANE/MTA-STS, IP reputation), parsing genuinely broken MIME, threading, and storage.

Hosted agent-mail products solve this well and run on someone else's infrastructure, closed. The self-hostable mail servers that exist — Postfix+Dovecot, iRedMail, Stalwart — solve the plumbing but have no notion of an agent: no per-agent inbox provisioning, no threads as API resources, no MCP, no way for an agent to own a mailbox.

OpenMail is the intersection nobody occupies: agent-native, self-hostable, and permissively licensed.

What makes it agent-native

  • Inboxes are API resources, provisioned in one call — not Unix accounts.
  • Threads are first-class, stitched from In-Reply-To/References. An agent asks for a conversation, not a folder listing.
  • extracted_text — the reply with quoted history stripped. An agent that reads full bodies re-reads the whole thread every turn and burns its context window on text it already has.
  • MCP server — an agent owns and operates its own mailbox as tools.
  • Webhooks + WebSocket message.received events. Push, not poll.
  • Humans too — standard IMAP/SMTP access is a first-class goal, not an afterthought, so a person can point Apple Mail or Thunderbird at the same mailbox an agent is driving.

Why Rust, and why our own crates

Two implementations of the mail plumbing exist in a permissive licence: Mox (MIT, Go) and — for the primitives only — Stalwart's published crates (Apache-2.0/MIT, Rust). Stalwart's server is AGPL-3.0, which is why nobody has shipped a permissively licensed Rust mail server.

We are building one. See docs/adr/0001-rust.md for the decision and its honest costs.

Concretely, this means writing what the Rust ecosystem does not have. At the time of writing, dane and mta-sts do not exist on crates.io at all — Stalwart keeps its implementations inside AGPL server crates. Ours ship standalone and permissive, so any Rust mail project can use them.

The workspace

Twelve crates in three tiers. Tier 1 is published to crates.io as a contribution to the Rust mail ecosystem and depends on nothing else here.

Tier 1 — standalone, publishable

Crate What Prior art in Rust
mail-dane DANE / TLSA verification for SMTP (RFC 7672) none — first permissive implementation
mail-mta-sts MTA-STS policy discovery, fetch, parse, cache (RFC 8461) none — first permissive implementation
mail-dsn Delivery Status Notifications (RFC 3464) none

Tier 2 — the mail engine

Crate What
openmail-smtpd Inbound SMTP: session state machine, STARTTLS, AUTH, PIPELINING
openmail-relay Outbound: smarthost relays (SES, Oracle, generic) and direct-to-MX
openmail-guard Abuse gate: iprev, DNSBL, rate limiting
openmail-junk Per-inbox Bayesian spam classification

Tier 3 — the agent-native layer (the product)

Crate What
openmail-core Domain model, threading, quote-stripping. No I/O.
openmail-store Postgres metadata + S3-compatible blobs
openmail-api The v0 REST API
openmail-mcp MCP server
openmail The binary: serve, smtpd, sender, mcp, migrate

Third-party

mail-parser, mail-builder, mail-auth (DKIM/DKIM2/SPF/DMARC/ARC), smtp-proto — all Apache-2.0 OR MIT, all from Stalwart Labs' separately published primitive crates — plus hickory-resolver for DNS and DNSSEC.

No AGPL, GPL, or LGPL code is linked into any OpenMail binary. We use none of the Stalwart server. See NOTICE and docs/adr/0003-own-crates.md.

Sending: bring your own reputation, or build your own

Outbound sits behind one interface with two paths:

  • Relay — SES, Oracle Cloud Email Delivery, SendGrid, Postmark, Resend, or any smarthost. Rents someone else's IP reputation; inbox placement on day one. Providers are declarative data, not special cases — crates/openmail-relay/src/providers.rs.
  • Direct-to-MX — we resolve MX and deliver ourselves, with MTA-STS and DANE enforced. Our reputation, our control, and a months-long IP warmup.

Receiving is always ours.

⚠️ Oracle Cloud blocks outbound TCP/25 for tenancies created after 2021-06-23. Inbound :25 is unaffected. So on OCI you receive directly and relay outbound on 587 — direct-to-MX is not possible there at all. docs/adr/0005-oracle-cloud.md.

Build

cargo check --workspace     # ~21s cold on a Ryzen 7 5800X
cargo test  --workspace
cargo clippy --workspace --all-targets   # zero warnings is the gate

unsafe_code = "forbid" across the workspace. This code parses hostile input from the open internet on port 25; there is no exception worth the risk.

Licence

Apache-2.0. Permissive on purpose: the point is that other people can build commercial products on top of this, including ones that compete with anything we might host later. See docs/adr/0002-apache-2.md for why Apache-2.0 rather than MIT or AGPL.

S
Description
Agent-native, self-hosted mail server in Go. Embeds Mox as a library. MIT.
Readme Apache-2.0
198 KiB
Languages
Rust 81.5%
HTML 16.7%
Dockerfile 1.8%