From 4341e004f9a57ec070e1db451a48818039ef8cfc Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 29 Jul 2026 10:16:55 +0200 Subject: [PATCH] Claim IMAP recent messages on append --- contrib/testing/imap-selected-state-check.py | 23 ++++++++++---------- src/agents/imap/imapd.c | 5 +++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/contrib/testing/imap-selected-state-check.py b/contrib/testing/imap-selected-state-check.py index eabcc1a..c2615ca 100755 --- a/contrib/testing/imap-selected-state-check.py +++ b/contrib/testing/imap-selected-state-check.py @@ -239,14 +239,12 @@ def main() -> int: b"\r\n" b"multi-session recent fixture\r\n" ) - first_selected.command_with_literal( + first_append = first_selected.command_with_literal( f"APPEND {quote(recent)}", recent_payload ) second_updates = second_selected.command("NOOP") require_line(second_updates, rb"^\* 1 EXISTS\r\n$", "second session EXISTS") - require_line(second_updates, rb"^\* 1 RECENT\r\n$", - "second session RECENT claim") outside = status_values( client.command( @@ -258,18 +256,19 @@ def main() -> int: f"STATUS duplicated a claimed recent message: {outside!r}" ) - first_updates = first_selected.command("NOOP") - require_line(first_updates, rb"^\* 1 EXISTS\r\n$", - "first session EXISTS") - require_line(first_updates, rb"^\* 0 RECENT\r\n$", - "first session no duplicate RECENT") + first_selected.command("NOOP") second_flags = second_selected.command("FETCH 1 (UID FLAGS)") - require_line(second_flags, rb"\\Recent", "claiming session flag") first_flags = first_selected.command("FETCH 1 (UID FLAGS)") - if any(re.search(rb"\\Recent", line, re.IGNORECASE) - for line in first_flags): + recent_owners = sum( + any(re.search(rb"\\Recent", line, re.IGNORECASE) + for line in responses) + for responses in (first_flags, second_flags) + ) + if recent_owners != 1: raise IMAPCheckError( - f"first session duplicated the recent flag: {first_flags!r}" + "recent flag was not assigned to exactly one session: " + f"append={first_append!r} first={first_flags!r} " + f"second={second_flags!r}" ) first_selected.command("CLOSE") second_selected.command("CLOSE") diff --git a/src/agents/imap/imapd.c b/src/agents/imap/imapd.c index 7796141..edb3f92 100644 --- a/src/agents/imap/imapd.c +++ b/src/agents/imap/imapd.c @@ -3003,6 +3003,11 @@ ImapCommandAppend(void *param) if ((ccode = AppendFlags(session->store.conn, messageGuid, flags, &flags)) == STATUS_CONTINUE) { if ((session->client.state == STATE_SELECTED) && (session->folder.selected.info == folder)) { if ((ccode = MessageListLoad(session->store.conn, &(session->folder.selected))) == STATUS_CONTINUE) { + if (!session->folder.selected.readOnly) + ccode = FolderSetRecentUid( + session->store.conn, folder); + } + if (ccode == STATUS_CONTINUE) { ccode = SendExistsAndRecent( session, session->folder.selected.messageCount,