From e4ae501112b007b4decd67d8c0ed8bd68ae2cd4a Mon Sep 17 00:00:00 2001 From: iequidoo Date: Tue, 17 Mar 2026 13:51:42 -0300 Subject: [PATCH] test: test_markseen_pre_msg: Check that MDN on pre-message changes message state to OutMdnRcvd (#8004) --- src/smtp.rs | 103 ++++++++++++++++++---------- src/tests/pre_messages/receiving.rs | 18 ++++- 2 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/smtp.rs b/src/smtp.rs index 020c575fd..76deb73f8 100644 --- a/src/smtp.rs +++ b/src/smtp.rs @@ -13,7 +13,7 @@ use crate::config::Config; use crate::contact::{Contact, ContactId}; use crate::context::Context; use crate::events::EventType; -use crate::log::{LogExt, warn}; +use crate::log::warn; use crate::message::Message; use crate::message::{self, MsgId}; use crate::mimefactory::MimeFactory; @@ -590,44 +590,77 @@ async fn send_mdn_rfc724_mid( if context.get_config_bool(Config::BccSelf).await? { add_self_recipients(context, &mut recipients, encrypted).await?; } - let recipients: Vec<_> = recipients - .into_iter() - .filter_map(|addr| { - async_smtp::EmailAddress::new(addr.clone()) - .with_context(|| format!("Invalid recipient: {addr}")) - .log_err(context) - .ok() - }) - .collect(); + #[cfg(not(test))] + { + use crate::log::LogExt; - match smtp_send(context, &recipients, &body, smtp, None).await { - SendResult::Success => { - if !recipients.is_empty() { - info!(context, "Successfully sent MDN for {rfc724_mid}."); + let recipients: Vec<_> = recipients + .into_iter() + .filter_map(|addr| { + async_smtp::EmailAddress::new(addr.clone()) + .with_context(|| format!("Invalid recipient: {addr}")) + .log_err(context) + .ok() + }) + .collect(); + + match smtp_send(context, &recipients, &body, smtp, None).await { + SendResult::Success => { + if !recipients.is_empty() { + info!(context, "Successfully sent MDN for {rfc724_mid}."); + } + context + .sql + .transaction(|transaction| { + let mut stmt = + transaction.prepare("DELETE FROM smtp_mdns WHERE rfc724_mid = ?")?; + stmt.execute((rfc724_mid,))?; + for additional_rfc724_mid in additional_rfc724_mids { + stmt.execute((additional_rfc724_mid,))?; + } + Ok(()) + }) + .await?; + Ok(true) } - context - .sql - .transaction(|transaction| { - let mut stmt = - transaction.prepare("DELETE FROM smtp_mdns WHERE rfc724_mid = ?")?; - stmt.execute((rfc724_mid,))?; - for additional_rfc724_mid in additional_rfc724_mids { - stmt.execute((additional_rfc724_mid,))?; - } - Ok(()) - }) - .await?; - Ok(true) + SendResult::Retry => { + info!( + context, + "Temporary SMTP failure while sending an MDN for {rfc724_mid}." + ); + Ok(false) + } + SendResult::Failure(err) => Err(err), } - SendResult::Retry => { - info!( - context, - "Temporary SMTP failure while sending an MDN for {rfc724_mid}." - ); - Ok(false) - } - SendResult::Failure(err) => Err(err), } + #[cfg(test)] + { + let _ = smtp; + context + .sql + .transaction(|t| { + t.execute( + "INSERT INTO smtp (rfc724_mid, recipients, mime, msg_id) + VALUES (?, ?, ?, ?)", + (rfc724_mid, recipients.join(" "), body, u32::MAX), + )?; + let mut stmt = t.prepare("DELETE FROM smtp_mdns WHERE rfc724_mid = ?")?; + stmt.execute((rfc724_mid,))?; + for additional_rfc724_mid in additional_rfc724_mids { + stmt.execute((additional_rfc724_mid,))?; + } + Ok(()) + }) + .await?; + Ok(true) + } +} + +#[cfg(test)] +pub(crate) async fn queue_mdn(context: &Context) -> Result<()> { + let queued = send_mdn(context, &mut Smtp::new()).await?; + assert!(queued); + Ok(()) } /// Tries to send a single MDN. Returns true if more MDNs should be sent. diff --git a/src/tests/pre_messages/receiving.rs b/src/tests/pre_messages/receiving.rs index e92f6d21d..170c19052 100644 --- a/src/tests/pre_messages/receiving.rs +++ b/src/tests/pre_messages/receiving.rs @@ -1,4 +1,6 @@ //! Tests about receiving Pre-Messages and Post-Message +use std::time::Duration; + use anyhow::{Context as _, Result}; use pretty_assertions::assert_eq; @@ -8,16 +10,18 @@ use crate::chat::send_msg; use crate::config::Config; use crate::contact; use crate::download::{DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD, PostMsgMetadata}; -use crate::message::{Message, MessageState, Viewtype, delete_msgs, markseen_msgs}; +use crate::message::{self, Message, MessageState, Viewtype, delete_msgs, markseen_msgs}; use crate::mimeparser::MimeMessage; use crate::param::Param; use crate::reaction::{get_msg_reactions, send_reaction}; use crate::receive_imf::receive_imf; +use crate::smtp; use crate::summary::assert_summary_texts; use crate::test_utils::TestContextManager; use crate::tests::pre_messages::util::{ big_webxdc_app, send_large_file_message, send_large_image_message, send_large_webxdc_message, }; +use crate::tools::{SystemTime, time}; use crate::webxdc::StatusUpdateSerial; /// Test that mimeparser can correctly detect and parse pre-messages and Post-Messages @@ -625,7 +629,7 @@ async fn test_markseen_pre_msg() -> Result<()> { alice.create_chat(bob).await; // Make sure the chat is accepted. tcm.section("Bob sends a large message to Alice"); - let (pre_message, post_message, _bob_msg_id) = + let (pre_message, post_message, bob_msg_id) = send_large_file_message(bob, bob_chat_id, Viewtype::File, &vec![0u8; 1_000_000]).await?; tcm.section("Alice receives a pre-message message from Bob"); @@ -644,6 +648,16 @@ async fn test_markseen_pre_msg() -> Result<()> { .await?, 1 ); + smtp::queue_mdn(alice).await?; + SystemTime::shift(Duration::from_secs(3600)); + bob.recv_msg_trash(&alice.pop_sent_msg().await).await; + let bob_msg = Message::load_from_db(bob, bob_msg_id).await?; + assert_eq!(bob_msg.get_state(), MessageState::OutMdnRcvd); + let read_receipts = message::get_msg_read_receipts(bob, bob_msg_id).await?; + assert_eq!(read_receipts.len(), 1); + let (contact_id, ts) = read_receipts[0]; + assert_eq!(contact_id, bob.add_or_lookup_contact_id(alice).await); + assert!(ts + 3600 - 60 < time()); tcm.section("Alice downloads message"); alice.recv_msg_trash(&post_message).await;