mirror of
https://github.com/chatmail/core.git
synced 2026-04-19 14:36:29 +03:00
fix: do not require the Message to render MDN
This commit is contained in:
95
src/smtp.rs
95
src/smtp.rs
@@ -361,7 +361,7 @@ pub(crate) async fn smtp_send(
|
||||
recipients: &[async_smtp::EmailAddress],
|
||||
message: &str,
|
||||
smtp: &mut Smtp,
|
||||
msg_id: MsgId,
|
||||
msg_id: Option<MsgId>,
|
||||
) -> SendResult {
|
||||
if std::env::var(crate::DCC_MIME_DEBUG).is_ok() {
|
||||
info!(context, "SMTP-sending out mime message:\n{message}");
|
||||
@@ -489,19 +489,22 @@ pub(crate) async fn smtp_send(
|
||||
};
|
||||
|
||||
if let SendResult::Failure(err) = &status {
|
||||
// We couldn't send the message, so mark it as failed
|
||||
match Message::load_from_db(context, msg_id).await {
|
||||
Ok(mut msg) => {
|
||||
if let Err(err) = message::set_msg_failed(context, &mut msg, &err.to_string()).await
|
||||
{
|
||||
error!(context, "Failed to mark {msg_id} as failed: {err:#}.");
|
||||
if let Some(msg_id) = msg_id {
|
||||
// We couldn't send the message, so mark it as failed
|
||||
match Message::load_from_db(context, msg_id).await {
|
||||
Ok(mut msg) => {
|
||||
if let Err(err) =
|
||||
message::set_msg_failed(context, &mut msg, &err.to_string()).await
|
||||
{
|
||||
error!(context, "Failed to mark {msg_id} as failed: {err:#}.");
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
context,
|
||||
"Failed to load {msg_id} to mark it as failed: {err:#}."
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
context,
|
||||
"Failed to load {msg_id} to mark it as failed: {err:#}."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,7 +580,7 @@ pub(crate) async fn send_msg_to_smtp(
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let status = smtp_send(context, &recipients_list, body.as_str(), smtp, msg_id).await;
|
||||
let status = smtp_send(context, &recipients_list, body.as_str(), smtp, Some(msg_id)).await;
|
||||
|
||||
match status {
|
||||
SendResult::Retry => {}
|
||||
@@ -706,7 +709,7 @@ pub(crate) async fn send_smtp_messages(context: &Context, connection: &mut Smtp)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tries to send MDN for message `msg_id` to `contact_id`.
|
||||
/// Tries to send MDN for message identified by `rfc724_mdn` to `contact_id`.
|
||||
///
|
||||
/// Attempts to aggregate additional MDNs for `contact_id` into sent MDN.
|
||||
///
|
||||
@@ -715,9 +718,9 @@ pub(crate) async fn send_smtp_messages(context: &Context, connection: &mut Smtp)
|
||||
/// points to non-existent message or contact.
|
||||
///
|
||||
/// Returns true on success, false on temporary error.
|
||||
async fn send_mdn_msg_id(
|
||||
async fn send_mdn_rfc724_mid(
|
||||
context: &Context,
|
||||
msg_id: MsgId,
|
||||
rfc724_mid: &str,
|
||||
contact_id: ContactId,
|
||||
smtp: &mut Smtp,
|
||||
) -> Result<bool> {
|
||||
@@ -727,26 +730,30 @@ async fn send_mdn_msg_id(
|
||||
}
|
||||
|
||||
// Try to aggregate additional MDNs into this MDN.
|
||||
let (additional_msg_ids, additional_rfc724_mids): (Vec<MsgId>, Vec<String>) = context
|
||||
let additional_rfc724_mids: Vec<String> = context
|
||||
.sql
|
||||
.query_map(
|
||||
"SELECT msg_id, rfc724_mid
|
||||
"SELECT rfc724_mid
|
||||
FROM smtp_mdns
|
||||
WHERE from_id=? AND msg_id!=?",
|
||||
(contact_id, msg_id),
|
||||
WHERE from_id=? AND rfc724_mid!=?",
|
||||
(contact_id, &rfc724_mid),
|
||||
|row| {
|
||||
let msg_id: MsgId = row.get(0)?;
|
||||
let rfc724_mid: String = row.get(1)?;
|
||||
Ok((msg_id, rfc724_mid))
|
||||
let rfc724_mid: String = row.get(0)?;
|
||||
Ok(rfc724_mid)
|
||||
},
|
||||
|rows| rows.collect::<Result<Vec<_>, _>>().map_err(Into::into),
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.unzip();
|
||||
.collect();
|
||||
|
||||
let msg = Message::load_from_db(context, msg_id).await?;
|
||||
let mimefactory = MimeFactory::from_mdn(context, &msg, additional_rfc724_mids).await?;
|
||||
let mimefactory = MimeFactory::from_mdn(
|
||||
context,
|
||||
contact_id,
|
||||
rfc724_mid.to_string(),
|
||||
additional_rfc724_mids.clone(),
|
||||
)
|
||||
.await?;
|
||||
let rendered_msg = mimefactory.render(context).await?;
|
||||
let body = rendered_msg.message;
|
||||
|
||||
@@ -755,21 +762,21 @@ async fn send_mdn_msg_id(
|
||||
.map_err(|err| format_err!("invalid recipient: {} {:?}", addr, err))?;
|
||||
let recipients = vec![recipient];
|
||||
|
||||
match smtp_send(context, &recipients, &body, smtp, msg_id).await {
|
||||
match smtp_send(context, &recipients, &body, smtp, None).await {
|
||||
SendResult::Success => {
|
||||
info!(context, "Successfully sent MDN for {msg_id}.");
|
||||
info!(context, "Successfully sent MDN for {rfc724_mid}.");
|
||||
context
|
||||
.sql
|
||||
.execute("DELETE FROM smtp_mdns WHERE msg_id = ?", (msg_id,))
|
||||
.execute("DELETE FROM smtp_mdns WHERE rfc724_mid = ?", (rfc724_mid,))
|
||||
.await?;
|
||||
if !additional_msg_ids.is_empty() {
|
||||
if !additional_rfc724_mids.is_empty() {
|
||||
let q = format!(
|
||||
"DELETE FROM smtp_mdns WHERE msg_id IN({})",
|
||||
sql::repeat_vars(additional_msg_ids.len())
|
||||
"DELETE FROM smtp_mdns WHERE rfc724_mid IN({})",
|
||||
sql::repeat_vars(additional_rfc724_mids.len())
|
||||
);
|
||||
context
|
||||
.sql
|
||||
.execute(&q, rusqlite::params_from_iter(additional_msg_ids))
|
||||
.execute(&q, rusqlite::params_from_iter(additional_rfc724_mids))
|
||||
.await?;
|
||||
}
|
||||
Ok(true)
|
||||
@@ -777,7 +784,7 @@ async fn send_mdn_msg_id(
|
||||
SendResult::Retry => {
|
||||
info!(
|
||||
context,
|
||||
"Temporary SMTP failure while sending an MDN for {msg_id}."
|
||||
"Temporary SMTP failure while sending an MDN for {rfc724_mid}."
|
||||
);
|
||||
Ok(false)
|
||||
}
|
||||
@@ -802,40 +809,40 @@ async fn send_mdn(context: &Context, smtp: &mut Smtp) -> Result<bool> {
|
||||
let Some(msg_row) = context
|
||||
.sql
|
||||
.query_row_optional(
|
||||
"SELECT msg_id, from_id FROM smtp_mdns ORDER BY retries LIMIT 1",
|
||||
"SELECT rfc724_mid, from_id FROM smtp_mdns ORDER BY retries LIMIT 1",
|
||||
[],
|
||||
|row| {
|
||||
let msg_id: MsgId = row.get(0)?;
|
||||
let rfc724_mid: String = row.get(0)?;
|
||||
let from_id: ContactId = row.get(1)?;
|
||||
Ok((msg_id, from_id))
|
||||
Ok((rfc724_mid, from_id))
|
||||
},
|
||||
)
|
||||
.await?
|
||||
else {
|
||||
return Ok(false);
|
||||
};
|
||||
let (msg_id, contact_id) = msg_row;
|
||||
let (rfc724_mid, contact_id) = msg_row;
|
||||
|
||||
context
|
||||
.sql
|
||||
.execute(
|
||||
"UPDATE smtp_mdns SET retries=retries+1 WHERE msg_id=?",
|
||||
(msg_id,),
|
||||
"UPDATE smtp_mdns SET retries=retries+1 WHERE rfc724_mid=?",
|
||||
(rfc724_mid.clone(),),
|
||||
)
|
||||
.await
|
||||
.context("Failed to update MDN retries count")?;
|
||||
|
||||
match send_mdn_msg_id(context, msg_id, contact_id, smtp).await {
|
||||
match send_mdn_rfc724_mid(context, &rfc724_mid, contact_id, smtp).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.
|
||||
warn!(
|
||||
context,
|
||||
"Error sending MDN for {msg_id}, removing it: {err:#}."
|
||||
"Error sending MDN for {rfc724_mid}, removing it: {err:#}."
|
||||
);
|
||||
context
|
||||
.sql
|
||||
.execute("DELETE FROM smtp_mdns WHERE msg_id = ?", (msg_id,))
|
||||
.execute("DELETE FROM smtp_mdns WHERE rfc724_mid = ?", (rfc724_mid,))
|
||||
.await?;
|
||||
Err(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user