Bump to Rust 2024

This commit is contained in:
mdecimus
2025-02-21 09:59:23 +01:00
parent b1d6e71715
commit 44f8ef29e1
92 changed files with 570 additions and 477 deletions

View File

@@ -1,7 +1,7 @@
[package]
name = "spam-filter"
version = "0.11.5"
edition = "2021"
edition = "2024"
resolver = "2"
[dependencies]

View File

@@ -7,11 +7,11 @@
use std::{collections::HashSet, future::Future, vec};
use common::{
scripts::{
functions::{array::cosine_similarity, unicode::CharUtils},
IsMixedCharset,
},
Server,
scripts::{
IsMixedCharset,
functions::{array::cosine_similarity, unicode::CharUtils},
},
};
use mail_parser::{HeaderName, MimeHeaders, PartType};
use nlp::tokenizers::types::TokenType;
@@ -291,7 +291,7 @@ impl SpamFilterAnalyzeMime for Server {
&& ct_subtype == "plain"
&& ct
.and_then(|ct| ct.attribute("charset"))
.map_or(true, |c| c.is_empty())
.is_none_or(|c| c.is_empty())
{
// Charset header is missing
ctx.result.add_tag("MISSING_CHARSET");
@@ -339,7 +339,7 @@ impl SpamFilterAnalyzeMime for Server {
"octet-stream" => {
if !is_encrypted
&& !has_content_id
&& cd.map_or(true, |cd| {
&& cd.is_none_or(|cd| {
!cd.c_type.eq_ignore_ascii_case("attachment")
&& !cd.has_attribute("filename")
})

View File

@@ -6,7 +6,7 @@
use std::future::Future;
use common::{scripts::functions::text::levenshtein_distance, Server};
use common::{Server, scripts::functions::text::levenshtein_distance};
use mail_parser::HeaderName;
use smtp_proto::{MAIL_BODY_8BITMIME, MAIL_BODY_BINARYMIME, MAIL_SMTPUTF8};
use store::ahash::HashSet;
@@ -85,7 +85,7 @@ impl SpamFilterAnalyzeRecipient for Server {
// Validate unnecessary encoding in recipient headers
let raw_utf8 = raw_utf8.unwrap_or_default();
if recipients.iter().all(|rcpt| {
rcpt.name.as_ref().map_or(true, |name| name.is_ascii())
rcpt.name.as_ref().is_none_or(|name| name.is_ascii())
&& rcpt.email.address.is_ascii()
}) && raw_utf8.contains("=?")
&& raw_utf8.contains("?=")

View File

@@ -6,12 +6,12 @@
use std::{borrow::Cow, collections::HashSet, future::Future, time::Duration};
use common::{ip_to_bytes, Server, KV_BAYES_MODEL_GLOBAL, KV_BAYES_MODEL_USER};
use common::{KV_BAYES_MODEL_GLOBAL, KV_BAYES_MODEL_USER, Server, ip_to_bytes};
use mail_auth::DmarcResult;
use nlp::{
bayes::{
tokenize::{symbols, BayesInputToken, BayesTokenizer},
BayesModel, TokenHash, Weights,
tokenize::{BayesInputToken, BayesTokenizer, symbols},
},
tokenizers::{
osb::{Gram, OsbToken, OsbTokenizer},
@@ -22,7 +22,7 @@ use store::dispatch::lookup::KeyValue;
use trc::AddContext;
use utils::cache::TtlEntry;
use crate::{analysis::url::UrlParts, Email, IpParts, SpamFilterContext, TextPart};
use crate::{Email, IpParts, SpamFilterContext, TextPart, analysis::url::UrlParts};
pub trait BayesClassifier {
fn bayes_train(
@@ -116,9 +116,11 @@ impl BayesClassifier for Server {
}
if model.weights.is_empty() {
trc::bail!(trc::SpamEvent::TrainError
.into_err()
.reason("No weights found"));
trc::bail!(
trc::SpamEvent::TrainError
.into_err()
.reason("No weights found")
);
}
trc::event!(
@@ -216,8 +218,7 @@ impl BayesClassifier for Server {
ctx.input.account_id,
TokenHash::from(Gram::Uni { t1: &token }),
)
.await
.map(Weights::from)?;
.await?;
osb_tokens.push(OsbToken {
inner: weights,
idx: 1,
@@ -234,8 +235,7 @@ impl BayesClassifier for Server {
) {
let weights = self
.bayes_weights_for_token(ctx.input.account_id, token.inner)
.await
.map(Weights::from)?;
.await?;
osb_tokens.push(OsbToken {
inner: weights,
idx: token.idx,
@@ -260,8 +260,7 @@ impl BayesClassifier for Server {
) {
let weights = self
.bayes_weights_for_token(ctx.input.account_id, token.inner)
.await
.map(Weights::from)?;
.await?;
osb_tokens.push(OsbToken {
inner: weights,
idx: token.idx,
@@ -275,8 +274,7 @@ impl BayesClassifier for Server {
) {
let weights = self
.bayes_weights_for_token(ctx.input.account_id, token.inner)
.await
.map(Weights::from)?;
.await?;
osb_tokens.push(OsbToken {
inner: weights,
idx: token.idx,
@@ -365,10 +363,11 @@ impl BayesClassifier for Server {
};
if let Some(account_id) = ctx.input.account_id {
trc::error!(err
.span_id(ctx.input.span_id)
.account_id(account_id)
.caused_by(trc::location!()));
trc::error!(
err.span_id(ctx.input.span_id)
.account_id(account_id)
.caused_by(trc::location!())
);
} else {
trc::error!(err.span_id(ctx.input.span_id).caused_by(trc::location!()));
}

View File

@@ -25,46 +25,46 @@ pub enum HtmlToken {
}
pub(crate) const A: u64 = b'a' as u64;
pub(crate) const IMG: u64 = (b'i' as u64) | (b'm' as u64) << 8 | (b'g' as u64) << 16;
pub(crate) const IMG: u64 = (b'i' as u64) | ((b'm' as u64) << 8) | ((b'g' as u64) << 16);
pub(crate) const HEAD: u64 =
(b'h' as u64) | (b'e' as u64) << 8 | (b'a' as u64) << 16 | (b'd' as u64) << 24;
(b'h' as u64) | ((b'e' as u64) << 8) | ((b'a' as u64) << 16) | ((b'd' as u64) << 24);
pub(crate) const BODY: u64 =
(b'b' as u64) | (b'o' as u64) << 8 | (b'd' as u64) << 16 | (b'y' as u64) << 24;
(b'b' as u64) | ((b'o' as u64) << 8) | ((b'd' as u64) << 16) | ((b'y' as u64) << 24);
pub(crate) const META: u64 =
(b'm' as u64) | (b'e' as u64) << 8 | (b't' as u64) << 16 | (b'a' as u64) << 24;
(b'm' as u64) | ((b'e' as u64) << 8) | ((b't' as u64) << 16) | ((b'a' as u64) << 24);
pub(crate) const LINK: u64 =
(b'l' as u64) | (b'i' as u64) << 8 | (b'n' as u64) << 16 | (b'k' as u64) << 24;
(b'l' as u64) | ((b'i' as u64) << 8) | ((b'n' as u64) << 16) | ((b'k' as u64) << 24);
pub(crate) const HREF: u64 =
(b'h' as u64) | (b'r' as u64) << 8 | (b'e' as u64) << 16 | (b'f' as u64) << 24;
pub(crate) const SRC: u64 = (b's' as u64) | (b'r' as u64) << 8 | (b'c' as u64) << 16;
(b'h' as u64) | ((b'r' as u64) << 8) | ((b'e' as u64) << 16) | ((b'f' as u64) << 24);
pub(crate) const SRC: u64 = (b's' as u64) | ((b'r' as u64) << 8) | ((b'c' as u64) << 16);
pub(crate) const WIDTH: u64 = (b'w' as u64)
| (b'i' as u64) << 8
| (b'd' as u64) << 16
| (b't' as u64) << 24
| (b'h' as u64) << 32;
| ((b'i' as u64) << 8)
| ((b'd' as u64) << 16)
| ((b't' as u64) << 24)
| ((b'h' as u64) << 32);
pub(crate) const HEIGHT: u64 = (b'h' as u64)
| (b'e' as u64) << 8
| (b'i' as u64) << 16
| (b'g' as u64) << 24
| (b'h' as u64) << 32
| (b't' as u64) << 40;
pub(crate) const REL: u64 = (b'r' as u64) | (b'e' as u64) << 8 | (b'l' as u64) << 16;
| ((b'e' as u64) << 8)
| ((b'i' as u64) << 16)
| ((b'g' as u64) << 24)
| ((b'h' as u64) << 32)
| ((b't' as u64) << 40);
pub(crate) const REL: u64 = (b'r' as u64) | ((b'e' as u64) << 8) | ((b'l' as u64) << 16);
pub(crate) const CONTENT: u64 = (b'c' as u64)
| (b'o' as u64) << 8
| (b'n' as u64) << 16
| (b't' as u64) << 24
| (b'e' as u64) << 32
| (b'n' as u64) << 40
| (b't' as u64) << 48;
| ((b'o' as u64) << 8)
| ((b'n' as u64) << 16)
| ((b't' as u64) << 24)
| ((b'e' as u64) << 32)
| ((b'n' as u64) << 40)
| ((b't' as u64) << 48);
pub(crate) const HTTP_EQUIV: u64 = (b'h' as u64)
| (b't' as u64) << 8
| (b't' as u64) << 16
| (b'p' as u64) << 24
| (b'-' as u64) << 32
| (b'e' as u64) << 40
| (b'q' as u64) << 48
| (b'u' as u64) << 56;
| ((b't' as u64) << 8)
| ((b't' as u64) << 16)
| ((b'p' as u64) << 24)
| ((b'-' as u64) << 32)
| ((b'e' as u64) << 40)
| ((b'q' as u64) << 48)
| ((b'u' as u64) << 56);
pub fn html_to_tokens(input: &str) -> Vec<HtmlToken> {
let input = input.as_bytes();
@@ -98,7 +98,7 @@ pub fn html_to_tokens(input: &str) -> Vec<HtmlToken> {
});
}
while matches!(iter.peek(), Some((_, &ch)) if ch.is_ascii_whitespace()) {
while matches!(iter.peek(), Some(&(_, &ch)) if ch.is_ascii_whitespace()) {
pos += 1;
iter.next();
}
@@ -135,7 +135,7 @@ pub fn html_to_tokens(input: &str) -> Vec<HtmlToken> {
let mut is_end_tag = false;
loop {
match iter.peek() {
Some((_, &b'/')) => {
Some(&(_, &b'/')) => {
is_end_tag = true;
pos += 1;
iter.next();
@@ -184,7 +184,7 @@ pub fn html_to_tokens(input: &str) -> Vec<HtmlToken> {
in_quote = !in_quote;
}
b'=' if !in_quote => {
while matches!(iter.peek(), Some((_, &ch)) if ch.is_ascii_whitespace())
while matches!(iter.peek(), Some(&(_, &ch)) if ch.is_ascii_whitespace())
{
iter.next();
}