Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
smtp::{
|
||||
inbound::TestMessage,
|
||||
session::{TestSession, VerifyResponse, load_test_message},
|
||||
},
|
||||
utils::server::TestServerBuilder,
|
||||
};
|
||||
use registry::{
|
||||
schema::{
|
||||
enums::MtaQueueQuotaKey,
|
||||
prelude::ObjectType,
|
||||
structs::{
|
||||
Expression, ExpressionMatch, MtaQueueQuota, MtaStageData, SenderAuth, SpamSettings,
|
||||
},
|
||||
},
|
||||
types::{list::List, map::Map},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn data() {
|
||||
let mut test = TestServerBuilder::new("smtp_data_test")
|
||||
.await
|
||||
.with_http_listener(19004)
|
||||
.await
|
||||
.disable_services()
|
||||
.capture_queue()
|
||||
.build()
|
||||
.await;
|
||||
|
||||
// Create test users
|
||||
let admin = test.account("admin");
|
||||
for (name, secret, description, aliases) in [
|
||||
("[email protected]", "12345 + extra safety", "John Doe", &[]),
|
||||
("[email protected]", "abcde + extra safety", "Jane Smith", &[]),
|
||||
(
|
||||
"[email protected]",
|
||||
"p4ssw0rd + extra safety",
|
||||
"Bill Foobar",
|
||||
&[],
|
||||
),
|
||||
(
|
||||
"[email protected]",
|
||||
"p4ssw0rd + extra safety",
|
||||
"Mike Foobar",
|
||||
&[],
|
||||
),
|
||||
] {
|
||||
admin
|
||||
.create_user_account(name, secret, description, aliases, vec![])
|
||||
.await;
|
||||
}
|
||||
|
||||
// Add test settings
|
||||
admin.mta_no_auth().await;
|
||||
admin
|
||||
.registry_create_object(SpamSettings {
|
||||
enable: false,
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(SenderAuth {
|
||||
dmarc_verify: Expression {
|
||||
else_: "relaxed".into(),
|
||||
..Default::default()
|
||||
},
|
||||
reverse_ip_verify: Expression {
|
||||
else_: "relaxed".into(),
|
||||
..Default::default()
|
||||
},
|
||||
spf_ehlo_verify: Expression {
|
||||
else_: "relaxed".into(),
|
||||
..Default::default()
|
||||
},
|
||||
spf_from_verify: Expression {
|
||||
else_: "relaxed".into(),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaStageData {
|
||||
add_auth_results_header: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.3'".into(),
|
||||
then: "true".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
add_date_header: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.3'".into(),
|
||||
then: "true".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
add_message_id_header: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.3'".into(),
|
||||
then: "true".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
add_received_header: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.3'".into(),
|
||||
then: "true".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
add_received_spf_header: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.3'".into(),
|
||||
then: "true".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
add_return_path_header: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.3'".into(),
|
||||
then: "true".into(),
|
||||
}]),
|
||||
else_: "false".into(),
|
||||
},
|
||||
max_messages: Expression {
|
||||
match_: List::from_iter([ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.1'".into(),
|
||||
then: "1".into(),
|
||||
}]),
|
||||
else_: "100".into(),
|
||||
},
|
||||
max_received_headers: Expression {
|
||||
else_: "3".into(),
|
||||
..Default::default()
|
||||
},
|
||||
max_message_size: Expression {
|
||||
match_: List::from_iter([
|
||||
ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.4'".into(),
|
||||
then: "100".into(),
|
||||
},
|
||||
ExpressionMatch {
|
||||
if_: "remote_ip = '10.0.0.5'".into(),
|
||||
then: "0".into(),
|
||||
},
|
||||
]),
|
||||
else_: "104857600".into(),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaQueueQuota {
|
||||
description: None,
|
||||
enable: true,
|
||||
key: Map::new(vec![MtaQueueQuotaKey::Sender]),
|
||||
match_: Expression {
|
||||
else_: "sender = '[email protected]'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
messages: Some(1),
|
||||
size: None,
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaQueueQuota {
|
||||
description: None,
|
||||
enable: true,
|
||||
key: Map::new(vec![MtaQueueQuotaKey::RcptDomain]),
|
||||
match_: Expression {
|
||||
else_: "rcpt_domain = 'foobar.org'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
messages: None,
|
||||
size: Some(450),
|
||||
})
|
||||
.await;
|
||||
admin
|
||||
.registry_create_object(MtaQueueQuota {
|
||||
description: None,
|
||||
enable: true,
|
||||
key: Map::new(vec![MtaQueueQuotaKey::Rcpt]),
|
||||
match_: Expression {
|
||||
else_: "rcpt = '[email protected]'".into(),
|
||||
..Default::default()
|
||||
},
|
||||
messages: None,
|
||||
size: Some(450),
|
||||
})
|
||||
.await;
|
||||
admin.reload_settings().await;
|
||||
test.reload_core();
|
||||
test.expect_reload_settings().await;
|
||||
|
||||
// Test queue message builder
|
||||
let mut session = test.new_mta_session();
|
||||
session.data.remote_ip_str = "10.0.0.1".into();
|
||||
session.eval_session_params().await;
|
||||
session.test_builder().await;
|
||||
|
||||
// Send DATA without RCPT
|
||||
session.ehlo("mx.doe.org").await;
|
||||
session.ingest(b"DATA\r\n").await.unwrap();
|
||||
session.response().assert_code("503 5.5.1");
|
||||
|
||||
// Send BDAT without MAIL FROM
|
||||
session.ingest(b"BDAT 10\r\n0123456789").await.unwrap();
|
||||
session
|
||||
.response()
|
||||
.assert_code("503 5.5.1")
|
||||
.assert_contains("MAIL is required")
|
||||
.assert_not_contains("552");
|
||||
|
||||
// Send BDAT without RCPT
|
||||
session.mail_from("[email protected]", "250").await;
|
||||
session.ingest(b"BDAT 10\r\n0123456789").await.unwrap();
|
||||
session
|
||||
.response()
|
||||
.assert_code("503 5.5.1")
|
||||
.assert_contains("RCPT is required")
|
||||
.assert_not_contains("552");
|
||||
session.rset().await;
|
||||
|
||||
// Send a BDAT chunk exceeding the maximum message size
|
||||
let mut size_session = test.new_mta_session();
|
||||
size_session.data.remote_ip_str = "10.0.0.4".into();
|
||||
size_session.eval_session_params().await;
|
||||
size_session.ehlo("mx.doe.org").await;
|
||||
size_session.mail_from("[email protected]", "250").await;
|
||||
size_session.rcpt_to("[email protected]", "250").await;
|
||||
let mut chunk = b"BDAT 200 LAST\r\n".to_vec();
|
||||
chunk.extend_from_slice(&[b'A'; 200]);
|
||||
size_session.ingest(&chunk).await.unwrap();
|
||||
size_session.response().assert_code("552 5.3.4");
|
||||
size_session.rset().await;
|
||||
|
||||
// A maximum message size of zero disables the limit
|
||||
size_session.data.remote_ip_str = "10.0.0.5".into();
|
||||
size_session.eval_session_params().await;
|
||||
size_session
|
||||
.ingest(b"MAIL FROM:<[email protected]> SIZE=1073741824\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
size_session.response().assert_code("250");
|
||||
size_session.rset().await;
|
||||
size_session
|
||||
.send_message("[email protected]", &["[email protected]"], "test:no_dkim", "250")
|
||||
.await;
|
||||
test.expect_message().await;
|
||||
|
||||
// Send broken message
|
||||
session
|
||||
.send_message("[email protected]", &["[email protected]"], "invalid", "550 5.7.7")
|
||||
.await;
|
||||
|
||||
// Naive Loop detection
|
||||
session
|
||||
.send_message(
|
||||
"[email protected]",
|
||||
&["[email protected]"],
|
||||
"test:loop",
|
||||
"450 4.4.6",
|
||||
)
|
||||
.await;
|
||||
|
||||
// No headers should be added to messages from 10.0.0.1
|
||||
session
|
||||
.send_message("[email protected]", &["[email protected]"], "test:no_msgid", "250")
|
||||
.await;
|
||||
assert_eq!(
|
||||
test.expect_message().await.read_message(&test).await,
|
||||
format!("{}\r\n", load_test_message("no_msgid", "messages"))
|
||||
);
|
||||
|
||||
// Maximum one message per session is allowed for 10.0.0.1
|
||||
session.mail_from("[email protected]", "250").await;
|
||||
session.rcpt_to("[email protected]", "250").await;
|
||||
session.ingest(b"DATA\r\n").await.unwrap();
|
||||
session.response().assert_code("452 4.4.5");
|
||||
session.rset().await;
|
||||
|
||||
// Headers should be added to messages from 10.0.0.3
|
||||
session.data.remote_ip_str = "10.0.0.3".into();
|
||||
session.eval_session_params().await;
|
||||
session
|
||||
.send_message("[email protected]", &["[email protected]"], "test:no_msgid", "250")
|
||||
.await;
|
||||
test.expect_message()
|
||||
.await
|
||||
.read_lines(&test)
|
||||
.await
|
||||
.assert_contains("From: ")
|
||||
.assert_contains("To: ")
|
||||
.assert_contains("Subject: ")
|
||||
.assert_contains("Date: ")
|
||||
.assert_contains("Message-ID: ")
|
||||
.assert_contains("Return-Path: ")
|
||||
.assert_contains("Received: ")
|
||||
.assert_contains("Authentication-Results: ")
|
||||
.assert_contains("Received-SPF: ");
|
||||
|
||||
// Send a message using multiple BDAT chunks
|
||||
session.mail_from("[email protected]", "250").await;
|
||||
session.rcpt_to("[email protected]", "250").await;
|
||||
let message = load_test_message("no_msgid", "messages");
|
||||
let (first, last) = message.as_bytes().split_at(message.len() / 2);
|
||||
let mut chunk = format!("BDAT {}\r\n", first.len()).into_bytes();
|
||||
chunk.extend_from_slice(first);
|
||||
session.ingest(&chunk).await.unwrap();
|
||||
session.response().assert_code("250 2.6.0");
|
||||
let mut chunk = format!("BDAT {} LAST\r\n", last.len()).into_bytes();
|
||||
chunk.extend_from_slice(last);
|
||||
session.ingest(&chunk).await.unwrap();
|
||||
session.response().assert_code("250");
|
||||
test.expect_message()
|
||||
.await
|
||||
.read_lines(&test)
|
||||
.await
|
||||
.assert_contains("Subject: ")
|
||||
.assert_contains("Received: ");
|
||||
|
||||
// Only one message is allowed in the queue from [email protected]
|
||||
session.data.remote_ip_str = "10.0.0.2".into();
|
||||
session.eval_session_params().await;
|
||||
session
|
||||
.send_message("[email protected]", &["[email protected]"], "test:no_dkim", "250")
|
||||
.await;
|
||||
session
|
||||
.send_message(
|
||||
"[email protected]",
|
||||
&["[email protected]"],
|
||||
"test:no_dkim",
|
||||
"452 4.3.1",
|
||||
)
|
||||
.await;
|
||||
|
||||
// Release quota
|
||||
test.clear_queue().await;
|
||||
|
||||
// Only 1500 bytes are allowed in the queue to domain foobar.org
|
||||
session
|
||||
.send_message(
|
||||
"[email protected]",
|
||||
&["[email protected]"],
|
||||
"test:no_dkim",
|
||||
"250",
|
||||
)
|
||||
.await;
|
||||
session
|
||||
.send_message(
|
||||
"[email protected]",
|
||||
&["[email protected]"],
|
||||
"test:no_dkim",
|
||||
"452 4.3.1",
|
||||
)
|
||||
.await;
|
||||
|
||||
// Only 1500 bytes are allowed in the queue to recipient [email protected]
|
||||
session
|
||||
.send_message(
|
||||
"[email protected]",
|
||||
&["[email protected]"],
|
||||
"test:no_dkim",
|
||||
"250",
|
||||
)
|
||||
.await;
|
||||
session
|
||||
.send_message(
|
||||
"[email protected]",
|
||||
&["[email protected]"],
|
||||
"test:no_dkim",
|
||||
"452 4.3.1",
|
||||
)
|
||||
.await;
|
||||
|
||||
// Make sure store is empty
|
||||
test.clear_queue().await;
|
||||
let admin = test.account("admin");
|
||||
admin.registry_destroy_all(ObjectType::MtaQueueQuota).await;
|
||||
admin
|
||||
.registry_destroy_all(ObjectType::MtaInboundThrottle)
|
||||
.await;
|
||||
test.assert_is_empty().await;
|
||||
}
|
||||
Reference in New Issue
Block a user