Fixed Ipv6thenIpv4 SMTP lookups

This commit is contained in:
mdecimus
2023-09-05 14:22:16 +02:00
parent 56b1fb893d
commit 6404d27dd9
7 changed files with 409 additions and 84 deletions

View File

@@ -7,18 +7,18 @@ set "address4" "jane@example.org";
set "address5" "john@localhost";
set "address6" "jane@localhost";
if not string :is "${address1.base_domain()}" "${address2.base_domain()}" {
reject "${address1.base_domain()} != ${address2.base_domain()}";
if not string :is "${address1.subdomain_part()}" "${address2.subdomain_part()}" {
reject "${address1.subdomain_part()} != ${address2.subdomain_part()}";
stop;
}
if not string :is "${address3.base_domain()}" "${address4.base_domain()}" {
reject "${address3.base_domain()} != ${address4.base_domain()}";
if not string :is "${address3.subdomain_part()}" "${address4.subdomain_part()}" {
reject "${address3.subdomain_part()} != ${address4.subdomain_part()}";
stop;
}
if not string :is "${address5.base_domain()}" "${address6.base_domain()}" {
reject "${address5.base_domain()} != ${address6.base_domain()}";
if not string :is "${address5.subdomain_part()}" "${address6.subdomain_part()}" {
reject "${address5.subdomain_part()} != ${address6.subdomain_part()}";
stop;
}

View File

@@ -75,7 +75,7 @@ async fn lookup_ip() {
// Ipv4 strategy
core.queue.config.ip_strategy = IfBlock::new(IpLookupStrategy::Ipv4thenIpv6);
let (source_ips, remote_ips) = core
let resolve_result = core
.resolve_host(
&NextHop::MX("mx.foobar.org"),
&RecipientDomain::new("envelope"),
@@ -83,15 +83,17 @@ async fn lookup_ip() {
)
.await
.unwrap();
assert!(ipv4.contains(&match source_ips.unwrap() {
assert!(ipv4.contains(&match resolve_result.source_ipv4.unwrap() {
std::net::IpAddr::V4(v4) => v4,
_ => unreachable!(),
}));
assert!(remote_ips.contains(&"172.168.0.100".parse().unwrap()));
assert!(resolve_result
.remote_ips
.contains(&"172.168.0.100".parse().unwrap()));
// Ipv6 strategy
core.queue.config.ip_strategy = IfBlock::new(IpLookupStrategy::Ipv6thenIpv4);
let (source_ips, remote_ips) = core
let resolve_result = core
.resolve_host(
&NextHop::MX("mx.foobar.org"),
&RecipientDomain::new("envelope"),
@@ -99,11 +101,13 @@ async fn lookup_ip() {
)
.await
.unwrap();
assert!(ipv6.contains(&match source_ips.unwrap() {
assert!(ipv6.contains(&match resolve_result.source_ipv6.unwrap() {
std::net::IpAddr::V6(v6) => v6,
_ => unreachable!(),
}));
assert!(remote_ips.contains(&"e:f::a".parse().unwrap()));
assert!(resolve_result
.remote_ips
.contains(&"e:f::a".parse().unwrap()));
}
#[test]

View File

@@ -0,0 +1,110 @@
/*
* 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 std::{
sync::Arc,
time::{Duration, Instant},
};
use mail_auth::{IpLookupStrategy, MX};
use utils::config::ServerProtocol;
use crate::smtp::{
inbound::TestQueueEvent, outbound::start_test_server, session::TestSession, TestConfig,
TestSMTP,
};
use smtp::{
config::IfBlock,
core::{Session, SMTP},
queue::{manager::Queue, DeliveryAttempt},
};
#[tokio::test]
#[serial_test::serial]
async fn ip_lookup_strategy() {
/*tracing::subscriber::set_global_default(
tracing_subscriber::FmtSubscriber::builder()
.with_max_level(tracing::Level::TRACE)
.finish(),
)
.unwrap();*/
// Start test server
let mut core = SMTP::test();
core.session.config.rcpt.relay = IfBlock::new(true);
let mut remote_qr = core.init_test_queue("smtp_iplookup_remote");
let _rx = start_test_server(core.into(), &[ServerProtocol::Smtp]);
for strategy in [IpLookupStrategy::Ipv6Only, IpLookupStrategy::Ipv6thenIpv4] {
println!("-> Strategy: {:?}", strategy);
// Add mock DNS entries
let mut core = SMTP::test();
core.queue.config.ip_strategy = IfBlock::new(IpLookupStrategy::Ipv6thenIpv4);
core.resolvers.dns.mx_add(
"foobar.org",
vec![MX {
exchanges: vec!["mx.foobar.org".to_string()],
preference: 10,
}],
Instant::now() + Duration::from_secs(10),
);
if matches!(strategy, IpLookupStrategy::Ipv6thenIpv4) {
core.resolvers.dns.ipv4_add(
"mx.foobar.org",
vec!["127.0.0.1".parse().unwrap()],
Instant::now() + Duration::from_secs(10),
);
}
core.resolvers.dns.ipv6_add(
"mx.foobar.org",
vec!["::1".parse().unwrap()],
Instant::now() + Duration::from_secs(10),
);
// Retry on failed STARTTLS
let mut local_qr = core.init_test_queue("smtp_iplookup_local");
core.session.config.rcpt.relay = IfBlock::new(true);
let core = Arc::new(core);
let mut queue = Queue::default();
let mut session = Session::test(core.clone());
session.data.remote_ip = "10.0.0.1".parse().unwrap();
session.eval_session_params().await;
session.ehlo("mx.test.org").await;
session
.send_message("john@test.org", &["bill@foobar.org"], "test:no_dkim", "250")
.await;
DeliveryAttempt::from(local_qr.read_event().await.unwrap_message())
.try_deliver(core.clone(), &mut queue)
.await;
if matches!(strategy, IpLookupStrategy::Ipv6thenIpv4) {
local_qr.read_event().await.unwrap_done();
remote_qr.read_event().await.unwrap_message();
} else {
let status = local_qr.read_event().await.unwrap_retry().inner.domains[0]
.status
.to_string();
assert!(status.contains("Connection refused"));
}
}
}

View File

@@ -32,6 +32,7 @@ use super::add_test_certs;
pub mod dane;
pub mod extensions;
pub mod ip_lookup;
pub mod lmtp;
pub mod mta_sts;
pub mod smtp;