Phase 0: scaffold Jerboa Proton Mail reader
ober
8c6c143af3de323ad6a54c0e7c08b9934130857e
new file mode 100644 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +.DS_Store +*.so +*.dylib +*.o +*.wpo +*.boot +*.log +*.eml +*.mbox +/protonmail-read +/protonmail-read-bin +.protonmail-reader.local +exports/ +cache/ +tmp/ new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +JERBOA_HOME ?= $(realpath $(CURDIR)/../jerboa) +SCHEME ?= $(JERBOA_HOME)/.chez/bin/scheme + +.PHONY: help run test doctor clean +.DEFAULT_GOAL := help + +help: + @echo "jerboa-protonmail" + @echo "" + @echo "Development:" + @echo " bin/protonmail-read --help Run the checked-in launcher" + @echo " make run ARGS='--help' Run the CLI under the interpreter" + @echo " make doctor Run the placeholder doctor command" + @echo " make test Run smoke tests" + @echo " make clean Remove generated local artifacts" + @echo "" + @echo "Environment:" + @echo " JERBOA_HOME = $(JERBOA_HOME)" + @echo " SCHEME = $(SCHEME)" + +run: + JERBOA_HOME=$(JERBOA_HOME) \ + $(SCHEME) -q --libdirs $(CURDIR):$(JERBOA_HOME)/lib \ + --script main.ss -- $(ARGS) + +doctor: + $(MAKE) run ARGS='doctor' + +test: + JERBOA_HOME=$(JERBOA_HOME) \ + $(SCHEME) -q --libdirs $(CURDIR):$(JERBOA_HOME)/lib \ + --script test/test-all.ss + +clean: + rm -f protonmail-read protonmail-read-bin + rm -rf exports cache tmp new file mode 100644 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# jerboa-protonmail + +Read-only Proton Mail access experiments in Jerboa. + +The stable first target is a local IMAP client for Proton Mail Bridge. Bridge +handles Proton authentication, key management, and local decryption; this tool +will initially list folders, list messages, fetch raw messages, decode common +email formats, and export `.eml` files without mutating mailbox state. + +The native direct-Proton track is documented in `plan.md`, but it is not the +first implementation path. + +## Current Status + +Phase 0 is a project scaffold: + +- CLI entry point. +- Environment config helper. +- Smoke tests. +- Makefile. +- Project plan. + +No live Proton or Bridge connection is attempted yet. + +## Development + +```sh +make run ARGS='--help' +make doctor +make test +``` + +By default the Makefile expects Jerboa at `../jerboa`. Override with: + +```sh +make JERBOA_HOME=/path/to/jerboa test +``` + +## Bridge Configuration + +Later phases will read Bridge IMAP settings from environment variables: + +```sh +export PROTON_BRIDGE_HOST=127.0.0.1 +export PROTON_BRIDGE_PORT=1143 +export PROTON_BRIDGE_USER='bridge-generated-user' +export PROTON_BRIDGE_PASSWORD='bridge-generated-password' +export PROTON_BRIDGE_TLS=auto +``` + +Use Bridge-generated IMAP credentials, not your Proton account password. new file mode 100755 --- /dev/null +++ b/bin/protonmail-read @@ -0,0 +1,9 @@ +#!/bin/sh +set -eu + +repo_dir=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) +jerboa_home=${JERBOA_HOME:-"$repo_dir/../jerboa"} +scheme=${SCHEME:-"$jerboa_home/.chez/bin/scheme"} + +exec "$scheme" -q --libdirs "$repo_dir:$jerboa_home/lib" \ + --script "$repo_dir/main.ss" -- "$@" new file mode 100644 --- /dev/null +++ b/main.ss @@ -0,0 +1,31 @@ +#!chezscheme +;;; Script entry point for protonmail-read. + +(import (except (chezscheme) + make-hash-table hash-table? + sort sort! + printf fprintf + path-extension path-absolute? + with-input-from-string with-output-to-string + iota 1+ 1- + partition + make-date make-time)) + +(define home (or (getenv "HOME") ".")) +(define jerboa-dir + (or (getenv "JERBOA_HOME") + (string-append home "/mine/jerboa"))) +(define project-dir + (or (getenv "JERBOA_PROTONMAIL_DIR") + (current-directory))) + +(library-directories + (append + (list (cons project-dir project-dir) + (cons (string-append jerboa-dir "/lib") + (string-append jerboa-dir "/lib"))) + (library-directories))) + +(import (protonmail cli)) + +(run-cli (command-line-arguments)) new file mode 100644 --- /dev/null +++ b/plan.md @@ -0,0 +1,804 @@ +# Jerboa Proton Mail Reader Plan + +## Goal + +Build a Jerboa program that can access Proton Mail for read-only workflows: + +- List folders/mailboxes. +- List recent messages. +- Fetch and decode selected messages. +- Search mail by basic criteria. +- Export raw messages as `.eml`. + +The first version will not send email, delete email, move email, mark email as read, or modify mailbox state. + +## Current Recommendation + +Use Proton Mail Bridge as the integration boundary. + +Proton Mail Bridge handles Proton authentication, key management, and local decryption, then exposes a local IMAP/SMTP interface. Our Jerboa program should talk to Bridge over local IMAP and stay read-only. + +This is much lower risk than trying to reimplement Proton's private web API flow. The public client source is useful reference material, and local Jerboa projects already provide TCP/TLS/HTTP and OpenPGP building blocks, but direct API integration would still require tracking Proton auth, key unlocking, encrypted message formats, and upstream API changes. + +Treat the project as two tracks: + +1. Bridge track: build a read-only IMAP client first. +2. Native track: research a direct Proton client after the Bridge path works. + +The native track is more feasible than initially assumed because this machine already has `jerboa-pgp`, `jerboa-ssl`, `jerboa-https`, and `jerboa-crypto`. + +## Source Facts + +- Proton states that Proton apps are open source: + - https://proton.me/community/open-source +- Proton Mail web clients are in a public monorepo: + - https://github.com/ProtonMail/WebClients +- Proton Mail Bridge is open source: + - https://github.com/ProtonMail/proton-bridge + - https://proton.me/blog/bridge-open-source +- Proton explains that normal IMAP cannot connect directly to Proton Mail because stored mail is end-to-end or zero-access encrypted: + - https://proton.me/support/why-you-need-bridge +- Proton Mail Bridge creates local IMAP and SMTP servers on the user's computer: + - https://proton.me/support/why-you-need-bridge + - https://github.com/ProtonMail/proton-bridge +- Proton Bridge supports IMAP/SMTP, not POP3: + - https://proton.me/support/imap-smtp-and-pop3-setup +- Proton Mail Bridge is currently available for paid Proton Mail plans: + - https://proton.me/support/imap-smtp-and-pop3-setup +- Bridge has a CLI mode: + - https://proton.me/support/bridge-cli-guide + +## Local Jerboa Assets + +Local projects under `/Users/user/mine/jerboa*` provide useful pieces: + +- `/Users/user/mine/jerboa-pgp` + - Jerboa CLI and FFI bindings over a Rust crypto backend. + - Uses pure-Rust `rPGP` for OpenPGP interop. + - Exposes `jpgp-pgp-decrypt`, `jpgp-pgp-encrypt`, `jpgp-pgp-sign`, and `jpgp-pgp-verify`. + - Current inbound OpenPGP decrypt path expects ASCII-armored OpenPGP messages and supports SEIPDv1/RFC 4880 style messages through `rPGP`. + - Does not currently advertise support for GnuPG 2.5 proprietary OCB packet/tag 20. +- `/Users/user/mine/jerboa-ssl` + - Provides TCP and TLS client primitives: + - `tcp-connect` + - `tcp-read` + - `tcp-write` + - `ssl-connect` + - `ssl-read` + - `ssl-write` +- `/Users/user/mine/jerboa-https` + - Provides an HTTP/1.1 client over TLS: + - `http-get` + - `http-post` + - `http-put` + - `http-delete` + - `http-head` +- `/Users/user/mine/jerboa-crypto` + - Provides digest, HMAC, symmetric crypto, AEAD, Ed25519, random bytes, and scrypt bindings. +- `/Users/user/mine/jerboa-yubikey` + - Provides OpenPGP card/YubiKey management support. This is probably optional for Proton Mail, but useful if later workflows involve hardware-held OpenPGP keys. + +Implication: a native direct Proton client is not blocked by lack of GPG/OpenPGP primitives. The harder work is Proton-specific auth/session handling, key-unlock flow, API compatibility, payload format mapping, and tests against realistic encrypted message fixtures. + +## Non-Goals + +- No direct Proton web API client in the first release. A native API client can be a later research track. +- No SMTP/send support. +- No mailbox mutation: + - No delete. + - No archive. + - No move. + - No copy. + - No flag changes. + - No expunge. +- No credential storage in repository files. +- No background daemon in the first release. +- No GUI in the first release. + +## Assumptions + +- Proton Mail Bridge is installed and running on the same machine. +- The Proton account has a plan that supports Bridge. +- The user has logged into Bridge through its GUI or CLI. +- The Jerboa program receives Bridge's local IMAP configuration from environment variables or an ignored local config file. +- Bridge provides decrypted RFC 5322 messages over IMAP after local decryption. +- The initial tool can be a CLI. + +## Key Risks + +### Bridge Compatibility + +Bridge is designed for desktop email clients, and Proton warns that unsupported clients may behave differently because IMAP implementations vary. We should keep the IMAP command surface small and conservative. + +Mitigation: + +- Start with basic commands only. +- Prefer UID-based operations. +- Avoid commands that alter state. +- Use `BODY.PEEK[]` instead of `BODY[]` to avoid marking messages as read. +- Add transcript tests for IMAP parsing. + +### Credential Handling + +Bridge uses generated IMAP credentials. These are still sensitive because they allow local access to decrypted mail through Bridge. + +Mitigation: + +- Read credentials from environment variables first. +- Support a local config file only if it is gitignored and permission-checked. +- Never print passwords in logs. +- Redact credentials in error messages. + +### Local Plaintext Exposure + +Bridge decrypts messages locally. Our tool will see plaintext email. + +Mitigation: + +- Keep default behavior streaming/read-only. +- Do not cache message bodies by default. +- If caching is added later, make it opt-in and document that it stores plaintext. +- Store exported `.eml` files only when explicitly requested. + +### MIME Complexity + +Real email is messy: nested multiparts, encoded headers, quoted-printable bodies, base64 attachments, different charsets, malformed messages, and HTML-only messages. + +Mitigation: + +- Implement a small MIME parser with fixtures. +- Preserve raw `.eml` output even when friendly decoding fails. +- Decode common cases first: + - RFC 5322 headers. + - RFC 2047 encoded words. + - Multipart boundaries. + - `text/plain`. + - `text/html` fallback. + - `base64`. + - `quoted-printable`. + - UTF-8. + - ISO-8859-1 fallback if available. + +## Proposed CLI + +The binary can be named `protonmail-read`. + +```text +protonmail-read folders +protonmail-read list --folder INBOX --limit 20 +protonmail-read show --folder INBOX --uid 12345 +protonmail-read raw --folder INBOX --uid 12345 +protonmail-read search --folder INBOX --from someone@example.com +protonmail-read search --folder INBOX --subject invoice +protonmail-read search --folder INBOX --since 2026-01-01 +protonmail-read export-eml --folder INBOX --uid 12345 --output message.eml +protonmail-read doctor +``` + +## Configuration + +Prefer environment variables: + +```text +PROTON_BRIDGE_HOST=127.0.0.1 +PROTON_BRIDGE_PORT=1143 +PROTON_BRIDGE_USER=bridge-generated-user +PROTON_BRIDGE_PASSWORD=bridge-generated-password +PROTON_BRIDGE_TLS=auto +``` + +Optional later local config path: + +```text +.protonmail-reader.local +``` + +Rules: + +- Add local config files to `.gitignore`. +- Refuse to read config files that are group/world-readable if they contain a password. +- Redact all secrets from diagnostics. + +## Architecture + +Bridge track: + +```text +CLI + | + +-- config + | + +-- imap-client + | | + | +-- transport + | +-- command writer + | +-- response parser + | +-- literal reader + | +-- mailbox model + | + +-- message + | | + | +-- rfc5322 parser + | +-- header decoder + | +-- mime parser + | +-- content-transfer decoder + | +-- body selector + | + +-- render + | + +-- table output + +-- message output + +-- raw output + +-- eml export +``` + +Native research track: + +```text +CLI + | + +-- config + | + +-- proton-api + | | + | +-- http transport (/Users/user/mine/jerboa-https) + | +-- auth/session research + | +-- mailbox/message API + | + +-- proton-crypto + | | + | +-- key unlock research + | +-- OpenPGP decrypt (/Users/user/mine/jerboa-pgp) + | +-- digest/HMAC/KDF (/Users/user/mine/jerboa-crypto) + | + +-- message + | | + | +-- rfc5322 parser + | +-- header decoder + | +-- mime parser + | + +-- render +``` + +The Bridge track should not depend on `jerboa-pgp`; Bridge already returns decrypted RFC 5322 mail over IMAP. The native track should reuse `jerboa-pgp` where the Proton payload format matches its current OpenPGP decrypt surface, or extend `jerboa-pgp` if Proton needs lower-level packet/session-key operations. + +## Module Layout + +Proposed files: + +```text +Makefile +README.md +.gitignore +src/main.scm +src/config.scm +src/cli.scm +src/imap/transport.scm +src/imap/client.scm +src/imap/parser.scm +src/imap/model.scm +src/mail/rfc5322.scm +src/mail/header.scm +src/mail/mime.scm +src/mail/encoding.scm +src/render.scm +test/imap-parser-test.scm +test/mail-header-test.scm +test/mime-test.scm +test/fixtures/simple.eml +test/fixtures/multipart.eml +test/fixtures/encoded-headers.eml +test/fixtures/quoted-printable.eml +test/fixtures/base64.eml +``` + +The exact Jerboa module syntax should follow local Jerboa conventions once we scaffold the project. + +## Transport Strategy + +Use existing local Jerboa transport code first. + +For Bridge IMAP: + +- Prefer `/Users/user/mine/jerboa-ssl` plain TCP primitives if Bridge exposes local plaintext IMAP. +- Use `/Users/user/mine/jerboa-ssl` TLS primitives if Bridge requires TLS. +- Keep an `openssl s_client` fallback only as a debugging tool. + +For native Proton API research: + +- Prefer `/Users/user/mine/jerboa-https` for HTTPS requests. +- Add JSON helpers if current Jerboa stdlib JSON support is insufficient. +- Keep API code isolated from IMAP code. + +The transport interface should hide this choice: + +```text +connect(host, port, tls-mode) -> connection +send-line(connection, line) +read-line(connection) -> line +read-bytes(connection, n) -> bytes +close(connection) +``` + +This lets us replace the transport later without rewriting the IMAP client. + +## Native Proton Client Research Track + +This track is not required for the first usable version, but it is now realistic enough to document. + +### What We Already Have + +- HTTPS client capability through `jerboa-https`. +- TCP/TLS primitives through `jerboa-ssl`. +- OpenPGP operations through `jerboa-pgp`. +- Crypto primitives through `jerboa-crypto`. +- CLI/project patterns from nearby Jerboa projects. + +### What Still Needs Research + +- Proton account authentication flow. +- Session persistence and refresh. +- Whether the current official client API can be used without relying on brittle private behavior. +- How Proton exposes encrypted user keys to clients. +- How to unlock/decrypt Proton mailbox keys. +- Exact encrypted message payload format: + - ASCII-armored OpenPGP vs binary packet data. + - Whole-message encryption vs per-part/session-key workflows. + - Attachment encryption format. +- Whether `jerboa-pgp` needs lower-level OpenPGP APIs beyond its current `secret armor + passphrase + armored message -> plaintext` wrapper. +- Key transparency or address verification behavior needed for a secure client. +- Rate limits and API error behavior. + +### Native Track Milestones + +1. Read official open-source client code paths for login, key unlock, message list, and message body fetch. +2. Write a short API map: + - endpoints + - request headers + - auth/session tokens + - encrypted payload shapes + - required crypto operations +3. Build a fixture-only decrypt test: + - no live Proton credentials + - fake or exported encrypted payloads only + - call `jerboa-pgp` directly +4. Build a live metadata-only probe: + - login + - list labels/folders + - list message metadata + - no body decrypt yet +5. Build live read-only decrypt: + - fetch one message + - decrypt + - feed plaintext into the shared RFC 5322/MIME parser +6. Decide whether native mode is worth supporting beside Bridge mode. + +### Native Track Exit Criteria + +Native mode should only become a supported path if: + +- Auth works repeatably without manual browser scraping. +- Message decrypt works against current Proton payloads. +- Secret handling is no worse than Bridge mode. +- Breakage risk is documented. +- Tests cover payload parsing and failure cases. +- Bridge mode remains available as the stable path. + +## IMAP Command Scope + +Milestone 1 requires: + +- Server greeting read. +- Tagged commands. +- `CAPABILITY`. +- `LOGIN`. +- `LIST "" "*"` or equivalent. +- `SELECT`. +- `UID SEARCH`. +- `UID FETCH`. +- `LOGOUT`. + +Use UID-based access: + +```text +A001 CAPABILITY +A002 LOGIN "user" "password" +A003 LIST "" "*" +A004 SELECT "INBOX" +A005 UID SEARCH ALL +A006 UID FETCH 12345 BODY.PEEK[] +A007 LOGOUT +``` + +Later commands: + +- `NOOP` for health checks. +- `UID FETCH <uid> (FLAGS INTERNALDATE RFC822.SIZE BODY.PEEK[HEADER.FIELDS (...)])` for efficient listing. +- `UID SEARCH FROM`. +- `UID SEARCH SUBJECT`. +- `UID SEARCH SINCE`. + +Avoid for now: + +- `STORE`. +- `EXPUNGE`. +- `COPY`. +- `MOVE`. +- `APPEND`. +- `CREATE`. +- `DELETE`. +- SMTP commands. + +## IMAP Parser Requirements + +The parser must handle: + +- Tagged completion responses: + - `A001 OK ...` + - `A001 NO ...` + - `A001 BAD ...` +- Untagged responses: + - `* OK ...` + - `* CAPABILITY ...` + - `* LIST (...) "/" "INBOX"` + - `* 23 EXISTS` + - `* SEARCH 1 2 3` + - `* 1 FETCH (...)` +- Literals: + - `{1234}\r\n` + - Then exactly 1234 bytes of message data. +- Quoted strings. +- Escaped characters inside quoted strings. +- NIL atoms. +- Parenthesized lists. + +Keep parser output structured enough that command handlers do not parse raw strings repeatedly. + +## Message Decoding Requirements + +### Header Parser + +Support: + +- Header/body split on first blank line. +- Header unfolding. +- Case-insensitive header names. +- Multiple headers with same name. +- Raw header preservation. + +Important headers: + +- `From` +- `To` +- `Cc` +- `Bcc` +- `Subject` +- `Date` +- `Message-ID` +- `In-Reply-To` +- `References` +- `Content-Type` +- `Content-Transfer-Encoding` + +### Encoded Header Words + +Support RFC 2047 forms: + +```text +=?UTF-8?B?...?= +=?UTF-8?Q?...?= +``` + +Initial charsets: + +- UTF-8. +- US-ASCII. +- ISO-8859-1 if available. + +### MIME + +Support: + +- Single-part text messages. +- `multipart/alternative`. +- `multipart/mixed`. +- Nested multipart. +- Boundary parsing. +- Content type parameters. +- Charset parameters. +- Attachment metadata. + +Body selection: + +1. Prefer `text/plain`. +2. Fall back to simple text extraction from `text/html`. +3. Indicate attachments by filename/content type without decoding them into the main body view. + +### Content-Transfer-Encoding + +Support: + +- `7bit`. +- `8bit`. +- `binary`. +- `base64`. +- `quoted-printable`. + +## Output Design + +### Folder Listing + +```text +Name Flags +INBOX \HasNoChildren +Archive \HasNoChildren +Sent \HasNoChildren +``` + +### Message Listing + +```text +UID Date From Subject +12345 2026-05-28 09:14 person@example.com Example subject +``` + +### Message View + +```text +From: Person <person@example.com> +To: User <user@proton.me> +Date: Thu, 28 May 2026 09:14:00 -0600 +Subject: Example subject + +Plain text body... + +Attachments: +- invoice.pdf application/pdf 182341 bytes +``` + +## Implementation Milestones + +### Milestone 0: Project Setup + +Deliverables: + +- Initialize project structure. +- Add `README.md`. +- Add `.gitignore`. +- Add `Makefile`. +- Add a placeholder CLI entry point. +- Verify `jerboa` can run or compile the entry point. + +Exit criteria: + +- `make test` or equivalent runs a placeholder test. +- `protonmail-read --help` prints basic usage. + +### Milestone 1: Bridge Connectivity Probe + +Deliverables: + +- Load config from environment variables. +- Connect to Bridge IMAP. +- Read greeting. +- Send `CAPABILITY`. +- Send `LOGIN`. +- Send `LIST`. +- Send `LOGOUT`. +- Implement `doctor`. + +Exit criteria: + +- `protonmail-read doctor` confirms: + - Config is present. + - Bridge host/port is reachable. + - Login succeeds. + - Mailbox list can be fetched. +- Secrets are redacted in all output. + +### Milestone 2: IMAP Parser + +Deliverables: + +- Structured parser for tagged/untagged responses. +- Literal support. +- Quoted string support. +- Unit tests from canned transcripts. + +Exit criteria: + +- Parser handles realistic `LIST`, `SEARCH`, and `FETCH` responses. +- Parser tests cover error responses and literals. + +### Milestone 3: Folder and Message Listing + +Deliverables: + +- `folders`. +- `list --folder`. +- Efficient header-only fetch where possible. +- UID-based listing. + +Exit criteria: + +- Can list mailbox folders. +- Can list recent messages without fetching full message bodies. +- Does not mark messages as read. + +### Milestone 4: Raw Fetch and Export + +Deliverables: + +- `raw --folder --uid`. +- `export-eml --folder --uid --output`. +- Full message fetch using `BODY.PEEK[]`. + +Exit criteria: + +- Can fetch a message as raw RFC 5322 text. +- Can export `.eml`. +- Message remains unread if it was unread before fetching. + +### Milestone 5: Header and MIME Decoding + +Deliverables: + +- RFC 5322 parser. +- RFC 2047 header decoder. +- MIME parser. +- Base64 decoder. +- Quoted-printable decoder. +- Body selector. +- Fixture tests. + +Exit criteria: + +- `show --folder --uid` prints decoded headers and readable body for common emails. +- Fixtures cover plain text, multipart, encoded headers, base64, and quoted-printable. + +### Milestone 6: Search + +Deliverables: + +- `search --folder --from`. +- `search --folder --subject`. +- `search --folder --since`. +- Combine criteria where IMAP supports it. + +Exit criteria: + +- Search returns UIDs and summary rows. +- Search output can be piped into `show` or `export-eml` workflows manually. + +### Milestone 7: Hardening + +Deliverables: + +- Timeout handling. +- Better IMAP error messages. +- Redacted debug logs. +- Config validation. +- Tests for malformed server responses. +- Documentation for Bridge setup. + +Exit criteria: + +- Common Bridge failures produce useful errors: + - Bridge not running. + - Wrong port. + - Bad credentials. + - TLS mismatch. + - Folder not found. + - UID not found. + +## Testing Strategy + +### Unit Tests + +Test without Proton Mail or Bridge: + +- IMAP response parser. +- IMAP literal handling. +- Header parsing. +- Header decoding. +- MIME boundary parsing. +- Content-transfer decoding. +- CLI option parsing. +- Config loading and redaction. + +### Fixture Tests + +Use committed fake `.eml` files only. Do not commit real email. + +Fixture categories: + +- Simple plain text. +- Multipart alternative. +- Multipart mixed with attachment. +- Encoded subject. +- Encoded sender name. +- Base64 body. +- Quoted-printable body. +- HTML-only body. +- Malformed but recoverable message. + +### Integration Tests + +Run only when explicitly enabled: + +```text +PROTON_BRIDGE_INTEGRATION=1 make integration-test +``` + +Rules: + +- Never require real credentials in CI. +- Never print message bodies in integration test logs by default. +- Prefer a dedicated test mailbox/folder. +- Use read-only commands only. + +## Security Checklist + +- No secrets committed. +- `.gitignore` covers local config and exported mail. +- No password printed in normal output. +- No password printed in debug output. +- No raw message printed unless user explicitly runs `raw`. +- No message body cached by default. +- No mailbox mutation commands. +- Use `BODY.PEEK[]`. +- Treat exported `.eml` files as sensitive. +- Document that Bridge exposes decrypted mail to local clients. + +## Documentation Needed + +README sections: + +- What this tool does. +- What this tool does not do. +- Proton Bridge requirement. +- Paid plan requirement. +- How to get Bridge IMAP settings. +- Environment variable setup. +- Example commands. +- Security notes. +- Troubleshooting. +- Development setup. +- Test commands. + +## Open Questions + +- Does local Bridge require TLS, STARTTLS, or plain local IMAP on this machine? +- What exact port is Bridge configured to use? +- Does Bridge return stable UID behavior for all target folders? +- Should we support a local keychain lookup later, or keep environment variables only? +- Should `show` render HTML as stripped text, or should it optionally write HTML to a file? +- Should attachment export be included later? +- For native mode, does Proton's current message payload fit `jerboa-pgp`'s existing armored-message decrypt API? +- For native mode, what Proton API/auth surfaces are stable enough to rely on? + +## Future Enhancements + +- Attachment export. +- Local encrypted cache. +- Incremental sync metadata. +- JSON output for scripting. +- Notmuch/Maildir export. +- Read-only TUI. +- Optional SMTP support after read-only behavior is solid. +- Direct Proton API mode using `jerboa-https`, `jerboa-crypto`, and `jerboa-pgp`. +- Lower-level `jerboa-pgp` APIs if Proton payloads need packet/session-key operations instead of whole armored-message decrypt. + +## First Implementation Slice + +Build the smallest useful vertical path: + +1. `protonmail-read doctor` +2. Read environment config. +3. Connect to Bridge. +4. Login. +5. List folders. +6. Logout. +7. Add transcript tests for the parser. + +This proves the local Proton Bridge integration before spending time on MIME decoding and richer CLI behavior. new file mode 100644 --- /dev/null +++ b/protonmail/cli.ss @@ -0,0 +1,83 @@ +#!chezscheme +;;; (protonmail cli) - subcommand dispatch for protonmail-read. + +(library (protonmail cli) + (export run-cli usage-string) + + (import (except (chezscheme) + make-hash-table hash-table? + sort sort! + printf fprintf + path-extension path-absolute? + with-input-from-string with-output-to-string + iota 1+ 1- + partition + make-date make-time) + (protonmail config)) + + (define version "0.0.0-phase0") + + (define usage-string + (string-append + "usage: protonmail-read <command> [options]\n" + "\n" + "commands:\n" + " folders List folders (phase 3)\n" + " list --folder INBOX --limit N List messages (phase 3)\n" + " show --folder INBOX --uid UID Decode one message (phase 5)\n" + " raw --folder INBOX --uid UID Print raw RFC 5322 message (phase 4)\n" + " export-eml --uid UID --output F Export raw message (phase 4)\n" + " search --folder INBOX ... Search messages (phase 6)\n" + " doctor Check local configuration\n" + " version Print version\n" + " help Print this help\n")) + + (define (println s) + (display s) + (newline)) + + (define (die code msg)