Sovite is a Mail Transfer Agent (MTA) written in Elixir/OTP, meant as a modern alternative to Postfix. This document lists the features to build, the standards to implement, and the order to build them in.


1. Vision & Principles

  • Secure by default. TLS everywhere it is possible, no open relay ever, modern crypto only, least privilege.
  • Correct before clever. Strict RFC compliance on the wire, lenient-but-safe parsing of real-world input ("be liberal in what you accept" only where it is safe).
  • Crash-safe queue. No accepted message is ever lost. 250 OK means the message is durably on disk.
  • OTP-native. One supervised process per connection / delivery attempt, isolated failures, hot config reload, built-in clustering as a long-term differentiator.
  • Ecosystem compatible. Speak the protocols the existing mail ecosystem already uses (milter, Postfix policy delegation, LMTP, sendmail(1)) so users can migrate without replacing their filters, spam scanners, and mailbox servers.
  • Observable. Every message has a traceable lifecycle; metrics and structured logs come built in.
  • Simple configuration. One readable config file with validation and clear error messages, plus a migration helper for Postfix main.cf / master.cf.

Non-goals

  • IMAP / POP3 / JMAP server (use Dovecot, Stalwart, etc.; Sovite delivers to them via LMTP).
  • Webmail or a GUI mail client.
  • A built-in content-based spam classifier (integrate Rspamd / SpamAssassin via milter instead).
  • Mailing list management (Mailman-style). Only list-related header standards are in scope.

2. Architecture Overview (target)

ComponentRolePostfix equivalent
ListenerAccepts TCP connections, PROXY protocol, connection limitsmaster, postscreen
SMTP serverInbound SMTP / Submission / LMTP-in session state machinesmtpd
CleanupHeader normalization, address rewriting, Received: / Message-ID: / Date: insertioncleanup, trivial-rewrite
Queue managerDurable queue, scheduling, retry/backoff, per-destination concurrencyqmgr
SMTP clientOutbound delivery with MX resolution, TLS policy, connection reusesmtp
Local/LMTP deliveryHand-off to mailbox servers, pipes, Maildirlocal, lmtp, virtual, pipe
Bounce serviceDSN generation, delay warningsbounce
Routing dataDomains, aliases, mailboxes, transports, access rules: typed tables in Sovite's database, managed with sovitectl*_maps, postmap
CLIQueue inspection, flush, hold, delete, config checkpostqueue, postsuper, postconf, mailq

3. Phased Roadmap

Each phase has a "Definition of Done". A phase is not finished until its interoperability tests pass.

Phase 0 — Foundations

  • [x] Project layout: OTP application, supervision tree design, release build (mix release)
  • [x] Configuration system: file format, schema validation, defaults, sovite config check
  • [x] Logging conventions: structured logs with a per-message queue ID
  • [x] Telemetry events defined from day one (connection, command, queue, delivery)
  • [x] Test harness: SMTP client test helpers, fake DNS resolver, fake remote MTAs
  • [x] Property-based / fuzz testing setup for the parsers
  • [x] CI: format, credo/dialyzer, tests, coverage
  • [x] Security model doc: privileges, file ownership, threat model

Done when: the empty application builds as a release, loads and validates config, and has a working test harness.

Phase 1 — Core SMTP Receiver (MVP inbound)

  • [x] TCP listener with acceptor pool, connection limits (global and per-IP)
  • [x] SMTP session state machine: EHLO/HELO, MAIL, RCPT, DATA, RSET, NOOP, QUIT, VRFY (disabled by default), HELP
  • [x] Strict command-line parsing, line length limits, bare-LF / bare-CR handling (SMTP smuggling protection)
  • [x] ESMTP extensions: PIPELINING, SIZE, 8BITMIME, ENHANCEDSTATUSCODES
  • [x] Timeouts per RFC 5321 §4.5.3.2
  • [x] Dot-stuffing / un-stuffing, message size enforcement while streaming
  • [x] Received: header with RFC 3848 transmission types
  • [x] Recipient validation against configured local/relay domains (reject unknown users at RCPT time)
  • [x] Open relay prevention: relay only for authenticated users or trusted networks
  • [x] Durable spool: write + fsync before replying 250

Standards: RFC 5321, RFC 5322, RFC 1870, RFC 6152, RFC 2920, RFC 2034, RFC 3463, RFC 5248, RFC 3848

Done when: Sovite accepts mail from Postfix, Exim, and swaks, stores it durably, and passes an open-relay test.

Phase 2 — Queue & Outbound Delivery (MVP outbound)

  • [x] Queue structure: incoming, active, deferred, hold, corrupt
  • [x] Queue file format: versioned, checksummed envelope + message body, crash recovery on startup
  • [x] Scheduler: exponential backoff, maximum queue lifetime (default 5 days), per-destination concurrency and rate limits
  • [x] DNS resolution: MX, A/AAAA fallback (implicit MX), Null MX handling, preference ordering, randomization among equal-preference hosts
  • [x] IPv4 + IPv6 dual-stack delivery with fallback
  • [x] SMTP client: EHLO negotiation, pipelining, connection caching/reuse
  • [x] Multi-recipient messages: per-recipient status tracking, partial failures
  • [x] Bounces: DSN generation for permanent failures, delay warnings (configurable)
  • [x] Double-bounce handling and null-sender (<>) rules
  • [x] postmaster@ and abuse@ always accepted
  • [x] Smart host / relayhost support

Standards: RFC 5321 §4.5.4 (retry strategy) & §5 (address resolution), RFC 7505 (Null MX), RFC 3461, RFC 3464, RFC 6522, RFC 3834

Done when: Sovite can relay to Gmail/Outlook/Postfix, retries correctly on 4xx, bounces correctly on 5xx, and survives kill -9 mid-delivery with no lost or duplicated mail (beyond what SMTP inherently allows).

Phase 3 — TLS & Submission

  • [x] STARTTLS on port 25 (server and client side)
  • [x] Implicit TLS submission on port 465
  • [x] Submission on port 587 with mandatory auth
  • [x] TLS 1.2 and 1.3 only; modern cipher suites; configurable per listener
  • [x] Multiple certificates with SNI selection
  • [x] Automatic certificate reload; optional ACME (Let's Encrypt) integration
  • [x] Outbound opportunistic TLS by default; per-destination TLS policy (none / may / encrypt / verify / dane)
  • [x] SMTP AUTH: PLAIN, LOGIN (legacy compat), SCRAM-SHA-256, OAUTHBEARER
  • [x] Auth backends: static file, SQL (Sovite's own database via Ecto: SQLite by default, PostgreSQL or MySQL), LDAP, Dovecot SASL protocol
  • [x] Auth only offered after TLS (configurable but secure default)
  • [x] Brute-force protection: auth failure rate limiting and temporary bans
  • [x] Sender login maps (authenticated user may only send as allowed addresses)
  • [x] Message submission fixes: add missing Date: / Message-ID:, strip/rewrite client headers

Standards: RFC 3207, RFC 6409, RFC 8314, RFC 4954, RFC 4422, RFC 4616, RFC 5802, RFC 7677, RFC 7628, RFC 8446, RFC 8996, RFC 9325 (BCP 195), RFC 7817, RFC 9525, RFC 7435, RFC 6186

Done when: Thunderbird, Apple Mail, and Outlook can submit mail; testssl.sh reports no weak configuration.

Phase 4 — Routing, Rewriting & Routing Data

  • [x] Routing data in Sovite's database: a migration and typed schema per table (domains, aliases, mailboxes, moved users, transports, sender relays, access rules, address rewrites, BCC rules), managed with sovitectl
  • [x] Aliases: full address, local part, and @domain catch-all, expanded recursively with loop and size limits
  • [x] Domain classes: local, aliased, hosted (mailboxes), relay
  • [x] Sender/recipient address rewriting, hiding subdomains, rewriting header addresses for trusted and authenticated clients
  • [x] Moved users (5.1.6), recipient BCC, sender BCC, always-BCC
  • [x] Transports: per-domain/per-recipient next hop and transport (smtp, lmtp, local, mailbox, error, retry, discard)
  • [x] Sender-dependent relay host, outbound IP, and relay credentials
  • [x] Address extensions (user+tag@) with configurable delimiter
  • [x] Restriction chains with access rules at CONNECT, HELO, MAIL, RCPT, DATA, END-OF-DATA stages (reject, defer, discard, hold, warn)
  • [x] Changes apply without restart (tables read live; domains cached for a few seconds)

Done when: a typical virtual-hosting setup (hosted domains + aliases + transport to LMTP) can be expressed in Sovite. (LMTP delivery itself arrives in Phase 5.)

Phase 5 — Local Delivery & Mailbox Hand-off

  • [x] LMTP client (to Dovecot, Cyrus, Stalwart) over TCP and Unix sockets
  • [x] LMTP server mode (optional, for use behind other MTAs)
  • [x] Maildir delivery (optional, for simple setups)
  • [x] Pipe transport (deliver to external command, with sandboxing)
  • [x] Delivered-To: header and mail loop detection (hop count limit)
  • [x] Return-Path: insertion at final delivery

Standards: RFC 2033, RFC 9228, RFC 5321 §6.3 (loop detection)

Done when: end-to-end inbound → Dovecot LMTP works with per-recipient status codes.

Phase 6 — Email Authentication

  • [ ] SPF verification for inbound (MAIL FROM and HELO identities), with DNS lookup limits enforced
  • [ ] DKIM verification (RSA-SHA256, Ed25519); reject RSA-SHA1 per RFC 8301
  • [ ] DKIM signing for outbound: multiple selectors, per-domain keys, dual signing (RSA + Ed25519), key rotation support
  • [ ] DMARC evaluation with alignment checks and policy enforcement (configurable: report-only / enforce)
  • [ ] DMARC aggregate report generation (optional, opt-in)
  • [ ] ARC verification and sealing (for forwarders and mailing lists)
  • [ ] Authentication-Results: header generation; strip forged incoming Authentication-Results: for our own authserv-id
  • [ ] Sender Rewriting Scheme (SRS) for forwarded mail
  • [ ] DNS helper CLI: print the SPF, DKIM, DMARC, MTA-STS, and TLS-RPT records a domain needs

Standards: RFC 7208, RFC 6376, RFC 8301, RFC 8463, RFC 7489 (and DMARCbis as it lands), RFC 8617, RFC 8601, RFC 7372, RFC 6591

Done when: outbound mail passes SPF/DKIM/DMARC at Gmail and Outlook; inbound verdicts match reference implementations on a test corpus.

Phase 7 — Transport Security Policies

  • [ ] DNSSEC-validating resolver integration (or require a local validating resolver)
  • [ ] DANE outbound: TLSA lookup and verification (DANE-EE, DANE-TA)
  • [ ] MTA-STS outbound: policy fetch, caching, enforcement, testing mode
  • [ ] MTA-STS inbound: serve policy (or document how to host it)
  • [ ] TLS-RPT: collect TLS delivery results and send daily reports
  • [ ] REQUIRETLS extension
  • [ ] Precedence rules when DANE and MTA-STS both apply (DANE wins)

Standards: RFC 4033–4035, RFC 6698, RFC 7671, RFC 7672, RFC 8461, RFC 8460, RFC 8689

Done when: delivery to DANE-enabled and MTA-STS-enabled domains enforces policy; mismatch tests correctly defer mail.

Phase 8 — Anti-Abuse (postscreen-like)

  • [ ] Pre-greeting ("early talker") detection
  • [ ] DNSBL / DNSWL checks with weighted scoring
  • [ ] RHSBL checks for sender/HELO domains
  • [ ] Greylisting (built in, optional)
  • [ ] Reverse DNS / FCrDNS checks (configurable strictness)
  • [ ] HELO validation policies
  • [ ] Rate limits: per-IP connections, messages, recipients; per authenticated user sending quotas
  • [ ] Tarpitting on suspicious behavior
  • [ ] Protocol hygiene: reject pipelining abuse, non-SMTP commands, bare LF (SMTP smuggling)
  • [ ] Outbound abuse protection: detect compromised accounts by volume / bounce rate spikes

Standards: RFC 5782 (DNSBL), RFC 5965 (ARF, for feedback loops)

Done when: bot traffic from a replay corpus is rejected before DATA with a low false-positive rate.

Phase 9 — Ecosystem Compatibility

  • [ ] Milter protocol (Sendmail milter v6) client: works with Rspamd, OpenDKIM, OpenDMARC, ClamAV-milter
  • [ ] Postfix policy delegation protocol: works with policyd-spf, postgrey, and other existing policy servers
  • [ ] sendmail(1)-compatible binary (sendmail, mailq, newaliases) for local apps and cron
  • [ ] PROXY protocol v1/v2 (behind HAProxy / load balancers)
  • [ ] XCLIENT / XFORWARD (optional, for proxies and content filters)
  • [ ] Content filter re-injection (after-queue filtering via SMTP/LMTP)
  • [ ] Postfix config migration tool: read main.cf / master.cf and produce a Sovite config plus a report of unsupported settings

Done when: a stock Postfix + Rspamd + Dovecot setup can be migrated to Sovite + Rspamd + Dovecot with the migration tool.

Phase 10 — Internationalization

  • [ ] SMTPUTF8 extension (UTF-8 local parts and domains)
  • [ ] IDNA2008 domain handling (U-label / A-label conversion)
  • [ ] UTF-8 header handling
  • [ ] Downgrade behavior when next hop lacks SMTPUTF8 (bounce with clear DSN)
  • [ ] Internationalized DSNs

Standards: RFC 6530, RFC 6531, RFC 6532, RFC 6533, RFC 5890–5893

Phase 11 — Additional ESMTP Extensions

  • [ ] CHUNKING / BDAT and BINARYMIME
  • [ ] DSN extension (NOTIFY, RET, ENVID, ORCPT) — full support
  • [ ] ETRN (queue run for a domain)
  • [ ] FUTURERELEASE (optional)
  • [ ] DELIVERBY (optional)
  • [ ] MT-PRIORITY (optional)
  • [ ] RRVS (optional)

Standards: RFC 3030, RFC 3461, RFC 1985, RFC 4865, RFC 2852, RFC 6710, RFC 7293

Phase 12 — Operations & Observability

  • [ ] CLI: sovite queue list|show|flush|hold|release|delete|requeue, sovite config check|show|diff, sovite route ADDRESS (show how the routing tables resolve an address), sovite status
  • [ ] Message tracing: follow a message from connection to final delivery by queue ID or Message-ID
  • [ ] Prometheus metrics endpoint; OpenTelemetry traces
  • [ ] Structured JSON logs + classic syslog-style output
  • [ ] Admin HTTP API (authenticated, local-only by default)
  • [ ] Optional LiveDashboard-based status UI
  • [ ] Graceful shutdown and drain; zero-downtime config reload
  • [ ] systemd integration: socket activation, sd_notify, hardening directives
  • [ ] Packaging: container image, .deb / .rpm, release tarballs
  • [ ] Log-based tooling compatibility (pflogsumm-style summary report)

Phase 13 — Scale & Clustering (differentiator)

  • [ ] Multiple nodes sharing configuration
  • [ ] Distributed queue / queue handover when a node goes down
  • [ ] Cluster-wide rate limits and greylisting state
  • [ ] Shared connection caching per destination across nodes
  • [ ] Per-tenant isolation (multi-tenant hosting): separate limits, keys, IP pools
  • [ ] Outbound IP pool management and warm-up schedules

Phase 14 — Hardening for 1.0

  • [ ] External security audit
  • [ ] Fuzzing campaign on SMTP parser, MIME/header parser, DNS response handling, queue file reader
  • [ ] Long-running soak tests (weeks) with real traffic mirrors
  • [ ] Performance benchmarks vs Postfix (throughput, latency, memory per connection)
  • [ ] Complete documentation: admin guide, config reference, migration guide, security guide
  • [ ] Stable config format and queue format with documented upgrade path
  • [ ] Interop test matrix against Postfix, Exim, Microsoft Exchange/365, Gmail, Stalwart, OpenSMTPD

4. Standards Compliance Matrix

Level: MUST = required for 1.0, SHOULD = planned for 1.0, MAY = optional / later.

Core SMTP & Message Format

StandardTitleLevelPhase
RFC 5321Simple Mail Transfer ProtocolMUST1–2
RFC 5322Internet Message FormatMUST1
RFC 2045–2049MIMEMUST (parsing for DKIM/DSN)1–6
RFC 6409Message SubmissionMUST3
RFC 8314Implicit TLS for SubmissionMUST3
RFC 3848ESMTP Transmission TypesMUST1
RFC 7505Null MXMUST2
RFC 2033LMTPMUST5
RFC 9228Delivered-To Header FieldSHOULD5

ESMTP Extensions

StandardExtensionLevelPhase
RFC 1870SIZEMUST1
RFC 61528BITMIMEMUST1
RFC 2920PIPELININGMUST1
RFC 2034 / RFC 3463 / RFC 5248ENHANCEDSTATUSCODESMUST1
RFC 3207STARTTLSMUST3
RFC 4954AUTHMUST3
RFC 3461DSNMUST11
RFC 3030CHUNKING / BINARYMIMESHOULD11
RFC 6531SMTPUTF8SHOULD10
RFC 8689REQUIRETLSSHOULD7
RFC 1985ETRNMAY11
RFC 4865FUTURERELEASEMAY11
RFC 2852DELIVERBYMAY11
RFC 6710MT-PRIORITYMAY11
RFC 7293RRVSMAY11

Delivery Status & Reporting

StandardTitleLevelPhase
RFC 3464DSN Message FormatMUST2
RFC 6522multipart/reportMUST2
RFC 3834Automatic ResponsesMUST2
RFC 6533Internationalized DSNsSHOULD10
RFC 5965Abuse Reporting Format (ARF)MAY8
RFC 6591Authentication Failure ReportingMAY6

Authentication & SASL

StandardTitleLevelPhase
RFC 4422SASLMUST3
RFC 4616PLAINMUST3
RFC 5802 / RFC 7677SCRAM / SCRAM-SHA-256SHOULD3
RFC 7628OAUTHBEARERSHOULD3
draft-murchison-sasl-loginLOGIN (legacy clients)SHOULD3

Email Authentication

StandardTitleLevelPhase
RFC 7208SPFMUST6
RFC 6376DKIMMUST6
RFC 8301DKIM Crypto UpdateMUST6
RFC 8463DKIM Ed25519SHOULD6
RFC 7489 / DMARCbisDMARCMUST6
RFC 8601Authentication-ResultsMUST6
RFC 7372Email Auth Status CodesSHOULD6
RFC 8617ARCSHOULD6
SRS (de-facto spec)Sender Rewriting SchemeSHOULD6

Transport Security

StandardTitleLevelPhase
RFC 8446TLS 1.3MUST3
RFC 8996Deprecate TLS 1.0 / 1.1MUST3
RFC 9325 (BCP 195)TLS RecommendationsMUST3
RFC 7817 / RFC 9525TLS Server Identity for EmailMUST3
RFC 7435Opportunistic SecurityMUST3
RFC 7672 / RFC 6698 / RFC 7671DANE for SMTP / TLSASHOULD7
RFC 4033–4035DNSSECSHOULD7
RFC 8461MTA-STSSHOULD7
RFC 8460SMTP TLS ReportingSHOULD7

Internationalization

StandardTitleLevelPhase
RFC 6530EAI OverviewSHOULD10
RFC 6532Internationalized HeadersSHOULD10
RFC 5890–5893IDNA2008SHOULD10

Anti-Abuse & Lists

StandardTitleLevelPhase
RFC 5782DNS Blacklists / WhitelistsSHOULD8
RFC 2369List-* Headers (pass-through, preserve for DKIM)SHOULD6
RFC 8058One-Click Unsubscribe (preserve for DKIM signing)SHOULD6

Ecosystem Protocols (non-RFC)

SpecPurposeLevelPhase
Sendmail Milter protocol v6Content filters (Rspamd, OpenDKIM, ClamAV)MUST9
Postfix policy delegationPolicy servers (postgrey, policyd-spf)SHOULD9
HAProxy PROXY protocol v1/v2Load balancer client IP passthroughSHOULD9
Dovecot SASL auth protocolReuse Dovecot user database for SMTP AUTHSHOULD3
sendmail(1) CLI conventionsLocal mail submission by appsMUST9
XCLIENT / XFORWARDProxy and content filter attribute passingMAY9
ACME (RFC 8555)Automatic certificatesMAY3

5. Security Requirements (cross-cutting)

  • Never an open relay; relay permission must be explicit (authenticated user or trusted network).
  • Bind privileged ports without running the VM as root (systemd socket activation or CAP_NET_BIND_SERVICE).
  • Queue files readable only by the Sovite user; secrets (DKIM keys, TLS keys, auth DB credentials) never logged.
  • Hard limits on everything parsed from the network: line length, header count, header size, recipients per message, message size, nesting depth of MIME, DNS response size, SPF lookup count.
  • No atom creation from untrusted input (BEAM atom table exhaustion).
  • Protection against SMTP smuggling (strict <CRLF>.<CRLF> handling, bare LF/CR policy).
  • Protection against STARTTLS command injection (discard buffered plaintext after TLS handshake).
  • Constant-time comparison for credentials; password hashes with modern KDFs (Argon2id / bcrypt / SCRAM salted).
  • Reproducible builds and signed releases.
  • Documented responsible disclosure process (SECURITY.md).

6. Quality & Testing Strategy

  • Unit + property tests for every parser (SMTP commands, addresses, headers, MIME, DNS records, SPF/DMARC records).
  • Conformance tests derived from RFC examples and test suites (e.g. the SPF test suite (pyspf YAML), DKIM test vectors).
  • Interop tests in CI using containers: Postfix, Exim, OpenSMTPD, Dovecot, Rspamd.
  • Chaos tests: kill nodes and processes during delivery; corrupt queue files; DNS timeouts and SERVFAIL.
  • Load tests: sustained throughput, connection storms, large messages, many recipients.
  • Fuzzing of all network-facing parsers.

7. Milestones Summary

MilestonePhasesOutcome
0.1 — "It relays"0, 1, 2Receive, queue, and deliver mail reliably
0.2 — "It's safe on the internet"3, 4, 5TLS, submission, auth, virtual hosting, LMTP to Dovecot
0.3 — "It's trusted by big providers"6, 7SPF/DKIM/DMARC/ARC, DANE, MTA-STS
0.4 — "It replaces Postfix"8, 9Anti-abuse, milter, policy servers, migration tool
0.5 — "It's complete"10, 11, 12SMTPUTF8, full ESMTP, operations tooling
0.6 — "It scales"13Clustering, multi-tenant
1.0 — "Production ready"14Audited, benchmarked, documented, stable formats