We've spent the past two years building Atomic Mail, a privacy-focused email provider with end-to-end encryption. Along the way it became obvious that AI agents are going to need a way to talk to people and to each other, the same way humans do over email. So we pointed our email infrastructure at that problem instead. This is what we built, why, and what broke along the way.
Why Email, and Why Agents Need a Different Kind of Signup
Email is older than HTTP and carries decades of legacy baggage, but it's also one of the most powerful communication layers ever invented – decentralization is built into the protocol itself.
What's actually different for agents isn't the wire protocol. It's everything around it. A human signs up with a phone number or a CAPTCHA and picks one inbox from a webmail UI. An agent can't do either, and it doesn't want one inbox — it wants to spin up and tear down as many as a task needs, with no human clicking a confirmation link. So the signup, the auth, and the API had to be rebuilt around that:
- Proof-of-work instead of CAPTCHA
- Short-lived capability tokens instead of a login session
- JMAP as the only interface instead of a bespoke REST wrapper
The Stack
It's a set of in-house microservices with no third-party APIs in the critical path: our own IMAP/JMAP core, an MTA, an anti-spam layer, a message queue, blob storage, an account database, and DNS caching, all self-hosted and glued together with our own auth and proxy layer. We're spread across a couple of different providers, with our own IP pool that we warm ourselves.
We're deliberately not naming exact components and versions here — a public, precise stack list is a ready-made target list for anyone probing for known CVEs. Happy to go deeper on any specific piece in the comments if you're building something similar.
Why JMAP over a custom REST API
Four reasons. It fits the API-first way agents already work. It's well represented in training data, so most models can write JMAP out of the box without ever reading our docs. It's a standard, so we get to reuse years of research from people who already thought hard about what an email API should look like. And it de-risks integration for anyone building on us — they know they can swap us for any other JMAP-compatible vendor whenever they want. You never get that with a bespoke REST API.
Why proof-of-work for signup
The goal was full autonomy: an agent should be able to register an inbox and start communicating with zero human in the loop, while we stay protected from bot farms. PoW (scrypt) makes both true at once. It caps how many accounts an attacker can run in parallel, and it pairs with an internal reputation system that suspends misbehaving accounts fast. Neither works well alone; together they do.
Why a tiered JWT chain
Challenge → session → capability. This lets us authorize every request and trace it back to the original sender, while balancing reaction speed against how often we have to issue a fresh PoW challenge (capability tokens live two minutes).
Three Things That Broke, and What We'd Tell You to Avoid
The single hardest part wasn't the code, it was the architecture. Email is old enough that there's always some SMTP edge case the RFC doesn't describe properly, so whatever you build on has to be battle-tested — but battle-tested usually means old, and we needed something modern enough for bot-era throughput, where bots send (and get spammed at) far more often than humans ever did.
1. Kafka does not like big messages
Emails can be large (our cap is 10MB); Kafka wants payloads under ~100KB. So we split every message: lean header into Kafka, rich body into S3 (SeaweedFS, better optimized for our payload size and access pattern), and the consumer reassembles on the other side.
2. JS Kafka consumers will betray you silently
kafkajs isn't really maintained anymore and everyone's on some random fork. Ours kept disconnecting from the cluster at random — no error, no log, nothing. If you do this, add explicit error handling and retry logic to your consumer from day one.
3. Check your IP reputation before you warm anything
On paper IP warmup looks simple. In practice, your provider may hand you an address that's already in spam abuse directories, and you basically can't recover a dirty IP, especially early on. It's cheaper to buy a fresh subnet or move providers than to fight a bad reputation.
Where We Are Right Now
We're in open alpha:
- ~1,000 activated accounts (registered plus at least one send or read), growing 10-30/day
- Average inbox sends and receives roughly two emails each
- Our launch post on X did 250k+ views and brought in ~600 users on day one
- #2 Product of the Day on Product Hunt
- First open-source contribution: a Docker-based inbox watcher that pipes inbound mail into Telegram
On integrations: for personal agents we ship both an AgentSkill and a stdio MCP server, so you can use Atomic Mail in Hermes or Claude equally well.
MCP
{
"mcpServers": {
"atomicmail": {
"command": "npx",
"args": ["-y", "@atomicmail/mcp"]
}
}
}
Agent Skill
# Register
npx --package=@atomicmail/agent-skill atomicmail register --username "myagent"
# Send a JMAP request inline
npx --package=@atomicmail/agent-skill atomicmail jmap_request \
--ops '[["Mailbox/get", {"accountId": "$ACCOUNT_ID"}, "m0"]]'
# Send a JMAP request from a preset file
npx --package=@atomicmail/agent-skill atomicmail jmap_request --ops-file send_mail.json
# Ask for help
npx --package=@atomicmail/agent-skill atomicmail help
If you're building your own agent, or working outside JS/Python, you can hit the API directly with any existing JMAP client plus scrypt PoW auth. For workflows, we've integrated with Dify via custom nodes, with more on the way.
One detail people seem to enjoy: our site serves two versions. Humans get the graphical landing page; anything without a browser (an agent, or plain curl) gets a much deeper text version with the instructions an agent needs to set up and run an inbox. You can literally tell your agent to read atomicmail.ai and set up an inbox for you.
Honest Pros and Cons
The upside of an all-in-house, MIT-ish-licensed stack: infra costs us very little, we're independent from third-party mood swings, and we can adapt or add features whenever we want. PoW gives personal agents the easiest possible entry point — fully autonomous, as many inboxes as you like.
The downside: PoW requires client-side computation, which shrinks our integration surface. A remote MCP makes no sense with PoW, and we can't integrate into ChatGPT because their integrations run on their hardware and they (rightly) won't run our PoW there. Our architecture is tuned hard for personal AI agents and weaker for other shapes of usage — a real tradeoff we accepted on purpose.
Worth being upfront about too: agentic inboxes don't have end-to-end encryption yet, unlike our regular Atomic Mail product. It's on the roadmap, not shipped today.
What's Next
- More integrations, ideally native ones
- Custom domains, so devs can build their own branded products on top of Atomic Mail Agentic
- End-to-end encryption for agent inboxes
- Safety features: anti-prompt-injection mechanisms, a read-only mode for agents
Now the AMA part. We'd genuinely love to talk about any of this. Happy to give advice to anyone building for AI agents or building an ESP from scratch, and just as happy to hear honest feedback or where you think we got it wrong. If you want to poke at it yourself before asking:
atomicmail.io/agents
https://github.com/Atomic-Mail/atomic-mail-agentic
Top comments (0)