Issue Description
IMAP IDLE clients do not receive real-time new-message notifications when mail is delivered into the currently selected mailbox on Stalwart. The TCP/TLS connection stays open and IDLE appears active, but new mail is only discovered later by periodic polling/sync.
Expected Behavior
When an IMAP client has selected INBOX and entered IDLE, then a new message is delivered to INBOX, Stalwart should promptly send untagged selected-mailbox updates such as:
- 1 EXISTS
- 1 FETCH (FLAGS () UID 1)
The client should wake immediately without waiting for its periodic sync interval.
Actual Behavior
Stalwart accepts the IDLE connection, keeps it open, and periodically refreshes correctly, but does not push EXISTS / FETCH notifications for new mail delivered to the selected mailbox.
In our observed production case, all new-message detection lined up with the client’s 15-minute periodic sync rather than the actual delivery time.
Reproduction Steps
- Connect to Stalwart over IMAPS.
- Authenticate as a user.
- Select INBOX.
- Enter IDLE.
- Deliver a new message to that same account’s INBOX via SMTP/LMTP.
- Observe the active IDLE connection.
Expected: immediate untagged EXISTS / FETCH.
Actual: no selected-mailbox new-message notification is sent on the IDLE connection.
Relevant Log Output
From client-side testing/telemetry:
IDLE TCP connections establish successfully and re-issue every ~26 minutes.
Stalwart silently never pushes EXISTS notifications to the IDLE channel.
Every new-mail detection lines up with the 15-minute periodic sync, not with mail arrival times.
TLS and IMAP connectivity were otherwise healthy:
- OK [CAPABILITY IMAP4rev2 IMAP4rev1 ENABLE SASL-IR LITERAL+ ID UTF8=ACCEPT JMAPACCESS AUTH=PLAIN AUTH=OAUTHBEARER AUTH=XOAUTH2] Stalwart IMAP4rev2 at your service.
a1 OK CAPABILITY completed
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Internal
Directory Backend
Internal
Additional Context
he fix changes IMAP IDLE change processing so selected-mailbox email changes are handled before general mailbox STATUS changes.
Previously, write_changes processed mailbox status updates first, then selected mailbox email changes. In the selected-mailbox delivery case, that ordering could cause the client to receive mailbox-level status activity
without the expected selected-mailbox EXISTS / FETCH notifications.
The patch:
- Processes selected mailbox changes first.
- Emits EXISTS / FETCH for changed messages in the selected mailbox.
- Then processes general mailbox STATUS updates.
- Avoids returning early after selected mailbox handling, so unrelated mailbox status updates are still sent.
A regression test was added for SMTP/LMTP delivery into a selected INBOX while the client is in IDLE.
Tested with:
cargo fmt --package imap --check
STORE=Sqlite cargo test -p tests imap – --nocapture
Patch branch:
GitHub - brocktice/stalwart at fix-imap-idle-smtp-exists · GitHub
Compare link:
Comparing stalwartlabs:main...brocktice:fix-imap-idle-smtp-exists · stalwartlabs/stalwart · GitHub
Upstream PR could not be opened because repository owners have restricted PR creation to collaborators.
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on