Skip to main content
ClaudeWave

A safe, self-hosted gateway between your iCloud mailbox and your AI assistant

SubagentsOfficial Registry0 stars0 forks● PythonApache-2.0Updated today
ClaudeWave Trust Score
95/100
✓ Verified
Passed
  • ✓Open-source license (Apache-2.0)
  • ✓Actively maintained (<30d)
  • ✓Clear description
  • ✓Topics declared
  • ✓Documented (README)
Last scanned: 10/12/2026
Install as a Claude Code subagent
Method: Clone
Terminal
git clone https://github.com/darrylmosher/mailroom && cp mailroom/*.md ~/.claude/agents/
1. Clone the repository and copy the agent .md definitions into ~/.claude/agents (or .claude/agents inside a project).
2. Start a new Claude Code session to load the agents.
3. Delegate work to them with the Task/Agent tool or by name.
Use cases

Subagents overview

# Mailroom

**A safe, self-hosted gateway between your iCloud mailbox and your AI assistant.**

Apple doesn't offer a mail API. Mailroom fills that gap for one person's iCloud account: it mirrors your mailbox into a local full-text index and exposes a small REST API and CLI designed for AI agents. It is fast to search, cheap in tokens, and built on the assumption that email is untrusted input and agents need brakes.

> Mailroom works *for* iCloud Mail; it is an independent project, not affiliated with Apple.

![mailctl searching mail, exposing a phishing email's hidden text, drafting a reply, archiving with undo](docs/demo.gif)

*Real output against the seeded test mailbox. The "bank" email arrives with `sender_verified: false`, its hidden `display:none` payload stripped and counted, and tracking parameters gone from its links; the drafted reply lands in Drafts for a human to send.*

## Why this exists

If you want your AI assistant to read and triage your mail, today's options are rough: thin IMAP pass-throughs (slow, no real search, and the agent gets a raw send button), Mail.app scrapers (need a Mac awake 24/7), or hosted email APIs (your mail transits someone else's cloud). Mailroom is the fourth option: one small service on your own box, holding one app-specific password, giving your agent exactly the capabilities you choose and nothing else.

## What makes it different

Two things drive the design: safety, and token efficiency.

### Safety

- **Three key tiers:** `read` < `write` < `send`. Give your agent the read key and it can never file, flag, or send anything. [THREAT_MODEL.md](THREAT_MODEL.md) maps each feature to the leg of the [lethal trifecta](https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/) it severs, and says plainly what no filter can guarantee.
- **Drafts-first sending.** By default, "send" saves the message to your Drafts folder for you to review and send from Mail. Optional allowlist mode sends directly to approved recipients only, with an hourly cap. Blocked recipients and Bcc are checked against the same list; the hourly cap counts in-flight and outcome-unknown sends too. Drafts and sends carry attachments; copying an attachment off a received message is allowed into drafts only, so an injected email can never get its own payload forwarded without a human looking at it first.
- **Prompt-injection stripping.** Text hidden from human readers (`display:none`, zero-size fonts, invisible Unicode) is removed and counted, so your agent can tell you "this email hid 1,400 characters from you." Every content response is labelled untrusted. Stripping is mitigation, not a guarantee; the threat model spells out its limits.
- **`sender_verified`.** SPF/DKIM/DMARC alignment distilled into one flag, so "this is your bank" claims are checkable without the agent parsing headers. A spoofed trailing `Authentication-Results` header can't override the receiving server's verdict.
- **7-day undo; nothing permanently deleted.** Every action returns an undo token. Moves to Trash and Junk are off by default, because iCloud purges those folders on its own.
- **Malicious-domain lists (optional, none bundled).** Point `DOMAIN_BLOCKLISTS` at the same public feeds Pi-hole uses (URLhaus, Phishing Army, your own file) and every link and sender domain is checked locally at read time: flagged in `annotate` mode, withheld entirely in `redact` mode. Lists are reactive, so this is a third deterministic signal beside `sender_verified` and the hidden-text count, never a guarantee. Off by default, which keeps the no-extra-egress claim below true.
- **Idempotent writes.** Every write takes an `Idempotency-Key`; retries and races can't double-send or double-file. SMTP submission is driven step by step so "nothing went out, retry freely" and "it may have been delivered, never resend" are told apart exactly.

### Token efficiency

- A message comes back as its new text only: quoted history and signatures are stripped, with the removed size reported. A whole conversation arrives in one call, each message without its quotes.
- Links become `[n]` references with tracking parameters (`utm_*`, `fbclid`, `gclid`, …) stripped; the cleaned URLs ride in a separate list.
- Local SQLite FTS5 search across every folder at once, diacritic-insensitive ("cafe" finds "café"), in milliseconds. iCloud's weak IMAP search is never in the loop.
- A long-poll change feed (`/changes?cursor=N`) delivers new mail and flag changes with summaries attached, so the agent rarely needs a second call. For the reverse direction, `WEBHOOK_URL` POSTs HMAC-signed `message.new` events with the summary included, so new mail can wake your agent instead of the agent polling.

![The same email as a raw source and as the cleaned view the agent receives](docs/what-the-agent-sees.svg)

And it understands how real iCloud accounts work: every address on the account is tracked per message (`received_as`), including iCloud+ custom domains and catch-alls, and replies go out from the address the mail arrived at.

## The API

| | endpoint | tier |
|---|---|---|
| status, sync progress, policy | `GET /status` | read |
| search / list (`q`, `from`, `to`, `folder`, `received_as`, `since`, `until`, `unread`, `flagged`, `has_attachments`, `bulk`, `from_me`, `order`, `limit`, `offset`) | `GET /messages` | read |
| one message (`view=new\|full`) | `GET /messages/{id}` | read |
| attachment (`format=raw\|text`; text works for text, HTML and PDF) | `GET /messages/{id}/attachments/{index}` | read |
| whole conversation | `GET /threads/{thread_id}` | read |
| change feed (long-poll `wait` ≤ 55 s) | `GET /changes?cursor=N` | read |
| identities / folders / audit log / outbox | `GET /identities` `/folders` `/actions` `/outbox` | read |
| calendar agenda, recurrences expanded (opt-in: `CALENDAR=1`) | `GET /calendar?since&until` | read |
| archive, move, mark read/unread, flag/unflag with Apple Mail colors (+ spam/trash if enabled) | `POST /messages/{id}/actions` | write |
| undo any action | `POST /actions/{id}/undo` | write |
| drafts with attachments (create / replace / discard) | `POST /drafts`, `PUT`/`DELETE /drafts/{id}` | write |
| send (policy decides: sent, or drafted for approval) | `POST /send` | send |

Errors come back as `{"error": {"code", "message"}}` where the message tells the agent what to do next (`trash_disabled`: archive instead; `stale_location`: retry shortly). The bundled `mailctl` CLI wraps all of it in JSON output and adds an automatic `Idempotency-Key` to writes.

## Where to run it

![How mailroom works: iCloud synced to a local index, served to an agent through tiered keys](docs/architecture.svg)

Mailroom is one small service with a SQLite file: it runs anywhere Python 3.11 runs, a Mac included. Four ways to run it, simplest first:

| topology | network setup | notes |
|---|---|---|
| **Your own computer** (macOS LaunchAgent, no root) | none; everything on `127.0.0.1` | `./deploy/launchd/install.sh`. Your agent on the same machine needs no Tailscale, no proxy, nothing exposed. |
| **Same VM as your agent** (a cloud box running your assistant) | none; both talk over `127.0.0.1` | Same idea, Linux: install.sh or Docker, point `MAILROOM_URL` at `http://127.0.0.1:8420`. |
| **Homelab VM**, agent connects in | `tailscale serve` (or your reverse proxy) | Your mail index stays on hardware you own. |
| **Cloud VM**, agent connects in | `tailscale serve` (or TLS proxy) | Same as homelab operationally; read the [cloud section of the threat model](THREAT_MODEL.md#running-in-the-cloud) first. |

Settings worth knowing: `WINDOW_DAYS` sets how much history to mirror, `365` by default or `0` for your entire mailbox, never pruned (a decade of mail indexes to a few hundred MB of SQLite). `mailroom serve --env-file` reads a plain config file, so local setups need no systemd or Docker at all. `HEALTHCHECK_PING_URL` pings healthchecks.io or an Uptime Kuma push monitor after every clean sync. `WEBHOOK_URL` and `WEBHOOK_SECRET` turn the change feed into signed pushes for your agent. Search accepts `flag_color=orange` and friends, matching Apple Mail's colored flags exactly.

**Cloud provider notes.** Mailroom needs IMAP egress (`imap.mail.me.com:993`) everywhere, and SMTP egress (`smtp.mail.me.com:587`) only for real sending. In the default drafts-first mode everything, drafts included, travels over IMAP, so a blocked SMTP port costs you nothing. Providers differ here: Hetzner leaves 587 open (only 25/465 are blocked for new accounts), while DigitalOcean blocks 25/465/587 outright on new accounts, even authenticated. On DigitalOcean you're in drafts mode unless support unblocks you, and `mailroom-check` will say exactly that. There's no evidence of Apple refusing app-specific-password IMAP logins from datacenter IPs (hosted products like Nylas rely on that path), and mailroom's single connection and 20-second poll sit far below Apple's rate limits.

Not a good fit: serverless or scale-to-zero platforms. The sync worker wants a persistent disk and a long-lived process.

## Quickstart (systemd)

```bash
git clone https://github.com/darrylmosher/mailroom && cd mailroom
sudo ./deploy/install.sh          # user, venv, /etc/mailroom, random API keys, systemd unit
# paste your app-specific password (appleid.apple.com -> Sign-In and Security), then Ctrl-D:
sudo sh -c 'umask 077; cat > /etc/mailroom/creds/IMAP_PASS'
sudoedit /etc/mailroom/config.env # IMAP_USER, SMTP_USER, IDENTITIES, MY_DOMAINS
sudo mailroom-check               # logs in, lists folders + roles, tests SMTP auth; sends nothing
sudo systemctl enable --now mailroom
```

The service binds to `127.0.0.1` only. Put it on your tailnet (`sudo tailscale serve --bg --https=443 http://127.0.0.1:8420`) or behind any reverse proxy you trust. Skip all of that when your agent runs on the same box. Egress needed: `imap.mail.me.com:993`, plus `smtp.mail.me.com:587` only for allowlist-mode sending.

Bootstrapping a fresh cloud VM? [deplo
ai-agentsclaudeemailicloudimapmcpself-hosted

What people ask about mailroom

What is darrylmosher/mailroom?

+

darrylmosher/mailroom is subagents for the Claude AI ecosystem. A safe, self-hosted gateway between your iCloud mailbox and your AI assistant It has 0 GitHub stars and its last recorded update is dated 2026-10-11.

How do I install mailroom?

+

You can install mailroom by cloning the repository (https://github.com/darrylmosher/mailroom) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is darrylmosher/mailroom safe to use?

+

Our security agent has analyzed darrylmosher/mailroom and assigned a Trust Score of 95/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.

Who maintains darrylmosher/mailroom?

+

darrylmosher/mailroom is maintained by darrylmosher. The last recorded GitHub activity is dated 2026-10-11, with 3 open issues.

Are there alternatives to mailroom?

+

Yes. On ClaudeWave you can browse similar subagents at /categories/agents, sorted by popularity or recent activity.

Deploy mailroom to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: darrylmosher/mailroom
[![Featured on ClaudeWave](https://claudewave.com/api/badge/darrylmosher-mailroom)](https://claudewave.com/repo/darrylmosher-mailroom)
<a href="https://claudewave.com/repo/darrylmosher-mailroom"><img src="https://claudewave.com/api/badge/darrylmosher-mailroom" alt="Featured on ClaudeWave: darrylmosher/mailroom" width="320" height="64" /></a>

More Subagents

mailroom alternatives