mirror of
https://github.com/chatmail/core.git
synced 2026-04-26 01:46:34 +03:00
feat: mimefactory: Order message recipients by time of addition (#6872)
Sort recipients by `add_timestamp DESC` so that if the group is large and there are multiple SMTP messages, a newly added member receives the member addition message earlier and has gossiped keys of other members (otherwise the new member may receive messages from other members earlier and fail to verify them).
This commit is contained in:
@@ -253,6 +253,10 @@ impl MimeFactory {
|
||||
let mut missing_key_addresses = BTreeSet::new();
|
||||
context
|
||||
.sql
|
||||
// Sort recipients by `add_timestamp DESC` so that if the group is large and there
|
||||
// are multiple SMTP messages, a newly added member receives the member addition
|
||||
// message earlier and has gossiped keys of other members (otherwise the new member
|
||||
// may receive messages from other members earlier and fail to verify them).
|
||||
.query_map(
|
||||
"SELECT
|
||||
c.authname,
|
||||
@@ -266,7 +270,8 @@ impl MimeFactory {
|
||||
LEFT JOIN contacts c ON cc.contact_id=c.id
|
||||
LEFT JOIN public_keys k ON k.fingerprint=c.fingerprint
|
||||
WHERE cc.chat_id=?
|
||||
AND (cc.contact_id>9 OR (cc.contact_id=1 AND ?))",
|
||||
AND (cc.contact_id>9 OR (cc.contact_id=1 AND ?))
|
||||
ORDER BY cc.add_timestamp DESC",
|
||||
(msg.chat_id, chat.typ == Chattype::Group),
|
||||
|row| {
|
||||
let authname: String = row.get(0)?;
|
||||
|
||||
@@ -2,6 +2,7 @@ use deltachat_contact_tools::ContactAddress;
|
||||
use mail_builder::headers::Header;
|
||||
use mailparse::{MailHeaderMap, addrparse_header};
|
||||
use std::str;
|
||||
use std::time::Duration;
|
||||
|
||||
use super::*;
|
||||
use crate::chat::{
|
||||
@@ -16,6 +17,7 @@ use crate::message;
|
||||
use crate::mimeparser::MimeMessage;
|
||||
use crate::receive_imf::receive_imf;
|
||||
use crate::test_utils::{TestContext, TestContextManager, get_chat_msg};
|
||||
use crate::tools::SystemTime;
|
||||
|
||||
fn render_email_address(display_name: &str, addr: &str) -> String {
|
||||
let mut output = Vec::<u8>::new();
|
||||
@@ -867,6 +869,43 @@ async fn test_dont_remove_self() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_new_member_is_first_recipient() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
let charlie = &tcm.charlie().await;
|
||||
|
||||
let bob_id = alice.add_or_lookup_contact_id(bob).await;
|
||||
let charlie_id = alice.add_or_lookup_contact_id(charlie).await;
|
||||
|
||||
let group = alice
|
||||
.create_group_with_members(ProtectionStatus::Unprotected, "Group", &[bob])
|
||||
.await;
|
||||
alice.send_text(group, "Hi! I created a group.").await;
|
||||
|
||||
SystemTime::shift(Duration::from_secs(60));
|
||||
add_contact_to_chat(alice, group, charlie_id).await?;
|
||||
let sent_msg = alice.pop_sent_msg().await;
|
||||
assert!(
|
||||
sent_msg
|
||||
.recipients
|
||||
.starts_with(&charlie.get_config(Config::Addr).await?.unwrap())
|
||||
);
|
||||
|
||||
remove_contact_from_chat(alice, group, bob_id).await?;
|
||||
alice.pop_sent_msg().await;
|
||||
SystemTime::shift(Duration::from_secs(60));
|
||||
add_contact_to_chat(alice, group, bob_id).await?;
|
||||
let sent_msg = alice.pop_sent_msg().await;
|
||||
assert!(
|
||||
sent_msg
|
||||
.recipients
|
||||
.starts_with(&bob.get_config(Config::Addr).await?.unwrap())
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Regression test: mimefactory should never create an empty to header,
|
||||
/// also not if the Selftalk parameter is missing
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
|
||||
Reference in New Issue
Block a user