Skip to content
bottlemail· 5 min read

How bottlemail routes an email to an inbox it cannot read

bottlemail addresses bottles by email address instead of a name. Encrypting the address and indexing a hash of it means the server can deliver a letter without ever holding the identity in plaintext.

The Messages in a Bottle mechanic works because nobody signs up. Address a bottle to a name and you have a nice anonymous ritual; address it to an email address and you have a private inbox, but you have also given the server a list of everyone's real identities.

bottlemail resolves that by making the address something the server can act on without being able to read.

Two columns, two purposes

  • recipient_encrypted — AES-256-GCM ciphertext, stored as iv:tag:ciphertext
  • recipient_hash — HMAC-SHA256 of the normalised address, keyed with a server-held pepper

The hash is the lookup key. When someone signs in with an email address, we HMAC it with the pepper and query for a match — an indexed equality check, no decryption, no scan.

The ciphertext is what would let you recover the address. It is only ever decrypted server-side, and in practice it never is: nothing in the product needs to read it back.

Why the pepper matters

A plain SHA-256 of an email address is trivially reversible — there are not many email addresses. Salting does not help much either, because the attacker controls the input. The pepper lives in an environment variable, never in the database, so a database dump alone reveals nothing usable: every candidate address would have to be tested against a key the attacker does not have.

The projection is the real safety net

Encryption is only as good as the code around it. The public feed query selects seven named columns, and neither recipient_hash nor recipient_encrypted is among them. No application bug — a stray SELECT *, a debugging log, an over-broad serializer — can leak what the query never asks for.

That is a stronger guarantee than encrypting correctly and hoping every future query is careful. We would rather make the leak structurally impossible than make it unlikely.

What it bought

A real private inbox with no registration path at all. Senders never make an account. The recipient proves control of an address once, and their letters are waiting. The identity primitive is the entire product — the 500-character notebook page, the seven papers and the drawing canvas are just the interface on top of it.

bottlemail is retired now, but the model is the clearest thing we have built for explaining how we think about identity: store what you need to act, encrypt what you need to keep, and make the plain version impossible to select.

#cryptography#privacy#design#sqlite

Grallumae Technologies

Kerala

Get in touch →

[Get in touch]

Have something that needs building?

We take on a small number of contract projects — product builds, privacy-critical backend work, and taking an idea from zero to shipped. Tell us what you're working on.

Taking on select projects for 2026