The IMAP We Think We Know
For most developers, IMAP is a straightforward tool: connect to a server, select a mailbox, and fetch messages. It’s celebrated for its server-side storage, which allows multiple clients to see the same state of an inbox—read, unread, flagged, or filed
away. This synchronization is IMAP’s superpower. When building a basic email client, the initial steps seem simple enough. The protocol identifies messages in a folder with numbers, making it easy to request 'messages 1 through 10'. This is where the trouble begins, because not all numbers are created equal.
The Hidden Detail: Sequence Numbers vs. UIDs
The critical detail most engineers skip is the fundamental difference between a message sequence number and a Unique Identifier (UID). A sequence number is temporary and relative; it represents a message's position in the current session. If you have 10 messages, they are numbered 1-10. If you delete message #3, what was #4 becomes #3, what was #5 becomes #4, and so on. The sequence numbers are reordered to fill the gap. Relying on these shifting numbers to track which emails a user has seen, moved, or deleted is a recipe for disaster. This is the trap.
Why Sequence Numbers Are a Trap
Imagine your application fetches messages 1-50. The user deletes an email. In the background, the server re-indexes the mailbox. The app, unaware, then asks for message 51, but because the sequence has changed, it might accidentally skip a message or re-download one it already has. This leads to common, frustrating bugs: emails that won't stay marked as 'read', messages that reappear after being deleted, or entire batches of new emails being missed during a sync. It creates an unstable and unreliable user experience because the client's map of the mailbox is built on quicksand.
The Power of UIDs for Reliable Syncing
The correct way to manage messages is with UIDs. Unlike sequence numbers, a UID is assigned to a message and is guaranteed to be stable and unique within a specific mailbox folder for that session. The specification even states it 'SHOULD NOT' change between sessions. When you build an application that tracks messages by their UIDs, you are using a permanent address, not a temporary seating assignment. Even if other messages are deleted or moved, a message's UID remains the same. To make this even more robust, IMAP provides a 'UIDVALIDITY' value for each folder. If that value changes, it's a signal to the client that the UIDs have been reset and it needs to resync the mailbox from scratch—a crucial check for data integrity.
Bonus Tip: Stop Polling with IDLE
Another powerful but underused feature is the IMAP 'IDLE' command. Many applications resort to polling—checking the server every few minutes for new mail. This is inefficient, consuming server resources and draining battery on mobile devices. The IDLE command allows a client to tell the server, 'I'm waiting'. The server then keeps the connection open and sends a notification the instant a new message arrives, effectively enabling push notifications. Combining UID-based tracking with the IDLE command creates a modern, efficient, and stable email experience—the kind users have come to expect.













