Summary
- RFC 9738 lets an IMAP server return
OKafter processing only the newest bounded tranche of a SEARCH, FETCH, STORE, MOVE or UID EXPUNGE request;MESSAGELIMITcarries the incompleteness signal and a low-water UID. - COPY and MULTIAPPEND keep their atomic contract and perform no work when the request is too large, while other command families may produce real partial effects that the client must continue and reconcile.
- The advertised ceiling is a coordination value, not proof of a currently enforced hard limit, universal client support, a frozen mailbox or a complete user-visible outcome.
The server returned a thousand FETCH responses and ended with OK. Every response was valid. Every returned flag belonged to a real message. The command still had not covered the requested set.
That is not an error hidden behind a success word. It is the state RFC 9738 was designed to make explicit. An IMAP server that advertises MESSAGELIMIT=1000 can process the highest one thousand UIDs from a larger request, return the lowest UID it reached, and complete the invocation with a tagged OK [MESSAGELIMIT 1000 …]. The work reported by that invocation succeeded. The older portion did not run.
Many operational systems have only one field for the result: success or failure. RFC 9738 shows why that field is insufficient. The correct record needs at least two dimensions: whether the invocation succeeded, and whether it exhausted the population the client intended to process.
A limit on one command is not a limit on the mailbox
MESSAGELIMIT=N is a per-command processing ceiling. It applies to SEARCH, FETCH, STORE, COPY and MOVE, including UID variants, as well as APPEND and UID EXPUNGE. SAVELIMIT=N is narrower and applies when the server limits only COPY and APPEND families. The RFC says the advertised value should not be below one thousand.
None of those statements says the mailbox contains at most N messages. The number is not a retention policy, storage quota, message-size limit or promise about search cardinality. For SEARCH, it bounds messages examined, not messages that happen to match. A query can inspect one thousand messages and return only seven matches; those seven are not evidence that the remaining requested messages were examined and failed the predicate.
That distinction matters wherever a SEARCH answer becomes a count, compliance report or input to a later action. A plausible number is especially dangerous because it does not look truncated. A dashboard can show 37 unread messages with perfect arithmetic while silently excluding every message below the returned boundary.
When MESSAGELIMIT is returned, RFC 9738 requires the server to process from highest UID to lowest UID. The optional final value is the lowest UID processed in that invocation. It is a useful continuation seam. It is not a count, not a snapshot token, not proof that a message bearing that UID will still exist, and not permission to forget the selected mailbox's UIDVALIDITY.
OK describes the invocation, not the original intention
For FETCH, the server can emit the data for the newest tranche and then a tagged OK carrying the limit and low-water UID. For SEARCH, it can emit the matches found while examining that tranche and use the same form. For STORE, the flags on that tranche have actually changed. For MOVE, messages in that tranche can already have been copied to the destination and expunged from the source. For UID EXPUNGE, the selected deleted messages in the tranche can already be gone.
These are not previews. They are effects.
The client therefore cannot handle MESSAGELIMIT by merely changing a progress label. It must retain the original requested set, the exact command family, the processed UIDs it observed, the returned boundary and the next legal request. It must continue until a response arrives without the limit code, or until NO or BAD makes the unfinished remainder explicit.
Continuation differs by command. A UID STORE request must be narrowed so it no longer includes the returned lowest UID. UID MOVE may be repeated with the same UID set because the already moved messages have been expunged from the source; sequence-number MOVE must be updated because expunges change sequence numbers. UID EXPUNGE can repeat the same UID parameter. Treating these as one generic retry algorithm invites duplicated work, skipped messages or action against renumbered sequence positions.
The final tagged status is not the only place where the boundary can appear. If the server also needs to return EXPUNGEISSUED, that code occupies the tagged OK, and MESSAGELIMIT is sent in an untagged NO. A parser that reads only the last line can report clean success while discarding the signal that older messages remain. The complete receipt is the command tag, all untagged responses, returned message data, response codes and final status together.
Atomic commands draw a different line
The same numeric ceiling does not imply the same effect across commands.
COPY and UID COPY are atomic. If the population exceeds the permitted count, the server returns tagged NO [MESSAGELIMIT …] and copies nothing. MULTIAPPEND has the same all-or-nothing property: an oversized group appends no messages. Those commands do not leave a successful newest tranche for the client to close out.
MOVE is deliberately different. It need not be atomic, so an oversized move can change both source and destination for a bounded suffix before returning OK with the limit code. STORE and UID EXPUNGE likewise can leave real partial changes. A monitoring layer that maps every MESSAGELIMIT to “rejected” lies about those effects. One that maps every tagged OK to “complete” lies about the remainder.
The correct operation matrix has three classes: atomic refusal with no effect; successful partial execution with continuation required; and commands exempt from this ceiling. RFC 9738 says a server must not impose the message limit on EXPUNGE, CLOSE or STATUS UNSEEN. Their full-scope behavior is preserved. Even there, a protocol success proves the command result, not downstream disk durability, client synchronization or what a person eventually saw.
RFC 9394's PARTIAL extension adds another important contrast. If a client explicitly requests a PARTIAL range larger than the advertised ceiling, the server refuses the FETCH and does no work. Without that explicit page, a similar FETCH may return a successful implicit tranche. An explicit page contract and an implicitly truncated command are not interchangeable merely because both involve bounded work.
Saved search state can preserve the omission
SEARCHRES lets a client save a SEARCH result under $ for later commands. When a SEARCH succeeds but hits MESSAGELIMIT, RFC 9738 requires the saved result to be truncated as well. The variable contains the matches from the bounded search, not the hypothetical matches from the whole requested range.
That turns incompleteness into state. A later COPY, STORE or another SEARCH that references $ can be perfectly valid over the wrong population. The original warning may have disappeared from the later transcript even though its consequence remains.
Systems that persist saved searches therefore need provenance: selected mailbox, UIDVALIDITY, source query, time, limit value, returned low-water UID and completion state. $ is a convenience handle, not a certificate that its population is exhaustive.
RFC 9738 also defines UIDAFTER and UIDBEFORE to make UID ranges easier to express, especially with SEARCHRES. They help construct the next query. They do not freeze new arrivals, stop expunges, make a missing UID exist or survive a mailbox generation change. A continuation boundary is useful because it is limited; it becomes unsafe when treated as more durable than the mailbox semantics allow.
The advertised number may lead enforcement
The most revealing part of RFC 9738 is its compatibility guidance. Strictly imposing the limit on a client that does not understand it can make a large mailbox look smaller than it is. Old clients can return wrong SEARCH counts, miss older mail or fail COPY. The RFC describes this plainly as abandoning existing clients for large-mailbox operation.
Its transition paths are pragmatic. A server may advertise a limit and initially not enforce it. Clients that understand the capability voluntarily reduce their command size, while older clients continue to work. Later, a server may advertise one value as a soft limit and enforce a higher, undisclosed hard limit. Attempts beyond the advertised value can be logged so operators can observe whether clients have adapted before tightening enforcement.
This means the capability token has two related but distinct roles. It tells compliant clients which bound to honor. It does not independently prove that the server currently cuts every command at exactly that value. Deployment becomes real through client behavior, server enforcement and measured interoperability, not through the appearance of a capability string alone.
That staged approach is not dishonesty. It is a controlled compatibility period, provided the operator retains the difference between the advertised value and the enforced threshold. Trouble begins when metrics combine them. “Commands above N” may mean compliant clients violating the advertised request, legacy clients tolerated under a higher hard ceiling, or traffic observed before strict enforcement. Those populations require different decisions.
Whole-mailbox work needs a closeout ledger
Reliable automation should record the intended population and every invocation that acts on it. For each pass, retain the mailbox identity and UIDVALIDITY, command text, operation class, server capability snapshot, returned UIDs or effects, tagged status, untagged response codes, MESSAGELIMIT value and last UID. Record concurrent arrivals and expunges rather than pretending the mailbox stood still.
At closeout, reconcile at least four populations: messages intended when the job began; messages actually examined or changed; messages that disappeared before they could be processed; and messages that arrived outside the original scope. Any unresolved difference stays visible. Reaching a command without MESSAGELIMIT closes that request chain, but it does not retroactively freeze the mailbox or prove a later client rendered the outcome.
The neighbouring tools should retain their names. UIDBATCHES can produce bounded UID ranges for planning. PARTIAL can request a particular page. MESSAGELIMIT reports the ceiling encountered during command execution. SEARCHRES can retain a result population. QRESYNC can help synchronize change. Combining them may build a good system; collapsing them into a generic “batching” flag destroys the reason each exists.
RFC 9738 is valuable because it refuses a false binary. A server can truthfully say: this invocation succeeded, these were the messages I processed, and your larger intention remains unfinished. Leadership should demand the same precision from every layer above it. OK is one signed page in the record. It is not the end of the book.
Sources
- https://www.rfc-editor.org/rfc/rfc9738.html
- https://www.rfc-editor.org/rfc/rfc9738.txt
- https://www.rfc-editor.org/info/rfc9738/
- https://datatracker.ietf.org/doc/rfc9738/
- https://datatracker.ietf.org/doc/rfc9738/history/
- https://www.rfc-editor.org/errata/rfc9738
- https://www.rfc-editor.org/rfc/rfc9051.html
- https://www.rfc-editor.org/info/rfc9051/
- https://www.rfc-editor.org/rfc/rfc9394.html
- https://www.rfc-editor.org/info/rfc9394/
- https://www.rfc-editor.org/rfc/rfc5182.html
- https://www.rfc-editor.org/info/rfc5182/
- https://www.rfc-editor.org/rfc/rfc5256.html
- https://www.rfc-editor.org/info/rfc5256/
- https://www.rfc-editor.org/rfc/rfc3502.html
- https://www.rfc-editor.org/info/rfc3502/
- https://www.rfc-editor.org/rfc/rfc6851.html
- https://www.rfc-editor.org/info/rfc6851/
- https://www.rfc-editor.org/rfc/rfc4315.html
- https://www.rfc-editor.org/info/rfc4315/
- https://www.iana.org/assignments/imap-capabilities/
- https://datatracker.ietf.org/doc/draft-ietf-extra-imap-messagelimit/
- https://heng.lu/running-code-primary-the-patch-needed-to-preserve-the-internet-original-design/
- https://heng.lu/minimum-initial-specification-localized-future-decision-voluntary-adoption-internet-coordination-system/
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance
