Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Don't add "Failed to send message to ..." info messages to group chats #6318

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion deltachat-ffi/deltachat.h
Original file line number Diff line number Diff line change
Expand Up @@ -6911,7 +6911,7 @@ void dc_event_unref(dc_event_t* event);

/// "Failed to send message to %1$s."
///
/// Used in status messages.
/// Unused. Was used in group chat status messages.
/// - %1$s will be replaced by the name of the contact the message cannot be sent to
#define DC_STR_FAILED_SENDING_TO 74

Expand Down
78 changes: 9 additions & 69 deletions src/mimeparser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ use rand::distributions::{Alphanumeric, DistString};
use crate::aheader::{Aheader, EncryptPreference};
use crate::authres::handle_authres;
use crate::blob::BlobObject;
use crate::chat::{add_info_msg, ChatId};
use crate::chat::ChatId;
use crate::config::Config;
use crate::constants::{self, Chattype};
use crate::contact::{Contact, ContactId, Origin};
use crate::constants;
use crate::contact::ContactId;
use crate::context::Context;
use crate::decrypt::{
get_autocrypt_peerstate, get_encrypted_mime, keyring_from_peerstate, try_decrypt,
Expand All @@ -36,8 +36,7 @@ use crate::peerstate::Peerstate;
use crate::simplify::{simplify, SimplifiedText};
use crate::sync::SyncItems;
use crate::tools::{
create_smeared_timestamp, get_filemeta, parse_receive_headers, smeared_time, truncate_msg_text,
validate_id,
get_filemeta, parse_receive_headers, smeared_time, truncate_msg_text, validate_id,
};
use crate::{chatlist_events, location, stock_str, tools};

Expand Down Expand Up @@ -1665,18 +1664,8 @@ impl MimeMessage {
.get_header_value(HeaderDef::MessageId)
.and_then(|v| parse_message_id(&v).ok())
{
let mut to_list =
get_all_addresses_from_header(&report.headers, "x-failed-recipients");
let to = if to_list.len() != 1 {
// We do not know which recipient failed
None
} else {
to_list.pop()
};

return Ok(Some(DeliveryReport {
rfc724_mid: original_message_id,
failed_recipient: to.map(|s| s.addr),
failure,
}));
}
Expand Down Expand Up @@ -1774,7 +1763,6 @@ impl MimeMessage {
{
self.delivery_report = Some(DeliveryReport {
rfc724_mid: original_message_id,
failed_recipient: None,
failure: true,
})
}
Expand Down Expand Up @@ -1912,7 +1900,6 @@ pub(crate) struct Report {
#[derive(Debug)]
pub(crate) struct DeliveryReport {
pub rfc724_mid: String,
pub failed_recipient: Option<String>,
pub failure: bool,
}

Expand Down Expand Up @@ -2278,37 +2265,26 @@ async fn handle_ndn(
let msgs: Vec<_> = context
.sql
.query_map(
concat!(
"SELECT",
" m.id AS msg_id,",
" c.id AS chat_id,",
" c.type AS type",
" FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id",
" WHERE rfc724_mid=? AND from_id=1",
),
"SELECT id FROM msgs
WHERE rfc724_mid=? AND from_id=1",
(&failed.rfc724_mid,),
|row| {
let msg_id: MsgId = row.get("msg_id")?;
let chat_id: ChatId = row.get("chat_id")?;
let chat_type: Chattype = row.get("type")?;
Ok((msg_id, chat_id, chat_type))
let msg_id: MsgId = row.get(0)?;
Ok(msg_id)
},
|rows| Ok(rows.collect::<Vec<_>>()),
)
.await?;

let error = if let Some(error) = error {
error
} else if let Some(failed_recipient) = &failed.failed_recipient {
format!("Delivery to {failed_recipient} failed.").clone()
} else {
"Delivery to at least one recipient failed.".to_string()
};
let err_msg = &error;

let mut first = true;
for msg in msgs {
let (msg_id, chat_id, chat_type) = msg?;
let msg_id = msg?;
let mut message = Message::load_from_db(context, msg_id).await?;
let aggregated_error = message
.error
Expand All @@ -2320,47 +2296,11 @@ async fn handle_ndn(
aggregated_error.as_ref().unwrap_or(err_msg),
)
.await?;
if first {
// Add only one info msg for all failed messages
ndn_maybe_add_info_msg(context, failed, chat_id, chat_type).await?;
}
first = false;
}

Ok(())
}

async fn ndn_maybe_add_info_msg(
context: &Context,
failed: &DeliveryReport,
chat_id: ChatId,
chat_type: Chattype,
) -> Result<()> {
match chat_type {
Chattype::Group | Chattype::Broadcast => {
if let Some(failed_recipient) = &failed.failed_recipient {
let contact_id =
Contact::lookup_id_by_addr(context, failed_recipient, Origin::Unknown)
.await?
.context("contact ID not found")?;
let contact = Contact::get_by_id(context, contact_id).await?;
// Tell the user which of the recipients failed if we know that (because in
// a group, this might otherwise be unclear)
let text = stock_str::failed_sending_to(context, contact.get_display_name()).await;
add_info_msg(context, chat_id, &text, create_smeared_timestamp(context)).await?;
context.emit_event(EventType::ChatModified(chat_id));
}
}
Chattype::Mailinglist => {
// ndn_maybe_add_info_msg() is about the case when delivery to the group failed.
// If we get an NDN for the mailing list, just issue a warning.
warn!(context, "ignoring NDN for mailing list.");
}
Chattype::Single => {}
}
Ok(())
}

#[cfg(test)]
mod tests {
use mailparse::ParsedMail;
Expand Down
12 changes: 2 additions & 10 deletions src/receive_imf/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,18 +868,10 @@ async fn test_parse_ndn_group_msg() -> Result<()> {
assert_eq!(msg.state, MessageState::OutFailed);

let msgs = chat::get_chat_msgs(&t, msg.chat_id).await?;
let msg_id = if let ChatItem::Message { msg_id } = msgs.last().unwrap() {
msg_id
} else {
let ChatItem::Message { msg_id } = *msgs.last().unwrap() else {
panic!("Wrong item type");
};
let last_msg = Message::load_from_db(&t, *msg_id).await?;

assert_eq!(
last_msg.text,
stock_str::failed_sending_to(&t, "[email protected]").await
);
assert_eq!(last_msg.from_id, ContactId::INFO);
assert_eq!(msg_id, msg.id);
Ok(())
}

Expand Down
8 changes: 1 addition & 7 deletions src/stock_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ pub enum StockMessage {
#[strum(props(fallback = "Message from %1$s"))]
SubjectForNewContact = 73,

/// Unused. Was used in group chat status messages.
#[strum(props(fallback = "Failed to send message to %1$s."))]
FailedSendingTo = 74,

Expand Down Expand Up @@ -980,13 +981,6 @@ pub(crate) async fn subject_for_new_contact(context: &Context, self_name: &str)
.replace1(self_name)
}

/// Stock string: `Failed to send message to %1$s.`.
pub(crate) async fn failed_sending_to(context: &Context, name: &str) -> String {
translated(context, StockMessage::FailedSendingTo)
.await
.replace1(name)
}

/// Stock string: `Message deletion timer is disabled.`.
pub(crate) async fn msg_ephemeral_timer_disabled(
context: &Context,
Expand Down
Loading