elektromail 0.1.0

A minimal, Rust-based IMAP + SMTP mail server for local development and testing
Documentation

elektromail

License: EUPL-1.2

A minimal IMAP/SMTP mail server written in Rust, designed for development and testing purposes.

Features

  • IMAP4rev2 server on port 1143 (default)
  • SMTP server for receiving mail
  • In-memory storage (no persistence)
  • Zero configuration required
  • RFC 9051 compliance test harness

Installation

Docker (Recommended)

Pull from GitLab Container Registry:

# Login to GitLab registry (if private)
docker login registry.gitlab.com

# Pull latest image (multi-arch: amd64/arm64)
docker pull registry.gitlab.com/wolfgang3235717/elektromail:latest

# Or pull a specific version
docker pull registry.gitlab.com/wolfgang3235717/elektromail:v0.1.0

Run the container:

docker run --rm -p 2525:2525 -p 1143:1143 \
  -e ELEKTROMAIL_USERS=demo:demo \
  registry.gitlab.com/wolfgang3235717/elektromail:latest

Cargo (crates.io)

Once published, add to your Cargo.toml:

[dev-dependencies]
elektromail = "0.1"

Or install as a binary:

cargo install elektromail

From Source

git clone https://gitlab.com/wolfgang3235717/elektromail.git
cd elektromail
cargo build --release

Quick Start

# Run the server
cargo run

# Run with custom credentials
ELEKTROMAIL_USERS=demo:demo cargo run

# Run all tests
cargo test

# Run RFC 9051 compliance tests only
cargo test rfc9051

Configuration

Environment variables:

  • ELEKTROMAIL_USERS - Comma-separated user:pass entries (optional user:email:pass form supported)
  • ELEKTROMAIL_AUTH_DISABLED - Set to 1, true, or yes to disable authentication
  • SMTP_PORT - SMTP listen port (default 2525)
  • IMAP_PORT - IMAP listen port (default 1143)
  • BIND_ADDR - Bind address (default 0.0.0.0)

Defaults:

  • Credentials: user / pass
  • Ports: SMTP 2525, IMAP 1143

Docker

Build and run:

docker build -t elektromail:local .
docker run --rm -p 2525:2525 -p 1143:1143 -e ELEKTROMAIL_USERS=demo:demo elektromail:local

Tested and recommended stack:

  • Rancher Desktop (Docker CLI / dockerd compatible)

Docker integration tests:

ELEKTROMAIL_DOCKER_TESTS=1 cargo test docker_procedere_smoke -- --nocapture

CI hint:

  • Set ELEKTROMAIL_DOCKER_HOST=docker when using Docker-in-Docker.

GitLab CI setup guide: docs/gitlab-ci-setup.md

RFC 9051 Compliance Test Harness

This project includes a comprehensive test harness for validating IMAP server implementations against RFC 9051 (IMAP4rev2).

Test Coverage

210 tests covering all major IMAP commands:

Section Commands Tests
6.1 Any State CAPABILITY, NOOP, LOGOUT 19
6.2 Not Authenticated LOGIN, STARTTLS, AUTHENTICATE 22
6.3 Authenticated SELECT, EXAMINE, CREATE, DELETE, RENAME, SUBSCRIBE, LIST, NAMESPACE, STATUS, APPEND, IDLE, ENABLE 92
6.4 Selected CLOSE, UNSELECT, EXPUNGE, SEARCH, FETCH, STORE, COPY, MOVE 77

Testing Against Local Server

# Test the bundled elektromail server
cargo test rfc9051

Testing Against External IMAP Servers

The harness can validate any IMAP server:

# Test against an external server
RFC9051_TEST_HOST=imap.example.com \
RFC9051_TEST_PORT=993 \
RFC9051_TEST_USER=testuser \
RFC9051_TEST_PASS=testpass \
RFC9051_TEST_TLS=true \
cargo test rfc9051

Test Organization

Tests are organized by RFC section:

tests/rfc9051/
├── mod.rs                    # Configuration and test client
├── client.rs                 # IMAP test client with TLS support
├── response.rs               # Response parser
├── assertions.rs             # RFC-specific assertions
├── fixtures.rs               # Test messages
└── section6_commands/
    ├── any_state/            # CAPABILITY, NOOP, LOGOUT
    ├── not_authenticated/    # LOGIN, STARTTLS, AUTHENTICATE
    ├── authenticated/        # SELECT, EXAMINE, CREATE, etc.
    └── selected/             # FETCH, STORE, SEARCH, etc.

RFC Documentation

Local reference documentation is available in docs/rfc9051/:

IMAP Commands Reference

Any State

  • CAPABILITY - List server capabilities
  • NOOP - No operation (keepalive)
  • LOGOUT - End session

Not Authenticated

  • LOGIN user pass - Authenticate with credentials
  • STARTTLS - Upgrade to TLS
  • AUTHENTICATE mechanism - SASL authentication

Authenticated

  • SELECT mailbox - Open mailbox read-write
  • EXAMINE mailbox - Open mailbox read-only
  • CREATE mailbox - Create new mailbox
  • DELETE mailbox - Delete mailbox
  • RENAME old new - Rename mailbox
  • SUBSCRIBE mailbox - Subscribe to mailbox
  • UNSUBSCRIBE mailbox - Unsubscribe from mailbox
  • LIST ref pattern - List mailboxes
  • NAMESPACE - Get namespace prefixes
  • STATUS mailbox (items) - Get mailbox status
  • APPEND mailbox message - Add message to mailbox
  • IDLE - Wait for updates
  • ENABLE capability - Enable extension

Selected

  • CLOSE - Close mailbox, expunge deleted
  • UNSELECT - Close mailbox, keep deleted
  • EXPUNGE - Remove deleted messages
  • SEARCH criteria - Find messages
  • FETCH seq items - Retrieve message data
  • STORE seq flags - Modify message flags
  • COPY seq mailbox - Copy messages
  • MOVE seq mailbox - Move messages

Development

Running Specific Tests

# Run a specific command's tests
cargo test rfc9051::section6_commands::authenticated::select

# Run with output
cargo test rfc9051 -- --nocapture

# Run single-threaded (useful for debugging)
cargo test rfc9051 -- --test-threads=1

Adding New Tests

  1. Create a new test file in the appropriate section6_commands/ subdirectory
  2. Add the module to the parent mod.rs
  3. Use the TestClient from crate::rfc9051
  4. Use assertions from crate::rfc9051::assertions

Example:

use crate::rfc9051::{TestClient, TestConfig};
use crate::rfc9051::assertions::*;

#[tokio::test]
async fn test_my_command() -> std::io::Result<()> {
    let server = Server::start(Default::default()).await?;
    let mut client = TestClient::connect(TestConfig::for_addr(server.imap_addr())).await?;

    client.login_default().await?;

    let response = client.send_command("MY COMMAND").await?;
    assert_ok(&response, "MY COMMAND");

    client.logout().await?;
    server.stop().await?;
    Ok(())
}

Credits

This project was inspired by GreenMail by Marcel May. GreenMail is an excellent Java-based email server for testing purposes. elektromail aims to provide a similar experience for developers who prefer a Rust-based solution.

License

This project is licensed under the European Union Public Licence v1.2 (EUPL-1.2) - see the LICENSE file for details.