← Rahim Nathwani

mailbox-viewer: a Gmail-style viewer for public-records mailboxes

Codegithub.com/rahimnathwani/mailbox-viewer

Why I built it

Responses to public-records requests (FOIA, or the California Public Records Act) often arrive as a PST or mbox file. Most people don't know how to open one. If they're lucky they can import it into Apple Mail or desktop Outlook. Even then, it's hard to share with anyone else, and impossible to link to a specific thread, or a specific spot in a thread.

Jmail, the Gmail-style viewer for the Epstein emails, showed what this should feel like, and Hacker News loved it. I hoped its authors would open-source the code. As far as I know they haven't.

My first attempt was built for one PST file I had received. It was usable, but it only worked for that mailbox: no threading, keyword search only, one JSON file per message, and a manual PST-to-mbox conversion before anything else. I wanted something I could reuse every time a new mailbox arrived, and that anyone with a mailbox file and Cloudflare and Vercel accounts could use too. So I rebuilt it from scratch with Claude Opus 5.5 (xhigh).

How it works

mbv build turns a mailbox (PST, mbox or Maildir) into:

  • Parquet files holding messages, threads and attachments.
  • A word index for keyword and phrase search.
  • Embeddings for semantic search.

Upload those to any static host that supports HTTP range requests (Cloudflare R2, for example) and deploy one front end (on Vercel, for example) for any number of mailboxes. There is no backend. The browser queries the Parquet files with DuckDB-WASM, fetching only the byte ranges it needs.

Features

  • Conversations. Threads are rebuilt from References and In-Reply-To headers, then Outlook's Thread-Index, then reply subjects shared by the same people.
  • Folders become labels, as in Gmail.
  • Gmail search operators. from:, has:attachment, before:, OR, "exact phrases".
  • Attachment search. Text inside PDF and Office attachments is searchable.
  • Semantic search. A small embedding model (snowflake-arctic-embed-xs) runs in the browser. Its results are fused with keyword results by reciprocal rank.
  • Deep links. Every view has its own URL, so you can link to a search, a conversation, or a conversation with the search hits highlighted.
  • Safe rendering. Email HTML is sanitized and shown in a sandboxed iframe, and remote images are blocked.

Scale

On a synthetic 50,000-message mailbox, a search downloads 0.1–0.7 MB and opening a conversation about 0.5 MB, because the browser fetches only byte ranges. The build takes about a minute and a half without embeddings, 15–20 minutes with them.

Caveat

Nothing is redacted for you. Whatever is in the mailbox file ends up on the site.

Code (MIT), install instructions and a Docker image: github.com/rahimnathwani/mailbox-viewer.