@@ -560,10 +560,13 @@ pub(crate) async fn receive_imf_inner(
560560 return Ok ( None ) ;
561561 }
562562 let msg = Message :: load_from_db_optional ( context, old_msg_id) . await ?;
563- if msg. is_none ( ) {
564- message:: prune_tombstone ( context, rfc724_mid) . await ?;
563+ // The tombstone being pruned means that we expected the message to appear on IMAP after
564+ // deletion. NB: Not all such messages have `msgs.deleted=1`, see how external deletion
565+ // requests deal with message reordering.
566+ match msg. is_none ( ) && !message:: prune_tombstone ( context, rfc724_mid) . await ? {
567+ true => replace_msg_id = None ,
568+ false => replace_msg_id = Some ( old_msg_id) ,
565569 }
566- replace_msg_id = Some ( old_msg_id) ;
567570 if let Some ( msg) = msg. filter ( |msg| msg. download_state ( ) != DownloadState :: Done ) {
568571 // the message was partially downloaded before and is fully downloaded now.
569572 info ! (
@@ -574,32 +577,39 @@ pub(crate) async fn receive_imf_inner(
574577 } else {
575578 replace_chat_id = None ;
576579 }
577- } else {
578- replace_msg_id = if rfc724_mid_orig == rfc724_mid {
579- None
580- } else if let Some ( ( old_msg_id, old_ts_sent) ) =
581- message:: rfc724_mid_exists ( context, rfc724_mid_orig) . await ?
582- {
583- message:: prune_tombstone ( context, rfc724_mid_orig) . await ?;
584- if imap:: is_dup_msg (
585- mime_parser. has_chat_version ( ) ,
586- mime_parser. timestamp_sent ,
587- old_ts_sent,
588- ) {
589- info ! ( context, "Deleting duplicate message {rfc724_mid_orig}." ) ;
590- let target = context. get_delete_msgs_target ( ) . await ?;
591- context
592- . sql
593- . execute (
594- "UPDATE imap SET target=? WHERE folder=? AND uidvalidity=? AND uid=?" ,
595- ( target, folder, uidvalidity, uid) ,
596- )
597- . await ?;
598- }
599- Some ( old_msg_id)
580+ } else if rfc724_mid_orig == rfc724_mid {
581+ replace_msg_id = None ;
582+ replace_chat_id = None ;
583+ } else if let Some ( ( old_msg_id, old_ts_sent, is_trash) ) = message:: rfc724_mid_exists_ex (
584+ context,
585+ rfc724_mid_orig,
586+ "chat_id=3" , // Trash
587+ )
588+ . await ?
589+ {
590+ if is_trash && !message:: prune_tombstone ( context, rfc724_mid_orig) . await ? {
591+ replace_msg_id = None ;
592+ } else if imap:: is_dup_msg (
593+ mime_parser. has_chat_version ( ) ,
594+ mime_parser. timestamp_sent ,
595+ old_ts_sent,
596+ ) {
597+ info ! ( context, "Deleting duplicate message {rfc724_mid_orig}." ) ;
598+ let target = context. get_delete_msgs_target ( ) . await ?;
599+ context
600+ . sql
601+ . execute (
602+ "UPDATE imap SET target=? WHERE folder=? AND uidvalidity=? AND uid=?" ,
603+ ( target, folder, uidvalidity, uid) ,
604+ )
605+ . await ?;
606+ replace_msg_id = Some ( old_msg_id) ;
600607 } else {
601- None
602- } ;
608+ replace_msg_id = Some ( old_msg_id) ;
609+ }
610+ replace_chat_id = None ;
611+ } else {
612+ replace_msg_id = None ;
603613 replace_chat_id = None ;
604614 }
605615
0 commit comments