Move spam messages to Junk folders when spam headers are present

This commit is contained in:
mdecimus 2023-12-21 10:56:28 +01:00
parent 91e8597998
commit 57885e6db6
4 changed files with 31 additions and 2 deletions

View file

@ -141,6 +141,14 @@ impl crate::Config {
.unwrap_or(true), .unwrap_or(true),
encrypt: settings.property_or_static("jmap.encryption.enable", "true")?, encrypt: settings.property_or_static("jmap.encryption.enable", "true")?,
encrypt_append: settings.property_or_static("jmap.encryption.append", "false")?, encrypt_append: settings.property_or_static("jmap.encryption.append", "false")?,
spam_header: settings.value("jmap.spam.header").and_then(|v| {
v.split_once(':').map(|(k, v)| {
(
mail_parser::HeaderName::parse(k.trim().to_string()).unwrap(),
v.trim().to_string(),
)
})
}),
http_headers: settings http_headers: settings
.values("jmap.http.headers") .values("jmap.http.headers")
.map(|(_, v)| { .map(|(_, v)| {

View file

@ -48,7 +48,7 @@ use utils::map::vec_map::VecMap;
use crate::{ use crate::{
email::index::{IndexMessage, VisitValues, MAX_ID_LENGTH}, email::index::{IndexMessage, VisitValues, MAX_ID_LENGTH},
mailbox::UidMailbox, mailbox::{UidMailbox, INBOX_ID, JUNK_ID},
services::housekeeper::Event, services::housekeeper::Event,
IngestError, JMAP, IngestError, JMAP,
}; };
@ -84,7 +84,7 @@ impl JMAP {
#[allow(clippy::blocks_in_if_conditions)] #[allow(clippy::blocks_in_if_conditions)]
pub async fn email_ingest( pub async fn email_ingest(
&self, &self,
params: IngestEmail<'_>, mut params: IngestEmail<'_>,
) -> Result<IngestedEmail, IngestError> { ) -> Result<IngestedEmail, IngestError> {
// Check quota // Check quota
let mut raw_message_len = params.raw_message.len() as i64; let mut raw_message_len = params.raw_message.len() as i64;
@ -106,6 +106,21 @@ impl JMAP {
reason: "Failed to parse e-mail message.".to_string(), reason: "Failed to parse e-mail message.".to_string(),
})?; })?;
// Check for Spam headers
if let Some((header_name, header_value)) = &self.config.spam_header {
if params.mailbox_ids == [INBOX_ID]
&& message.root_part().headers().iter().any(|header| {
&header.name == header_name
&& header
.value()
.as_text()
.map_or(false, |value| value.contains(header_value))
})
{
params.mailbox_ids[0] = JUNK_ID;
}
}
// Obtain message references and thread name // Obtain message references and thread name
let thread_id = { let thread_id = {
let mut references = Vec::with_capacity(5); let mut references = Vec::with_capacity(5);

View file

@ -40,6 +40,7 @@ use jmap_proto::{
}, },
types::{collection::Collection, property::Property}, types::{collection::Collection, property::Property},
}; };
use mail_parser::HeaderName;
use nlp::language::Language; use nlp::language::Language;
use services::{ use services::{
delivery::spawn_delivery_manager, delivery::spawn_delivery_manager,
@ -157,6 +158,8 @@ pub struct Config {
pub oauth_expiry_refresh_token_renew: u64, pub oauth_expiry_refresh_token_renew: u64,
pub oauth_max_auth_attempts: u32, pub oauth_max_auth_attempts: u32,
pub spam_header: Option<(HeaderName<'static>, String)>,
pub http_headers: Vec<(hyper::header::HeaderName, hyper::header::HeaderValue)>, pub http_headers: Vec<(hyper::header::HeaderName, hyper::header::HeaderValue)>,
pub encrypt: bool, pub encrypt: bool,

View file

@ -11,6 +11,9 @@ blob = "__BLOB_STORE__"
enable = true enable = true
append = false append = false
[jmap.spam]
header = "X-Spam-Status: Yes"
[jmap.fts] [jmap.fts]
default-language = "en" default-language = "en"