All posts
EngineeringMarch 1, 2026

What Most Email Clients Get Wrong About IMAP

Isaac Hinman

Here's a dirty secret of the email client industry: most modern email clients don't actually use IMAP.

Spark, Superhuman, Edison Mail, and others connect to Gmail using Google's proprietary API. They connect to Outlook using Microsoft's Graph API. They might fall back to IMAP for other providers, but the primary accounts that 90% of their users connect are handled through vendor-specific APIs that have nothing to do with IMAP.

This isn't necessarily wrong. But it explains a lot about why these clients behave the way they do, why they have the privacy characteristics they have, and why building a truly provider-agnostic email client is so much harder than it looks.

Why everyone avoids raw IMAP

IMAP (Internet Message Access Protocol) is the universal standard for email access. Every major email provider supports it. In theory, any IMAP client should work with any IMAP server. In practice, IMAP is one of the most painful protocols to implement correctly.

It's a stateful protocol in a stateless world. IMAP maintains a persistent connection between client and server. You SELECT a mailbox. You're now "in" that mailbox. You FETCH messages. You STORE flags. Every command operates within the context of that selected mailbox state. Modern software architecture is built around stateless, idempotent operations. Background jobs, worker queues, serverless functions: none of these map cleanly onto a protocol that requires you to maintain a long-lived TCP connection with server-side state.

This creates real engineering headaches. If your background sync job crashes halfway through, where do you resume? If two sync processes run concurrently against the same account, they can step on each other's state. If the connection drops (which it will), you need to re-establish the session, re-authenticate, re-select the mailbox, and figure out what changed since you were last connected. IMAP's UIDVALIDITY mechanism is supposed to help with this, but in practice it's a blunt instrument that sometimes forces a complete resync of the entire mailbox.

Providers don't follow the RFCs. The IMAP specification (RFC 3501 and its extensions) describes how servers should behave. In reality, almost every major email provider deviates from the spec in ways that break naive implementations.

Gmail's IMAP implementation is particularly creative, because Gmail doesn't have folders in the traditional sense... it has labels. A single message can have multiple labels, which means it can appear in multiple IMAP "folders" simultaneously. When you delete a message from one folder, you're removing a label, not deleting the message. The same message has different sequence numbers in different folders but the same UID. The \Deleted flag doesn't mean what the RFC says it means. Gmail's [Gmail]/All Mail folder contains every message, which means a naive sync that processes all folders will download every message multiple times.

Yahoo Mail has its own quirks. Its IMAP implementation has historically been slow, unreliable, and missing standard extensions that most clients depend on. IDLE support (the IMAP command for push notifications) is inconsistent. Search capabilities are limited. Connection limits are aggressive.

iCloud Mail follows the spec more closely than most, but has its own performance characteristics and timeout behaviors that differ from what the RFC implies.

Microsoft's Exchange/Outlook IMAP implementation adds proprietary extensions while simultaneously not supporting some standard ones. The behavior of MOVE vs COPY + DELETE, the handling of special-use folders, the way flags are synchronized: all of these have provider-specific edge cases.

IMAP extensions are a minefield. The base IMAP protocol is limited. Important features like message threading, push notifications, and efficient sync require extensions: CONDSTORE, QRESYNC, IDLE, THREAD, SORT, MOVE, SPECIAL-USE, and dozens more. Not every server supports every extension. Some servers advertise extensions they don't fully implement. Some extensions interact with each other in ways that the individual RFCs don't address.

Building a robust IMAP client means implementing graceful fallbacks for every extension. If the server supports CONDSTORE, use it for efficient change detection. If not, fall back to comparing flag states manually. If the server supports QRESYNC, use it for fast resync after disconnection. If not, do a full UID comparison. If the server supports IDLE, use it for push notifications. If not, poll on an interval. Every combination multiplies the test matrix.

Why the API shortcut is tempting

Compare all of this to the Gmail API. Google gives you a clean REST interface: you make HTTP requests, you get JSON responses. Pagination is handled, search is handled, labels are first-class citizens, and push notifications work through Google Cloud Pub/Sub. There's no connection state to manage, no protocol quirks to work around, no RFC compliance issues to debug.

The Microsoft Graph API offers similar convenience for Outlook accounts. Clean REST endpoints, OAuth authentication, well-documented behavior.

From an engineering perspective, using these APIs is the rational choice. You ship faster. You have fewer bugs. The experience for Gmail and Outlook users is better.

But there are two significant costs.

Cost 1: Your emails go through their servers

This is the privacy issue. When an email client uses the Gmail API or Microsoft Graph API, they typically need to run a backend service that authenticates with Google or Microsoft on your behalf. Your OAuth tokens live on their servers. Your email data flows through their infrastructure. They can read your emails. They can analyze your emails. They can store your emails.

Spark is transparent about this: their server-side infrastructure powers features like Smart Inbox and team collaboration. Superhuman's infrastructure similarly processes your email to deliver its speed and features.

For some users, this is an acceptable tradeoff. For others, it's a dealbreaker.

When you use raw IMAP, no third party needs to integrate with proprietary APIs on your behalf. Even if email data passes through a sync layer, what matters is how that data is treated: is it scanned, analyzed, or monetized? With IMAP and proper encryption, your emails can be synced without ever being readable by the service handling them.

Cost 2: Provider lock-in

An email client built on the Gmail API works great with Gmail. It works great with Outlook if they also integrate the Graph API. But what about Yahoo? What about iCloud? What about Fastmail, ProtonMail Bridge, your company's Exchange server, your university's email, or any of the thousands of other email providers that exist?

For each new provider, you either need to integrate another proprietary API (if one exists) or fall back to IMAP anyway. Most clients choose to simply not support these providers, or support them poorly.

This is why Superhuman only works with Gmail and Outlook. It's not a technical limitation of email. It's a business decision about which APIs to integrate.

IMAP is the universal protocol. If you build on IMAP, you support every email provider by default. Your users can connect their Gmail, their work Exchange account, their personal Fastmail, and their old Yahoo address, all in the same client, all using the same sync engine.

How Marco handles IMAP

Marco is built on raw IMAP. No Gmail API. No Graph API. IMAP connections to your email provider, using the open standard.

This was a deliberate architectural choice, and it was significantly harder than taking the API shortcut. Here's how we handle the challenges.

Stateful protocol, stateless sync. Marco's sync engine is designed to be idempotent even though IMAP isn't. Each sync operation establishes a connection, does its work, and cleans up. If a sync fails partway through, the next run picks up where it left off using local state tracking, not IMAP session state. We use CONDSTORE and QRESYNC where available to minimize the work each sync needs to do, and fall back gracefully when these extensions aren't supported.

Provider quirks are handled per-provider. Marco maintains a compatibility layer that adapts its behavior based on which provider it's talking to. Gmail's label model, Yahoo's timeout behavior, iCloud's performance characteristics: these are all accounted for in the sync engine. When we encounter a new quirk (and we still do), we add it to the compatibility layer and push an update.

Everything is local. Because Marco syncs via IMAP to your device, all your emails are available locally. Search is a local database query, not an IMAP SEARCH command. This is faster, more reliable, and works offline. It also means we don't need a server-side component that processes your email.

The hard path is the right path

Building on raw IMAP is harder. It takes longer. It means dealing with a protocol that was designed 40 years ago for a world that no longer exists. It means testing against dozens of email providers, each with their own interpretation of the specification.

But it's the right choice for an email client that prioritizes privacy and universal compatibility. Your emails should go directly from your provider to your device. Your email client should work with every email provider, not just the two biggest ones. And you shouldn't need to trust a third party with your inbox just to get a decent user experience.

That's what Marco is built on. Raw IMAP. No proprietary APIs. No scanning or monetizing your data. It's harder to build. It's better to use.