From 0bbd0c89a6aca64d5b3ba79c361ef9f510ca8586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rasmus=20B=C3=A6kgaard?= Date: Sat, 28 Mar 2026 23:19:31 +0100 Subject: [PATCH] fix(imap4): accept SORT data when server returns tagged NO Dovecot may return valid SORT results in an untagged response but then send a tagged NO (e.g. "Requested sort would have taken too long"). The sort data is still valid and usable. Previously, normalizeSortResponse relied solely on the tagged response status, discarding perfectly good sort data when the server returned NO. This caused SOGo's mail view to fail with "could not sort contents of URL" on large mailboxes served by Dovecot instances with aggressive sort-time policies. Now, if sort data was received in the untagged response, the result is promoted to success regardless of the tagged status. Co-Authored-By: Claude Opus 4.6 (1M context) --- sope-mime/NGImap4/NGImap4ResponseNormalizer.m | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/sope-mime/NGImap4/NGImap4ResponseNormalizer.m b/sope-mime/NGImap4/NGImap4ResponseNormalizer.m index 9d865889b..4d35cbd8d 100644 --- a/sope-mime/NGImap4/NGImap4ResponseNormalizer.m +++ b/sope-mime/NGImap4/NGImap4ResponseNormalizer.m @@ -129,15 +129,28 @@ - (NSMutableDictionary *)normalizeResponse:(NGHashMap *)_map { } - (NSDictionary *)normalizeSortResponse:(NGHashMap *)_map { - /* filter for sort response (search : NSArray (msn)) */ + /* + Filter for sort response (sort: NSArray of UIDs). + + Some IMAP servers (e.g. Dovecot) may return SORT data in an untagged + response but then send a tagged NO (e.g. "sort would have taken too + long"). The data is still valid, so if we received sort results we + treat the command as successful regardless of the tagged status. + */ id obj; NSMutableDictionary *result; result = [self normalizeResponse:_map]; - - if ((obj = [[_map objectEnumeratorForKey:@"sort"] nextObject]) != nil) + + if ((obj = [[_map objectEnumeratorForKey:@"sort"] nextObject]) != nil) { [result setObject:obj forKey:@"sort"]; - + + /* Promote to success when sort data was returned despite a tagged NO */ + if (![[result objectForKey:@"result"] boolValue]) { + [result setObject:[NSNumber numberWithBool:YES] forKey:@"result"]; + } + } + return result; }