From 818df189bd2557d49b3eb0a3c9c57f4abca52214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean=20Charles=20Del=C3=A9pine?= Date: Fri, 28 Aug 2026 13:05:07 +0200 Subject: [PATCH] fix: invalidate cached SEARCH results on message deletion/move When the backend's 'cache' parameter is enabled, _deleteMsgs() correctly invalidates the FETCH data cache and the message map for a mailbox when messages vanish (VANISHED response after EXPUNGE or MOVE), but never touched the SEARCH result cache (CACHE_SEARCH/ CACHE_SEARCHID metadata). Since that cache's validity is keyed off the mailbox's tracked sync token rather than off actual message-set changes, a MOVE that does not visibly advance the local HIGHESTMODSEQ leaves stale UIDs in the SEARCH cache. A subsequent search() on that mailbox then serves those vanished UIDs, and any FETCH/STORE issued against them silently returns nothing. --- lib/Horde/Imap/Client/Base.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/Horde/Imap/Client/Base.php b/lib/Horde/Imap/Client/Base.php index 98cd373a..422775ac 100644 --- a/lib/Horde/Imap/Client/Base.php +++ b/lib/Horde/Imap/Client/Base.php @@ -3889,6 +3889,24 @@ protected function _deleteMsgs( $mbox_ob->setStatus(Horde_Imap_Client::STATUS_SYNCVANISHED, $ids_ob->ids); $mbox_ob->map->remove($ids); + /* The message set in this mailbox just changed (message(s) + * expunged/moved out). Any cached SEARCH results for this + * mailbox may now reference vanished UIDs, so they can no + * longer be trusted even if the tracked sync token has not + * (yet) advanced. Only touch the cache if a SEARCH was + * actually cached for this mailbox. */ + $search_md = $this->_cache->getMetaData( + $mailbox, + null, + [self::CACHE_SEARCHID] + ); + if (isset($search_md[self::CACHE_SEARCHID])) { + $this->_cache->setMetaData($mailbox, null, [ + self::CACHE_SEARCH => [], + self::CACHE_SEARCHID => null, + ]); + } + return $ids_ob; }