From 212f0b803ba788fbffbda79e04b08e3aa7fa050a Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 29 Jul 2026 23:01:20 +0200 Subject: [PATCH] Document completed IMAP IDLE tests --- contrib/testing/README.md | 5 ++++ docs/imap.md | 15 +++++++++- docs/release-testing-0.7.md | 2 +- docs/test-evidence/0.7-r1.md | 54 ++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/contrib/testing/README.md b/contrib/testing/README.md index 06aafac..757e988 100644 --- a/contrib/testing/README.md +++ b/contrib/testing/README.md @@ -75,6 +75,11 @@ one-off files in `/tmp`: CREATE/SELECT/CLOSE/DELETE cycles in one authenticated session. It guards against exhaustion of the Store's fixed watch table when the last watcher leaves a collection. +- `imap-idle-check.py` verifies RFC 2177 in authenticated and selected states. + It pipelines `DONE` in the same TLS record as `IDLE`, rejects an invalid + continuation without losing the session, receives concurrent EXISTS, + FLAGS, and EXPUNGE updates, accepts a deliberately fragmented `DONE`, and + proves that repeated disconnects release selected-folder watches. - `upstream-imaptest-check.py` runs the generic Dovecot ImapTest project against live Bongo IMAPS. Scripted mode stages a selected core, search, `imap-01-11`, `imap-01-12`, `imap-01-13`, `imap-01-14`, or complete diff --git a/docs/imap.md b/docs/imap.md index f4d2146..b0baa31 100644 --- a/docs/imap.md +++ b/docs/imap.md @@ -34,6 +34,18 @@ size remains available. A request that would expose a UTF-8 header receives silently corrupting addresses or invalidating DKIM signatures through an ad-hoc downgrade. +`IDLE` is available after authentication, with or without a selected +mailbox. In selected state, Bongo sends unsolicited EXISTS, FETCH FLAGS, and +EXPUNGE updates as Store changes become visible. The first event check happens +immediately and subsequent checks are bounded; clients do not need to issue a +NOOP to receive them. `DONE` is case-insensitive but must be the complete +continuation line. Any other line completes the outstanding IDLE with tagged +BAD while leaving the connection usable. Bongo also checks data already held +in its application and GnuTLS input buffers before waiting on the network +socket, so a client may safely pipeline `DONE` in the same TLS record. An +IDLE session which reaches the server's 29-minute bound receives BYE and must +reconnect; clients may end and renew IDLE sooner. + AUTH capabilities are generated from the GNU GSASL mechanisms which Bongo has actually enabled. Password mechanisms are advertised only on a TLS connection; unencrypted connections offer STARTTLS and keep LOGIN disabled. @@ -51,7 +63,8 @@ See [Mail storage quotas](quotas.md). Relevant standards are [RFC 9051](https://www.rfc-editor.org/rfc/rfc9051.html), [RFC 3501](https://www.rfc-editor.org/rfc/rfc3501.html), +[RFC 2177](https://www.rfc-editor.org/rfc/rfc2177.html), [RFC 5161](https://www.rfc-editor.org/rfc/rfc5161.html), -[RFC 5198](https://www.rfc-editor.org/rfc/rfc5198.html), and +[RFC 5198](https://www.rfc-editor.org/rfc/rfc5198.html), [RFC 6855](https://www.rfc-editor.org/rfc/rfc6855.html), and [RFC 9208](https://www.rfc-editor.org/rfc/rfc9208.html). diff --git a/docs/release-testing-0.7.md b/docs/release-testing-0.7.md index 71a13ac..10ebd69 100644 --- a/docs/release-testing-0.7.md +++ b/docs/release-testing-0.7.md @@ -182,7 +182,7 @@ review does not mark an open live test as passed. | IMAP-12 | EXPUNGE/UID EXPUNGE preserve sequence and UID semantics | [PASS](test-evidence/0.7-r1.md#imap-12) | | | | IMAP-13 | SEARCH/UID SEARCH sets, flags, dates, sizes, HEADER/SUBJECT/FROM/TO | [PASS](test-evidence/0.7-r1.md#imap-13) | | | | IMAP-14 | SEARCH BODY/TEXT/NOT/OR/CHARSET, ESEARCH RETURN, saved `$` set | [PASS](test-evidence/0.7-r1.md#imap-14) | | | -| IMAP-15 | IDLE notifications and DONE with concurrent delivery/disconnect | | | | +| IMAP-15 | IDLE notifications and DONE with concurrent delivery/disconnect | [PASS](test-evidence/0.7-r1.md#imap-15) | | | | IMAP-16 | ENABLE UTF8=ACCEPT and UTF-8 mailbox/message names | | | | | IMAP-17 | SPECIAL-USE and CREATE-SPECIAL-USE folders | | | | | IMAP-18 | Old-client plain IMAP4 subset without rev1/rev2 assumptions | | | | diff --git a/docs/test-evidence/0.7-r1.md b/docs/test-evidence/0.7-r1.md index 302cc6a..d050bd0 100644 --- a/docs/test-evidence/0.7-r1.md +++ b/docs/test-evidence/0.7-r1.md @@ -3859,6 +3859,60 @@ failed command or skipped capability. The normal build and the strict `-Wall -Wextra -Werror` build each passed all 107 CTest cases. No external mail, public DNS, or Internet recipient was used. +## IMAP-15 + +Result: **PASS** + +Commit `f4af9f8f` was installed as the Gentoo GCC 15.3.0 debug build and +tested on 2026-07-29. Bongo accepts IDLE in authenticated and selected state, +performs an immediate Store event check, and emits concurrent EXISTS, FETCH +FLAGS, and EXPUNGE responses without requiring NOOP. A complete +case-insensitive `DONE` ends IDLE with tagged OK; any other continuation ends +that IDLE with tagged BAD while preserving the authenticated session. + +The audit found that the old loop waited on the raw socket before asking +ConnIO for the continuation. If the command reader had already buffered +`DONE`, or GnuTLS had decrypted it into its record buffer, no new socket +readability event was required and IDLE could wait unnecessarily. ConnIO now +exposes one input-pending check covering both its application buffer and +`gnutls_record_check_pending()`. The IDLE state machine consults it before +`select()`. Native tests cover both buffer sources, invalid and +case-insensitive continuations, immediate timeout, and argument errors. + +The reusable live test used three simultaneous IMAPS sessions. It pipelined +`IDLE` and `DONE` in one TLS write, recovered after an invalid continuation, +observed a message append, flag update, and expunge from a second session, +then completed a deliberately fragmented `DONE`. Ten further selected IDLE +connections were closed without `DONE`; a surviving eleventh connection +selected and idled successfully, proving cleanup of abandoned Store watches: + +```text +IMAP-15 PASS host=127.0.0.1:993 auth-state=yes tls-pipelined-done=yes invalid=bad/reusable notifications=exists/flags/expunge fragmented-done=yes disconnect-watch-cleanup=yes +``` + +The behavior was compared directly with Dovecot 2.4.4 +`src/imap/cmd-idle.c` and `src/imap/imap-commands.c`, and Cyrus IMAP 3.12.3 +`imap/imapd.c`, `imap/idle.c`, and the capability state table. Both reference +servers accept post-authentication IDLE, require a complete DONE continuation, +flush concurrent mailbox changes, and clean up notification state on +completion or disconnect. Dovecot additionally demonstrated the requirement +to process input already pending in the protocol stream rather than relying +only on socket readiness. + +The adjacent live IMAP-01 through IMAP-04, IMAP-07, and 76-cycle Store-watch +tests passed again on the installed build. The complete combined Dovecot +ImapTest 01-through-14 corpus also remained green: + +```text +35 test groups: 0 failed, 0 skipped due to missing capabilities +base protocol: 0/439 individual commands failed +extensions: 0/88 individual commands failed +PASS: Dovecot ImapTest imap-01-14 suite (35 scripted test groups, combined) +``` + +The normal and strict `-Wall -Wextra -Werror` builds each passed all 107 CTest +cases. The tests used only the local disposable Bongo installation. + ## IMAP retrospective source audit Result: **PASS for IMAP-01 through IMAP-08**