Karti TripathiandClaude Opus 5 f0ec4ad691 Add ROADMAP; settle ADR 0005 with a measured OCI port test
cloud-1 (phx) and cloud-2 (us-sanjose-1) are both already OCI aarch64
instances, so the open question in ADR 0005 was answerable directly rather
than by reading forum posts. Measured from cloud-2:

  BLOCKED  25    gmail-smtp-in.l.google.com, aspmx.l.google.com
  OPEN     587/465/2525  gmail, sendgrid, SES, OCI Email Delivery

The community reports claiming 587 and 2525 are also blocked are wrong.
Only 25 is blocked, exactly as Oracle documents, so relay works and the
launch host is viable. Inbound :25 reachability is still unverified — that
is a VCN security-list change, not a platform limit.

ROADMAP.md carries the goal, three success signals that are deliberately
not v0.1, a definition-of-ready checklist, and five standing rules.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JkyvfNJGTshJNE9FtwPLk7
2026-09-02 13:38:01 -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%