mirror of
https://github.com/chatmail/core.git
synced 2026-05-19 06:46:32 +03:00
Stop extracting group IDs from Message-IDs
This commit is contained in:
@@ -12,9 +12,7 @@ use crate::constants::{
|
|||||||
};
|
};
|
||||||
use crate::contact::{addr_cmp, normalize_name, Contact, Origin, VerifiedStatus};
|
use crate::contact::{addr_cmp, normalize_name, Contact, Origin, VerifiedStatus};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::dc_tools::{
|
use crate::dc_tools::{dc_create_smeared_timestamp, dc_smeared_time, time};
|
||||||
dc_create_smeared_timestamp, dc_extract_grpid_from_rfc724_mid, dc_smeared_time, time,
|
|
||||||
};
|
|
||||||
use crate::ephemeral::{stock_ephemeral_timer_changed, Timer as EphemeralTimer};
|
use crate::ephemeral::{stock_ephemeral_timer_changed, Timer as EphemeralTimer};
|
||||||
use crate::error::{bail, ensure, format_err, Result};
|
use crate::error::{bail, ensure, format_err, Result};
|
||||||
use crate::events::EventType;
|
use crate::events::EventType;
|
||||||
@@ -1132,9 +1130,9 @@ async fn create_or_lookup_group(
|
|||||||
set_better_msg(mime_parser, &better_msg);
|
set_better_msg(mime_parser, &better_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let grpid = try_getting_grpid(mime_parser);
|
let grpid = if let Some(grpid) = mime_parser.get(HeaderDef::ChatGroupId) {
|
||||||
|
grpid.clone()
|
||||||
if grpid.is_empty() {
|
} else {
|
||||||
let mut member_ids: Vec<u32> = to_ids.iter().copied().collect();
|
let mut member_ids: Vec<u32> = to_ids.iter().copied().collect();
|
||||||
if !member_ids.contains(&from_id) {
|
if !member_ids.contains(&from_id) {
|
||||||
member_ids.push(from_id);
|
member_ids.push(from_id);
|
||||||
@@ -1182,7 +1180,7 @@ async fn create_or_lookup_group(
|
|||||||
info!(context, "could not create adhoc-group: {:?}", err);
|
info!(context, "could not create adhoc-group: {:?}", err);
|
||||||
err
|
err
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// now we have a grpid that is non-empty
|
// now we have a grpid that is non-empty
|
||||||
// but we might not know about this group
|
// but we might not know about this group
|
||||||
@@ -1449,37 +1447,6 @@ async fn create_or_lookup_group(
|
|||||||
Ok((chat_id, chat_id_blocked))
|
Ok((chat_id, chat_id_blocked))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_getting_grpid(mime_parser: &MimeMessage) -> String {
|
|
||||||
if let Some(optional_field) = mime_parser.get(HeaderDef::ChatGroupId) {
|
|
||||||
return optional_field.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(extracted_grpid) = mime_parser
|
|
||||||
.get(HeaderDef::MessageId)
|
|
||||||
.and_then(|value| dc_extract_grpid_from_rfc724_mid(&value))
|
|
||||||
{
|
|
||||||
return extracted_grpid.to_string();
|
|
||||||
}
|
|
||||||
if !mime_parser.has_chat_version() {
|
|
||||||
if let Some(extracted_grpid) = extract_grpid(mime_parser, HeaderDef::InReplyTo) {
|
|
||||||
return extracted_grpid.to_string();
|
|
||||||
} else if let Some(extracted_grpid) = extract_grpid(mime_parser, HeaderDef::References) {
|
|
||||||
return extracted_grpid.to_string();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// try extract a grpid from a message-id list header value
|
|
||||||
fn extract_grpid(mime_parser: &MimeMessage, headerdef: HeaderDef) -> Option<&str> {
|
|
||||||
let header = mime_parser.get(headerdef)?;
|
|
||||||
let parts = header
|
|
||||||
.split(',')
|
|
||||||
.map(str::trim)
|
|
||||||
.filter(|part| !part.is_empty());
|
|
||||||
parts.filter_map(dc_extract_grpid_from_rfc724_mid).next()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates ad-hoc group and returns chat ID on success.
|
/// Creates ad-hoc group and returns chat ID on success.
|
||||||
async fn create_adhoc_group(
|
async fn create_adhoc_group(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
@@ -1898,42 +1865,6 @@ mod tests {
|
|||||||
assert_eq!(res, "b94d27b9934d3e08");
|
assert_eq!(res, "b94d27b9934d3e08");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
async fn test_grpid_simple() {
|
|
||||||
let context = TestContext::new().await;
|
|
||||||
let raw = b"Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
|
|
||||||
From: hello\n\
|
|
||||||
Subject: outer-subject\n\
|
|
||||||
In-Reply-To: <lqkjwelq123@123123>\n\
|
|
||||||
References: <Gr.HcxyMARjyJy.9-uvzWPTLtV@nauta.cu>\n\
|
|
||||||
\n\
|
|
||||||
hello\x00";
|
|
||||||
let mimeparser = MimeMessage::from_bytes(&context.ctx, &raw[..])
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::InReplyTo), None);
|
|
||||||
let grpid = Some("HcxyMARjyJy");
|
|
||||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::References), grpid);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
async fn test_grpid_from_multiple() {
|
|
||||||
let context = TestContext::new().await;
|
|
||||||
let raw = b"Received: (Postfix, from userid 1000); Mon, 4 Dec 2006 14:51:39 +0100 (CET)\n\
|
|
||||||
From: hello\n\
|
|
||||||
Subject: outer-subject\n\
|
|
||||||
In-Reply-To: <Gr.HcxyMARjyJy.9-qweqwe@asd.net>\n\
|
|
||||||
References: <qweqweqwe>, <Gr.HcxyMARjyJy.9-uvzWPTLtV@nau.ca>\n\
|
|
||||||
\n\
|
|
||||||
hello\x00";
|
|
||||||
let mimeparser = MimeMessage::from_bytes(&context.ctx, &raw[..])
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
let grpid = Some("HcxyMARjyJy");
|
|
||||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::InReplyTo), grpid);
|
|
||||||
assert_eq!(extract_grpid(&mimeparser, HeaderDef::References), grpid);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dc_create_incoming_rfc724_mid() {
|
fn test_dc_create_incoming_rfc724_mid() {
|
||||||
let mut members = ContactIds::new();
|
let mut members = ContactIds::new();
|
||||||
|
|||||||
@@ -279,31 +279,6 @@ pub(crate) fn dc_create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the group id (grpid) from a message id (mid)
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `mid` - A string that holds the message id. Leading/Trailing <>
|
|
||||||
/// characters are automatically stripped.
|
|
||||||
pub(crate) fn dc_extract_grpid_from_rfc724_mid(mid: &str) -> Option<&str> {
|
|
||||||
let mid = mid.trim_start_matches('<').trim_end_matches('>');
|
|
||||||
|
|
||||||
if mid.len() < 9 || !mid.starts_with("Gr.") {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(mid_without_offset) = mid.get(3..) {
|
|
||||||
if let Some(grpid_len) = mid_without_offset.find('.') {
|
|
||||||
/* strict length comparison, the 'Gr.' magic is weak enough */
|
|
||||||
if grpid_len == 11 || grpid_len == 16 {
|
|
||||||
return Some(mid_without_offset.get(0..grpid_len).unwrap());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
// the returned suffix is lower-case
|
// the returned suffix is lower-case
|
||||||
pub fn dc_get_filesuffix_lc(path_filename: impl AsRef<str>) -> Option<String> {
|
pub fn dc_get_filesuffix_lc(path_filename: impl AsRef<str>) -> Option<String> {
|
||||||
Path::new(path_filename.as_ref())
|
Path::new(path_filename.as_ref())
|
||||||
@@ -785,56 +760,18 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dc_extract_grpid_from_rfc724_mid() {
|
|
||||||
// Should return None if we pass invalid mid
|
|
||||||
let mid = "foobar";
|
|
||||||
let grpid = dc_extract_grpid_from_rfc724_mid(mid);
|
|
||||||
assert_eq!(grpid, None);
|
|
||||||
|
|
||||||
// Should return None if grpid has a length which is not 11 or 16
|
|
||||||
let mid = "Gr.12345678.morerandom@domain.de";
|
|
||||||
let grpid = dc_extract_grpid_from_rfc724_mid(mid);
|
|
||||||
assert_eq!(grpid, None);
|
|
||||||
|
|
||||||
// Should return extracted grpid for grpid with length of 11
|
|
||||||
let mid = "Gr.12345678901.morerandom@domain.de";
|
|
||||||
let grpid = dc_extract_grpid_from_rfc724_mid(mid);
|
|
||||||
assert_eq!(grpid, Some("12345678901"));
|
|
||||||
|
|
||||||
// Should return extracted grpid for grpid with length of 11
|
|
||||||
let mid = "Gr.1234567890123456.morerandom@domain.de";
|
|
||||||
let grpid = dc_extract_grpid_from_rfc724_mid(mid);
|
|
||||||
assert_eq!(grpid, Some("1234567890123456"));
|
|
||||||
|
|
||||||
// Should return extracted grpid for grpid with length of 11
|
|
||||||
let mid = "<Gr.12345678901.morerandom@domain.de>";
|
|
||||||
let grpid = dc_extract_grpid_from_rfc724_mid(mid);
|
|
||||||
assert_eq!(grpid, Some("12345678901"));
|
|
||||||
|
|
||||||
// Should return extracted grpid for grpid with length of 11
|
|
||||||
let mid = "<Gr.1234567890123456.morerandom@domain.de>";
|
|
||||||
let grpid = dc_extract_grpid_from_rfc724_mid(mid);
|
|
||||||
assert_eq!(grpid, Some("1234567890123456"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dc_create_outgoing_rfc724_mid() {
|
fn test_dc_create_outgoing_rfc724_mid() {
|
||||||
// create a normal message-id
|
// create a normal message-id
|
||||||
let mid = dc_create_outgoing_rfc724_mid(None, "foo@bar.de");
|
let mid = dc_create_outgoing_rfc724_mid(None, "foo@bar.de");
|
||||||
assert!(mid.starts_with("Mr."));
|
assert!(mid.starts_with("Mr."));
|
||||||
assert!(mid.ends_with("bar.de"));
|
assert!(mid.ends_with("bar.de"));
|
||||||
assert!(dc_extract_grpid_from_rfc724_mid(mid.as_str()).is_none());
|
|
||||||
|
|
||||||
// create a message-id containing a group-id
|
// create a message-id containing a group-id
|
||||||
let grpid = dc_create_id();
|
let grpid = dc_create_id();
|
||||||
let mid = dc_create_outgoing_rfc724_mid(Some(&grpid), "foo@bar.de");
|
let mid = dc_create_outgoing_rfc724_mid(Some(&grpid), "foo@bar.de");
|
||||||
assert!(mid.starts_with("Gr."));
|
assert!(mid.starts_with("Gr."));
|
||||||
assert!(mid.ends_with("bar.de"));
|
assert!(mid.ends_with("bar.de"));
|
||||||
assert_eq!(
|
|
||||||
dc_extract_grpid_from_rfc724_mid(mid.as_str()),
|
|
||||||
Some(grpid.as_str())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use async_std::sync::Receiver;
|
|||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
use crate::constants::{
|
use crate::constants::{
|
||||||
ShowEmails, Viewtype, DC_CONTACT_ID_SELF, DC_FETCH_EXISTING_MSGS_COUNT,
|
Chattype, ShowEmails, Viewtype, DC_CONTACT_ID_SELF, DC_FETCH_EXISTING_MSGS_COUNT,
|
||||||
DC_FOLDERS_CONFIGURED_VERSION, DC_LP_AUTH_OAUTH2,
|
DC_FOLDERS_CONFIGURED_VERSION, DC_LP_AUTH_OAUTH2,
|
||||||
};
|
};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
@@ -30,9 +30,7 @@ use crate::mimeparser;
|
|||||||
use crate::oauth2::dc_get_oauth2_access_token;
|
use crate::oauth2::dc_get_oauth2_access_token;
|
||||||
use crate::param::Params;
|
use crate::param::Params;
|
||||||
use crate::provider::Socket;
|
use crate::provider::Socket;
|
||||||
use crate::{
|
use crate::{chat, scheduler::InterruptInfo, stock::StockMessage};
|
||||||
chat, dc_tools::dc_extract_grpid_from_rfc724_mid, scheduler::InterruptInfo, stock::StockMessage,
|
|
||||||
};
|
|
||||||
use crate::{config::Config, dc_receive_imf::dc_receive_imf_inner};
|
use crate::{config::Config, dc_receive_imf::dc_receive_imf_inner};
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
@@ -41,7 +39,6 @@ pub mod scan_folders;
|
|||||||
pub mod select_folder;
|
pub mod select_folder;
|
||||||
mod session;
|
mod session;
|
||||||
|
|
||||||
use chat::get_chat_id_by_grpid;
|
|
||||||
use client::Client;
|
use client::Client;
|
||||||
use mailparse::SingleInfo;
|
use mailparse::SingleInfo;
|
||||||
use message::Message;
|
use message::Message;
|
||||||
@@ -1603,23 +1600,18 @@ pub(crate) async fn prefetch_should_download(
|
|||||||
headers: &[mailparse::MailHeader<'_>],
|
headers: &[mailparse::MailHeader<'_>],
|
||||||
show_emails: ShowEmails,
|
show_emails: ShowEmails,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
if let Some(rfc724_mid) = headers.get_header_value(HeaderDef::MessageId) {
|
let is_chat_message = headers.get_header_value(HeaderDef::ChatVersion).is_some();
|
||||||
if let Some(group_id) = dc_extract_grpid_from_rfc724_mid(&rfc724_mid) {
|
let parent = get_prefetch_parent_message(context, headers).await?;
|
||||||
if let Ok((chat_id, _, _)) = get_chat_id_by_grpid(context, group_id).await {
|
let is_reply_to_chat_message = parent.is_some();
|
||||||
if !chat_id.is_unset() {
|
if let Some(parent) = parent {
|
||||||
// This might be a group command, like removing a group member.
|
let chat = chat::Chat::load_from_db(context, parent.get_chat_id()).await?;
|
||||||
// We really need to fetch this to avoid inconsistent group state.
|
if chat.typ == Chattype::Group {
|
||||||
return Ok(true);
|
// This might be a group command, like removing a group member.
|
||||||
}
|
// We really need to fetch this to avoid inconsistent group state.
|
||||||
}
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_chat_message = headers.get_header_value(HeaderDef::ChatVersion).is_some();
|
|
||||||
let is_reply_to_chat_message = get_prefetch_parent_message(context, headers)
|
|
||||||
.await?
|
|
||||||
.is_some();
|
|
||||||
|
|
||||||
let maybe_ndn = if let Some(from) = headers.get_header_value(HeaderDef::From_) {
|
let maybe_ndn = if let Some(from) = headers.get_header_value(HeaderDef::From_) {
|
||||||
let from = from.to_ascii_lowercase();
|
let from = from.to_ascii_lowercase();
|
||||||
from.contains("mailer-daemon") || from.contains("mail-daemon")
|
from.contains("mailer-daemon") || from.contains("mail-daemon")
|
||||||
|
|||||||
Reference in New Issue
Block a user