Fixed Ipv6thenIpv4 SMTP lookups
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
110
tests/src/smtp/outbound/ip_lookup.rs
Normal file
110
tests/src/smtp/outbound/ip_lookup.rs
Normal 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user