From 45f8355a9e8da27c725be1c49affd3353ca77dbd Mon Sep 17 00:00:00 2001 From: Shautvast Date: Wed, 25 Feb 2026 19:38:16 +0100 Subject: [PATCH] Update CLAUDE.md with current architecture and implementation details Add ProtonMail bridge, body cache, credentials, SMTP, setup wizard, and key development notes including the UIDVALIDITY/UIDNEXT imap-proto quirk. Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e82a9ee..19fa21e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,19 +4,23 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -**tui_mail** is a TUI email client built with Rust and Ratatui. It connects to IMAP servers (including Gmail) and displays inbox messages with a split-pane interface: email list on top, message preview on the bottom. +**tui_mail** is a TUI email client built with Rust and Ratatui. It supports standard IMAP servers (including Gmail) and ProtonMail (via an in-process bridge). It displays inbox messages with a split-pane interface: email list on top, message preview on the bottom. **User documentation:** see [`USAGE.md`](USAGE.md) for setup instructions, keyboard shortcuts, and configuration reference. ## Build and Run Commands ```bash -# Build the project +# Build the project (standard IMAP) cargo build # Run the application cargo run +# Build/run with ProtonMail support +cargo build --features proton +cargo run --features proton + # Build optimized release version cargo build --release @@ -49,26 +53,55 @@ Connection details: localhost:143 (IMAP) or localhost:993 (IMAPS). See `MAIL_SER ## Architecture +### Main app (`src/`) + - **`src/main.rs`** — Terminal setup/teardown, delegates to `lib::main` - **`src/lib.rs`** — Main event loop, UI rendering, worker thread coordination -- **`src/inbox.rs`** — IMAP inbox operations (refresh, fetch older, fetch body) +- **`src/inbox.rs`** — IMAP inbox operations (refresh, fetch older, fetch body, search, delete) - **`src/connect.rs`** — IMAP connection handling (plain TCP and TLS) -- **`src/config.rs`** — Configuration loading from `config.toml` +- **`src/config.rs`** — Configuration loading from `config.toml`; provider selection (IMAP vs Proton) +- **`src/credentials.rs`** — OS keychain access via the `keyring` crate +- **`src/smtp.rs`** — Outgoing mail via SMTP using `lettre` +- **`src/setup.rs`** — First-run interactive setup wizard +- **`src/store.rs`** — Local encrypted body cache (AES-256-GCM, key stored in `storage.key` file) + +### ProtonMail bridge (`proton-bridge/`) + +A separate workspace crate that runs as an in-process local IMAP/SMTP server. + +- **`proton-bridge/src/lib.rs`** — Entry point (`start()`); authenticates with ProtonMail API, binds local ports, spawns async tasks +- **`proton-bridge/src/imap_server.rs`** — Local IMAP server (LOGIN, SELECT, FETCH, SEARCH, STORE, EXPUNGE) +- **`proton-bridge/src/smtp_server.rs`** — Local SMTP server for outgoing mail +- **`proton-bridge/src/api.rs`** — ProtonMail REST API client (message list, fetch, delete, send) +- **`proton-bridge/src/auth.rs`** — SRP authentication and session management +- **`proton-bridge/src/crypto.rs`** — PGP key derivation and message decryption/encryption +- **`proton-bridge/src/store.rs`** — In-memory message metadata store for the bridge +- **`proton-bridge/src/srp.rs`** — SRP-6a implementation matching ProtonMail's go-srp ### Key patterns - IMAP operations run in a **background worker thread** communicating via `mpsc` channels, keeping the UI responsive - Emails are loaded in **batches of 50**, with lazy loading when scrolling past the end +- A **navigation debounce** (150 ms) avoids firing body fetches on every keypress while scrolling +- The worker checks `wanted_body_seq` (an `AtomicU32`) to drop stale body requests +- **Body cache**: fetched message bodies are AES-256-GCM encrypted and written to `{data_dir}/tuimail/bodies/{hash}.enc`; cache key is the `Message-ID` header value +- Credentials (IMAP/SMTP/Proton passwords) are stored in the **OS keychain** via `keyring` +- The encryption key for the body cache is stored in `{data_dir}/tuimail/storage.key` (mode 0600) to avoid repeated keychain prompts - **Tab** switches focus between inbox list and preview pane -- Selection is **preserved across refreshes** by matching IMAP sequence numbers +- Selection is preserved across refreshes by matching IMAP sequence numbers ## Key Dependencies - **ratatui (0.30)**: TUI framework providing widgets, layouts, and rendering - **crossterm (0.29)**: Cross-platform terminal manipulation (raw mode, events, alternate screen) - **imap (2.4)**: IMAP protocol client -- **native-tls (0.2)**: TLS support for secure IMAP connections (Gmail) +- **native-tls (0.2)**: TLS support for secure IMAP connections +- **lettre (0.11)**: SMTP client for sending mail - **chrono (0.4)**: Date parsing and timezone conversion +- **mailparse (0.15)**: MIME email parsing for body extraction +- **aes-gcm (0.10)**: AES-256-GCM authenticated encryption for the body cache +- **keyring (3)**: OS keychain access (apple-native / linux-native / windows-native) +- **dirs (5)**: Platform-correct data directory paths ## Development Notes @@ -76,3 +109,5 @@ Connection details: localhost:143 (IMAP) or localhost:993 (IMAPS). See `MAIL_SER - Terminal is set to raw mode to capture individual key presses - The alternate screen prevents terminal history pollution - `config.toml` contains credentials and is gitignored — see `config.toml.example` for the format +- `proton-bridge/bridge.toml` contains ProtonMail credentials and is gitignored +- The ProtonMail bridge imap_server SELECT response must **not** include `UIDVALIDITY`/`UIDNEXT` lines — imap-proto 0.10 (used by imap 2.4) does not fully consume them, causing tag desync on subsequent commands