Compare commits

...

1 Commits

Author SHA1 Message Date
iequidoo
88ed20ea52 test: Add function to get sent MDN as SentMessage 2026-06-22 21:13:23 -03:00
2 changed files with 66 additions and 41 deletions

View File

@@ -492,7 +492,35 @@ async fn send_mdns(context: &Context, connection: &mut Smtp) -> Result<()> {
return Ok(());
}
let more_mdns = send_mdn(context, connection).await?;
let more_mdns = send_mdn(context, async |rfc724_mid, body, recipients| {
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, connection, None).await {
SendResult::Success => {
if !recipients.is_empty() {
info!(context, "Successfully sent MDN for {rfc724_mid}.");
}
Ok(true)
}
SendResult::Retry => {
info!(
context,
"Temporary SMTP failure while sending an MDN for {rfc724_mid}."
);
Ok(false)
}
SendResult::Failure(err) => Err(err),
}
})
.await?;
if !more_mdns {
// No more MDNs to send or one of them failed.
return Ok(());
@@ -550,7 +578,7 @@ async fn send_mdn_rfc724_mid(
context: &Context,
rfc724_mid: &str,
contact_id: ContactId,
smtp: &mut Smtp,
send_fn: impl AsyncFnOnce(&str, String, Vec<String>) -> Result<bool>,
) -> Result<bool> {
let contact = Contact::get_by_id(context, contact_id).await?;
if contact.is_blocked() {
@@ -590,48 +618,29 @@ 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();
message::insert_tombstone(context, &rendered_msg.rfc724_mid).await?;
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)
}
SendResult::Retry => {
info!(
context,
"Temporary SMTP failure while sending an MDN for {rfc724_mid}."
);
Ok(false)
}
SendResult::Failure(err) => Err(err),
let sent = send_fn(rfc724_mid, body, recipients).await?;
if sent {
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(sent)
}
/// Tries to send a single MDN. Returns true if more MDNs should be sent.
async fn send_mdn(context: &Context, smtp: &mut Smtp) -> Result<bool> {
pub(crate) async fn send_mdn(
context: &Context,
send_fn: impl AsyncFnOnce(&str, String, Vec<String>) -> Result<bool>,
) -> Result<bool> {
if !context.should_send_mdns().await? {
context.sql.execute("DELETE FROM smtp_mdns", []).await?;
return Ok(false);
@@ -668,7 +677,7 @@ async fn send_mdn(context: &Context, smtp: &mut Smtp) -> Result<bool> {
.await
.context("Failed to update MDN retries count")?;
match send_mdn_rfc724_mid(context, &rfc724_mid, contact_id, smtp).await {
match send_mdn_rfc724_mid(context, &rfc724_mid, contact_id, send_fn).await {
Err(err) => {
// If there is an error, for example there is no message corresponding to the msg_id in the
// database, do not try to send this MDN again.

View File

@@ -43,7 +43,7 @@ use crate::mimeparser::{MimeMessage, SystemMessage};
use crate::pgp::SeipdVersion;
use crate::receive_imf::{ReceivedMsg, receive_imf};
use crate::securejoin::{get_securejoin_qr, join_securejoin};
use crate::smtp::msg_has_pending_smtp_job;
use crate::smtp::{self, msg_has_pending_smtp_job};
use crate::stock_str::StockStrings;
use crate::tools::time;
@@ -1080,6 +1080,22 @@ ORDER BY id"
res
}
pub async fn get_sent_mdn(&self) -> SentMessage<'_> {
let mut sent_mdn = None;
smtp::send_mdn(self, async |_rfc724_mid, body, recipients| {
sent_mdn = Some(SentMessage {
payload: body,
sender_msg_id: MsgId::new(u32::MAX),
sender_context: &self.ctx,
recipients: recipients.join(" "),
});
Ok(true)
})
.await
.expect("smtp::send_mdn");
sent_mdn.unwrap()
}
pub async fn golden_test_chat(&self, chat_id: ChatId, filename: &str) {
let filename = Path::new("test-data/golden/").join(filename);