# claude-mail-buddy — Plan ## Concept Poll a dedicated IMAP mailbox for incoming mail from a trusted sender, dispatch the message as a prompt to Claude Code via [claude-remote](../claude-remote/), and have Claude reply via a CCC `send-email` action. --- ## Sender Verification The `allowed_sender` config filter is a basic check but not cryptographically sound. Stronger options (in increasing strength): - **`Authentication-Results` header** — check that the inbound mail server stamped DKIM/SPF pass before dispatching. Practical and low-effort since your mail server already does the verification. - **DKIM** — cryptographic signature from the sending domain's DNS key. Proves the message genuinely originated from that domain. - **PGP/S/MIME** — end-to-end signature tied to the sender's personal key, independent of mail infrastructure. Strongest guarantee; requires signing outbound mail from your client. For now, `allowed_sender` substring match is sufficient for exploration. Worth adding `Authentication-Results` checking before using this for anything sensitive. --- ## Implementation Stages ### ✅ Stage 1 — Explore the message object Receive a message and `inspect()` the full imapflow msg object to understand what data is available (headers, body parts, envelope, flags, etc.). ### ✅ Stage 2 — Prompt construction Parse the message into a well-formed prompt using `mailparser`. Use HTML body for better encoding/structure fidelity. Instruct Claude to reply via CCC per `email_protocol.md`. ### ✅ Stage 3 — CCC send-email action `send-email` action already existed in `claude-code-conduit` with full SMTP, permission store, and topic-based access control. Tested and working end-to-end. ### ✅ Stage 4 — Wire it together `make_prompt` + `send_to_claude` wired up. Full flow working: email in → Claude processes → replies via CCC send-email → email out. ### Stage 5 — Adaptive polling High/low frequency mode: switch to fast polling (e.g. 10s) when a message arrives, step back down to slow polling (e.g. 45s) after a configurable idle period with no new messages (e.g. 5 minutes). Keeps the conversation feeling responsive without hammering the server during quiet periods. ### Stage 6 — Persist last UID Save the last processed UID to a state file so the script picks up where it left off across restarts rather than skipping everything that existed at startup. ### Stage 7 — Hardening - Verify `Authentication-Results` header for DKIM/SPF pass - Mark messages seen only after successful dispatch - Reconnect/retry logic for IMAP drops