Summary

  • RFC 5232 lets Sieve build and test a flag set for the message currently being processed, then attach flags to the copy delivered by keep or fileinto.
  • That request is not a general edit to the IMAP store: unsupported permanent flags must be ignored without turning their rejection into a script runtime failure.

The mark travelled with a delivery decision

An incoming message can carry a subject line, a sender, a route through a delivery system and eventually a place in a mailbox. An IMAP flag belongs to a different layer: it is state associated with a message in a store. RFC 5232 connected Sieve filtering to that state, but it did not erase the boundary between deciding how to deliver one message and rewriting a mailbox at large.

Published in January 2008, RFC 5232 added the imap4flags Sieve capability. It required four actions or tests—setflag, addflag, removeflag and hasflag—plus a :flags argument for keep and fileinto. The first three manipulate a set; the test can ask whether a named flag is present. The delivery argument carries a set of flags with the current message’s copy as it is filed.

That set has an execution-local life. At the beginning of a script run, the extension’s internal flag variable is empty. setflag replaces its contents; addflag accumulates; removeflag takes selected names out. hasflag can inspect the current set. If the separate Variables extension is available, scripts can keep named sets too. Without it, an explicit variable name is an error, but the internal set remains available. Flags are case-insensitive words, and a script cannot rely on the interpreter to preserve their order, spelling case or duplicate entries.

The important hand-off happens at delivery. A keep or fileinto action with :flags uses the list supplied there for the stored copy. Without :flags, the action uses the current internal set. That same set applies to implicit keep—the default disposition when no explicit delivery action has replaced it. A script may therefore add a marker in one branch and let a later delivery action carry it, or supply an explicit list at the point of filing.

But RFC 5232 names the message in the current Sieve execution, not any message the user can select from a mailbox. The extension explicitly does not authorize setting flags on an arbitrary message already in the IMAP store. Nor does it affect a separate message created as a side effect of another action. It is a delivery-time hook, not an IMAP-wide mutation API.

The receiving mailbox is a second boundary. :flags says which flags should accompany the delivered copy; it cannot make every target store support them. The interpreter must ignore flags that the mailbox cannot store permanently. Crucially, that inability must not be promoted into a Sieve runtime failure. The RFC's example makes a fileinto carrying an unstoreable \Deleted flag equivalent to the same fileinto without that request. IMAP defines \Deleted as a mark for later expunging, not proof of physical erasure, so neither the flag request nor the rule itself is a deletion receipt.

This is why “the rule set the flag” can compress too many claims. A script may have evaluated a branch; the interpreter may have formed a flag list; a delivery action may have requested it; the mailbox may have accepted only a subset for permanent storage; and a client may later present the resulting state. Each is a separate observation. RFC 5232 does not dictate whether the interpreter connects to IMAP as a client or accesses the mailstore directly, so the deployment surface can differ while the extension's stated semantics remain the same.

There is even a rule for competing delivery actions. If duplicate-message elimination combines multiple keep or fileinto actions, RFC 5232 says the last flag-list value must win. The final stored copy is not necessarily a union of all branch-local intentions. Policy authors must inspect the order and the actual disposition algorithm rather than infer a message's final markers by collecting every addflag seen in the script.

The January 2008 extension belongs to the Sieve family, alongside the base language in RFC 5228, named variables in RFC 5229 and relational tests in RFC 5231. Those neighboring standards explain how a script parses, stores and tests values; they do not change RFC 5232's delivery boundary. Later IMAP4rev2 in RFC 9051 distinguishes permanent from session-only flags and deprecates \Recent, reinforcing that a requested marker and durable state are not synonyms. The standard records a protocol contract, not evidence that any named server implemented it or that a message reached a reader with a particular badge.

Sources