diff --git a/src/download.rs b/src/download.rs index 3f1026327..d4ad5ec1d 100644 --- a/src/download.rs +++ b/src/download.rs @@ -283,8 +283,9 @@ mod tests { use super::*; use crate::chat::{get_chat_msgs, send_msg}; use crate::ephemeral::Timer; + use crate::message::delete_msgs; use crate::receive_imf::receive_imf_from_inbox; - use crate::test_utils::{E2EE_INFO_MSGS, TestContext}; + use crate::test_utils::{E2EE_INFO_MSGS, TestContext, TestContextManager}; #[test] fn test_downloadstate_values() { @@ -543,4 +544,43 @@ mod tests { Ok(()) } + + /// Tests that fully downloading the message + /// works even if the Message-ID already exists + /// in the database assigned to the trash chat. + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_partial_download_trashed() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + + let imf_raw = b"From: Bob \n\ + To: Alice \n\ + Chat-Version: 1.0\n\ + Subject: subject\n\ + Message-ID: \n\ + Date: Sun, 14 Nov 2021 00:10:00 +0000\ + Content-Type: text/plain"; + + // Download message from Bob partially. + let partial_received_msg = + receive_imf_from_inbox(alice, "first@example.org", imf_raw, false, Some(100000)) + .await? + .unwrap(); + assert_eq!(partial_received_msg.msg_ids.len(), 1); + + // Delete the received message. + // Not it is still in the database, + // but in the trash chat. + delete_msgs(alice, &[partial_received_msg.msg_ids[0]]).await?; + + // Fully download message after deletion. + let full_received_msg = + receive_imf_from_inbox(alice, "first@example.org", imf_raw, false, None).await?; + + // The message does not reappear. + // However, `receive_imf` should not fail. + assert!(full_received_msg.is_none()); + + Ok(()) + } } diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 9ddcfed0b..51de43da9 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -557,13 +557,17 @@ pub(crate) async fn receive_imf_inner( // make sure, this check is done eg. before securejoin-processing. let (replace_msg_id, replace_chat_id); if let Some((old_msg_id, _)) = message::rfc724_mid_exists(context, rfc724_mid).await? { - let msg = Message::load_from_db(context, old_msg_id).await?; replace_msg_id = Some(old_msg_id); - replace_chat_id = if msg.download_state() != DownloadState::Done { + replace_chat_id = if let Some(msg) = Message::load_from_db_optional(context, old_msg_id) + .await? + .filter(|msg| msg.download_state() != DownloadState::Done) + { // the message was partially downloaded before and is fully downloaded now. info!(context, "Message already partly in DB, replacing."); Some(msg.chat_id) } else { + // The message was already fully downloaded + // or cannot be loaded because it is deleted. None }; } else {