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.