@@ -13,7 +13,7 @@ use std::{
13
13
time:: { Duration , UNIX_EPOCH } ,
14
14
} ;
15
15
16
- use anyhow:: { bail, format_err, Context as _, Result } ;
16
+ use anyhow:: { bail, ensure , format_err, Context as _, Result } ;
17
17
use async_channel:: Receiver ;
18
18
use async_imap:: types:: { Fetch , Flag , Name , NameAttribute , UnsolicitedResponse } ;
19
19
use deltachat_contact_tools:: ContactAddress ;
@@ -540,10 +540,14 @@ impl Imap {
540
540
return Ok ( false ) ;
541
541
}
542
542
543
- session
544
- . select_with_uidvalidity ( context, folder)
543
+ let create = false ;
544
+ let folder_exists = session
545
+ . select_with_uidvalidity ( context, folder, create)
545
546
. await
546
547
. with_context ( || format ! ( "Failed to select folder {folder:?}" ) ) ?;
548
+ if !folder_exists {
549
+ return Ok ( false ) ;
550
+ }
547
551
548
552
if !session. new_mail && !fetch_existing_msgs {
549
553
info ! ( context, "No new emails in folder {folder:?}." ) ;
@@ -835,44 +839,51 @@ impl Session {
835
839
folder : & str ,
836
840
folder_meaning : FolderMeaning ,
837
841
) -> Result < ( ) > {
842
+ let uid_validity;
838
843
// Collect pairs of UID and Message-ID.
839
844
let mut msgs = BTreeMap :: new ( ) ;
840
845
841
- self . select_with_uidvalidity ( context, folder) . await ?;
846
+ let create = false ;
847
+ let folder_exists = self
848
+ . select_with_uidvalidity ( context, folder, create)
849
+ . await ?;
850
+ if folder_exists {
851
+ let mut list = self
852
+ . uid_fetch ( "1:*" , RFC724MID_UID )
853
+ . await
854
+ . with_context ( || format ! ( "Can't resync folder {folder}" ) ) ?;
855
+ while let Some ( fetch) = list. try_next ( ) . await ? {
856
+ let headers = match get_fetch_headers ( & fetch) {
857
+ Ok ( headers) => headers,
858
+ Err ( err) => {
859
+ warn ! ( context, "Failed to parse FETCH headers: {}" , err) ;
860
+ continue ;
861
+ }
862
+ } ;
863
+ let message_id = prefetch_get_message_id ( & headers) ;
842
864
843
- let mut list = self
844
- . uid_fetch ( "1:*" , RFC724MID_UID )
845
- . await
846
- . with_context ( || format ! ( "can't resync folder {folder}" ) ) ?;
847
- while let Some ( fetch) = list. try_next ( ) . await ? {
848
- let headers = match get_fetch_headers ( & fetch) {
849
- Ok ( headers) => headers,
850
- Err ( err) => {
851
- warn ! ( context, "Failed to parse FETCH headers: {}" , err) ;
852
- continue ;
865
+ if let ( Some ( uid) , Some ( rfc724_mid) ) = ( fetch. uid , message_id) {
866
+ msgs. insert (
867
+ uid,
868
+ (
869
+ rfc724_mid,
870
+ target_folder ( context, folder, folder_meaning, & headers) . await ?,
871
+ ) ,
872
+ ) ;
853
873
}
854
- } ;
855
- let message_id = prefetch_get_message_id ( & headers) ;
856
-
857
- if let ( Some ( uid) , Some ( rfc724_mid) ) = ( fetch. uid , message_id) {
858
- msgs. insert (
859
- uid,
860
- (
861
- rfc724_mid,
862
- target_folder ( context, folder, folder_meaning, & headers) . await ?,
863
- ) ,
864
- ) ;
865
874
}
866
- }
867
875
868
- info ! (
869
- context,
870
- "Resync: collected {} message IDs in folder {}" ,
871
- msgs. len( ) ,
872
- folder,
873
- ) ;
876
+ info ! (
877
+ context,
878
+ "resync_folder_uids: Collected {} message IDs in {folder}." ,
879
+ msgs. len( ) ,
880
+ ) ;
874
881
875
- let uid_validity = get_uidvalidity ( context, folder) . await ?;
882
+ uid_validity = get_uidvalidity ( context, folder) . await ?;
883
+ } else {
884
+ warn ! ( context, "resync_folder_uids: No folder {folder}." ) ;
885
+ uid_validity = 0 ;
886
+ }
876
887
877
888
// Write collected UIDs to SQLite database.
878
889
context
@@ -1039,7 +1050,11 @@ impl Session {
1039
1050
// MOVE/DELETE operations. This does not result in multiple SELECT commands
1040
1051
// being sent because `select_folder()` does nothing if the folder is already
1041
1052
// selected.
1042
- self . select_with_uidvalidity ( context, folder) . await ?;
1053
+ let create = false ;
1054
+ let folder_exists = self
1055
+ . select_with_uidvalidity ( context, folder, create)
1056
+ . await ?;
1057
+ ensure ! ( folder_exists, "No folder {folder}" ) ;
1043
1058
1044
1059
// Empty target folder name means messages should be deleted.
1045
1060
if target. is_empty ( ) {
@@ -1133,30 +1148,40 @@ impl Session {
1133
1148
. await ?;
1134
1149
1135
1150
for ( folder, rowid_set, uid_set) in UidGrouper :: from ( rows) {
1136
- if let Err ( err) = self . select_with_uidvalidity ( context, & folder) . await {
1137
- warn ! ( context, "store_seen_flags_on_imap: Failed to select {folder}, will retry later: {err:#}." ) ;
1151
+ let create = false ;
1152
+ let folder_exists = match self . select_with_uidvalidity ( context, & folder, create) . await {
1153
+ Err ( err) => {
1154
+ warn ! (
1155
+ context,
1156
+ "store_seen_flags_on_imap: Failed to select {folder}, will retry later: {err:#}." ) ;
1157
+ continue ;
1158
+ }
1159
+ Ok ( folder_exists) => folder_exists,
1160
+ } ;
1161
+ if !folder_exists {
1162
+ warn ! ( context, "store_seen_flags_on_imap: No folder {folder}." ) ;
1138
1163
} else if let Err ( err) = self . add_flag_finalized_with_set ( & uid_set, "\\ Seen" ) . await {
1139
1164
warn ! (
1140
1165
context,
1141
1166
"Cannot mark messages {uid_set} in {folder} as seen, will retry later: {err:#}." ) ;
1167
+ continue ;
1142
1168
} else {
1143
1169
info ! (
1144
1170
context,
1145
1171
"Marked messages {} in folder {} as seen." , uid_set, folder
1146
1172
) ;
1147
- context
1148
- . sql
1149
- . transaction ( |transaction| {
1150
- let mut stmt =
1151
- transaction. prepare ( "DELETE FROM imap_markseen WHERE id = ?" ) ?;
1152
- for rowid in rowid_set {
1153
- stmt. execute ( ( rowid, ) ) ?;
1154
- }
1155
- Ok ( ( ) )
1156
- } )
1157
- . await
1158
- . context ( "Cannot remove messages marked as seen from imap_markseen table" ) ?;
1159
1173
}
1174
+ context
1175
+ . sql
1176
+ . transaction ( |transaction| {
1177
+ let mut stmt = transaction. prepare ( "DELETE FROM imap_markseen WHERE id = ?" ) ?;
1178
+ for rowid in rowid_set {
1179
+ stmt. execute ( ( rowid, ) ) ?;
1180
+ }
1181
+ Ok ( ( ) )
1182
+ } )
1183
+ . await
1184
+ . context ( "Cannot remove messages marked as seen from imap_markseen table" ) ?;
1160
1185
}
1161
1186
1162
1187
Ok ( ( ) )
@@ -1172,9 +1197,14 @@ impl Session {
1172
1197
return Ok ( ( ) ) ;
1173
1198
}
1174
1199
1175
- self . select_with_uidvalidity ( context, folder)
1200
+ let create = false ;
1201
+ let folder_exists = self
1202
+ . select_with_uidvalidity ( context, folder, create)
1176
1203
. await
1177
- . context ( "failed to select folder" ) ?;
1204
+ . context ( "Failed to select folder" ) ?;
1205
+ if !folder_exists {
1206
+ return Ok ( ( ) ) ;
1207
+ }
1178
1208
1179
1209
let mailbox = self
1180
1210
. selected_mailbox
@@ -1630,7 +1660,7 @@ fn format_setmetadata(folder: &str, device_token: &str) -> String {
1630
1660
impl Session {
1631
1661
/// Returns success if we successfully set the flag or we otherwise
1632
1662
/// think add_flag should not be retried: Disconnection during setting
1633
- /// the flag, or other imap-errors, returns true as well.
1663
+ /// the flag, or other imap-errors, returns Ok as well.
1634
1664
///
1635
1665
/// Returning error means that the operation can be retried.
1636
1666
async fn add_flag_finalized_with_set ( & mut self , uid_set : & str , flag : & str ) -> Result < ( ) > {
@@ -1677,7 +1707,11 @@ impl Session {
1677
1707
self . close ( ) . await ?;
1678
1708
// Before moving emails to the mvbox we need to remember its UIDVALIDITY, otherwise
1679
1709
// emails moved before that wouldn't be fetched but considered "old" instead.
1680
- self . select_with_uidvalidity ( context, folder) . await ?;
1710
+ let create = false ;
1711
+ let folder_exists = self
1712
+ . select_with_uidvalidity ( context, folder, create)
1713
+ . await ?;
1714
+ ensure ! ( folder_exists, "No MVBOX folder {:?}??" , & folder) ;
1681
1715
return Ok ( Some ( folder) ) ;
1682
1716
}
1683
1717
}
@@ -1688,7 +1722,10 @@ impl Session {
1688
1722
// Some servers require namespace-style folder names like "INBOX.DeltaChat", so we try all
1689
1723
// the variants here.
1690
1724
for folder in folders {
1691
- match self . select_with_uidvalidity ( context, folder) . await {
1725
+ match self
1726
+ . select_with_uidvalidity ( context, folder, create_mvbox)
1727
+ . await
1728
+ {
1692
1729
Ok ( _) => {
1693
1730
info ! ( context, "MVBOX-folder {} created." , folder) ;
1694
1731
return Ok ( Some ( folder) ) ;
@@ -2539,10 +2576,14 @@ async fn add_all_recipients_as_contacts(
2539
2576
) ;
2540
2577
return Ok ( ( ) ) ;
2541
2578
} ;
2542
- session
2543
- . select_with_uidvalidity ( context, & mailbox)
2579
+ let create = false ;
2580
+ let folder_exists = session
2581
+ . select_with_uidvalidity ( context, & mailbox, create)
2544
2582
. await
2545
2583
. with_context ( || format ! ( "could not select {mailbox}" ) ) ?;
2584
+ if !folder_exists {
2585
+ return Ok ( ( ) ) ;
2586
+ }
2546
2587
2547
2588
let recipients = session
2548
2589
. get_all_recipients ( context)
0 commit comments