UID alone is not a permanent identity

RFC 9051 defines UIDs as unique identifiers within a mailbox and ties their persistence to UIDVALIDITY. The pair matters. A stored UID of 4821 from one validity epoch is not guaranteed to refer to the same logical message after UIDVALIDITY changes. A reply system that persists only “last UID” has therefore lost enough context to know where it is. The safe cursor includes mailbox identity and UIDVALIDITY, not just an integer.

Check UIDVALIDITY every time the mailbox is selected

When the worker SELECTs or EXAMINEs INBOX, capture the server’s UIDVALIDITY response before issuing incremental searches. Compare it with the value stored alongside your cursor. If they match, normal UID-based incremental processing can continue. If they differ, stop the incremental path. Do not “guess” that the new UIDs probably continued upward. The specification uses UIDVALIDITY precisely so clients can detect when old UID assumptions are no longer valid.

Invalidate cache before processing new UIDs

Mark any cache keyed only by old mailbox UIDs as stale: processed-message set, thread mappings, attachment references, or reply classifications. This does not necessarily mean deleting business records. Your CRM can keep the fact that a prospect replied; what must be invalidated is the mapping that says IMAP UID 1742 is the source message. Preserve stable fields such as Message-ID, sender, recipient, date, and your own campaign identifiers so the resynchronization can reconnect mailbox data to application state.

Resynchronize with a bounded window

For a small outbound mailbox, a practical recovery is to scan a bounded recent window—by internal date or another server-supported search—then deduplicate using durable message identifiers and application state. The window should comfortably cover the period since the last known successful poll plus clock uncertainty. Avoid downloading the entire mailbox if years of mail are present. The goal is to rediscover replies that may have arrived around the migration without treating every historic message as new.

Use Message-ID as evidence, not as the IMAP cursor

RFC 5322 recommends Message-ID for message identity and reply threading, and it is useful for deduplication across a UID reset. It is not a substitute for IMAP synchronization by itself because malformed or duplicate identifiers can exist. Combine server state and message headers: UIDVALIDITY+UID for efficient mailbox traversal, Message-ID/In-Reply-To/References for logical message relationships, and your own database keys for campaign state. Each layer solves a different problem.

Guard against duplicate side effects during resync

A recovery scan will often rediscover messages the application already processed. Classification can be repeated; side effects should not. Before canceling follow-ups, creating CRM notes, or notifying a salesperson, check whether that logical reply has already produced the action. Use a deterministic event key such as mailbox account + normalized Message-ID + action type when available. UIDVALIDITY changes should cause a rescan, not a second wave of customer-facing workflow events.

Log the migration as an infrastructure incident

Store old UIDVALIDITY, new UIDVALIDITY, first detection time, mailbox name, provider, and resync window. If the change coincides with a provider migration or mailbox restore, attach that context. The next time a cursor anomaly occurs, you can distinguish a normal mailbox reconstruction from a programming bug. A small team benefits from this because otherwise a silent skipped-reply failure may be noticed only when follow-ups reach people who already answered.

Test the failure mode intentionally

In staging, simulate a UIDVALIDITY change by replacing the stored value while leaving old UIDs in the cache. The worker should refuse incremental processing, trigger resynchronization, deduplicate previously handled messages, and continue with a fresh cursor only after the new epoch is established. This is a better test than assuming the edge case will be rare. Mailbox migrations, restores, or server behavior can make it real, and reply cancellation is too important to depend on an untested happy path.

Design the resync path before you ever see a UIDVALIDITY change

RFC 4549 is explicit that when a mailbox’s UIDVALIDITY differs from the cached value, cached UIDs for that mailbox are no longer valid and pending actions referring to those UIDs must be discarded or treated as failed. A reply detector should therefore persist the pair `(mailbox, UIDVALIDITY, last processed UID)`, not only the last UID. On selection, compare the server’s value before running an incremental search. If it changed, stop normal cursor processing immediately so an old UID cannot be mistaken for a different message in the new UID namespace.

The recovery scan should be bounded by business evidence rather than by an arbitrary “fetch everything” response. Search a recent date window that comfortably covers open outbound conversations, fetch Message-ID/In-Reply-To/References and sender fields without triggering side effects, and run the same idempotent correlation logic used for normal ingestion. Deduplicate downstream actions with stable conversation or message keys because the rescan may rediscover replies processed before the cache was invalidated. After reconciliation, store the new UIDVALIDITY and a fresh high-water UID. Finally, test this branch with a synthetic mailbox fixture; rare synchronization code that has never been exercised is exactly where duplicate CRM updates and missed follow-up cancellations tend to appear.

Field checklist

  • Persist UIDVALIDITY with every mailbox UID cursor.
  • Compare UIDVALIDITY immediately after SELECT or EXAMINE.
  • Invalidate old UID mappings when the value changes.
  • Rescan a bounded recent window and deduplicate with stable message evidence.
  • Make CRM and follow-up side effects idempotent during resync.
  • Add an automated test for UIDVALIDITY mismatch recovery.

Primary sources

Standards and provider policies can change. These links are the reference points used for this field note.

  1. RFC 9051 — IMAP4rev2IETF / RFC EditorMailbox flags, UIDs, BODY.PEEK and IMAP4rev2 behavior.
  2. RFC 4549 — Synchronization Operations for Disconnected IMAP4 ClientsIETF / RFC EditorOperational guidance for UIDVALIDITY checks, cache invalidation and mailbox synchronization.
  3. RFC 5322 — Internet Message FormatIETF / RFC EditorMessage header structure, Message-ID, In-Reply-To and References threading fields.