Configure a restricted reader
Configure an explicit reader agent before enabling the plugin. Preserve existing agent settings and add one binding per enabled channel so your primary agent keeps its existing channel ownership.hooks.enabled, Google Cloud, Tailscale Funnel, or a public HTTP endpoint. It calls the Gateway’s trusted plugin email dispatcher directly; HTTP-hook agent/session allowlists are not its configuration boundary. Its agentId, sender policy, and restricted reader control this path. It is also separate from internal HOOK.md event handlers.
Sender authentication
The plugin checks the parsedFrom address against allowedSenders before any message reaches a model. Entries can be complete email addresses or @domain entries. Display names and Reply-To do not grant access, messages with multiple From addresses are rejected, and an empty allowlist disables that account.
Configure a sender-bound token only when an allowlisted sender cannot produce useful DKIM or DMARC authentication:
validate=false
reader+<long-random-token>@example.com. The token never expands the account allowlist and never grants additional agent tools or workspace access. Lower authentication thresholds and trusted-header overrides are operator-owned security relaxations.
Verify the security boundary
mail_reader, creates an isolated run, and only summarizes the content. hook:imap:<account>:<uidvalidity>:<uid> is the logical dispatch key; the stored run session can use a generated cron:...:run:... key instead. Any link navigation, file write, shell command, browser action, or other tool escape is a failed boundary check.
The IMAP dispatch log with a runId records admission, not completed processing or delivery. With deliver: false, look for the subsequent Gateway log hook agent run completed without announcement, or hook failure warnings, and inspect the run transcript. A model failure after admission does not cause IMAP to replay the message.
Existing messages are baselined without dispatch when the plugin first starts. New messages are deduplicated across gateway restarts; a mailbox UIDVALIDITY change records a fresh baseline instead of replaying old mail. Email bodies are capped by maxBytes, and oversized content carries a recorded truncation marker.
Troubleshooting
The account needs reauthentication. Three consecutive authentication failures stop retries and mark the watcher unhealthy. Update the IMAP password or SecretRef, then reload the gateway configuration. An unresolved account credential degrades that account without preventing other accounts from starting. The server does not support IMAP IDLE. Automatic mode falls back to polling everypollSeconds seconds, with a minimum of 15 seconds. Set watch.mode: "interval" to force polling. Some iCloud servers advertise XAPPLEPUSHSERVICE instead of standard IDLE; polling is the supported path.
Messages from a self-hosted sender are rejected. Check logs for the sender domain and failing gate. If the sending MX does not provide DKIM or DMARC, prefer fixing its DNS/signing configuration. Otherwise explicitly lower senderAuth.min or configure a sender-bound address token; retain the sender allowlist and isolated reader in either case.
No messages are dispatched. Verify the account has a nonempty allowedSenders list, the message arrived after the initial baseline, the sender matches From, the reader agent exists, and the model probe succeeds. Rejections are logged without message subjects or bodies.