diff --git a/crates/common/src/config/spamfilter.rs b/crates/common/src/config/spamfilter.rs index e8aa856d..d8b76d7b 100644 --- a/crates/common/src/config/spamfilter.rs +++ b/crates/common/src/config/spamfilter.rs @@ -451,21 +451,24 @@ impl PyzorConfig { impl ClassifierConfig { pub fn parse(config: &mut Config) -> Option { - if !config - .property_or_default("spam-filter.classifier.enable", "true") - .unwrap_or(true) - { - return None; - } + let ccfh = match config.value("spam-filter.classifier.model") { + Some("ftrl-fh") | None => false, + Some("ftrl-ccfh") => true, + Some("disabled") => return None, + Some(other) => { + config.new_build_error( + "spam-filter.classifier.model", + format!("Invalid model type: {}", other), + ); + return None; + } + }; let w_params = FtrlParameters::parse(config, "spam-filter.classifier.parameters", 20); - let i_params = if config - .property_or_default("spam-filter.classifier.ccfh.enable", "false") - .unwrap_or(false) - { + let i_params = if ccfh { Some(FtrlParameters::parse( config, - "spam-filter.classifier.ccfh.parameters", + "spam-filter.classifier.parameters.ccfh", w_params.feature_hash_size - 2, )) } else { diff --git a/crates/email/src/message/ingest.rs b/crates/email/src/message/ingest.rs index 3472ce40..e9c7f7d9 100644 --- a/crates/email/src/message/ingest.rs +++ b/crates/email/src/message/ingest.rs @@ -7,7 +7,7 @@ use super::crypto::{EncryptMessage, EncryptMessageError}; use crate::{ cache::{MessageCacheFetch, email::MessageCacheAccess, mailbox::MailboxCacheAccess}, - mailbox::{INBOX_ID, JUNK_ID, SENT_ID, UidMailbox}, + mailbox::{INBOX_ID, JUNK_ID, SENT_ID, TRASH_ID, UidMailbox}, message::{ crypto::EncryptionParams, index::{IndexMessage, extractors::VisitText}, @@ -446,7 +446,9 @@ impl EmailIngest for Server { if params.keywords.contains(&Keyword::Junk) { train_spam = Some(true); } else if params.keywords.contains(&Keyword::NotJunk) { - train_spam = Some(false); + if !params.mailbox_ids.contains(&TRASH_ID) { + train_spam = Some(false); + } } else if params.mailbox_ids[0] == JUNK_ID { train_spam = Some(true); } else if params.mailbox_ids[0] == INBOX_ID { diff --git a/crates/imap/src/op/store.rs b/crates/imap/src/op/store.rs index 472b9abd..72b81dc3 100644 --- a/crates/imap/src/op/store.rs +++ b/crates/imap/src/op/store.rs @@ -12,7 +12,10 @@ use crate::{ use ahash::AHashSet; use common::{listener::SessionStream, storage::index::ObjectIndexBuilder}; use directory::Permission; -use email::message::{ingest::EmailIngest, metadata::MessageData}; +use email::{ + mailbox::TRASH_ID, + message::{ingest::EmailIngest, metadata::MessageData}, +}; use imap_proto::{ Command, ResponseCode, ResponseType, StatusResponse, protocol::{ @@ -250,7 +253,8 @@ impl SessionData { if keyword == &Keyword::Junk { train_spam = Some(true); break; - } else if keyword == &Keyword::NotJunk { + } else if keyword == &Keyword::NotJunk && !data.inner.has_mailbox_id(TRASH_ID) { + // Only train as ham if not in Trash (Apple likes to add NotJunk to trashed items, which would be spammy) train_spam = Some(false); break; } @@ -258,7 +262,9 @@ impl SessionData { if train_spam.is_none() { for keyword in new_data.removed_keywords(data.inner) { if keyword == &Keyword::Junk { - train_spam = Some(false); + if !data.inner.has_mailbox_id(TRASH_ID) { + train_spam = Some(false); + } break; } } diff --git a/crates/store/src/backend/elastic/main.rs b/crates/store/src/backend/elastic/main.rs index c49555a6..8d814cbf 100644 --- a/crates/store/src/backend/elastic/main.rs +++ b/crates/store/src/backend/elastic/main.rs @@ -10,7 +10,6 @@ use crate::{ CalendarSearchField, ContactSearchField, EmailSearchField, SearchableField, TracingSearchField, }, - write::SearchIndex, }; use reqwest::{Error, Response, Url}; use serde_json::{Value, json}; @@ -118,6 +117,8 @@ impl ElasticSearchStore { #[cfg(feature = "test_mode")] pub async fn drop_indexes(&self) -> trc::Result<()> { + use crate::write::SearchIndex; + for index in &[ SearchIndex::Email, SearchIndex::Calendar, diff --git a/crates/store/src/backend/meili/main.rs b/crates/store/src/backend/meili/main.rs index 81cc571c..1e7fc422 100644 --- a/crates/store/src/backend/meili/main.rs +++ b/crates/store/src/backend/meili/main.rs @@ -10,7 +10,6 @@ use crate::{ CalendarSearchField, ContactSearchField, EmailSearchField, SearchableField, TracingSearchField, }, - write::SearchIndex, }; use reqwest::{Error, Response, Url}; use serde_json::{Value, json}; @@ -148,6 +147,8 @@ impl MeiliSearchStore { #[cfg(feature = "test_mode")] pub async fn drop_indexes(&self) -> trc::Result<()> { + use crate::write::SearchIndex; + for index in &[ SearchIndex::Email, SearchIndex::Calendar,