IMAP: check each pipelined command when it runs #237

Merged
jcoffey-dev merged 1 commits from fix/imap-pipelined-select into main 2026-10-29 19:02:49 +00:00
1 Commits
Author SHA1 Message Date
jcoffey-dev 6bfee4638d IMAP: check each pipelined command when it runs
ci / fork-checks (pull_request) Skipped
ci / build (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 10m6s
Every command in a read buffer was checked against the session state
before any of them ran. A SELECT pipelined with the FETCH or STORE after
it got "BAD No mailbox is selected" for those, though RFC 9051 allows
pipelining them. The other way round was worse: with a mailbox selected,
UNSELECT (or CLOSE, or UNAUTHENTICATE) followed in the same write by
FETCH let the FETCH through, and its handler then found no mailbox and
panicked on unreachable!(), dropping the connection.

Each command is now checked just before it runs, in the state the
commands before it left. Commands batched with the one before them
(FETCH, STATUS, CREATE, DELETE) are each checked, and counted against
the rate limit, on their own; one that isn't allowed is answered and
left out, and a refusal that ends the session still ends it. STARTTLS
still returns before anything pipelined after it runs.

The pipelining test now sends SELECT with STORE and FETCH in one write,
and expects BAD for a FETCH pipelined after UNSELECT. On the old code it
fails (the session panicked); with this change the imap suite passes.
2026-10-29 11:48:59 -07:00