mirror of
https://github.com/chatmail/core.git
synced 2026-05-05 22:36:30 +03:00
First try implementing mailing lists
This commit is contained in:
17
src/chat.rs
17
src/chat.rs
@@ -2502,6 +2502,23 @@ pub(crate) fn get_chat_id_by_grpid(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_chat_id_by_mailinglistid(
|
||||||
|
context: &Context,
|
||||||
|
listid: impl AsRef<str>,
|
||||||
|
) -> Result<(ChatId, Blocked), sql::Error> {
|
||||||
|
context.sql.query_row(
|
||||||
|
"SELECT id, blocked, type FROM chats WHERE grpid=?;",
|
||||||
|
params![listid.as_ref()],
|
||||||
|
|row| {
|
||||||
|
let chat_id = row.get::<_, ChatId>(0)?;
|
||||||
|
|
||||||
|
let b = row.get::<_, Option<Blocked>>(1)?.unwrap_or_default();
|
||||||
|
Ok((chat_id, b))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Adds a message to device chat.
|
/// Adds a message to device chat.
|
||||||
///
|
///
|
||||||
/// Optional `label` can be provided to ensure that message is added only once.
|
/// Optional `label` can be provided to ensure that message is added only once.
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ pub enum Chattype {
|
|||||||
Single = 100,
|
Single = 100,
|
||||||
Group = 120,
|
Group = 120,
|
||||||
VerifiedGroup = 130,
|
VerifiedGroup = 130,
|
||||||
|
MailingList = 140,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Chattype {
|
impl Default for Chattype {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use itertools::join;
|
|||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::chat::{self, Chat, ChatId};
|
use crate::chat::{self, Chat, ChatId};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
@@ -415,9 +416,34 @@ fn add_parts(
|
|||||||
|
|
||||||
if chat_id.is_unset() {
|
if chat_id.is_unset() {
|
||||||
// check if the message belongs to a mailing list
|
// check if the message belongs to a mailing list
|
||||||
if mime_parser.is_mailinglist_message() {
|
if let Some(list_id_header) = mime_parser.get(HeaderDef::ListId) {
|
||||||
*chat_id = ChatId::new(DC_CHAT_ID_TRASH);
|
let create_blocked = if !test_normal_chat_id.is_unset()
|
||||||
info!(context, "Message belongs to a mailing list and is ignored.",);
|
&& test_normal_chat_id_blocked == Blocked::Not
|
||||||
|
{
|
||||||
|
Blocked::Not
|
||||||
|
} else {
|
||||||
|
Blocked::Deaddrop
|
||||||
|
};
|
||||||
|
|
||||||
|
let (new_chat_id, new_chat_id_blocked) = create_or_lookup_mailinglist(
|
||||||
|
context,
|
||||||
|
if test_normal_chat_id.is_unset() {
|
||||||
|
allow_creation
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
},
|
||||||
|
create_blocked,
|
||||||
|
list_id_header,
|
||||||
|
)?;
|
||||||
|
*chat_id = new_chat_id;
|
||||||
|
chat_id_blocked = new_chat_id_blocked;
|
||||||
|
if !chat_id.is_unset()
|
||||||
|
&& chat_id_blocked != Blocked::Not
|
||||||
|
&& create_blocked == Blocked::Not
|
||||||
|
{
|
||||||
|
new_chat_id.unblock(context);
|
||||||
|
chat_id_blocked = Blocked::Not;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1096,6 +1122,35 @@ fn create_or_lookup_group(
|
|||||||
Ok((chat_id, chat_id_blocked))
|
Ok((chat_id, chat_id_blocked))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_or_lookup_mailinglist(
|
||||||
|
context: &Context,
|
||||||
|
allow_creation: bool,
|
||||||
|
create_blocked: Blocked,
|
||||||
|
list_id_header: &str,
|
||||||
|
) -> Result<(ChatId, Blocked)> {
|
||||||
|
let re = Regex::new(r"^(.*.)<(.*.)>$").unwrap();
|
||||||
|
let (name, listid) = match re.captures(list_id_header) {
|
||||||
|
Some(cap) => (cap[1].to_string(), cap[2].to_string()),
|
||||||
|
None => (list_id_header.to_string(), list_id_header.to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
match chat::get_chat_id_by_mailinglistid(context, &listid) {
|
||||||
|
Ok((chat_id, blocked)) => Ok((chat_id, blocked)),
|
||||||
|
|
||||||
|
Err(_) => {
|
||||||
|
// list does not exist but should be created
|
||||||
|
|
||||||
|
if !allow_creation {
|
||||||
|
info!(context, "creating list forbidden by caller");
|
||||||
|
return Ok((ChatId::new(0), Blocked::Not));
|
||||||
|
}
|
||||||
|
|
||||||
|
let chat_id = create_mailinglist_record(context, &listid, &name, create_blocked);
|
||||||
|
Ok((chat_id, create_blocked))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// try extract a grpid from a message-id list header value
|
/// try extract a grpid from a message-id list header value
|
||||||
fn extract_grpid(mime_parser: &MimeMessage, headerdef: HeaderDef) -> Option<&str> {
|
fn extract_grpid(mime_parser: &MimeMessage, headerdef: HeaderDef) -> Option<&str> {
|
||||||
let header = mime_parser.get(headerdef)?;
|
let header = mime_parser.get(headerdef)?;
|
||||||
@@ -1258,6 +1313,46 @@ fn create_group_record(
|
|||||||
chat_id
|
chat_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_mailinglist_record(
|
||||||
|
context: &Context,
|
||||||
|
listid: impl AsRef<str>,
|
||||||
|
name: impl AsRef<str>,
|
||||||
|
create_blocked: Blocked,
|
||||||
|
) -> ChatId {
|
||||||
|
if sql::execute(
|
||||||
|
context,
|
||||||
|
&context.sql,
|
||||||
|
"INSERT INTO chats (type, name, listid, blocked, created_timestamp) VALUES(?, ?, ?, ?, ?);",
|
||||||
|
params![
|
||||||
|
Chattype::MailingList,
|
||||||
|
name.as_ref(),
|
||||||
|
listid.as_ref(),
|
||||||
|
create_blocked,
|
||||||
|
time(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
warn!(
|
||||||
|
context,
|
||||||
|
"Failed to create group '{}' for listid={}",
|
||||||
|
name.as_ref(),
|
||||||
|
listid.as_ref()
|
||||||
|
);
|
||||||
|
return ChatId::new(0);
|
||||||
|
}
|
||||||
|
let row_id = sql::get_rowid(context, &context.sql, "chats", "listid", listid.as_ref());
|
||||||
|
let chat_id = ChatId::new(row_id);
|
||||||
|
info!(
|
||||||
|
context,
|
||||||
|
"Created group '{}' listid={} as {}",
|
||||||
|
name.as_ref(),
|
||||||
|
listid.as_ref(),
|
||||||
|
chat_id
|
||||||
|
);
|
||||||
|
chat_id
|
||||||
|
}
|
||||||
|
|
||||||
fn create_adhoc_grp_id(context: &Context, member_ids: &[u32]) -> String {
|
fn create_adhoc_grp_id(context: &Context, member_ids: &[u32]) -> String {
|
||||||
/* algorithm:
|
/* algorithm:
|
||||||
- sort normalized, lowercased, e-mail addresses alphabetically
|
- sort normalized, lowercased, e-mail addresses alphabetically
|
||||||
|
|||||||
Reference in New Issue
Block a user