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 <noreply@anthropic.com>
5 KiB
5 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
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 for setup instructions, keyboard shortcuts, and configuration reference.
Build and Run Commands
# 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
# Check code without building
cargo check
# Format code
cargo fmt
# Run clippy linter
cargo clippy
Test Mail Server
A Docker-based IMAP mail server is available for testing:
# Start the mail server
docker-compose up -d
# Create a test user
docker exec -it mailserver setup email add test@example.com password123
# Stop the mail server
docker-compose down
Connection details: localhost:143 (IMAP) or localhost:993 (IMAPS). See MAIL_SERVER_SETUP.md for detailed usage including Gmail configuration.
Architecture
Main app (src/)
src/main.rs— Terminal setup/teardown, delegates tolib::mainsrc/lib.rs— Main event loop, UI rendering, worker thread coordinationsrc/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 fromconfig.toml; provider selection (IMAP vs Proton)src/credentials.rs— OS keychain access via thekeyringcratesrc/smtp.rs— Outgoing mail via SMTP usinglettresrc/setup.rs— First-run interactive setup wizardsrc/store.rs— Local encrypted body cache (AES-256-GCM, key stored instorage.keyfile)
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 tasksproton-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 mailproton-bridge/src/api.rs— ProtonMail REST API client (message list, fetch, delete, send)proton-bridge/src/auth.rs— SRP authentication and session managementproton-bridge/src/crypto.rs— PGP key derivation and message decryption/encryptionproton-bridge/src/store.rs— In-memory message metadata store for the bridgeproton-bridge/src/srp.rs— SRP-6a implementation matching ProtonMail's go-srp
Key patterns
- IMAP operations run in a background worker thread communicating via
mpscchannels, 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(anAtomicU32) 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 theMessage-IDheader 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
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
- 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
- Uses Rust edition 2024
- Terminal is set to raw mode to capture individual key presses
- The alternate screen prevents terminal history pollution
config.tomlcontains credentials and is gitignored — seeconfig.toml.examplefor the formatproton-bridge/bridge.tomlcontains ProtonMail credentials and is gitignored- The ProtonMail bridge imap_server SELECT response must not include
UIDVALIDITY/UIDNEXTlines — imap-proto 0.10 (used by imap 2.4) does not fully consume them, causing tag desync on subsequent commands