summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormdecimus <mauro@stalw.art>2023-09-19 19:02:42 +0200
committermdecimus <mauro@stalw.art>2023-09-19 19:02:42 +0200
commit5068ecdd9e9ce9d60cb68e9f86a1d15c19033629 (patch)
treed7b1834917c235a923cf105235d02f7ef8e424f9
parentbb7f43ecab5493c2d3d8ac18fb9f8d245cdd219a (diff)
v0.3.8v0.3.8
-rw-r--r--CHANGELOG.md13
-rw-r--r--Cargo.lock88
-rw-r--r--crates/antispam/src/import/mod.rs1
-rw-r--r--crates/antispam/src/import/spamassassin.rs21
-rw-r--r--crates/cli/Cargo.toml2
-rw-r--r--crates/imap/Cargo.toml2
-rw-r--r--crates/install/Cargo.toml2
-rw-r--r--crates/jmap/Cargo.toml2
-rw-r--r--crates/main/Cargo.toml2
-rw-r--r--crates/smtp/Cargo.toml2
-rw-r--r--crates/smtp/src/config/scripts.rs3
-rw-r--r--crates/smtp/src/scripts/event_loop.rs4
-rw-r--r--crates/smtp/src/scripts/functions/html.rs2
-rw-r--r--crates/smtp/src/scripts/functions/image.rs3
-rw-r--r--crates/smtp/src/scripts/functions/misc.rs47
-rw-r--r--crates/smtp/src/scripts/functions/mod.rs31
-rw-r--r--crates/smtp/src/scripts/functions/text.rs18
-rw-r--r--crates/utils/Cargo.toml2
-rw-r--r--resources/config/sieve/html.sieve111
-rw-r--r--resources/config/sieve/subject.sieve83
-rw-r--r--tests/resources/smtp/antispam/base64.txt142
-rw-r--r--tests/resources/smtp/antispam/html.test239
-rw-r--r--tests/resources/smtp/antispam/html_mime.txt94
-rw-r--r--tests/resources/smtp/antispam/multipart_alternative.txt217
-rw-r--r--tests/resources/smtp/antispam/quoted_printable.txt93
-rw-r--r--tests/resources/smtp/antispam/received.txt45
-rw-r--r--tests/resources/smtp/antispam/subject.test5
-rw-r--r--tests/resources/smtp/antispam/text.txt64
-rw-r--r--tests/src/smtp/inbound/antispam.rs60
29 files changed, 632 insertions, 766 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21a6b4cf..1708c705 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/).
+## [0.3.8] - 2023-09-19
+
+## Added
+- Journal logging support
+- IMAP support for UTF8 APPEND
+
+### Changed
+- Replaced `rpgp` with `sequoia-pgp` due to rpgp bug.
+
+### Fixed
+- Fix: IMAP folders that contain a & can't be used (#90)
+- Fix: Ignore empty lines in IMAP requests
+
## [0.3.7] - 2023-09-05
## Added
diff --git a/Cargo.lock b/Cargo.lock
index 076541f4..bb2c5025 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -93,9 +93,9 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.0.5"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783"
+checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0"
dependencies = [
"memchr",
]
@@ -262,7 +262,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -284,7 +284,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -295,7 +295,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -506,7 +506,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
- "syn 2.0.33",
+ "syn 2.0.37",
"which",
]
@@ -805,9 +805,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.4.3"
+version = "4.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6"
+checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
dependencies = [
"clap_builder",
"clap_derive",
@@ -815,9 +815,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.4.2"
+version = "4.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
+checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
dependencies = [
"anstream",
"anstyle",
@@ -834,7 +834,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -1285,7 +1285,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -1308,9 +1308,9 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "dyn-clone"
-version = "1.0.13"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555"
+checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd"
[[package]]
name = "eax"
@@ -1457,7 +1457,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -1685,7 +1685,7 @@ checksum = "83c8d52fe8b46ab822b4decdcc0d6d85aeedfc98f0d52ba2bd4aec4a97807516"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
"try_map",
]
@@ -1771,7 +1771,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -2146,11 +2146,13 @@ dependencies = [
[[package]]
name = "hyper-util"
version = "0.0.0"
-source = "git+https://github.com/hyperium/hyper-util#229757e565e0935a7a3b1d0f9e9ab88d9310e779"
+source = "git+https://github.com/hyperium/hyper-util#450cca83f141b263a4add02938ffeb5518cbddc2"
dependencies = [
+ "bytes",
"futures-channel",
"futures-util",
"http",
+ "http-body 1.0.0-rc.2",
"hyper 1.0.0-rc.4",
"once_cell",
"pin-project-lite",
@@ -2221,7 +2223,7 @@ checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
[[package]]
name = "imap"
-version = "0.3.7"
+version = "0.3.8"
dependencies = [
"ahash 0.8.3",
"dashmap",
@@ -2395,7 +2397,7 @@ dependencies = [
[[package]]
name = "jmap"
-version = "0.3.7"
+version = "0.3.8"
dependencies = [
"aes",
"aes-gcm",
@@ -2735,7 +2737,7 @@ dependencies = [
[[package]]
name = "mail-parser"
version = "0.9.0"
-source = "git+https://github.com/stalwartlabs/mail-parser#e5a4e65112fd8aa4c527d37b87413d939f1259a1"
+source = "git+https://github.com/stalwartlabs/mail-parser#816d944f2e29e024e93eca8b0980e50ecb54aa4b"
dependencies = [
"encoding_rs",
"serde",
@@ -2758,7 +2760,7 @@ dependencies = [
[[package]]
name = "mail-server"
-version = "0.3.7"
+version = "0.3.8"
dependencies = [
"directory",
"imap",
@@ -3110,7 +3112,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -3121,9 +3123,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-src"
-version = "300.1.3+3.1.2"
+version = "300.1.4+3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd2c101a165fff9935e34def4669595ab1c7847943c42be86e21503e482be107"
+checksum = "80b6658b21fe1eba923af26cfe9c57a1a075a8190df2cd869a9bcd730093ffa2"
dependencies = [
"cc",
]
@@ -3428,7 +3430,7 @@ dependencies = [
"phf_shared 0.11.2",
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -3466,7 +3468,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -3545,7 +3547,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d"
dependencies = [
"proc-macro2",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -4406,7 +4408,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -4454,7 +4456,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -4550,7 +4552,7 @@ checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
[[package]]
name = "sieve-rs"
version = "0.3.1"
-source = "git+https://github.com/stalwartlabs/sieve#d3f4c738e032707c5dbfcf0236fe57f0a49fbbb7"
+source = "git+https://github.com/stalwartlabs/sieve#0392401321ec961a54c4b1a3235a1c2d02b45972"
dependencies = [
"ahash 0.8.3",
"bincode",
@@ -4609,7 +4611,7 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
[[package]]
name = "smtp"
-version = "0.3.7"
+version = "0.3.8"
dependencies = [
"ahash 0.8.3",
"blake3",
@@ -4934,7 +4936,7 @@ dependencies = [
[[package]]
name = "stalwart-cli"
-version = "0.3.7"
+version = "0.3.8"
dependencies = [
"clap",
"console",
@@ -4956,7 +4958,7 @@ dependencies = [
[[package]]
name = "stalwart-install"
-version = "0.3.7"
+version = "0.3.8"
dependencies = [
"base64 0.21.4",
"clap",
@@ -5069,9 +5071,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.33"
+version = "2.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668"
+checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
dependencies = [
"proc-macro2",
"quote",
@@ -5202,7 +5204,7 @@ checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -5314,7 +5316,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -5471,7 +5473,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
@@ -5768,7 +5770,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "utils"
-version = "0.3.7"
+version = "0.3.8"
dependencies = [
"ahash 0.8.3",
"dashmap",
@@ -5860,7 +5862,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
"wasm-bindgen-shared",
]
@@ -5894,7 +5896,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -6254,7 +6256,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.33",
+ "syn 2.0.37",
]
[[package]]
diff --git a/crates/antispam/src/import/mod.rs b/crates/antispam/src/import/mod.rs
index 76bd3e6c..0e180d8c 100644
--- a/crates/antispam/src/import/mod.rs
+++ b/crates/antispam/src/import/mod.rs
@@ -72,6 +72,7 @@ enum TestFlag {
Learn,
NoAutoLearn,
Publish,
+ NoPublish,
Multiple,
NoTrim,
DomainsOnly,
diff --git a/crates/antispam/src/import/spamassassin.rs b/crates/antispam/src/import/spamassassin.rs
index 0198af0d..3ba575b9 100644
--- a/crates/antispam/src/import/spamassassin.rs
+++ b/crates/antispam/src/import/spamassassin.rs
@@ -750,6 +750,7 @@ pub fn import_spamassassin(path: PathBuf, extension: String, do_warn: bool) {
"learn" => {TestFlag::Learn}
"noautolearn" => {TestFlag::NoAutoLearn}
"publish" => {TestFlag::Publish}
+ "nopublish" => {TestFlag::NoPublish}
"multiple" => {TestFlag::Multiple}
"notrim" => {TestFlag::NoTrim}
"domains_only" => {TestFlag::DomainsOnly}
@@ -986,7 +987,7 @@ pub fn import_spamassassin(path: PathBuf, extension: String, do_warn: bool) {
//println!("description: {:#?}", descriptions);
//println!("scores: {:#?}", ifs);
- for test_name in replace_rules {
+ /*for test_name in replace_rules {
if let Some(rule) = rules.get_mut(&test_name) {
match rule.t.pattern() {
Some(pattern) if !pattern.is_empty() => {
@@ -999,13 +1000,16 @@ pub fn import_spamassassin(path: PathBuf, extension: String, do_warn: bool) {
} else {
eprintln!("Warning: Test {test_name:?} not found for replace_rules command.",);
}
- }
+ }*/
let mut var_to_rule: HashMap<String, String> = HashMap::new();
let mut rules = rules
.into_iter()
.flat_map(|(name, mut rule)| {
let mut result = vec![];
+ if name.starts_with("T_") {
+ return vec![];
+ }
rule.name = name;
match &mut rule.t {
@@ -1410,12 +1414,14 @@ pub fn import_spamassassin(path: PathBuf, extension: String, do_warn: bool) {
eprintln!("Warning: Test {} is never linked to.", rule.name);
}
continue;
- } else if !processed_rules.contains(&rule.name) {
+ } else if !rule.flags.contains(&TestFlag::NoPublish)
+ && !processed_rules.contains(&rule.name)
+ {
write!(&mut script, "{rule}").unwrap();
}
}
- for (lang, texts) in descriptions {
+ /*for (lang, texts) in descriptions {
let mut file = fs::File::create(format!(
"/Users/me/code/mail-server/_ignore/descriptions_{}.txt",
lang
@@ -1424,7 +1430,7 @@ pub fn import_spamassassin(path: PathBuf, extension: String, do_warn: bool) {
for (name, text) in texts {
//file.write_all(format!("set {:?} {:?}", name, text).as_bytes());
}
- }
+ }*/
fs::write(
"/Users/me/code/mail-server/_ignore/script.sieve",
@@ -1574,6 +1580,11 @@ impl Display for Rule {
write!(f, "if match_uri {:?}", pattern)?;
}
RuleType::Eval { function, params } => {
+ write!(f, "if eval {function} {params:?}")?;
+ self.fmt_match(f, 1)?;
+ f.write_str("}\n\n");
+ return Ok(());
+
match function.as_str() {
"check_from_in_auto_welcomelist" | "check_from_in_auto_whitelist" => {
f.write_str(concat!(
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index 4f819f0d..d9747e36 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -5,7 +5,7 @@ authors = ["Stalwart Labs Ltd. <hello@stalw.art>"]
license = "AGPL-3.0-only"
repository = "https://github.com/stalwartlabs/cli"
homepage = "https://github.com/stalwartlabs/cli"
-version = "0.3.7"
+version = "0.3.8"
edition = "2021"
readme = "README.md"
resolver = "2"
diff --git a/crates/imap/Cargo.toml b/crates/imap/Cargo.toml
index c3eeb3b2..df76ad0c 100644
--- a/crates/imap/Cargo.toml
+++ b/crates/imap/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "imap"
-version = "0.3.7"
+version = "0.3.8"
edition = "2021"
resolver = "2"
diff --git a/crates/install/Cargo.toml b/crates/install/Cargo.toml
index c23ad6f9..a58d5650 100644
--- a/crates/install/Cargo.toml
+++ b/crates/install/Cargo.toml
@@ -5,7 +5,7 @@ authors = ["Stalwart Labs Ltd. <hello@stalw.art>"]
license = "AGPL-3.0-only"
repository = "https://github.com/stalwartlabs/mail-server"
homepage = "https://github.com/stalwartlabs/mail-server"
-version = "0.3.7"
+version = "0.3.8"
edition = "2021"
readme = "README.md"
resolver = "2"
diff --git a/crates/jmap/Cargo.toml b/crates/jmap/Cargo.toml
index e9549243..737803fa 100644
--- a/crates/jmap/Cargo.toml
+++ b/crates/jmap/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "jmap"
-version = "0.3.7"
+version = "0.3.8"
edition = "2021"
resolver = "2"
diff --git a/crates/main/Cargo.toml b/crates/main/Cargo.toml
index f1eb2aaf..928b1d58 100644
--- a/crates/main/Cargo.toml
+++ b/crates/main/Cargo.toml
@@ -7,7 +7,7 @@ homepage = "https://stalw.art"
keywords = ["imap", "jmap", "smtp", "email", "mail", "server"]
categories = ["email"]
license = "AGPL-3.0-only"
-version = "0.3.7"
+version = "0.3.8"
edition = "2021"
resolver = "2"
diff --git a/crates/smtp/Cargo.toml b/crates/smtp/Cargo.toml
index 2502dce8..8802330a 100644
--- a/crates/smtp/Cargo.toml
+++ b/crates/smtp/Cargo.toml
@@ -7,7 +7,7 @@ homepage = "https://stalw.art/smtp"
keywords = ["smtp", "email", "mail", "server"]
categories = ["email"]
license = "AGPL-3.0-only"
-version = "0.3.7"
+version = "0.3.8"
edition = "2021"
resolver = "2"
diff --git a/crates/smtp/src/config/scripts.rs b/crates/smtp/src/config/scripts.rs
index d0fcbc8b..50ff8811 100644
--- a/crates/smtp/src/config/scripts.rs
+++ b/crates/smtp/src/config/scripts.rs
@@ -52,6 +52,9 @@ impl ConfigSieve for Config {
.with_max_local_variables(8192)
.with_max_header_size(10240)
.with_max_includes(10)
+ .with_no_capability_check(
+ self.property_or_static("sieve.no-capability-check", "false")?,
+ )
.register_plugins()
.register_functions(&mut fnc_map);
diff --git a/crates/smtp/src/scripts/event_loop.rs b/crates/smtp/src/scripts/event_loop.rs
index 870f9c85..aad8d8ff 100644
--- a/crates/smtp/src/scripts/event_loop.rs
+++ b/crates/smtp/src/scripts/event_loop.rs
@@ -348,7 +348,9 @@ impl SMTP {
#[cfg(feature = "test_mode")]
if let Some(expected_variables) = params.expected_variables {
for var_name in instance.global_variable_names() {
- if !expected_variables.contains_key(var_name) {
+ if instance.global_variable(var_name).unwrap().to_bool()
+ && !expected_variables.contains_key(var_name)
+ {
panic!(
"Unexpected variable {var_name:?} with value {:?}\nExpected {:?}\nFound: {:?}",
instance.global_variable(var_name).unwrap(),
diff --git a/crates/smtp/src/scripts/functions/html.rs b/crates/smtp/src/scripts/functions/html.rs
index f0af219a..654a8489 100644
--- a/crates/smtp/src/scripts/functions/html.rs
+++ b/crates/smtp/src/scripts/functions/html.rs
@@ -48,7 +48,7 @@ pub fn fn_html_has_tag<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable
.into()
}
-pub fn fn_html_attr_int<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
+pub fn fn_html_attr_size<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
let t = v[0].to_cow();
let mut dimension = None;
diff --git a/crates/smtp/src/scripts/functions/image.rs b/crates/smtp/src/scripts/functions/image.rs
index a09ba710..9898bf7d 100644
--- a/crates/smtp/src/scripts/functions/image.rs
+++ b/crates/smtp/src/scripts/functions/image.rs
@@ -64,6 +64,9 @@ pub fn fn_img_metadata<'x>(ctx: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variab
"area" => imagesize::blob_size(bytes)
.ok()
.map(|s| Variable::Integer(s.width.saturating_mul(s.height) as i64)),
+ "dimension" => imagesize::blob_size(bytes)
+ .ok()
+ .map(|s| Variable::Integer(s.width.saturating_add(s.height) as i64)),
_ => None,
}
})
diff --git a/crates/smtp/src/scripts/functions/misc.rs b/crates/smtp/src/scripts/functions/misc.rs
new file mode 100644
index 00000000..a211dcc7
--- /dev/null
+++ b/crates/smtp/src/scripts/functions/misc.rs
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2023 Stalwart Labs Ltd.
+ *
+ * This file is part of Stalwart Mail Server.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ * in the LICENSE file at the top-level directory of this distribution.
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You can be released from the requirements of the AGPLv3 license by
+ * purchasing a commercial license. Please contact licensing@stalw.art
+ * for more details.
+*/
+
+use sieve::{runtime::Variable, Context};
+
+pub fn fn_is_empty<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
+ match &v[0] {
+ Variable::String(s) => s.is_empty(),
+ Variable::StringRef(s) => s.is_empty(),
+ Variable::Integer(_) | Variable::Float(_) => false,
+ Variable::Array(a) => a.is_empty(),
+ Variable::ArrayRef(a) => a.is_empty(),
+ }
+ .into()
+}
+
+pub fn fn_is_ip_addr<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
+ v[0].to_cow().parse::<std::net::IpAddr>().is_ok().into()
+}
+
+pub fn fn_is_var_names<'x>(ctx: &'x Context<'x>, _: Vec<Variable<'x>>) -> Variable<'x> {
+ Variable::Array(
+ ctx.global_variable_names()
+ .map(|v| Variable::from(v.to_string()))
+ .collect(),
+ )
+}
diff --git a/crates/smtp/src/scripts/functions/mod.rs b/crates/smtp/src/scripts/functions/mod.rs
index 2cca90c1..1493d138 100644
--- a/crates/smtp/src/scripts/functions/mod.rs
+++ b/crates/smtp/src/scripts/functions/mod.rs
@@ -26,15 +26,18 @@ mod email;
mod header;
pub mod html;
mod image;
+mod misc;
mod text;
-use sieve::{runtime::Variable, Context, FunctionMap};
+use sieve::{runtime::Variable, FunctionMap};
-use self::{array::*, email::*, header::*, html::*, image::*, text::*};
+use self::{array::*, email::*, header::*, html::*, image::*, misc::*, text::*};
pub fn register_functions() -> FunctionMap {
FunctionMap::new()
.with_function("trim", fn_trim)
+ .with_function("trim_start", fn_trim_start)
+ .with_function("trim_end", fn_trim_end)
.with_function("len", fn_len)
.with_function("count", fn_count)
.with_function("is_empty", fn_is_empty)
@@ -59,6 +62,7 @@ pub fn register_functions() -> FunctionMap {
.with_function("is_header_utf8_valid", fn_is_header_utf8_valid)
.with_function("img_metadata", fn_img_metadata)
.with_function("sort", fn_sort)
+ .with_function("is_ip_addr", fn_is_ip_addr)
.with_function_args("email_part", fn_email_part, 2)
.with_function_args("eq_ignore_case", fn_eq_ignore_case, 2)
.with_function_args("contains", fn_contains, 2)
@@ -71,10 +75,12 @@ pub fn register_functions() -> FunctionMap {
.with_function_args("levenshtein_distance", fn_levenshtein_distance, 2)
.with_function_args("html_has_tag", fn_html_has_tag, 2)
.with_function_args("html_attr", fn_html_attr, 2)
- .with_function_args("html_attr_int", fn_html_attr_int, 3)
+ .with_function_args("html_attr_size", fn_html_attr_size, 3)
.with_function_args("uri_part", fn_uri_part, 2)
.with_function_args("substring", fn_substring, 3)
.with_function_args("split", fn_split, 2)
+ .with_function_args("strip_prefix", fn_strip_prefix, 2)
+ .with_function_args("strip_suffix", fn_strip_suffix, 2)
.with_function_no_args("is_encoding_problem", fn_is_encoding_problem)
.with_function_no_args("is_attachment", fn_is_attachment)
.with_function_no_args("is_body", fn_is_body)
@@ -82,25 +88,6 @@ pub fn register_functions() -> FunctionMap {
.with_function_no_args("attachment_name", fn_attachment_name)
}
-pub fn fn_is_empty<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
- match &v[0] {
- Variable::String(s) => s.is_empty(),
- Variable::StringRef(s) => s.is_empty(),
- Variable::Integer(_) | Variable::Float(_) => false,
- Variable::Array(a) => a.is_empty(),
- Variable::ArrayRef(a) => a.is_empty(),
- }
- .into()
-}
-
-pub fn fn_is_var_names<'x>(ctx: &'x Context<'x>, _: Vec<Variable<'x>>) -> Variable<'x> {
- Variable::Array(
- ctx.global_variable_names()
- .map(|v| Variable::from(v.to_string()))
- .collect(),
- )
-}
-
pub trait ApplyString<'x> {
fn transform(&self, f: impl Fn(&str) -> Option<&str>) -> Variable<'x>;
fn transform_string<T: Into<Variable<'x>>>(
diff --git a/crates/smtp/src/scripts/functions/text.rs b/crates/smtp/src/scripts/functions/text.rs
index f2c6a3d2..e8eb8cb3 100644
--- a/crates/smtp/src/scripts/functions/text.rs
+++ b/crates/smtp/src/scripts/functions/text.rs
@@ -29,6 +29,14 @@ pub fn fn_trim<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
v[0].transform(|s| Some(s.trim()))
}
+pub fn fn_trim_end<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
+ v[0].transform(|s| Some(s.trim_end()))
+}
+
+pub fn fn_trim_start<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
+ v[0].transform(|s| Some(s.trim_start()))
+}
+
pub fn fn_len<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
match &v[0] {
Variable::String(s) => s.len(),
@@ -215,6 +223,16 @@ pub fn fn_substring<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x
.into()
}
+pub fn fn_strip_prefix<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
+ let prefix = v[1].to_cow();
+ v[0].transform(|s| s.strip_prefix(prefix.as_ref()))
+}
+
+pub fn fn_strip_suffix<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
+ let suffix = v[1].to_cow();
+ v[0].transform(|s| s.strip_suffix(suffix.as_ref()))
+}
+
pub fn fn_split<'x>(_: &'x Context<'x>, v: Vec<Variable<'x>>) -> Variable<'x> {
match &v[0] {
Variable::StringRef(s) => s
diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml
index bc3fefeb..dd6c1bcc 100644
--- a/crates/utils/Cargo.toml
+++ b/crates/utils/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "utils"
-version = "0.3.7"
+version = "0.3.8"
edition = "2021"
resolver = "2"
diff --git a/resources/config/sieve/html.sieve b/resources/config/sieve/html.sieve
new file mode 100644
index 00000000..8a25fe3d
--- /dev/null
+++ b/resources/config/sieve/html.sieve
@@ -0,0 +1,111 @@
+
+# Message only has text/html MIME parts
+if eval "header.content-type == 'text/html'" {
+ set "t.MIME_HTML_ONLY" "1";
+}
+
+foreverypart {
+ if eval "is_body() && eq_ignore_case(header.content-type, 'text/html')" {
+ # Tokenize HTML
+ set "html_tokens" "%{tokenize_html(part.text)}";
+ set "html_tokens_len" "%{len(html_tokens)}";
+ set "html_char_count" "0";
+ set "html_space_count" "0";
+ set "html_img_words" "0";
+ set "html_words" "0";
+ set "has_link_to_img" "0";
+ set "has_uri" "0";
+ set "has_text" "0";
+ set "in_head" "0";
+ set "in_body" "0";
+ set "in_anchor" "0";
+ set "in_anchor_href" "";
+
+ set "i" "0";
+ while "i < html_tokens_len" {
+ set "token" "%{html_tokens[i]}";
+ set "i" "%{i + 1}";
+
+ # Tokens starting with '_' are text nodes
+ if eval "starts_with(token, '_')" {
+ if eval "in_head == 0" {
+ set "html_char_count" "%{html_char_count + count_chars(token)}";
+ set "html_space_count" "%{html_space_count + count_spaces(token)}";
+
+ set "text" "%{to_lowercase(trim(strip_prefix(token, '_')))}";
+ set "html_words" "%{html_words + len(tokenize_words(text))}";
+
+ if eval "starts_with(text, 'https://') || starts_with(text, 'http://')" {
+ set "has_uri" "1";
+ if eval "in_anchor && !is_empty(in_anchor_href) &&
+ uri_part(text, 'scheme') != uri_part(in_anchor_href, 'scheme')" {
+ # The anchor text contains a distinct scheme compared to the target URL
+ set "t.HTTP_TO_HTTPS" "1";
+ }
+ } elsif eval "!is_empty(text)" {
+ set "has_text" "1";
+ }
+ }
+ } elsif eval "starts_with(token, '<img')" {
+ set "dimensions" "%{html_attr_size(token, 'width', 800) + html_attr_size(token, 'height', 600)}";
+
+ if eval "in_anchor && dimensions >= 210" {
+ set "has_link_to_img" "1";
+ }
+ if eval "dimensions > 100" {
+ # We assume that a single picture 100x200 contains approx 3 words of text
+ set "html_img_words" "%{html_img_words + dimensions / 100}";
+ }
+ } elsif eval "starts_with(token, '<head')" {
+ set "in_head" "%{in_head + 1}";
+ } elsif eval "starts_with(token, '</head')" {
+ set "in_head" "%{in_head - 1}";
+ } elsif eval "starts_with(token, '<body')" {
+ set "in_body" "%{in_body + 1}";
+ } elsif eval "starts_with(token, '</body')" {
+ set "in_body" "%{in_body - 1}";
+ } elsif eval "starts_with(token, '<a ')" {
+ set "in_anchor" "1";
+ set "in_anchor_href" "%{trim(html_attr(token, 'href'))}";
+
+ if eval "is_ip_addr(uri_part(in_anchor_href, 'host'))" {
+ # HTML anchor points to an IP address
+ set "t.HTTP_TO_IP" "1";
+ }
+ } elsif eval "in_anchor && starts_with(token, '</a')" {
+ set "in_anchor" "0";
+ } elsif eval "starts_with(token, '<link') &&
+ (contains_ignore_case(html_attr(token, 'rel'), 'stylesheet') ||
+ contains_ignore_case(html_attr(token, 'href'), '.css') )" {
+ set "t.EXT_CSS" "1";
+ }
+ }
+
+ # Check for unbalanced tags
+ if eval "in_head != 0 || in_body != 0" {
+ set "t.HTML_UNBALANCED_TAG" "1";
+ }
+
+ # Check for short HTML parts with a link to an image
+ if eval "has_link_to_img" {
+ if eval "html_char_count < 1024" {
+ set "t.HTML_SHORT_LINK_IMG_1" "1";
+ } elsif eval "html_char_count < 1536" {
+ set "t.HTML_SHORT_LINK_IMG_2" "1";
+ } elsif eval "html_char_count < 2048" {
+ set "t.HTML_SHORT_LINK_IMG_3" "1";
+ }
+ }
+
+ if eval "(!has_link_to_img || html_char_count >= 2048) &&
+ (html_img_words / (html_words + html_img_words) > 0.5)" {
+ # Message contains more images than text
+ set "t.HTML_TEXT_IMG_RATIO" "1";
+ }
+
+ if eval "has_uri && !has_text" {
+ set "t.BODY_URI_ONLY" "1";
+ }
+ }
+}
+
diff --git a/resources/config/sieve/subject.sieve b/resources/config/sieve/subject.sieve
new file mode 100644
index 00000000..202ab85a
--- /dev/null
+++ b/resources/config/sieve/subject.sieve
@@ -0,0 +1,83 @@
+
+set "thread_name" "%{thread_name(header.subject)}";
+set "subject_lcase" "%{to_lowercase(header.subject)}";
+set "raw_subject_lcase" "%{to_lowercase(header.subject.raw)}";
+set "is_ascii_subject" "%{is_ascii(subject_lcase)}";
+
+if eval "len(thread_name) >= 10 && count(tokenize_words(thread_name)) > 1 && is_uppercase(thread_name)" {
+ # Subject contains mostly capital letters
+ set "t.SUBJ_ALL_CAPS" "1";
+}
+
+if eval "count_chars(thread_name) > 200" {
+ # Subject is very long
+ set "t.SUBJ_VERY_LONG" "1";
+}
+
+if eval "contains(subject_lcase, 'http://') || contains(subject_lcase, 'http://')" {
+ # Subject contains a URL
+ set "t.URL_IN_SUBJECT" "1";
+}
+
+if eval "!is_ascii(raw_subject_lcase)" {
+ # Subject needs encoding
+ set "t.SUBJECT_NEEDS_ENCODING" "1";
+}
+
+if not exists "Subject" {
+ # Missing subject header
+ set "t.MISSING_SUBJECT" "1";
+}
+
+if eval "is_empty(trim(subject_lcase))" {
+ # Subject is empty
+ set "t.EMPTY_SUBJECT" "1";
+}
+
+if eval "is_ascii(subject_lcase) && contains(raw_subject_lcase, '=?') && contains(raw_subject_lcase, '?=')" {
+ if eval "contains(raw_subject_lcase, '?q?')" {
+ # Subject header is unnecessarily encoded in quoted-printable
+ set "t.SUBJ_EXCESS_QP" "1";
+ } elsif eval "contains(raw_subject_lcase, '?b?')" {
+ # Subject header is unnecessarily encoded in base64
+ set "t.SUBJ_EXCESS_BASE64" "1";
+ }
+}
+
+if eval "starts_with(subject_lcase, 're:') && is_empty(header.reply-to) && is_empty(header.references)" {
+ # Fake reply
+ set "t.FAKE_REPLY" "1";
+}
+
+set "subject_lcase_trim" "%{trim_end(subject_lcase)}";
+if eval "subject_lcase != subject_lcase_trim" {
+ # Subject ends with space characters
+ set "t.SUBJECT_ENDS_SPACES" "1";
+}
+
+if eval "contains(subject_lcase, '$') ||
+ contains(subject_lcase, '€') ||
+ contains(subject_lcase, '£') ||
+ contains(subject_lcase, '¥')" {
+ # Subject contains currency symbols
+ set "t.SUBJECT_HAS_CURRENCY" "1";
+}
+
+if eval "ends_with(subject_lcase_trim, '!')" {
+ # Subject ends with an exclamation mark
+ set "t.SUBJECT_ENDS_EXCLAIM" "1";
+} elsif eval "ends_with(subject_lcase_trim, '?')" {
+ # Subject ends with a question mark
+ set "t.SUBJECT_ENDS_QUESTION" "1";
+}
+
+if eval "contains(subject_lcase_trim, '!')" {
+ # Subject contains an exclamation mark
+ set "t.SUBJECT_HAS_EXCLAIM" "1";
+}
+
+if eval "contains(subject_lcase_trim, '?')" {
+ # Subject contains a question mark
+ set "t.SUBJECT_HAS_QUESTION" "1";
+}
+
diff --git a/tests/resources/smtp/antispam/base64.txt b/tests/resources/smtp/antispam/base64.txt
deleted file mode 100644
index c1f7bbd2..00000000
--- a/tests/resources/smtp/antispam/base64.txt
+++ /dev/null
@@ -1,142 +0,0 @@
-expect MIME_BASE64_TEXT __MIME_BASE64
-
-Return-Path: hello@public.hzptt.sd.cn
-X-Mmdf-To: jm
-Received: from salmon.maths.tcd.ie by maccullagh.maths.tcd.ie with SMTP
- id <aa56837@maccullagh>; 15 Apr 2001 02:36:50 +0100 (BST)
-Received: from dux1.tcd.ie by salmon.maths.tcd.ie with SMTP
- id <aa53188@salmon>; 15 Apr 2001 02:36:50 +0100 (BST)
-Received: from qd_mail3.sd.cninfo.net ([61.156.13.71])
- by dux1.tcd.ie (8.11.1/8.11.1) with ESMTP id f3F1ans26770
- for <jm@maths.tcd.ie>; Sun, 15 Apr 2001 02:36:50 +0100 (BST)
-Received: from Good ([206.172.87.3]) by qd_mail3.sd.cninfo.net with SMTP
- id <20010415013005.EXEK607.qd_mail3@Good> for <jm@maths.tcd.ie>;
- Sun, 15 Apr 2001 09:30:05 +0800
-From: keywordranking@excite.com
-To: jm@maths.tcd.ie
-Subject: Website traffic Building
-X-Mailer: WC Mail __ty__
-MIME-Version: 1.0
-Content-Type: multipart/mixed;boundary= "Z_MULTI_PART_MAIL_BOUNDAEY_S"
-Message-Id: <20010415013005.EXEK607.qd_mail3@Good>
-Date: Sun, 15 Apr 2001 09:30:33 +0800
-
-This is a multi-part message in MIME format.
-
---Z_MULTI_PART_MAIL_BOUNDAEY_S
-Content-Type: text/plain
-Content-Transfer-Encoding: base64
-
-V2UgaGF2ZSByYW5rZWQgdGhlIHRvcCB0ZW4gdHJhZmZpYyBidWlsZGluZyBzaXRlcyBvbiB0
-aGUgd2ViLCB0aGVzZSBzaXRlcw0KaGF2ZSBiZWVuIHJhbmtlZCBieSBvdXIgZXhwZXJ0cywg
-b3VyIGNsaWVudHMgYW5kIGJ5IHlvdSBvdXIgdmlzaXRvcnMuIENvbWUNCnRvIGh0dHA6Ly9t
-ZW1iZXJzLnRyaXBvZC5jby51ay90b3B0ZW5zaXRlcw0KDQpPbmUgb2YgdGhlIHRvcCB0ZW4g
-c2l0ZXMsIGNhbiBldmVuIGd1YXJhbnRlZSB0b3AgcGxhY2VtZW50IG9uIHRoZSB0b3AgdGVu
-DQpzZWFyY2ggZW5naW5lcy4gUmlnaHQgbm93IHRoZXkgYXJlIGFsc28gb2ZmZXJpbmcgdG8g
-Y2hlY2sgeW91ciBzaXRlJ3MNCnBvc2l0aW9uDQppbiB0aGUgc2VhcmNoIGVuZ2luZXMsIEZS
-RUUgT0YgQ0hBUkdFIQ0KDQpPdXIgc2l0ZSBoYXMgYmVlbiBkZXZlbG9wZWQgdG8gaGVscCB5
-b3UgZmluZCB0aGUgbW9zdCBjb3N0LWVmZmVjdGl2ZSB0cmFmZmljDQpvbiB0aGUgd2ViLiBQ
-bGVhc2UgZmVlbCBmcmVlIHRvIGNvbnRhY3QgdXMgd2l0aCBhbnkgcXVlc3Rpb25zLg0KDQoN
-Cg0KDQpUbyBCZSBSZW1vdmVkIFNlbmQgRS1NYWlsIHRvIHJlbW92ZWt3QGV4Y2l0ZS5jb20N
-Cg0KSUYgVEhJUyBJUyBOT1QgRE9ORSBPVVIgTElTVCBNQU5BR0VNRU5UIFNPRlRXQVJFIFdJ
-TEwgTk9UIEtOT1cgVE8NClJFTU9WRSBZT1UuDQoNCkFnYWluIHNlbmQgbWFpbCwgb3IgZm9y
-d2FyZCBtZXNzYWdlIHRvIHJlbW92ZWt3QGV4Y2l0ZS5jb20NCnRvIGJlIHJlbW92ZWQuDQog
-ICAg
---Z_MULTI_PART_MAIL_BOUNDAEY_S--
-
-<!-- NEXT TEST -->
-expect __mime_attachment base64_length_79_inf __mime_base64
-
-Return-Path: <president@whitehouse.gov>
-Received: from mailhost.whitehouse.gov ([192.168.51.200])
- by heartbeat.whitehouse.gov (8.8.8/8.8.8) with ESMTP id SAA22453
- for <vice-president@heartbeat.whitehouse.gov>;
- Mon, 13 Aug 1998 l8:14:23 +1000
-Received: from the_big_box.whitehouse.gov ([192.168.51.50])
- by mailhost.whitehouse.gov (8.8.8/8.8.7) with ESMTP id RAA20366
- for vice-president@whitehouse.gov; Mon, 13 Aug 1998 17:42:41 +1000
-Date: Mon, 13 Aug 1998 17:42:41 +1000
-Message-Id: <199804130742.RAA20366@mai1host.whitehouse.gov>
-From: Bill Clinton <president@whitehouse.gov>
-To: A1 (The Enforcer) Gore <vice-president@whitehouse.gov>
-Subject: Map of Argentina with Description
-MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="DC8------------DC8638F443D87A7F0726DEF7"
-
-This is a multi-part message in MIME format.
---DC8------------DC8638F443D87A7F0726DEF7
-Content-Type: text/plain; charset=us-ascii
-Content-Transfer-Encoding: 7bit
-
-Hi A1,
-
-I finally figured out this MIME thing. Pretty cool. I'll send you
-some sax music in .au files next week!
-
-Anyway, the attached image is really too small to get a good look at
-Argentina. Try this for a much better map:
-
- http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
-
-Then again, shouldn't the CIA have something like that?
-
-Bill
---DC8------------DC8638F443D87A7F0726DEF7
-Content-Type: image/gif; name="map_of_Argentina.gif"
-Content-Transfer-Encoding: base64
-Content-Disposition: attachment; filename="map_of_Argentina.gif"
-
-R01GOD1hJQA1AKIAAP/////78P/omn19fQAAAAAAAAAAAAAAACwAAAAAJQA1AAAD7Qi63P5wwEmjBC
-LrnQnhYCgM1wh+pkgqqeC9XrutmBm7hAK3tP31gFcAiFKVQrGFR6kscnonTe7FAAadGugmRu3CmiBt57fsVq3Y0VFKnpYdxPC6M7Ze4crnnHum4oN6LFJ1bn5NXTN7OF5fQkN5WYowBEN2dkGQGWJtSzqGTICJgnQuTJN/WJsojad9qXMuhIWdjXKjY4tenjo6tjVssk2gaWq3uGNX
-U6ZGxseyk8SasGw3J9GRzdTQky1iHNvcPNNI4TLeKdfMvy0vMqLrItvuxfDW8ubjueDtJufz7itICBxISKDBgwgTKjyYAAA7
---DC8------------DC8638F443D87A7F0726DEF7--
-<!-- NEXT TEST -->
-expect __mime_attachment base64_length_78_79 __mime_base64
-
-Return-Path: <president@whitehouse.gov>
-Received: from mailhost.whitehouse.gov ([192.168.51.200])
- by heartbeat.whitehouse.gov (8.8.8/8.8.8) with ESMTP id SAA22453
- for <vice-president@heartbeat.whitehouse.gov>;
- Mon, 13 Aug 1998 l8:14:23 +1000
-Received: from the_big_box.whitehouse.gov ([192.168.51.50])
- by mailhost.whitehouse.gov (8.8.8/8.8.7) with ESMTP id RAA20366
- for vice-president@whitehouse.gov; Mon, 13 Aug 1998 17:42:41 +1000
-Date: Mon, 13 Aug 1998 17:42:41 +1000
-Message-Id: <199804130742.RAA20366@mai1host.whitehouse.gov>
-From: Bill Clinton <president@whitehouse.gov>
-To: A1 (The Enforcer) Gore <vice-president@whitehouse.gov>
-Subject: Map of Argentina with Description
-MIME-Version: 1.0
-Content-Type: multipart/mixed;
- boundary="DC8------------DC8638F443D87A7F0726DEF7"
-
-This is a multi-part message in MIME format.
---DC8------------DC8638F443D87A7F0726DEF7
-Content-Type: text/plain; charset=us-ascii
-Content-Transfer-Encoding: 7bit
-
-Hi A1,
-
-I finally figured out this MIME thing. Pretty cool. I'll send you
-some sax music in .au files next week!
-
-Anyway, the attached image is really too small to get a good look at
-Argentina. Try this for a much better map:
-
- http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
-
-Then again, shouldn't the CIA have something like that?
-
-Bill
---DC8------------DC8638F443D87A7F0726DEF7
-Content-Type: image/gif; name="map_of_Argentina.gif"
-Content-Transfer-Encoding: base64
-Content-Disposition: attachment; filename="map_of_Argentina.gif"
-
-R01GOD1hJQA1AKIAAP/////78P/omn19fQAAAAAAAAAAAAAAACwAAAAAJQA1AAAD7Qi63P5wwEmjBC
-LrnQnhYCgM1wh+pkgqqeC9XrutmBm7hAK3tP31gFcAiFKVQrGFR6kscnonTe7FAAadGugmRu3CmiBt
-57fsVq3Y0VFKnpYdxPC6M7Ze4crnnHum4oN6LFJ1bn5NXTN7OF5fQkN5WYowBEN2dkGQGWJtSzqGTI
-CJgnQuTJN/WJsojad9qXMuhIWdjXKjY4tenjo6tjVssk2gaWq3uGNXU6ZGxseyk8SasGw3J9GRzdTQ
-ky1iHNvcPNNI4TLeKdfMvy0vMqLrItvuxfDW8ubjueDtJufz7itICBxISKDBgwgTKjyYAAA7
---DC8------------DC8638F443D87A7F0726DEF7--
diff --git a/tests/resources/smtp/antispam/html.test b/tests/resources/smtp/antispam/html.test
new file mode 100644
index 00000000..03f3ff1b
--- /dev/null
+++ b/tests/resources/smtp/antispam/html.test
@@ -0,0 +1,239 @@
+expect MIME_HTML_ONLY
+
+Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
+X-Sender: dwsauder@pop.example.com (Unverified)
+X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
+X-Priority: 2 (High)
+Date: Fri, 19 May 2000 00:29:55 -0400
+To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
+From: Doug Sauder <dwsauder@example.com>
+Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
+Mime-Version: 1.0
+Content-Type: text/html; charset="iso-8859-1"
+Content-Transfer-Encoding: quoted-printable
+
+<html>
+<font face=3D"Arial, Helvetica" size=3D5 color=3D"#0000FF"><b>Die Hasen und =
+die
+Fr=F6sche<br>
+<br>
+</font></b><font face=3D"Arial, Helvetica">Die Hasen klagten einst =FCber
+ihre mi=DFliche Lage; &quot;wir leben&quot;, sprach ein Redner, &quot;in
+steter Furcht vor Menschen und Tieren, eine Beute der Hunde, der Adler,
+ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der Tod selbst.
+Auf, la=DFt uns ein f=FCr allemal sterben.&quot; <br>
+<br>
+In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;
+allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt
+erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie au=
+fs
+schnellste untertauchten. <br>
+<br>
+&quot;Halt&quot;, rief nun eben dieser Sprecher, &quot;wir wollen das
+Ers=E4ufen noch ein wenig aufschieben, denn auch uns f=FCrchten, wie ihr
+seht, einige Tiere, welche also wohl noch ungl=FCcklicher sein m=FCssen als
+wir.&quot; <br>
+<br>
+</font></html>
+<!-- NEXT TEST -->
+expect HTTP_TO_HTTPS
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+https://mydomain.com
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
+<a href="http://mydomain.com">https://mydomain.com</a>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect HTTP_TO_IP
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+https://mydomain.com
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<head></head>
+<body>
+<p>some text</p>
+<a href="https://8.8.8.8/phisherino.php">https://mydomain.com</a>
+</body>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect EXT_CSS
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+https://mydomain.com
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<link href="https://domain.com/external.css#test">
+<p>some text</p>
+<a href="https://mydomain.com">https://mydomain.com</a>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect EXT_CSS
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+https://mydomain.com
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<link rel="stylesheet" href="https://domain.com/external">
+<p>some text</p>
+<a href="https://mydomain.com">https://mydomain.com</a>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect HTML_UNBALANCED_TAG
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+https://mydomain.com
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<link rel="unknown" href="https://domain.com/external">
+<head>hello
+<a href="https://mydomain.com">https://mydomain.com</a>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect HTML_UNBALANCED_TAG
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+https://mydomain.com
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<link rel="unknown" href="https://domain.com/external">
+<body>hello
+<a href="https://mydomain.com">https://mydomain.com</a>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect HTML_SHORT_LINK_IMG_1
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Testing
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<html>
+<head><title>Test</title></head>
+<body>
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam</p>
+<a href="https://herrspammer.com"><img src="cid:spammimg" width="200" height="200"></a>
+</body>
+</html>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect BODY_URI_ONLY
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Testing
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<html>
+<head><title>Test</title></head>
+<body>
+<p>http://myurl.com</>
+</body>
+</html>
+
+--=====================_714967308==_.ALT--
+<!-- NEXT TEST -->
+expect HTML_TEXT_IMG_RATIO
+
+Content-Type: multipart/alternative;
+ boundary="=====================_714967308==_.ALT"
+
+--=====================_714967308==_.ALT
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+
+Testing
+
+--=====================_714967308==_.ALT
+Content-Type: text/html; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+<html>
+<head><title>Test</title></head>
+<body>
+<a<img src="cid:spammimg1" width="200" height="200">
+<img src="cid:spammimg2" width="200" height="200">
+<img src="cid:spammimg3" width="200" height="200">
+</body>
+</html>
+
+--=====================_714967308==_.ALT--
diff --git a/tests/resources/smtp/antispam/html_mime.txt b/tests/resources/smtp/antispam/html_mime.txt
deleted file mode 100644
index f46604ed..00000000
--- a/tests/resources/smtp/antispam/html_mime.txt
+++ /dev/null
@@ -1,94 +0,0 @@
-expect __mime_html __mime_qp mime_html_only __mime_qpc
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: text/html; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-<html>
-<font face=3D"Arial, Helvetica" size=3D5 color=3D"#0000FF"><b>Die Hasen und =
-die
-Fr=F6sche<br>
-<br>
-</font></b><font face=3D"Arial, Helvetica">Die Hasen klagten einst =FCber
-ihre mi=DFliche Lage; &quot;wir leben&quot;, sprach ein Redner, &quot;in
-steter Furcht vor Menschen und Tieren, eine Beute der Hunde, der Adler,
-ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der Tod selbst.
-Auf, la=DFt uns ein f=FCr allemal sterben.&quot; <br>
-<br>
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;
-allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt
-erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie au=
-fs
-schnellste untertauchten. <br>
-<br>
-&quot;Halt&quot;, rief nun eben dieser Sprecher, &quot;wir wollen das
-Ers=E4ufen noch ein wenig aufschieben, denn auch uns f=FCrchten, wie ihr
-seht, einige Tiere, welche also wohl noch ungl=FCcklicher sein m=FCssen als
-wir.&quot; <br>
-<br>
-</font></html>
-<!-- NEXT TEST -->
-expect mime_html_mostly __mime_qpc=2 __mime_html __mime_qp
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: multipart/alternative;
- boundary="=====================_714967308==_.ALT"
-
---=====================_714967308==_.ALT
-Content-Type: text/html; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Die Hasen und die Fr=F6sche
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-
---=====================_714967308==_.ALT
-Content-Type: text/html; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Die Hasen und die Fr=F6sche
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
---=====================_714967308==_.ALT-- \ No newline at end of file
diff --git a/tests/resources/smtp/antispam/multipart_alternative.txt b/tests/resources/smtp/antispam/multipart_alternative.txt
deleted file mode 100644
index 8e7a0226..00000000
--- a/tests/resources/smtp/antispam/multipart_alternative.txt
+++ /dev/null
@@ -1,217 +0,0 @@
-expect mpart_alt_diff __mime_qp __mime_qpc=2
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: multipart/alternative;
- boundary="=====================_714967308==_.ALT"
-
---=====================_714967308==_.ALT
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Die Hasen und die Fr=F6sche
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-
---=====================_714967308==_.ALT
-Content-Type: text/html; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-<html>
-<font face=3D"Arial, Helvetica" size=3D5 color=3D"#0000FF"><b>Die Hasen und =
-die
-Fr=F6sche<br>
-<br>
-</font></b><font face=3D"Arial, Helvetica">Die Ha1sen kltagten eitnst =FCber
-ihre mi=DFliche Lage; &quot;wir leben&quot;, sprach ein Redner, &quot;in
-steter Furcht vor Menschen und Tieren, eine Beute der Hunde, der Adler,
-ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der Tod selbst.
-Auf, la=DFt uns ein f=FCr allemal sterben.&quot; <br>
-<br>
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;
-allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt
-erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie au=
-fs
-schnellste untertauchten. <br>
-<br>
-&quot;Halt&quot;, rief nun eben dieser Sprecher, &quot;wir wollen das
-Ers=E4ufen noch ein wenig aufschieben, denn auch uns f=FCrchten, wie ihr
-seht, einige Tiere, welche also wohl noch ungl=FCcklicher sein m=FCssen als
-wir.&quot; <br>
-<br>
-</font></html>
-
---=====================_714967308==_.ALT--
-<!-- NEXT TEST -->
-expect mpart_alt_diff_count __mime_qp __mime_qpc=2
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: multipart/alternative;
- boundary="=====================_714967308==_.ALT"
-
---=====================_714967308==_.ALT
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Die Hasen und die Fr=F6sche
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
---=====================_714967308==_.ALT
-Content-Type: text/html; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-<html>
-<font face=3D"Arial, Helvetica" size=3D5 color=3D"#0000FF"><b>Die Hasen und =
-die
-Fr=F6sche<br>
-<br>
-</font></b><font face=3D"Arial, Helvetica">Die Hasen klagten einst =FCber
-ihre mi=DFliche Lage; &quot;wir leben&quot;, sprach ein Redner, &quot;in
-steter Furcht vor Menschen und Tieren, eine Beute der Hunde, der Adler,
-ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der Tod selbst.
-Auf, la=DFt uns ein f=FCr allemal sterben.&quot; <br>
-<br>
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;
-allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt
-erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie au=
-fs
-schnellste untertauchten. <br>
-<br>
-&quot;Halt&quot;, rief nun eben dieser Sprecher, &quot;wir wollen das
-Ers=E4ufen noch ein wenig aufschieben, denn auch uns f=FCrchten, wie ihr
-seht, einige Tiere, welche also wohl noch ungl=FCcklicher sein m=FCssen als
-wir.&quot; <br>
-<br>
-</font></html>
-
---=====================_714967308==_.ALT--
-<!-- NEXT TEST -->
-expect multipart_alt_non_text __mime_qp __mime_qpc=2 __mime_attachment
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: multipart/alternative;
- boundary="=====================_714967308==_.ALT"
-
---=====================_714967308==_.ALT
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Die Hasen und die Fr=F6sche
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-
---=====================_714967308==_.ALT
-Content-Type: application/unknown; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Secret contents
-
---=====================_714967308==_.ALT-- \ No newline at end of file
diff --git a/tests/resources/smtp/antispam/quoted_printable.txt b/tests/resources/smtp/antispam/quoted_printable.txt
deleted file mode 100644
index 5f6295a6..00000000
--- a/tests/resources/smtp/antispam/quoted_printable.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-expect __mime_qp __mime_qpc=2
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: multipart/alternative;
- boundary="=====================_714967308==_.ALT"
-
---=====================_714967308==_.ALT
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Die Hasen und die Fr=F6sche
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein=
- Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
-
-
---=====================_714967308==_.ALT
-Content-Type: text/html; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-<html>
-<font face=3D"Arial, Helvetica" size=3D5 color=3D"#0000FF"><b>Die Hasen und =
-die
-Fr=F6sche<br>
-<br>
-</font></b><font face=3D"Arial, Helvetica">Die Hasen klagten einst =FCber
-ihre mi=DFliche Lage; &quot;wir leben&quot;, sprach ein Redner, &quot;in
-steter Furcht vor Menschen und Tieren, eine Beute der Hunde, der Adler,
-ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der Tod selbst.
-Auf, la=DFt uns ein f=FCr allemal sterben.&quot; <br>
-<br>
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;
-allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt
-erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie au=
-fs
-schnellste untertauchten. <br>
-<br>
-&quot;Halt&quot;, rief nun eben dieser Sprecher, &quot;wir wollen das
-Ers=E4ufen noch ein wenig aufschieben, denn auch uns f=FCrchten, wie ihr
-seht, einige Tiere, welche also wohl noch ungl=FCcklicher sein m=FCssen als
-wir.&quot; <br>
-<br>
-</font></html>
-
---=====================_714967308==_.ALT--
-<!-- NEXT TEST -->
-expect __mime_qp __mime_qpc mime_qp_long_line
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: quoted-printable
-
-Die Hasen und die Fr=F6sche
-
-Die Hasen klagten einst =FCber ihre mi=DFliche Lage; "wir leben", sprach ein Redner, "in steter Furcht vor Menschen und Tieren, eine Beute der Hunde,=
- der Adler, ja fast aller Raubtiere! Unsere stete Angst ist =E4rger als der=
- Tod selbst. Auf, la=DFt uns ein f=FCr allemal sterben."=20
-
-In einem nahen Teich wollten sie sich nun ers=E4ufen; sie eilten ihm zu;=
- allein das au=DFerordentliche Get=F6se und ihre wunderbare Gestalt=
- erschreckte eine Menge Fr=F6sche, die am Ufer sa=DFen, so sehr, da=DF sie=
- aufs schnellste untertauchten.=20
-
-"Halt", rief nun eben dieser Sprecher, "wir wollen das Ers=E4ufen noch ein=
- wenig aufschieben, denn auch uns f=FCrchten, wie ihr seht, einige Tiere,=
- welche also wohl noch ungl=FCcklicher sein m=FCssen als wir."=20
diff --git a/tests/resources/smtp/antispam/received.txt b/tests/resources/smtp/antispam/received.txt
deleted file mode 100644
index ae5a2390..00000000
--- a/tests/resources/smtp/antispam/received.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-helo_domain my.domain.com
-iprev_ptr some.other.host.com
-expect __forged_rcvd_trail
-
-From: john@example.com
-To: jane@example.com
-Subject: test
-
-test
-<!-- NEXT TEST -->
-expect __forged_rcvd_trail
-
-Return-Path: <president@whitehouse.gov>
-Received: from mailhost.whitehouse.gov ([192.168.51.200])
- by heartbeat.whitehouse.gov (8.8.8/8.8.8) with ESMTP id SAA22453
- for <vice-president@heartbeat.whitehouse.gov>;
- Mon, 13 Aug 1998 l8:14:23 +1000
-Received: from the_big_box.whitehouse.gov ([192.168.51.50])
- by mailhost.whitehouse.gov (8.8.8/8.8.7) with ESMTP id RAA20366
- for vice-president@whitehouse.gov; Mon, 13 Aug 1998 17:42:41 +1000
-Received: from mail1.insuranceiq.com (host66.insuranceiq.com [65.217.159.66] (may be forged))
- by dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id h2F0c2x31856 for <jm@jmason.org>;
- Sat, 15 Mar 2003 00:38:03 GMT
-Date: Mon, 13 Aug 1998 17:42:41 +1000
-Message-Id: <199804130742.RAA20366@mai1host.whitehouse.gov>
-From: Bill Clinton <president@whitehouse.gov>
-To: A1 (The Enforcer) Gore <vice-president@whitehouse.gov>
-Subject: Map of Argentina with Description
-MIME-Version: 1.0
-Content-Type: text/plain; charset=us-ascii
-Content-Transfer-Encoding: 7bit
-
-Hi A1,
-
-I finally figured out this MIME thing. Pretty cool. I'll send you
-some sax music in .au files next week!
-
-Anyway, the attached image is really too small to get a good look at
-Argentina. Try this for a much better map:
-
- http://www.1one1yp1anet.com/dest/sam/graphics/map-arg.htm
-
-Then again, shouldn't the CIA have something like that?
-
-Bill
diff --git a/tests/resources/smtp/antispam/subject.test b/tests/resources/smtp/antispam/subject.test
new file mode 100644
index 00000000..01035874
--- /dev/null
+++ b/tests/resources/smtp/antispam/subject.test
@@ -0,0 +1,5 @@
+expect SUBJ_ALL_CAPS
+
+Subject: HELLO WORLD
+
+Test
diff --git a/tests/resources/smtp/antispam/text.txt b/tests/resources/smtp/antispam/text.txt
deleted file mode 100644
index 52609d10..00000000
--- a/tests/resources/smtp/antispam/text.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-expect pp_mime_fake_ascii_text
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: text/plain; charset="iso-8859-1"
-Content-Transfer-Encoding: 7bit
-
-Test with some áéíóúñ
-<!-- NEXT TEST -->
-expect __uppercase_75_100
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: 7bit
-
-THIS IS A TEXT WITH A RIDICULOUSLY LONG LINE WITH PLENTY
-OF UPPERCASE, WHY ARE YOU SCREAMING? I'M NOT SCREAMING,
-YOU'RE SCREAMING. I'M NOT SCREAMING, YOU'RE SCREAMING.
-IT HAS TO BE AT LEAST 200 CHARACTERS LONG, SO I'LL JUST
-KEEP TYPING AND TYPING AND TYPING AND TYPING AND TYPING
-AND TYPING AND TYPING AND TYPING AND TYPING AND TYPING
-AND TYPING AND TYPING AND TYPING AND TYPING AND TYPING
-AND TYPING AND TYPING AND TYPING AND TYPING AND TYPING
-
-<!-- NEXT TEST -->
-expect __tvd_space_ratio
-
-Message-Id: <4.2.0.58.20000519002557.00a88870@pop.example.com>
-X-Sender: dwsauder@pop.example.com (Unverified)
-X-Mailer: QUALCOMM Windows Eudora Pro Version 4.2.0.58
-X-Priority: 2 (High)
-Date: Fri, 19 May 2000 00:29:55 -0400
-To: Heinz =?iso-8859-1?Q?M=FCller?= <mueller@example.com>
-From: Doug Sauder <dwsauder@example.com>
-Subject: =?iso-8859-1?Q?Die_Hasen_und_die_Fr=F6sche?=
-Mime-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: 7bit
-
-b v c
-u i i
-y a a
-c g l
-i r i
-a a s
-l
-i
-s
-
diff --git a/tests/src/smtp/inbound/antispam.rs b/tests/src/smtp/inbound/antispam.rs
index 23e13508..3e34e029 100644
--- a/tests/src/smtp/inbound/antispam.rs
+++ b/tests/src/smtp/inbound/antispam.rs
@@ -34,6 +34,7 @@ from-name = "Sieve Daemon"
from-addr = "sieve@foobar.org"
return-path = ""
hostname = "mx.foobar.org"
+no-capability-check = true
[sieve.limits]
redirects = 3
@@ -44,7 +45,6 @@ nested-includes = 5
duplicate-expiry = "7d"
[sieve.scripts]
-data = "file://%CFG_PATH%/config/sieve/antispam.sieve"
"#;
#[tokio::test]
@@ -55,49 +55,45 @@ async fn antispam() {
.finish(),
)
.unwrap();*/
-
- // Parse config
+ // Prepare config
let mut core = SMTP::test();
let qr = core.init_test_queue("smtp_antispam_test");
- let config = Config::parse(
- &CONFIG
- .replace("%PATH%", qr._temp_dir.temp_dir.as_path().to_str().unwrap())
- .replace(
- "%CFG_PATH%",
- PathBuf::from(env!("CARGO_MANIFEST_DIR"))
- .parent()
- .unwrap()
- .to_path_buf()
- .join("resources")
- .as_path()
- .to_str()
- .unwrap(),
- ),
- )
- .unwrap();
+ let mut config = CONFIG.replace("%PATH%", qr._temp_dir.temp_dir.as_path().to_str().unwrap());
+ let base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+ .parent()
+ .unwrap()
+ .to_path_buf()
+ .join("resources")
+ .join("config")
+ .join("sieve")
+ .to_str()
+ .unwrap()
+ .to_string();
+ for test_name in ["html", "subject"] {
+ config.push_str(&format!(
+ "{test_name} = \"file://{base_path}/{test_name}.sieve\"\n"
+ ));
+ }
+
+ // Parse config
+ let config = Config::parse(&config).unwrap();
let mut ctx = ConfigContext::new(&[]);
ctx.directory = config.parse_directory().unwrap();
core.sieve = config.parse_sieve(&mut ctx).unwrap();
let config = &mut core.session.config;
config.rcpt.relay = IfBlock::new(true);
let core = Arc::new(core);
- let script = ctx.scripts.get("data").unwrap().clone();
// Run tests
+ let base_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
+ .join("resources")
+ .join("smtp")
+ .join("antispam");
let span = tracing::info_span!("sieve_antispam");
- for file_name in fs::read_dir(
- PathBuf::from(env!("CARGO_MANIFEST_DIR"))
- .join("resources")
- .join("smtp")
- .join("antispam"),
- )
- .unwrap()
- {
- let file_name = file_name.unwrap().path();
-
- println!("===== {} =====", file_name.display());
+ for (test_name, script) in ctx.scripts {
+ println!("===== {test_name} =====");
- let contents = fs::read_to_string(&file_name).unwrap();
+ let contents = fs::read_to_string(base_path.join(format!("{test_name}.test"))).unwrap();
let mut lines = contents.lines();
let mut has_more = true;