It started with a question about passwords
I couldn't find an existing Runbox connector, and I wasn't comfortable putting an email credential into an assistant's configuration file. The open-source IMAP servers I did find wanted my password sitting in plain text in that file. The usual advice was to make an app password instead, which to me just seemed to be shifting the problem around: now that password would be sitting there, and anyone who got it could pretend to be the app.
So I asked a different question. Could an assistant work with my mail without the password ever living on the device doing the asking?

There was a second problem underneath the first one. My inbox was just a chronological list: roughly 5,500 messages of verification codes, deals that had expired months before, and important mail buried in between. Runbox's search is mostly broken, so finding anything specific meant opening Outlook. And sorting mail into folders meant Runbox's filter page, one hand-built rule at a time. Runbox offers no Sieve and no API, so this form was the only built-in way to do it:

What I had to work within
- One account. Mine. Nobody else should be able to get in, even by accident.
- My phone and my desktop. A local server on one computer wouldn't do; it had to run somewhere both could reach.
- No credentials on any device. Not the mailbox password, not an app password, and not a Cloudflare token either. Keeping secrets off devices is the entire point, so the fix for any problem can't be "put a key in a file."
- A runtime that isn't Node. Cloudflare Workers can't run the usual mail libraries, which turned out to matter a great deal.
What I built
A small server on my own subdomain that sits between the assistant and my mailbox. The assistant asks it to do something; it checks who's asking, does the work over IMAP, and answers. Here's the whole path:
Step 01
Ask from anywhere
Claude or ChatGPT, on my phone or my desktop, asks the server to do something with my mail.
Step 02 Gate
Identity check
GitHub sign-in, with exactly one account on the allowlist. Everyone else stops here.
Step 03
The password stays in Cloudflare
An encrypted secret, read only at the moment the server needs it. Once it's set, nobody can read it back, including me.
I have never had to give my password to the AI model, and I never will.
Step 04
Plain mail protocols, built by hand
Workers can't run the usual mail libraries, so the IMAP connection to Runbox was written from scratch.
Step 05 Gate
Preview before touching mail
A dry run reports what every rule would do and moves nothing.
Not right? Revise the rule and preview again, back to step 1.
Dry runs are optional, but I highly recommend them. A dry run shows, message by message, what the live run will do, so I can check it before anything moves.
Step 06
Runs without me
Every hour, a sweep with 289 rules sorts new mail. The rules can move or flag, but they can never delete. Then a separate retention pass sends aged mail to Trash, and permanently deletes only what has already waited 30 days there.
It's not perfect, but nothing goes straight from a folder to deleted. Mail waits 30 days in Trash first, so no single run can delete something by accident.
Where the judgment stays mine
If I had to put the whole project in one sentence, it's something I figured out along the way: don't let the model make the decisions, but let it gather all of the facts that you need in order to make your own decision.
The rules are that sentence in practice. I asked Claude Code what it thought should be routed where. My effort was signing off on what it picked, pointing out the ones I'd do differently, and refining others. That's how 289 rules came to exist, and every one of them passed through me.
A few things are deliberate:
- Rules can move mail or flag it. They can't delete it. There's no delete action to give them, and that was a choice.
- Any rule change can get a dry run first, and I use it. It reports what each rule would do without touching a single message.
- Retention is a separate process, and its settings change only through a pull request I merge. Advertisements go to Trash after 30 days, and shipping notices after 90. Receipts stay forever. Anything flagged stays, whatever folder it's in.
And when a rule gets something wrong, I fix it while I'm looking at the email. If an advertisement lands in Receipts because of some loophole, I tell the model what I just got and what the rule should do instead, and that's the whole process. I don't go through anybody else's interface to do it.
What it does now, and what it hasn't done yet
It works in claude.ai, in ChatGPT, and in the Claude app on my phone. Because it's an MCP server, it isn't tied to one assistant: it works with any AI app that supports remote MCP servers with OAuth sign-in. The first big sort filed about four fifths of that 5,500-message inbox on its own. Now new mail sorts itself every hour, and when I want to know when someone last wrote and what they asked, I can search by sender, subject, or whatever I happen to remember from the message, instead of scrolling through pages of email.
It isn't perfect. Every so often a message lands in the wrong folder, an advertisement in Receipts, say, and I tell the model the refinement it needs.
Retention's first run moved 2,376 messages to Trash. Trash empties itself after 30 days there, so the first real deletion can't happen before October 24, 2026. That hasn't happened yet. When it does, and it deletes only what it should, this becomes version 1.0. Sending from one of my own-domain addresses is built but hasn't been tried for real yet either.
What I didn't know when I started
I had no idea what I was doing or what I was getting into. I just had a vague idea of where I wanted it to finish.
It started as an "out of curiosity" question, and I was in no hurry. On the first day, I didn't know whether having my own domain on Cloudflare counted as having my own server. (It did, and that one answer is why this runs remotely instead of on one computer.) I typed git pull in a folder that wasn't a git repository. I asked whether I needed to rebase my pull.
The catching went both ways, starting on day one. My Outlook screenshots caught a wrong default in the code Claude had written. Claude caught me about to type my real password into the one settings file that gets committed to the repository. And the first real test failed with Invalid login or password, which turned out to be good news: it meant Runbox was answering a mail client written from scratch. The actual problem was a master switch on Runbox's App Passwords page. By the time the folder list came back, it was past midnight.
Two months later there are 17 tools, and I was there for the creation of all of them. I learned how IMAP servers actually work, how Cloudflare Workers and their secrets work, and how my own domain's email is put together. I never gave my password to the AI, not once. It went into a local file that git ignores, and then into an encrypted secret on Cloudflare. Once it's set, nobody can read it back, including me.
Runbox MCP
17 tools that let any MCP-compatible AI search, sort, and automate a Runbox mailbox
17 tools
Folders 3
Manage mailbox folders
list_foldersSee every mailbox foldercreate_folderAdd a new folderdelete_folderRemove a folder (guarded)
Messages 3
Find, read, and send
search_messagesFilter by sender, date, textread_messageOpen headers and bodysend_messageSend mail via SMTP
Triage 3
Act on selected messages
move_messagesFile selected messagesmark_messagesRead, unread, or flagdelete_messagesSend selected to Trash
Bulk 3
Act on everything that matches
move_matchingFile all matches at oncemark_matchingMark or flag in bulkdelete_matchingBulk-trash by filter
Automation 5
Rules and retention
list_rulesShow rules in run orderadd_ruleAppend a move/mark ruledelete_ruleRemove a rulerun_rules_nowSweep now, dry run firstrun_retention_nowAge out old mail
Partway through, I found out a commercial service called SaneBox already does much of this, which is why I'm not going to sell it. But it can't give me what I actually built: an IMAP controller on my own AI account that I change by talking to it. It also couldn't work without my password. Runbox has no OAuth, so any outside service would need my password on its servers, which is the exact thing this started out refusing to do.
The confidence carried over into other projects, too, like my meal planner, which has a secret API key of its own. It just helped me a lot.
If you want to build this way, have an idea of where you want to go, but don't think you need everything planned out from A to Z before you start. Let the conversation shape it. As Bob Ross would put it, more or less, sometimes a happy little tree turns out to want to live right there. You may change your mind. You may find things you didn't know were possible. Just remember whose decision it is.