113 lines
5 KiB
Markdown
113 lines
5 KiB
Markdown
# 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`](USAGE.md) for setup instructions, keyboard shortcuts, and configuration reference.
|
|
|
|
## Build and Run Commands
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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 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, search, delete)
|
|
- **`src/connect.rs`** — IMAP connection handling (plain TCP and TLS)
|
|
- **`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
|
|
|
|
## 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 paursing 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.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
|