#+TITLE: Proton Mail Bridge + cmail-action triage helper #+DATE: 2026-05-08 * What this is Notes for folding the Proton Mail Bridge + =cmail-action= triage helper setup into the archsetup install flow. Reproduces what was set up on ratio on 2026-05-08. * Why Proton Mail (=c@cjennings.net=, locally =cmail=) doesn't expose plain IMAP — it's end-to-end encrypted. Proton Mail Bridge is the official local daemon that decrypts on-the-fly and presents a local IMAP/SMTP endpoint at =127.0.0.1:1143= / =1025=. Once Bridge is running, anything that speaks IMAP (mbsync, mu, mu4e, custom helpers) talks to cmail the same way it talks to any other IMAP account. The triage workflow at =homelab/.ai/project-workflows/process-unread-emails.org= previously handled gmail/dmail (via the Gmail MCP server) but had no equivalent for cmail. The =cmail-action= helper closes that gap — it talks directly to Bridge's IMAP and provides the same operations the Gmail MCP gives the other two accounts: list unread, read body, mark read, star, unstar, trash. Pattern: full parity, Claude drives end-to-end, no switching to mu4e mid-flow. * End state to reproduce After the install completes, the system has: 1. =protonmail-bridge= installed from AUR. 2. First-run done: Proton account logged in, Bridge-generated IMAP password captured at =~/.config/.cmailpass= (mode 0600). 3. Bridge's self-signed cert at =~/.config/protonbridge.pem=. 4. Bridge running as a systemd user service (autostarts on login). 5. =cmail= account block in =~/.mbsyncrc= pointing at the local Bridge endpoint. 6. =~/.mail/cmail/= populated by mbsync. 7. =~/.local/bin/cmail-action= symlinked into PATH, pointing at =~/projects/claude-templates/.ai/scripts/cmail-action.py=. * Steps Pre-reqs: claude-templates already cloned at =~/projects/claude-templates= (the cmail-action.py script lives there), paid Proton plan (Bridge is gated behind paid tier). ** 1. Install Bridge from AUR #+begin_src bash yay -S protonmail-bridge #+end_src Pulls in =protonmail-bridge= and =protonmail-bridge-core= binaries. Don't use Flatpak. ** 2. First-run: log in and capture IMAP password This step is interactive and can't be automated — Proton requires real credentials. Run once on a new install: #+begin_src bash protonmail-bridge --cli #+end_src In the CLI: =login= → enter Proton account credentials → 2FA prompt if enabled. Bridge stores the account credentials in its own encrypted state under =~/.config/protonmail/bridge-v3/=. Then in the same CLI session, =info= prints the per-app IMAP and SMTP passwords Bridge generated for this account. Capture the IMAP password (NOT the Proton account password — these are distinct): #+begin_src bash echo 'BRIDGE_GENERATED_PASSWORD' > ~/.config/.cmailpass chmod 600 ~/.config/.cmailpass #+end_src The encrypted form lives in =~/code/archsetup/dotfiles/common/.config/.cmailpass.gpg= for sync across machines. The plaintext file at =~/.config/.cmailpass= is gitignored and decrypted locally as needed. ** 3. Export the Bridge cert Bridge ships a self-signed cert that mbsync and =cmail-action= pin against. Path inside Bridge state varies by version; locate and copy: #+begin_src bash find ~/.config/protonmail -name 'cert.pem' -print cp ~/.config/protonmail/bridge-v3/cert.pem ~/.config/protonbridge.pem #+end_src The cert's CN is =127.0.0.1=, so connecting to localhost validates against the pinned cert. =cmail-action= disables hostname verification anyway (cert lacks SAN; localhost + pinned cert is sufficient). ** 4. Configure mbsync for cmail Add the =cmail= block to =~/.mbsyncrc=. The current homelab setup has it; the canonical version lives in =dotfiles/common/.mbsyncrc= and is symlinked to =~/.mbsyncrc=. Key fields: #+begin_example IMAPAccount cmail Host 127.0.0.1 Port 1143 User c@cjennings.net PassCmd "cat ~/.config/.cmailpass" TLSType STARTTLS CertificateFile ~/.config/protonbridge.pem MaildirStore cmail-local Path ~/.mail/cmail/ Inbox ~/.mail/cmail/Inbox/ Trash ~/.mail/cmail/Trash/ SubFolders Verbatim #+end_example Plus channels for each folder (Inbox / Sent / Trash / Archive / Starred / Spam — Drafts and All Mail are intentionally omitted because Bridge has historically had sync issues on those two folders). Initial sync: #+begin_src bash mkdir -p ~/.mail/cmail mbsync cmail mu index #+end_src ** 5. Enable Bridge as a systemd user service The protonmail-bridge AUR package ships a unit at =/usr/lib/systemd/user/protonmail-bridge.service=. The unit calls =protonmail-bridge-core --noninteractive= directly (not the =protonmail-bridge --no-window= wrapper). Enable + start: #+begin_src bash systemctl --user enable --now protonmail-bridge #+end_src Verify: #+begin_src bash systemctl --user status protonmail-bridge ss -ltn | grep -E '127.0.0.1:(1143|1025)' #+end_src Expected: service active (running), both ports LISTEN. Bridge logs a non-fatal warning about =pass not initialized= because the =pass= keychain helper isn't set up — Bridge falls back to its own encrypted state under =~/.config/protonmail/=. Ignore. ** 6. Symlink cmail-action into PATH The script is the source-of-truth in claude-templates. The PATH entry is a symlink so updates to claude-templates immediately take effect: #+begin_src bash ln -s ~/projects/claude-templates/.ai/scripts/cmail-action.py \ ~/.local/bin/cmail-action #+end_src Verify: #+begin_src bash cmail-action folders # lists Proton IMAP folders cmail-action list-unread --limit 1 # returns JSON #+end_src * Notes / gotchas - *Bridge requires a paid Proton plan.* Bridge auth fails on free tier. If the install runs on a free-tier account, skip steps 2-6 with a clear error. - *Bridge sometimes resets UIDVALIDITY* after upgrades. The homelab =sync-email.org= workflow documents the recovery steps (delete =.uidvalidity= and =.mbsyncstate= under =~/.mail/cmail=, re-run mbsync). Doesn't affect =cmail-action= because the helper talks to Bridge live and doesn't keep its own state. - *The Bridge cert can rotate.* If =cmail-action folders= ever starts failing with cert errors, re-run step 3. - *Drafts and All Mail are intentionally omitted from mbsync* per the comment in =~/.mbsyncrc=. Don't add them back without testing — historical sync errors. - *=cmail-action= bypasses mbsync* for triage operations — it talks to Bridge's IMAP directly. mbsync is still used for offline reading via mu/mu4e, but the triage workflow doesn't depend on it.