Sign inSign up

smyile/rustmail

By smyile

•Updated 17 days ago

https://rustmail.app | A self-hosted SMTP mail catcher with web UI, REST API, and CI assertions.

Image
Integration & delivery
Developer tools
0

4.0K

smyile/rustmail repository overview

RustMail

⁠RustMail

A local SMTP mail catcher for development and CI, built in Rust. Your app sends email to RustMail instead of a real server, and every message lands in a web UI where you can inspect it, search it and assert on it in tests.

Website: rustmail.app⁠ · Docs: docs.rustmail.app⁠ · GitHub: rustmailapp/rustmail⁠

RustMail web UI: the inbox, an HTML email in desktop preview, and the details rail listing its links

⁠Quick Start

docker run -p 1025:1025 -p 8025:8025 smyile/rustmail:latest

Point your app's SMTP at localhost:1025, then open localhost:8025⁠. Emails show up in real time.

Coming from MailHog or Mailpit? RustMail uses the same default ports, SMTP 1025 and HTTP 8025, so your app's SMTP settings stay as they are.

⁠Docker Compose

services:
  rustmail:
    image: smyile/rustmail:latest
    ports:
      - "1025:1025"
      - "8025:8025"
    security_opt:
      - no-new-privileges:true
    volumes:
      - rustmail-data:/data
    restart: unless-stopped

volumes:
  rustmail-data:

⁠Supported Architectures

ArchitectureTag
linux/amd64latest
linux/arm64latest
linux/arm/v7latest

Multi-arch manifest: Docker automatically pulls the correct image for your platform.

⁠Persistence

The image stores emails at /data/rustmail.db by default. Mount a volume to /data to persist emails across container restarts.

For ephemeral (CI) usage, skip the volume:

docker run -p 1025:1025 -p 8025:8025 -e RUSTMAIL_EPHEMERAL=true smyile/rustmail:latest

⁠Environment Variables

All configuration is done via RUSTMAIL_* environment variables:

VariableDefaultDescription
RUSTMAIL_BIND0.0.0.0IP address to bind listeners to
RUSTMAIL_SMTP_PORT1025SMTP listener port
RUSTMAIL_HTTP_PORT8025HTTP and WebSocket port
RUSTMAIL_DB_PATH/data/rustmail.dbPath to SQLite database file
RUSTMAIL_RETENTION0Auto-delete messages after N hours (0 = keep forever)
RUSTMAIL_MAX_MESSAGES0Max messages to retain (0 = unlimited)
RUSTMAIL_MAX_MESSAGE_SIZE10485760Max accepted message size in bytes (10 MB)
RUSTMAIL_SMTP_TLS_CERTunsetPath to a PEM certificate for optional SMTP STARTTLS
RUSTMAIL_SMTP_TLS_KEYunsetPath to a PEM private key for optional SMTP STARTTLS
RUSTMAIL_EPHEMERALfalseUse in-memory SQLite (no data written to disk)
RUSTMAIL_WEBHOOK_URLunsetURL to POST on every new message
RUSTMAIL_LOG_LEVELinfoLog verbosity: trace, debug, info, warn, error
RUSTMAIL_RELEASE_HOSTunsetAllowed SMTP target for email release (host:port)
RUSTMAIL_ALLOWED_HOSTSunsetComma-separated host names browsers may reach RustMail on, such as mail.example.com. IP addresses and localhost are always answered
RUSTMAIL_ALLOWED_ORIGINSunsetComma-separated extra origins allowed to open the WebSocket, as scheme://host[:port]
RUSTMAIL_WS_BUFFER4096WebSocket events buffered for each client

See the configuration reference⁠ for every option.

⁠Ports

PortProtocolDescription
1025TCPSMTP server
8025TCPHTTP API, WebSocket, and Web UI

⁠Optional STARTTLS

STARTTLS uses the normal SMTP port via explicit upgrade. Both RUSTMAIL_SMTP_TLS_CERT and RUSTMAIL_SMTP_TLS_KEY are required; setting only one fails startup, and STARTTLS is advertised only when both are set.

Mount your TLS files read-only and set both environment variables:

docker run \
  -p 1025:1025 -p 8025:8025 \
  -v "$PWD/certs:/certs:ro" \
  -e RUSTMAIL_SMTP_TLS_CERT=/certs/smtp-cert.pem \
  -e RUSTMAIL_SMTP_TLS_KEY=/certs/smtp-key.pem \
  smyile/rustmail:latest

Clients must issue EHLO, then STARTTLS, and then EHLO again after the TLS handshake completes.

⁠Test emails in CI

Run the image as a service container, or use the RustMail GitHub Action⁠, then fail the build when an email is missing:

curl -f "localhost:8025/api/v1/assert/count?min=1&subject=Welcome"

The endpoint answers 200 when the condition holds and 417 otherwise. See CI integration⁠.

⁠Features

  • Persistent storage: SQLite-backed, emails survive restarts
  • Full-text search: FTS5 across subject, body, sender, and recipients
  • Real-time updates: WebSocket pushes new emails to the UI instantly
  • Modern UI: dark-mode-first, looks and feels like a real email client
  • DKIM/SPF/DMARC/ARC display: parses authentication headers with color-coded badges
  • REST assertion endpoints: GET /api/v1/assert/count?min=1&subject=Welcome
  • Webhook notifications: fire-and-forget POST on new email
  • Email release: forward captured emails to a real SMTP server
  • Export: download as EML or JSON
  • Retention policies: auto-purge by age or count

⁠Image Details

  • Base image: alpine:3.21
  • Runs as: non-root user rustmail
  • Healthcheck: built-in (HTTP check every 30s)
  • Volume: /data
  • Security: no-new-privileges recommended

⁠License

Licensed under either of MIT⁠ or Apache 2.0⁠, at your option.

Tag summary

Content type

Image

Digest

sha256:9b53d1f7c…

Size

9.2 MB

Last updated

17 days ago

docker pull smyile/rustmail