This commit is contained in:
mdecimus
2023-07-27 20:18:34 +02:00
parent 4f2f673baa
commit 3cea77b65e
58 changed files with 1696 additions and 368 deletions

View File

@@ -26,11 +26,11 @@ pub mod ldap;
pub mod smtp;
pub mod sql;
use directory::{config::ConfigDirectory, DirectoryConfig};
use directory::{config::ConfigDirectory, AddressMapping, DirectoryConfig};
use mail_send::Credentials;
use rustls::{Certificate, PrivateKey, ServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::{io::BufReader, sync::Arc};
use std::{borrow::Cow, io::BufReader, sync::Arc};
use tokio_rustls::TlsAcceptor;
const CONFIG: &str = r#"
@@ -389,3 +389,49 @@ impl core::fmt::Debug for Item {
}
}
}
#[test]
fn address_mappings() {
const MAPPINGS: &str = r#"
[enable]
catch-all = true
subaddressing = true
expected-sub = "john.doe@example.org"
expected-catch = "@example.org"
[disable]
catch-all = false
subaddressing = false
expected-sub = "john.doe+alias@example.org"
expected-catch = false
[custom]
catch-all = { map = "(.+)@(.+)$", to = "info@${2}" }
subaddressing = { map = "^([^.]+)\.([^.]+)@(.+)$", to = "${2}@${3}" }
expected-sub = "doe+alias@example.org"
expected-catch = "info@example.org"
"#;
let config = utils::config::Config::parse(MAPPINGS).unwrap();
const ADDR: &str = "john.doe+alias@example.org";
for test in ["enable", "disable", "custom"] {
let catch_all = AddressMapping::from_config(&config, (test, "catch-all")).unwrap();
let subaddressing = AddressMapping::from_config(&config, (test, "subaddressing")).unwrap();
assert_eq!(
subaddressing.to_subaddress(ADDR),
config.value_require((test, "expected-sub")).unwrap(),
"failed subaddress for {test:?}"
);
assert_eq!(
catch_all.to_catch_all(ADDR),
config
.property_require::<Option<String>>((test, "expected-catch"))
.unwrap()
.map(Cow::Owned),
"failed catch-all for {test:?}"
);
}
}

View File

@@ -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(),
}
}
}

View File

@@ -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},

View File

@@ -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},

View File

@@ -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);

View File

@@ -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()

View File

@@ -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;

View File

@@ -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(&[]));

View File

@@ -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"
);
}

View File

@@ -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();

View File

@@ -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},

View File

@@ -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);

View File

@@ -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),

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);