@@ -967,12 +967,10 @@ public override async Task ExecuteNativeRequestsAsync(List<IRequestBundle<Reques
967967
968968 public override async Task < List < MailCopy > > OnlineSearchAsync ( string queryText , List < IMailItemFolder > folders , CancellationToken cancellationToken = default )
969969 {
970- bool isFoldersIncluded = folders ? . Any ( ) ?? false ;
971-
972- var messagesToDownload = new List < Message > ( ) ;
970+ List < Message > messagesReturnedByApi = [ ] ;
973971
974972 // Perform search for each folder separately.
975- if ( isFoldersIncluded )
973+ if ( folders ? . Count > 0 )
976974 {
977975 var folderIds = folders . Select ( a => a . RemoteFolderId ) ;
978976
@@ -990,9 +988,9 @@ public override async Task<List<MailCopy>> OnlineSearchAsync(string queryText, L
990988
991989 if ( result ? . Value != null )
992990 {
993- lock ( messagesToDownload )
991+ lock ( messagesReturnedByApi )
994992 {
995- messagesToDownload . AddRange ( result . Value ) ;
993+ messagesReturnedByApi . AddRange ( result . Value ) ;
996994 }
997995 }
998996 } ) ;
@@ -1008,59 +1006,60 @@ public override async Task<List<MailCopy>> OnlineSearchAsync(string queryText, L
10081006 requestConfig . QueryParameters . Search = $ "\" { queryText } \" ";
10091007 requestConfig . QueryParameters . Select = [ "Id, ParentFolderId" ] ;
10101008 requestConfig . QueryParameters . Top = 1000 ;
1011- } ) ;
1009+ } , cancellationToken ) ;
10121010
10131011 var result = await mailQuery ;
10141012
10151013 if ( result ? . Value != null )
10161014 {
1017- lock ( messagesToDownload )
1018- {
1019- messagesToDownload . AddRange ( result . Value ) ;
1020- }
1015+ messagesReturnedByApi . AddRange ( result . Value ) ;
10211016 }
10221017 }
10231018
1024- // Do not download messages that exists, but return them for listing.
1019+ if ( messagesReturnedByApi . Count == 0 ) return [ ] ;
10251020
1026- var localFolders = await _outlookChangeProcessor . GetLocalFoldersAsync ( Account . Id ) . ConfigureAwait ( false ) ;
1021+ var localFolders = ( await _outlookChangeProcessor . GetLocalFoldersAsync ( Account . Id ) . ConfigureAwait ( false ) )
1022+ . ToDictionary ( x => x . RemoteFolderId ) ;
10271023
1028- var existingMessageIds = new List < string > ( ) ;
1024+ var messagesDictionary = messagesReturnedByApi . ToDictionary ( a => a . Id ) ;
10291025
1030- //Download missing messages.
1031- foreach ( var message in messagesToDownload )
1032- {
1033- var messageId = message . Id ;
1034- var parentFolderId = message . ParentFolderId ;
1026+ // Contains a list of message ids that potentially can be downloaded.
1027+ List < string > messageIdsWithKnownFolder = [ ] ;
10351028
1036- if ( ! localFolders . Any ( a => a . RemoteFolderId == parentFolderId ) )
1029+ // Validate that all messages are in a known folder.
1030+ foreach ( var message in messagesReturnedByApi )
1031+ {
1032+ if ( ! localFolders . ContainsKey ( message . ParentFolderId ) )
10371033 {
1038- Log . Warning ( $ "Search result returned a message from a folder that is not synchronized.") ;
1034+ Log . Warning ( "Search result returned a message from a folder that is not synchronized." ) ;
10391035 continue ;
10401036 }
10411037
1042- existingMessageIds . Add ( messageId ) ;
1043-
1044- var exists = await _outlookChangeProcessor . IsMailExistsAsync ( messageId ) . ConfigureAwait ( false ) ;
1038+ messageIdsWithKnownFolder . Add ( message . Id ) ;
1039+ }
10451040
1046- if ( ! exists )
1047- {
1048- // Check if folder exists. We can't download a mail without existing folder.
1041+ var locallyExistingMails = await _outlookChangeProcessor . AreMailsExistsAsync ( messageIdsWithKnownFolder ) . ConfigureAwait ( false ) ;
10491042
1050- var localFolder = localFolders . Find ( a => a . RemoteFolderId == parentFolderId ) ;
1043+ // Find messages that are not downloaded yet.
1044+ List < Message > messagesToDownload = [ ] ;
1045+ foreach ( var id in messagesDictionary . Keys . Except ( locallyExistingMails ) )
1046+ {
1047+ messagesToDownload . Add ( messagesDictionary [ id ] ) ;
1048+ }
10511049
1052- await DownloadSearchResultMessageAsync ( messageId , localFolder , cancellationToken ) . ConfigureAwait ( false ) ;
1053- }
1050+ foreach ( var message in messagesToDownload )
1051+ {
1052+ await DownloadSearchResultMessageAsync ( message . Id , localFolders [ message . ParentFolderId ] , cancellationToken ) . ConfigureAwait ( false ) ;
10541053 }
10551054
10561055 // Get results from database and return.
1057- return await _outlookChangeProcessor . GetMailCopiesAsync ( existingMessageIds ) ;
1056+ return await _outlookChangeProcessor . GetMailCopiesAsync ( messageIdsWithKnownFolder ) . ConfigureAwait ( false ) ;
10581057 }
10591058
10601059 private async Task < MimeMessage > DownloadMimeMessageAsync ( string messageId , CancellationToken cancellationToken = default )
10611060 {
10621061 var mimeContentStream = await _graphClient . Me . Messages [ messageId ] . Content . GetAsync ( null , cancellationToken ) . ConfigureAwait ( false ) ;
1063- return await MimeMessage . LoadAsync ( mimeContentStream ) . ConfigureAwait ( false ) ;
1062+ return await MimeMessage . LoadAsync ( mimeContentStream , cancellationToken ) . ConfigureAwait ( false ) ;
10641063 }
10651064
10661065 public override async Task < List < NewMailItemPackage > > CreateNewMailPackagesAsync ( Message message , MailItemFolder assignedFolder , CancellationToken cancellationToken = default )
0 commit comments