Last month I wired Claude up to my email infrastructure. Not "Claude writes an email draft and I paste it somewhere" but the agent checks my domain...
For further actions, you may consider blocking this person and/or reporting abuse
Your point about scoping the key first is the thing I'd underline hardest, and I'd push it past revocation into capability. If one key can both send and read events, a prompt injection sitting in an inbox the agent reads can turn itself into a send. A read-only key for the debugging flow, plus a separate send key you attach only when you actually want mail going out, keeps the "agent chains eagerly" habit away from the one tool that leaves the building.
Yes, this is a great point!
thanks for sharing!
🙏
The approval step is the right instinct, but its security value depends on what exactly is being approved. The UI should bind approval to the final recipient set, sender, subject, body hash, attachments, and idempotency key—not merely to “call
send_email.” If the agent edits any field after approval, the token should become invalid and the client should ask again. That closes a subtle time-of-check/time-of-use gap.I would also split credentials by capability and policy: read-only diagnostics versus sending, verified sender identities, recipient/domain allowlists where practical, per-run and daily quotas, and short-lived tokens. Treat bounce messages, display names, and imported contact fields as untrusted content too; they can flow back into the model and influence the next action. Finally, log an immutable receipt connecting the approved payload hash to the provider message ID and delivery events. Human confirmation is useful, but payload-bound approval, scoped credentials, and replay-safe receipts are what make unattended retries and incident review trustworthy.
this is a very good idea!
Email is a perfect test for agent permissions because the action looks simple but the risk is external. The agent needs drafts, recipients, idempotency, and a clear human checkpoint before anything leaves the system.
yes! exactly this!
One extra boundary I would add is a dry-run/commit split. Let the agent resolve recipients, render the final MIME payload, and return a preview plus a stable request ID first; only a separate commit call should send it. The commit handler can reject reused IDs and enforce the sender, recipient set, and body hash it saw in the preview. That makes retries safe and gives the approval UI something concrete to bind to, instead of approving an abstract send_email capability.
Oh yes this is a good one too!
surprise. I will try it
awesome! let me know how it goes!