- Add proton-bridge as optional dep behind `proton` feature flag
- New proton-bridge/src/lib.rs: pub fn start() spins a background Tokio
thread, pre-binds ports, and signals readiness via mpsc before returning
- src/main.rs: conditionally starts bridge before TUI enters raw mode;
derives effective IMAP/SMTP config via Provider enum
- src/config.rs: add Provider enum, optional imap/smtp, ProtonConfig/
BridgeConfig mirrors, effective_imap/smtp() helpers
- Remove all per-operation eprintln!/println! from imap_server, smtp_server,
and api.rs that fired during TUI operation and corrupted the display
- config.toml.example: unified format covering both imap and proton providers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements a minimal ESMTP listener (AUTH LOGIN/PLAIN, MAIL FROM, RCPT TO,
DATA, QUIT) that sends via the ProtonMail v4 API (create draft → send).
- ProtonMail internal recipients: Type 1 (encrypt to recipient's ECDH key)
- External recipients: Type 32 PGP/MIME — detached signature in a separate
application/pgp-signature MIME part so the body arrives clean in Gmail.
The MIME entity is wrapped in an OpenPGP-signed message (Signature=1) to
satisfy ProtonMail's mandatory signature check on all external sends.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Plain-TCP listener on 0.0.0.0 (handles both localhost and 127.0.0.1).
LOGIN, NOOP, SELECT (reloads inbox), FETCH header+body, SEARCH, STORE,
EXPUNGE (deletes on ProtonMail), LOGOUT.
FETCH body decrypts messages on demand: brief lock for ID lookup, API call
without lock, brief lock again for crypto. RFC 3501 literal format with
exact byte counts for imap-crate compatibility.
Also: update store.expunge() to return (ids, seqs) in descending order for
correct IMAP EXPUNGE response ordering; add chrono for RFC 2822 dates.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The key insight from go-proton-api SaltForKey: ProtonMail uses only the
last 31 chars of the bcrypt output as the key passphrase — not the full
60-char string. One line fix, two days of debugging.
Also adds the full crypto layer (crypto.rs): user key unlock, address key
token decryption, and message body decryption via rpgp. Includes SRP auth,
session caching with locked-scope handling, TOTP, and the ProtonMail API
client for inbox listing and message fetch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements typed async wrappers for the four endpoints tuimail needs:
- list_messages: GET /mail/v4/messages (paged inbox listing)
- get_message: GET /mail/v4/messages/{id} (full message with encrypted body)
- delete_messages: PUT /mail/v4/messages/delete (soft-delete to Trash)
- get_public_keys: GET /core/v4/keys (recipient keys for outbound mail)
All responses decoded through Envelope<T> with Code 1000 check.
main.rs smoke-tests the inbox listing after authentication.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Convert tuimail repo to Cargo workspace with tuimail and proton-bridge members
- Add proton-bridge binary crate with config, SRP 6a, and auth modules
- Implement ProtonMail SRP 6a exactly matching go-srp:
- Little-endian bigints throughout
- expandHash = SHA512(data||0..3) producing 256 bytes
- k, u, M1, M2 all via expandHash with 256-byte normalised inputs
- Password hashing v3/v4: bcrypt($2y$, salt+proton) + expandHash(output||N)
- Authenticate against Proton API (auth/info → auth/v4), verify server proof
- Persist session (UID, access/refresh tokens) to session.json
- Add bridge.toml and session.json to .gitignore (contain credentials/tokens)
- Add PROTON.md with full build plan for the mini-bridge
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>