4.7 KiB
Smol Mail
A minimalist, decentralized, end-to-end encrypted mail protocol.
Email should be simple again. Inspired by Spartan, Misfin, and LXMF. Smol Mail reduces electronic correspondence to its essentials: an address, a key and a message. One keypair per user, five operations, one binary message format. No sprawling infrastructure, no proprietary accounts, no advertising, no tracking. Anyone can run a server, anyone can write a client, and only the intended recipient can read a message.
A server learns which mailbox a message is for, how big it is and when it arrived. Nothing else — not the sender, not the subject, not the content.
- Minimal — five operations, four primitives, no extensibility mechanisms.
- Private — messages are sealed and signed; senders are absent from the wire format.
- Decentralized — independent servers, no federation, no directories.
- Portable — identity is a keypair, not an account.
Identity
Identity is one Ed25519 keypair. The 32-byte public key is the identity; the 32-byte seed is the only secret to back up. Encryption keys are derived from the same keypair, so there is exactly one thing to hold, move between servers, print on paper or scan from a screen.
Signatures prove authorship. A throwaway key per message means a stolen identity key cannot decrypt anything already sent.
Addressing
alice@example.org short form, resolved via the server
smol://alice@example.org/mfrggzdfmztwq2lknnwg23tpo… self-certifying, carries its own key
The short form is typeable. The long form carries the key itself, so an address shared by QR code, contact file or link needs no trust in any server at all. Either way, changing servers never changes an identity.
Keys learned from a server are pinned on first use. Later changes need a rotation certificate signed by the previous key, or explicit confirmation.
Recipients learn only the sender's key, never a name: a first contact arrives as a bare fingerprint until its address is known. A client may carry its full smol:// address in a signed Reply-To field so first contacts can be answered; receivers bind it only when its key matches the message's signer (SPEC.md §5.7).
Cryptography
Ed25519 · X25519 · ChaCha20-Poly1305 · SHA-256. Four established primitives, no novel cryptography, nothing else anywhere in the protocol. Transport is TCP with a Noise handshake — no certificates, no CA, no expiry.
What is not protected
Traffic analysis, delivery timing, mailbox size, and whether a user has an account on a given server. Run a server as a Tor onion service for metadata resistance; the transport needs no changes for it.
There is no forward secrecy on the recipient side: a seized recipient key decrypts ciphertext recorded while it was valid. Messages are signed, so they carry non-repudiation rather than deniability.
Version 1 excludes attachments, group messaging, federation, anonymous routing, multi-device synchronisation and key revocation.
Reference server
smolmaild.py is a complete server in one file. It declares its own dependencies inline, so there is nothing to install:
uv run smolmaild.py keygen
uv run smolmaild.py serve
keygen writes the server's static key to server.key and prints its public key in base32. Publish that public key through a trusted channel — clients pin it, and a mismatch aborts the handshake.
serve listens on 127.0.0.1:1961 by default and stores mail in mail.db. Use --host 0.0.0.0 to accept remote connections, and --invite-token to close registration. --help lists the size, quota, retention and rate limits.
Reference client
smolmail.py is a complete client in one file, with the same inline dependencies:
uv run smolmail.py keygen
uv run smolmail.py trust example.org <server-key>
uv run smolmail.py register alice@example.org
uv run smolmail.py resolve bob@example.org
echo "hello" | uv run smolmail.py send bob@example.org --subject Hi
uv run smolmail.py fetch
uv run smolmail.py list
uv run smolmail.py read <id>
import adds a contact from a smol:// address without trusting any server, contacts lists known keys and how each was learned, and rotate replaces the identity with a signed certificate your contacts accept automatically.
Mail is stored sealed and opened on demand, so the local database holds no plaintext. Superseded keys are retained after a rotation, because mail already addressed to them is readable with nothing else.
Specification
SPEC.md — wire format, operations, trust model and conformance.