Files
Stalwart/tests/src/smtp/outbound/extensions.rs
2024-02-10 15:39:05 +01:00

156 lines
5.2 KiB
Rust

/*
* 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::MX;
use smtp_proto::{MAIL_REQUIRETLS, MAIL_RET_HDRS, MAIL_SMTPUTF8, RCPT_NOTIFY_NEVER};
use utils::config::{if_block::IfBlock, ServerProtocol};
use crate::smtp::{
inbound::{TestMessage, TestQueueEvent},
outbound::start_test_server,
session::{TestSession, VerifyResponse},
TestConfig, TestSMTP,
};
use smtp::{
core::{Session, SMTP},
queue::{manager::Queue, DeliveryAttempt},
};
#[tokio::test]
#[serial_test::serial]
async fn extensions() {
/*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);
core.session.config.data.max_message_size = IfBlock::new(1500);
core.session.config.extensions.dsn = IfBlock::new(true);
core.session.config.extensions.requiretls = IfBlock::new(true);
let mut remote_qr = core.init_test_queue("smtp_ext_remote");
let _rx = start_test_server(core.into(), &[ServerProtocol::Smtp]);
// Add mock DNS entries
let mut core = SMTP::test();
core.resolvers.dns.mx_add(
"foobar.org",
vec![MX {
exchanges: vec!["mx.foobar.org".to_string()],
preference: 10,
}],
Instant::now() + Duration::from_secs(10),
);
core.resolvers.dns.ipv4_add(
"mx.foobar.org",
vec!["127.0.0.1".parse().unwrap()],
Instant::now() + Duration::from_secs(10),
);
// Successful delivery with DSN
let mut local_qr = core.init_test_queue("smtp_ext_local");
core.session.config.rcpt.relay = IfBlock::new(true);
core.session.config.extensions.dsn = IfBlock::new(true);
let core = Arc::new(core);
let mut queue = Queue::default();
let mut session = Session::test(core.clone());
session.data.remote_ip_str = "10.0.0.1".to_string();
session.eval_session_params().await;
session.ehlo("mx.test.org").await;
session
.send_message(
"john@test.org",
&["<bill@foobar.org> NOTIFY=SUCCESS,FAILURE"],
"test:no_dkim",
"250",
)
.await;
local_qr.expect_message_then_deliver().await
.try_deliver(core.clone())
.await;
local_qr
.read_event()
.await
.unwrap_message()
.read_lines(&core).await
.assert_contains("<bill@foobar.org> (delivered to")
.assert_contains("Final-Recipient: rfc822;bill@foobar.org")
.assert_contains("Action: delivered");
local_qr.read_event().await.unwrap_done();
remote_qr
.read_event()
.await
.unwrap_message()
.read_lines(&core).await
.assert_contains("using TLSv1.3 with cipher");
// Test SIZE extension
session
.send_message("john@test.org", &["bill@foobar.org"], "test:arc", "250")
.await;
local_qr.expect_message_then_deliver().await
.try_deliver(core.clone())
.await;
local_qr
.read_event()
.await
.unwrap_message()
.read_lines(&core).await
.assert_contains("<bill@foobar.org> (host 'mx.foobar.org' rejected command 'MAIL FROM:")
.assert_contains("Action: failed")
.assert_contains("Diagnostic-Code: smtp;552")
.assert_contains("Status: 5.3.4");
local_qr.read_event().await.unwrap_done();
remote_qr.assert_empty_queue();
// Test DSN, SMTPUTF8 and REQUIRETLS extensions
session
.send_message(
"<john@test.org> ENVID=abc123 RET=HDRS REQUIRETLS SMTPUTF8",
&["<bill@foobar.org> NOTIFY=NEVER"],
"test:no_dkim",
"250",
)
.await;
local_qr.expect_message_then_deliver().await
.try_deliver(core.clone())
.await;
local_qr.read_event().await.unwrap_done();
let message = remote_qr.expect_message().await();
assert_eq!(message.env_id, Some("abc123".to_string()));
assert!((message.flags & MAIL_RET_HDRS) != 0);
assert!((message.flags & MAIL_REQUIRETLS) != 0);
assert!((message.flags & MAIL_SMTPUTF8) != 0);
assert!((message.recipients.last().unwrap().flags & RCPT_NOTIFY_NEVER) != 0);
}