← Back to projects

Google Inbox was the best email client I have used, and Google killed it. I wanted it back as a native desktop application I own and can run forever, and I wanted it good enough to be the client I actually use every day.

A native Rust desktop client that brings back Inbox's bundles, snoozing, and reminders on top of real mail: IMAP and SMTP, OAuth2 against Gmail and Outlook, HTML rendering, and attachment handling. Daily-driver quality is the bar, so the unglamorous parts (auth that refreshes, threading, HTML sanitisation) have to be as solid as the inbox view itself.

01

A state-machine UI that does not thrash

The interface is Dioxus rsx driven by explicit state. Compose state lives in its own signal, separate from the thread body, so typing a reply does not re-render and re-sanitise the message you are reading. Getting the signal boundaries right is what keeps the UI responsive under real load.

02

Untrusted HTML, handled

Incoming email is hostile HTML. It is sanitised before rendering, and links are rewritten through a sentinel scheme so a click goes through my own handler instead of straight out to whatever the sender embedded. Email is attacker-controlled input and the client treats it that way.

03

Threading and bundling

Conversations are threaded with the JWZ algorithm, the same approach mail clients have used for decades. On top of that, messages are grouped into Inbox-style bundles by a heuristic layer with user rules layered over it, so the important mail and the newsletters end up in the right places.

04

Real auth, two providers

OAuth2 against Gmail and Outlook, with the token refresh and error handling that real accounts demand. This is the unglamorous part that decides whether an email client is usable or a demo.

05

Attachments read themselves

PDF text extraction and image OCR run in pure Rust with no system C dependencies, so a scanned receipt or a PDF itinerary can be searched and summarised. When the OCR models are absent it degrades to a no-op instead of failing, so the feature never blocks the client from starting.

// pure core, thin ui seam

Pure core, thin UI seam

The logic that can be tested lives off the UI behind pure functions, and the untestable UI dispatch is kept to a thin seam. It is the pattern that lets a one-person desktop app have a real test suite.

// signal boundaries for performance

Signal boundaries for performance

Splitting state by what actually changes together is how you keep a reactive UI fast. The compose-signal split is a concrete instance of a general rule.

// production desktop patterns in rust

Production desktop patterns in Rust

Real auth, HTML sanitisation, threading, attachment extraction. These are what a serious desktop client needs, and building them once transfers to any Rust GUI work.

RustDioxusIMAP/SMTPOAuth2SQLite
// more

See the rest of the work.