summaryrefslogtreecommitdiff
path: root/tests/src/smtp
diff options
context:
space:
mode:
authormdecimus <mauro@stalw.art>2023-07-27 20:18:34 +0200
committermdecimus <mauro@stalw.art>2023-07-27 20:18:34 +0200
commit3cea77b65e2863fc9a8e5f6b492b81292dc22843 (patch)
tree132d08058163a509789d007e61cc98d36ba1dd49 /tests/src/smtp
parent4f2f673baa65899c134d420d4a6375258a25f67c (diff)
v0.3.2
Diffstat (limited to 'tests/src/smtp')
-rw-r--r--tests/src/smtp/config.rs237
-rw-r--r--tests/src/smtp/inbound/auth.rs4
-rw-r--r--tests/src/smtp/inbound/data.rs6
-rw-r--r--tests/src/smtp/inbound/dmarc.rs20
-rw-r--r--tests/src/smtp/inbound/milter.rs10
-rw-r--r--tests/src/smtp/inbound/mod.rs1
-rw-r--r--tests/src/smtp/inbound/rcpt.rs6
-rw-r--r--tests/src/smtp/inbound/rewrite.rs169
-rw-r--r--tests/src/smtp/inbound/sign.rs16
-rw-r--r--tests/src/smtp/inbound/vrfy.rs6
-rw-r--r--tests/src/smtp/lookup/sql.rs6
-rw-r--r--tests/src/smtp/mod.rs2
-rw-r--r--tests/src/smtp/queue/dsn.rs3
-rw-r--r--tests/src/smtp/reporting/dmarc.rs3
-rw-r--r--tests/src/smtp/reporting/tls.rs3
15 files changed, 390 insertions, 102 deletions
diff --git a/tests/src/smtp/config.rs b/tests/src/smtp/config.rs
index 46c029c9..a1b0b13d 100644
--- a/tests/src/smtp/config.rs
+++ b/tests/src/smtp/config.rs
@@ -21,11 +21,11 @@
* for more details.
*/
-use std::{fs, net::IpAddr, path::PathBuf, sync::Arc, time::Duration};
+use std::{borrow::Cow, fs, net::IpAddr, path::PathBuf, sync::Arc, time::Duration};
use tokio::net::TcpSocket;
-use utils::config::{Config, Listener, Rate, Server, ServerProtocol};
+use utils::config::{Config, DynValue, Listener, Rate, Server, ServerProtocol};
use ahash::{AHashMap, AHashSet};
use directory::{config::ConfigDirectory, Lookup};
@@ -41,6 +41,20 @@ use smtp::{
use super::add_test_certs;
+struct TestEnvelope {
+ pub local_ip: IpAddr,
+ pub remote_ip: IpAddr,
+ pub sender_domain: String,
+ pub sender: String,
+ pub rcpt_domain: String,
+ pub rcpt: String,
+ pub helo_domain: String,
+ pub authenticated_as: String,
+ pub mx: String,
+ pub listener_id: u16,
+ pub priority: i16,
+}
+
#[test]
fn parse_conditions() {
let mut file = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
@@ -520,18 +534,139 @@ fn parse_servers() {
}
}
-struct TestEnvelope {
- pub local_ip: IpAddr,
- pub remote_ip: IpAddr,
- pub sender_domain: String,
- pub sender: String,
- pub rcpt_domain: String,
- pub rcpt: String,
- pub helo_domain: String,
- pub authenticated_as: String,
- pub mx: String,
- pub listener_id: u16,
- pub priority: i16,
+#[tokio::test]
+async fn eval_if() {
+ let mut file = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ file.push("resources");
+ file.push("smtp");
+ file.push("config");
+ file.push("rules-eval.toml");
+
+ let config = Config::parse(&fs::read_to_string(file).unwrap()).unwrap();
+ let servers = vec![
+ Server {
+ id: "smtp".to_string(),
+ internal_id: 123,
+ ..Default::default()
+ },
+ Server {
+ id: "smtps".to_string(),
+ internal_id: 456,
+ ..Default::default()
+ },
+ ];
+ let mut context = ConfigContext::new(&servers);
+ context.directory = config.parse_directory().unwrap();
+ let conditions = config.parse_conditions(&context).unwrap();
+
+ let envelope = TestEnvelope::from_config(&config);
+
+ for (key, conditions) in conditions {
+ //println!("============= Testing {:?} ==================", key);
+ let (_, expected_result) = key.rsplit_once('-').unwrap();
+ assert_eq!(
+ IfBlock {
+ if_then: vec![IfThen {
+ conditions,
+ then: true
+ }],
+ default: false,
+ }
+ .eval(&envelope)
+ .await,
+ &expected_result.parse::<bool>().unwrap(),
+ "failed for {key:?}"
+ );
+ }
+}
+
+#[tokio::test]
+async fn eval_dynvalue() {
+ let mut file = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ file.push("resources");
+ file.push("smtp");
+ file.push("config");
+ file.push("rules-dynvalue.toml");
+
+ let config = Config::parse(&fs::read_to_string(file).unwrap()).unwrap();
+ let mut context = ConfigContext::new(&[]);
+ context.directory = config.parse_directory().unwrap();
+
+ let envelope = TestEnvelope::from_config(&config);
+
+ for test_name in config.sub_keys("eval") {
+ //println!("============= Testing {:?} ==================", key);
+ let if_block = config
+ .parse_if_block::<Option<DynValue>>(
+ ("eval", test_name, "test"),
+ &context,
+ &[
+ EnvelopeKey::Recipient,
+ EnvelopeKey::RecipientDomain,
+ EnvelopeKey::Sender,
+ EnvelopeKey::SenderDomain,
+ EnvelopeKey::AuthenticatedAs,
+ EnvelopeKey::Listener,
+ EnvelopeKey::RemoteIp,
+ EnvelopeKey::LocalIp,
+ EnvelopeKey::Priority,
+ EnvelopeKey::Mx,
+ ],
+ )
+ .unwrap()
+ .unwrap();
+ let expected = config
+ .property_require::<Option<String>>(("eval", test_name, "expect"))
+ .unwrap()
+ .map(Cow::Owned);
+
+ assert_eq!(
+ if_block.eval_and_capture(&envelope).await.into_value(),
+ expected,
+ "failed for test {test_name:?}"
+ );
+ }
+
+ for test_name in config.sub_keys("maybe-eval") {
+ //println!("============= Testing {:?} ==================", key);
+ let if_block = config
+ .parse_if_block::<Option<DynValue>>(
+ ("maybe-eval", test_name, "test"),
+ &context,
+ &[
+ EnvelopeKey::Recipient,
+ EnvelopeKey::RecipientDomain,
+ EnvelopeKey::Sender,
+ EnvelopeKey::SenderDomain,
+ EnvelopeKey::AuthenticatedAs,
+ EnvelopeKey::Listener,
+ EnvelopeKey::RemoteIp,
+ EnvelopeKey::LocalIp,
+ EnvelopeKey::Priority,
+ EnvelopeKey::Mx,
+ ],
+ )
+ .unwrap()
+ .unwrap()
+ .map_if_block(
+ &context.directory.directories,
+ ("maybe-eval", test_name, "test"),
+ "test",
+ )
+ .unwrap();
+ let expected = config
+ .value_require(("maybe-eval", test_name, "expect"))
+ .unwrap();
+
+ assert!(if_block
+ .eval_and_capture(&envelope)
+ .await
+ .into_value()
+ .unwrap()
+ .is_local_domain(expected)
+ .await
+ .unwrap());
+ }
}
impl Envelope for TestEnvelope {
@@ -580,62 +715,22 @@ impl Envelope for TestEnvelope {
}
}
-#[tokio::test]
-async fn eval_if() {
- let mut file = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
- file.push("resources");
- file.push("smtp");
- file.push("config");
- file.push("rules-eval.toml");
-
- let config = Config::parse(&fs::read_to_string(file).unwrap()).unwrap();
- let servers = vec![
- Server {
- id: "smtp".to_string(),
- internal_id: 123,
- ..Default::default()
- },
- Server {
- id: "smtps".to_string(),
- internal_id: 456,
- ..Default::default()
- },
- ];
- let mut context = ConfigContext::new(&servers);
- context.directory = config.parse_directory().unwrap();
- let conditions = config.parse_conditions(&context).unwrap();
-
- let envelope = TestEnvelope {
- local_ip: config.property_require("envelope.local-ip").unwrap(),
- remote_ip: config.property_require("envelope.remote-ip").unwrap(),
- sender_domain: config.property_require("envelope.sender-domain").unwrap(),
- sender: config.property_require("envelope.sender").unwrap(),
- rcpt_domain: config.property_require("envelope.rcpt-domain").unwrap(),
- rcpt: config.property_require("envelope.rcpt").unwrap(),
- authenticated_as: config
- .property_require("envelope.authenticated-as")
- .unwrap(),
- mx: config.property_require("envelope.mx").unwrap(),
- listener_id: config.property_require("envelope.listener").unwrap(),
- priority: config.property_require("envelope.priority").unwrap(),
- helo_domain: config.property_require("envelope.helo-domain").unwrap(),
- };
-
- for (key, conditions) in conditions {
- //println!("============= Testing {:?} ==================", key);
- let (_, expected_result) = key.rsplit_once('-').unwrap();
- assert_eq!(
- IfBlock {
- if_then: vec![IfThen {
- conditions,
- then: true
- }],
- default: false,
- }
- .eval(&envelope)
- .await,
- &expected_result.parse::<bool>().unwrap(),
- "failed for {key:?}"
- );
+impl TestEnvelope {
+ pub fn from_config(config: &Config) -> Self {
+ Self {
+ local_ip: config.property_require("envelope.local-ip").unwrap(),
+ remote_ip: config.property_require("envelope.remote-ip").unwrap(),
+ sender_domain: config.property_require("envelope.sender-domain").unwrap(),
+ sender: config.property_require("envelope.sender").unwrap(),
+ rcpt_domain: config.property_require("envelope.rcpt-domain").unwrap(),
+ rcpt: config.property_require("envelope.rcpt").unwrap(),
+ authenticated_as: config
+ .property_require("envelope.authenticated-as")
+ .unwrap(),
+ mx: config.property_require("envelope.mx").unwrap(),
+ listener_id: config.property_require("envelope.listener").unwrap(),
+ priority: config.property_require("envelope.priority").unwrap(),
+ helo_domain: config.property_require("envelope.helo-domain").unwrap(),
+ }
}
}
diff --git a/tests/src/smtp/inbound/auth.rs b/tests/src/smtp/inbound/auth.rs
index 8cf014d0..013cccd8 100644
--- a/tests/src/smtp/inbound/auth.rs
+++ b/tests/src/smtp/inbound/auth.rs
@@ -23,7 +23,7 @@
use directory::config::ConfigDirectory;
use smtp_proto::{AUTH_LOGIN, AUTH_PLAIN};
-use utils::config::Config;
+use utils::config::{Config, DynValue};
use crate::smtp::{
session::{TestSession, VerifyResponse},
@@ -68,7 +68,7 @@ async fn auth() {
.parse_if(&ctx);
config.directory = r"[{if = 'remote-ip', eq = '10.0.0.1', then = 'local'},
{else = false}]"
- .parse_if::<Option<String>>(&ctx)
+ .parse_if::<Option<DynValue>>(&ctx)
.map_if_block(&ctx.directory.directories, "", "")
.unwrap();
config.errors_max = r"[{if = 'remote-ip', eq = '10.0.0.1', then = 2},
diff --git a/tests/src/smtp/inbound/data.rs b/tests/src/smtp/inbound/data.rs
index 411cbbed..c8169160 100644
--- a/tests/src/smtp/inbound/data.rs
+++ b/tests/src/smtp/inbound/data.rs
@@ -30,7 +30,7 @@ use crate::smtp::{
ParseTestConfig, TestConfig, TestSMTP,
};
use smtp::{
- config::{ConfigContext, IfBlock},
+ config::{ConfigContext, IfBlock, MaybeDynValue},
core::{Session, SMTP},
};
@@ -81,7 +81,9 @@ async fn data() {
let mut qr = core.init_test_queue("smtp_data_test");
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
- config.directory = IfBlock::new(Some(directory.directories.get("local").unwrap().clone()));
+ config.directory = IfBlock::new(Some(MaybeDynValue::Static(
+ directory.directories.get("local").unwrap().clone(),
+ )));
let mut config = &mut core.session.config;
config.data.add_auth_results = "[{if = 'remote-ip', eq = '10.0.0.3', then = true},
diff --git a/tests/src/smtp/inbound/dmarc.rs b/tests/src/smtp/inbound/dmarc.rs
index d070e294..eadc1eac 100644
--- a/tests/src/smtp/inbound/dmarc.rs
+++ b/tests/src/smtp/inbound/dmarc.rs
@@ -34,7 +34,7 @@ use mail_auth::{
report::DmarcResult,
spf::Spf,
};
-use utils::config::{Config, Rate};
+use utils::config::{Config, DynValue, Rate};
use crate::smtp::{
inbound::{sign::TextConfigContext, TestMessage, TestQueueEvent, TestReportingEvent},
@@ -42,7 +42,7 @@ use crate::smtp::{
ParseTestConfig, TestConfig, TestSMTP,
};
use smtp::{
- config::{AggregateFrequency, ConfigContext, IfBlock, VerifyStrategy},
+ config::{AggregateFrequency, ConfigContext, IfBlock, MaybeDynValue, VerifyStrategy},
core::{Session, SMTP},
};
@@ -134,7 +134,9 @@ async fn dmarc() {
let mut rr = core.init_test_report();
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
- config.directory = IfBlock::new(Some(directory.directories.get("local").unwrap().clone()));
+ config.directory = IfBlock::new(Some(MaybeDynValue::Static(
+ directory.directories.get("local").unwrap().clone(),
+ )));
let mut config = &mut core.session.config;
config.data.add_auth_results = IfBlock::new(true);
@@ -166,11 +168,17 @@ async fn dmarc() {
let mut config = &mut core.report.config;
config.spf.sign = "['rsa']"
- .parse_if::<Vec<String>>(&ctx)
+ .parse_if::<Vec<DynValue>>(&ctx)
+ .map_if_block(&ctx.signers, "", "")
+ .unwrap();
+ config.dmarc.sign = "['rsa']"
+ .parse_if::<Vec<DynValue>>(&ctx)
+ .map_if_block(&ctx.signers, "", "")
+ .unwrap();
+ config.dkim.sign = "['rsa']"
+ .parse_if::<Vec<DynValue>>(&ctx)
.map_if_block(&ctx.signers, "", "")
.unwrap();
- config.dmarc.sign = config.spf.sign.clone();
- config.dkim.sign = config.spf.sign.clone();
// SPF must pass
let core = Arc::new(core);
diff --git a/tests/src/smtp/inbound/milter.rs b/tests/src/smtp/inbound/milter.rs
index d9622678..fad22580 100644
--- a/tests/src/smtp/inbound/milter.rs
+++ b/tests/src/smtp/inbound/milter.rs
@@ -212,7 +212,7 @@ fn milter_address_modifications() {
// ChangeFrom
assert!(data
- .apply_modifications(
+ .apply_milter_modifications(
vec![Modification::ChangeFrom {
sender: "<>".to_string(),
args: String::new()
@@ -227,7 +227,7 @@ fn milter_address_modifications() {
// ChangeFrom with parameters
assert!(data
- .apply_modifications(
+ .apply_milter_modifications(
vec![Modification::ChangeFrom {
sender: "john@example.org".to_string(),
args: "REQUIRETLS ENVID=abc123".to_string(), //"NOTIFY=SUCCESS,FAILURE ENVID=abc123\n".to_string()
@@ -242,7 +242,7 @@ fn milter_address_modifications() {
// Add recipients
assert!(data
- .apply_modifications(
+ .apply_milter_modifications(
vec![
Modification::AddRcpt {
recipient: "bill@example.org".to_string(),
@@ -276,7 +276,7 @@ fn milter_address_modifications() {
// Remove recipients
assert!(data
- .apply_modifications(
+ .apply_milter_modifications(
vec![
Modification::DeleteRcpt {
recipient: "bill@example.org".to_string(),
@@ -319,7 +319,7 @@ fn milter_message_modifications() {
test.result,
String::from_utf8(
session_data
- .apply_modifications(test.modifications, &parsed_test_message)
+ .apply_milter_modifications(test.modifications, &parsed_test_message)
.unwrap()
)
.unwrap()
diff --git a/tests/src/smtp/inbound/mod.rs b/tests/src/smtp/inbound/mod.rs
index eb0fad89..0032c91f 100644
--- a/tests/src/smtp/inbound/mod.rs
+++ b/tests/src/smtp/inbound/mod.rs
@@ -42,6 +42,7 @@ pub mod limits;
pub mod mail;
pub mod milter;
pub mod rcpt;
+pub mod rewrite;
pub mod scripts;
pub mod sign;
pub mod throttle;
diff --git a/tests/src/smtp/inbound/rcpt.rs b/tests/src/smtp/inbound/rcpt.rs
index 3441f183..80b50deb 100644
--- a/tests/src/smtp/inbound/rcpt.rs
+++ b/tests/src/smtp/inbound/rcpt.rs
@@ -32,7 +32,7 @@ use crate::smtp::{
ParseTestConfig, TestConfig,
};
use smtp::{
- config::{ConfigContext, IfBlock},
+ config::{ConfigContext, IfBlock, MaybeDynValue},
core::{Session, State, SMTP},
};
@@ -75,7 +75,9 @@ async fn rcpt() {
let mut config_ext = &mut core.session.config.extensions;
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
- config.directory = IfBlock::new(Some(directory.directories.get("local").unwrap().clone()));
+ config.directory = IfBlock::new(Some(MaybeDynValue::Static(
+ directory.directories.get("local").unwrap().clone(),
+ )));
config.max_recipients = r"[{if = 'remote-ip', eq = '10.0.0.1', then = 3},
{else = 5}]"
.parse_if(&ConfigContext::new(&[]));
diff --git a/tests/src/smtp/inbound/rewrite.rs b/tests/src/smtp/inbound/rewrite.rs
new file mode 100644
index 00000000..eb895f58
--- /dev/null
+++ b/tests/src/smtp/inbound/rewrite.rs
@@ -0,0 +1,169 @@
+/*
+ * 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 crate::smtp::{inbound::sign::TextConfigContext, session::TestSession, TestConfig};
+use directory::config::ConfigDirectory;
+use smtp::{
+ config::{if_block::ConfigIf, scripts::ConfigSieve, ConfigContext, EnvelopeKey, IfBlock},
+ core::{Session, SMTP},
+};
+use utils::config::{Config, DynValue};
+
+const CONFIG: &str = r#"
+[session.mail]
+rewrite = [ { all-of = [ { if = "sender-domain", ends-with = ".foobar.net" },
+ { if = "sender", matches = "^([^.]+)@([^.]+)\.(.+)$"},
+ ], then = "${1}+${2}@${3}" },
+ { else = false } ]
+script = [ { if = "sender-domain", eq = "foobar.org", then = "mail" },
+ { else = false } ]
+
+[session.rcpt]
+rewrite = [ { all-of = [ { if = "rcpt-domain", eq = "foobar.net" },
+ { if = "rcpt", matches = "^([^.]+)\.([^.]+)@(.+)$"},
+ ], then = "${1}+${2}@${3}" },
+ { else = false } ]
+script = [ { if = "rcpt-domain", eq = "foobar.org", then = "rcpt" },
+ { else = false } ]
+
+[sieve]
+from-name = "Sieve Daemon"
+from-addr = "sieve@foobar.org"
+return-path = ""
+hostname = "mx.foobar.org"
+
+[sieve.limits]
+redirects = 3
+out-messages = 5
+received-headers = 50
+cpu = 10000
+nested-includes = 5
+duplicate-expiry = "7d"
+
+[sieve.scripts]
+mail = '''
+require ["variables", "envelope"];
+
+if allof( envelope :domain :is "from" "foobar.org",
+ envelope :localpart :contains "from" "admin" ) {
+ set "envelope.from" "MAILER-DAEMON@foobar.org";
+}
+
+'''
+
+rcpt = '''
+require ["variables", "envelope", "regex"];
+
+if allof( envelope :localpart :contains "to" ".",
+ envelope :regex "to" "(.+)@(.+)$") {
+ set :replace "." "" "to" "${1}";
+ set "envelope.to" "${to}@${2}";
+}
+
+'''
+
+"#;
+
+#[tokio::test]
+async fn address_rewrite() {
+ /*tracing::subscriber::set_global_default(
+ tracing_subscriber::FmtSubscriber::builder()
+ .with_max_level(tracing::Level::TRACE)
+ .finish(),
+ )
+ .unwrap();*/
+
+ // Prepare config
+ let available_keys = [
+ EnvelopeKey::Sender,
+ EnvelopeKey::SenderDomain,
+ EnvelopeKey::Recipient,
+ EnvelopeKey::RecipientDomain,
+ ];
+ let mut core = SMTP::test();
+ let mut ctx = ConfigContext::new(&[]).parse_signatures();
+ let settings = Config::parse(CONFIG).unwrap();
+ ctx.directory = settings.parse_directory().unwrap();
+ core.sieve = settings.parse_sieve(&mut ctx).unwrap();
+ let config = &mut core.session.config;
+ config.mail.script = settings
+ .parse_if_block::<Option<String>>("session.mail.script", &ctx, &available_keys)
+ .unwrap()
+ .unwrap_or_default()
+ .map_if_block(&ctx.scripts, "session.mail.script", "script")
+ .unwrap();
+ config.mail.rewrite = settings
+ .parse_if_block::<Option<DynValue>>("session.mail.rewrite", &ctx, &available_keys)
+ .unwrap()
+ .unwrap_or_default();
+ config.rcpt.script = settings
+ .parse_if_block::<Option<String>>("session.rcpt.script", &ctx, &available_keys)
+ .unwrap()
+ .unwrap_or_default()
+ .map_if_block(&ctx.scripts, "session.rcpt.script", "script")
+ .unwrap();
+ config.rcpt.rewrite = settings
+ .parse_if_block::<Option<DynValue>>("session.rcpt.rewrite", &ctx, &available_keys)
+ .unwrap()
+ .unwrap_or_default();
+ config.rcpt.relay = IfBlock::new(true);
+
+ // Init session
+ let mut session = Session::test(core);
+ session.data.remote_ip = "10.0.0.1".parse().unwrap();
+ session.eval_session_params().await;
+ session.ehlo("mx.doe.org").await;
+
+ // Sender rewrite using regex
+ session.mail_from("bill@doe.foobar.net", "250").await;
+ assert_eq!(
+ session.data.mail_from.as_ref().unwrap().address,
+ "bill+doe@foobar.net"
+ );
+ session.reset();
+
+ // Sender rewrite using sieve
+ session.mail_from("this_is_admin@foobar.org", "250").await;
+ assert_eq!(
+ session.data.mail_from.as_ref().unwrap().address_lcase,
+ "mailer-daemon@foobar.org"
+ );
+
+ // Recipient rewrite using regex
+ session.rcpt_to("mary.smith@foobar.net", "250").await;
+ assert_eq!(
+ session.data.rcpt_to.last().unwrap().address,
+ "mary+smith@foobar.net"
+ );
+
+ // Remove duplicates
+ session.rcpt_to("mary.smith@foobar.net", "250").await;
+ assert_eq!(session.data.rcpt_to.len(), 1);
+
+ // Recipient rewrite using sieve
+ session.rcpt_to("m.a.r.y.s.m.i.t.h@foobar.org", "250").await;
+ assert_eq!(
+ session.data.rcpt_to.last().unwrap().address,
+ "marysmith@foobar.org"
+ );
+}
diff --git a/tests/src/smtp/inbound/sign.rs b/tests/src/smtp/inbound/sign.rs
index 11c70cbe..6da52cc4 100644
--- a/tests/src/smtp/inbound/sign.rs
+++ b/tests/src/smtp/inbound/sign.rs
@@ -28,7 +28,7 @@ use mail_auth::{
common::{parse::TxtRecordParser, verify::DomainKey},
spf::Spf,
};
-use utils::config::Config;
+use utils::config::{Config, DynValue};
use crate::smtp::{
inbound::{TestMessage, TestQueueEvent},
@@ -36,7 +36,7 @@ use crate::smtp::{
ParseTestConfig, TestConfig, TestSMTP,
};
use smtp::{
- config::{auth::ConfigAuth, ConfigContext, IfBlock, VerifyStrategy},
+ config::{auth::ConfigAuth, ConfigContext, IfBlock, MaybeDynValue, VerifyStrategy},
core::{Session, SMTP},
};
@@ -81,7 +81,9 @@ report = true
[signature.ed]
public-key = '11qYAYKxCrfVS/7TyWQHOg7hcvPapiMlrwIaaPcHURo='
-private-key = 'nWGxne/9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A='
+private-key = '-----BEGIN PRIVATE KEY-----
+nWGxne/9WmC6hEr0kuwsxERJxWl7MmkZcDusAxyuf2A=
+-----END PRIVATE KEY-----'
domain = 'example.com'
selector = 'ed'
headers = ['From', 'To', 'Date', 'Subject', 'Message-ID']
@@ -152,7 +154,9 @@ async fn sign_and_seal() {
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
- config.directory = IfBlock::new(Some(directory.directories.get("local").unwrap().clone()));
+ config.directory = IfBlock::new(Some(MaybeDynValue::Static(
+ directory.directories.get("local").unwrap().clone(),
+ )));
let mut config = &mut core.session.config;
config.data.add_auth_results = IfBlock::new(true);
@@ -170,11 +174,11 @@ async fn sign_and_seal() {
config.arc.verify = config.spf.verify_ehlo.clone();
config.dmarc.verify = config.spf.verify_ehlo.clone();
config.dkim.sign = "['rsa']"
- .parse_if::<Vec<String>>(&ctx)
+ .parse_if::<Vec<DynValue>>(&ctx)
.map_if_block(&ctx.signers, "", "")
.unwrap();
config.arc.seal = "'ed'"
- .parse_if::<Option<String>>(&ctx)
+ .parse_if::<Option<DynValue>>(&ctx)
.map_if_block(&ctx.sealers, "", "")
.unwrap();
diff --git a/tests/src/smtp/inbound/vrfy.rs b/tests/src/smtp/inbound/vrfy.rs
index 3acbb6bb..d88414dc 100644
--- a/tests/src/smtp/inbound/vrfy.rs
+++ b/tests/src/smtp/inbound/vrfy.rs
@@ -29,7 +29,7 @@ use crate::smtp::{
ParseTestConfig, TestConfig,
};
use smtp::{
- config::{ConfigContext, IfBlock},
+ config::{ConfigContext, IfBlock, MaybeDynValue},
core::{Session, SMTP},
};
@@ -67,7 +67,9 @@ async fn vrfy_expn() {
let directory = Config::parse(DIRECTORY).unwrap().parse_directory().unwrap();
let mut config = &mut core.session.config.rcpt;
- config.directory = IfBlock::new(Some(directory.directories.get("local").unwrap().clone()));
+ config.directory = IfBlock::new(Some(MaybeDynValue::Static(
+ directory.directories.get("local").unwrap().clone(),
+ )));
let mut config = &mut core.session.config.extensions;
config.vrfy = r"[{if = 'remote-ip', eq = '10.0.0.1', then = true},
diff --git a/tests/src/smtp/lookup/sql.rs b/tests/src/smtp/lookup/sql.rs
index 6efe9d3c..8a672074 100644
--- a/tests/src/smtp/lookup/sql.rs
+++ b/tests/src/smtp/lookup/sql.rs
@@ -25,7 +25,7 @@ use std::time::Duration;
use directory::config::ConfigDirectory;
use smtp_proto::{AUTH_LOGIN, AUTH_PLAIN};
-use utils::config::Config;
+use utils::config::{Config, DynValue};
use crate::{
directory::sql::{create_test_directory, create_test_user_with_email, link_test_address},
@@ -115,7 +115,7 @@ async fn lookup_sql() {
// Enable AUTH
let mut config = &mut core.session.config.auth;
config.directory = r"'sql'"
- .parse_if::<Option<String>>(&ctx)
+ .parse_if::<Option<DynValue>>(&ctx)
.map_if_block(&ctx.directory.directories, "", "")
.unwrap();
config.mechanisms = IfBlock::new(AUTH_PLAIN | AUTH_LOGIN);
@@ -124,7 +124,7 @@ async fn lookup_sql() {
// Enable VRFY/EXPN/RCPT
let mut config = &mut core.session.config.rcpt;
config.directory = r"'sql'"
- .parse_if::<Option<String>>(&ctx)
+ .parse_if::<Option<DynValue>>(&ctx)
.map_if_block(&ctx.directory.directories, "", "")
.unwrap();
config.relay = IfBlock::new(false);
diff --git a/tests/src/smtp/mod.rs b/tests/src/smtp/mod.rs
index dc7539d8..6189a353 100644
--- a/tests/src/smtp/mod.rs
+++ b/tests/src/smtp/mod.rs
@@ -239,6 +239,7 @@ impl TestConfig for SessionConfig {
},
mail: Mail {
script: IfBlock::new(None),
+ rewrite: IfBlock::new(None),
},
rcpt: Rcpt {
script: IfBlock::new(None),
@@ -247,6 +248,7 @@ impl TestConfig for SessionConfig {
errors_max: IfBlock::new(3),
errors_wait: IfBlock::new(Duration::from_secs(1)),
max_recipients: IfBlock::new(3),
+ rewrite: IfBlock::new(None),
},
data: Data {
script: IfBlock::new(None),
diff --git a/tests/src/smtp/queue/dsn.rs b/tests/src/smtp/queue/dsn.rs
index f1768dad..cdc8c328 100644
--- a/tests/src/smtp/queue/dsn.rs
+++ b/tests/src/smtp/queue/dsn.rs
@@ -29,6 +29,7 @@ use std::{
use smtp_proto::{Response, RCPT_NOTIFY_DELAY, RCPT_NOTIFY_FAILURE, RCPT_NOTIFY_SUCCESS};
use tokio::{fs::File, io::AsyncReadExt};
+use utils::config::DynValue;
use crate::smtp::{
inbound::{sign::TextConfigContext, TestQueueEvent},
@@ -109,7 +110,7 @@ async fn generate_dsn() {
let ctx = ConfigContext::new(&[]).parse_signatures();
let mut config = &mut core.queue.config.dsn;
config.sign = "['rsa']"
- .parse_if::<Vec<String>>(&ctx)
+ .parse_if::<Vec<DynValue>>(&ctx)
.map_if_block(&ctx.signers, "", "")
.unwrap();
diff --git a/tests/src/smtp/reporting/dmarc.rs b/tests/src/smtp/reporting/dmarc.rs
index 779604b7..7f929476 100644
--- a/tests/src/smtp/reporting/dmarc.rs
+++ b/tests/src/smtp/reporting/dmarc.rs
@@ -32,6 +32,7 @@ use mail_auth::{
dmarc::Dmarc,
report::{ActionDisposition, Disposition, DmarcResult, Record, Report},
};
+use utils::config::DynValue;
use crate::smtp::{
inbound::{sign::TextConfigContext, TestMessage, TestQueueEvent},
@@ -66,7 +67,7 @@ async fn report_dmarc() {
config.path = IfBlock::new(temp_dir.temp_dir.clone());
config.hash = IfBlock::new(16);
config.dmarc_aggregate.sign = "['rsa']"
- .parse_if::<Vec<String>>(&ctx)
+ .parse_if::<Vec<DynValue>>(&ctx)
.map_if_block(&ctx.signers, "", "")
.unwrap();
config.dmarc_aggregate.max_size = IfBlock::new(4096);
diff --git a/tests/src/smtp/reporting/tls.rs b/tests/src/smtp/reporting/tls.rs
index fb72b8f1..2e213009 100644
--- a/tests/src/smtp/reporting/tls.rs
+++ b/tests/src/smtp/reporting/tls.rs
@@ -29,6 +29,7 @@ use mail_auth::{
mta_sts::TlsRpt,
report::tlsrpt::{FailureDetails, PolicyType, ResultType, TlsReport},
};
+use utils::config::DynValue;
use crate::smtp::{
inbound::{sign::TextConfigContext, TestMessage, TestQueueEvent},
@@ -63,7 +64,7 @@ async fn report_tls() {
config.path = IfBlock::new(temp_dir.temp_dir.clone());
config.hash = IfBlock::new(16);
config.tls.sign = "['rsa']"
- .parse_if::<Vec<String>>(&ctx)
+ .parse_if::<Vec<DynValue>>(&ctx)
.map_if_block(&ctx.signers, "", "")
.unwrap();
config.tls.max_size = IfBlock::new(4096);