mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-10-26 12:26:26 +08:00
Spawn a delivery thread for EmailSubmission/set requests (closes #1540)
This commit is contained in:
parent
e2ce576596
commit
a138fe33d6
7 changed files with 100 additions and 83 deletions
|
|
@ -34,6 +34,7 @@ This version includes **breaking changes** to the database layout and requires a
|
||||||
- Hide the current server version (#1435).
|
- Hide the current server version (#1435).
|
||||||
- Use the newest `X-Spam-Status` Header (#1308).
|
- Use the newest `X-Spam-Status` Header (#1308).
|
||||||
- MySQL Driver error: Transactions couldn't be nested (#1271).
|
- MySQL Driver error: Transactions couldn't be nested (#1271).
|
||||||
|
- Spawn a delivery thread for `EmailSubmission/set` requests (#1540).
|
||||||
|
|
||||||
## [0.11.8] - 2025-04-30
|
## [0.11.8] - 2025-04-30
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -582,7 +582,7 @@ impl EmailSubmissionSet for Server {
|
||||||
self.clone(),
|
self.clone(),
|
||||||
instance.clone(),
|
instance.clone(),
|
||||||
SessionData::local(
|
SessionData::local(
|
||||||
Box::pin(self.get_access_token(account_id))
|
self.get_access_token(account_id)
|
||||||
.await
|
.await
|
||||||
.caused_by(trc::location!())?,
|
.caused_by(trc::location!())?,
|
||||||
None,
|
None,
|
||||||
|
|
@ -592,14 +592,13 @@ impl EmailSubmissionSet for Server {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Spawn SMTP session to avoid overflowing the stack
|
||||||
|
let handle = tokio::spawn(async move {
|
||||||
// MAIL FROM
|
// MAIL FROM
|
||||||
let _ = Box::pin(session.handle_mail_from(mail_from)).await;
|
let _ = session.handle_mail_from(mail_from).await;
|
||||||
if let Some(error) = session.has_failed() {
|
if let Some(error) = session.has_failed() {
|
||||||
return Ok(Err(SetError::new(SetErrorType::ForbiddenMailFrom)
|
return Err(SetError::new(SetErrorType::ForbiddenMailFrom)
|
||||||
.with_description(format!(
|
.with_description(format!("Server rejected MAIL-FROM: {}", error.trim())));
|
||||||
"Server rejected MAIL-FROM: {}",
|
|
||||||
error.trim()
|
|
||||||
))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RCPT TO
|
// RCPT TO
|
||||||
|
|
@ -607,7 +606,7 @@ impl EmailSubmissionSet for Server {
|
||||||
let mut has_success = false;
|
let mut has_success = false;
|
||||||
for rcpt in rcpt_to {
|
for rcpt in rcpt_to {
|
||||||
let addr = rcpt.address.clone();
|
let addr = rcpt.address.clone();
|
||||||
let _ = Box::pin(session.handle_rcpt_to(rcpt)).await;
|
let _ = session.handle_rcpt_to(rcpt).await;
|
||||||
let response = session.has_failed();
|
let response = session.has_failed();
|
||||||
if response.is_none() {
|
if response.is_none() {
|
||||||
has_success = true;
|
has_success = true;
|
||||||
|
|
@ -618,16 +617,27 @@ impl EmailSubmissionSet for Server {
|
||||||
// DATA
|
// DATA
|
||||||
if has_success {
|
if has_success {
|
||||||
session.data.message = message;
|
session.data.message = message;
|
||||||
let response = Box::pin(session.queue_message()).await;
|
let response = session.queue_message().await;
|
||||||
if let smtp::core::State::Accepted(queue_id) = session.state {
|
if let smtp::core::State::Accepted(queue_id) = session.state {
|
||||||
submission.queue_id = Some(queue_id);
|
Ok((true, responses, Some(queue_id)))
|
||||||
} else {
|
} else {
|
||||||
return Ok(Err(SetError::new(SetErrorType::ForbiddenToSend)
|
Err(
|
||||||
.with_description(format!(
|
SetError::new(SetErrorType::ForbiddenToSend).with_description(format!(
|
||||||
"Server rejected DATA: {}",
|
"Server rejected DATA: {}",
|
||||||
std::str::from_utf8(&response).unwrap().trim()
|
std::str::from_utf8(&response).unwrap().trim()
|
||||||
))));
|
)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Ok((false, responses, None))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
match handle.await {
|
||||||
|
Ok(Ok((has_success, responses, queue_id))) => {
|
||||||
|
// Set queue ID
|
||||||
|
if let Some(queue_id) = queue_id {
|
||||||
|
submission.queue_id = Some(queue_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set responses
|
// Set responses
|
||||||
|
|
@ -658,6 +668,13 @@ impl EmailSubmissionSet for Server {
|
||||||
|
|
||||||
Ok(Ok(submission))
|
Ok(Ok(submission))
|
||||||
}
|
}
|
||||||
|
Ok(Err(err)) => Ok(Err(err)),
|
||||||
|
Err(err) => Err(trc::EventType::Server(trc::ServerEvent::ThreadError)
|
||||||
|
.reason(err)
|
||||||
|
.caused_by(trc::location!())
|
||||||
|
.details("Join Error")),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,9 @@ async fn build_server(mut config: Config, stores: Stores) -> (Server, watch::Sen
|
||||||
const SERVER: &str = r#"
|
const SERVER: &str = r#"
|
||||||
[server]
|
[server]
|
||||||
hostname = "'server{NODE_ID}.example.org'"
|
hostname = "'server{NODE_ID}.example.org'"
|
||||||
http.url = "'https://127.0.0.1:800{NODE_ID}'"
|
|
||||||
|
[http]
|
||||||
|
url = "'https://127.0.0.1:800{NODE_ID}'"
|
||||||
|
|
||||||
[cluster]
|
[cluster]
|
||||||
node-id = {NODE_ID}
|
node-id = {NODE_ID}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ use crate::{AssertConfig, add_test_certs};
|
||||||
const MOCK_HTTP_SERVER: &str = r#"
|
const MOCK_HTTP_SERVER: &str = r#"
|
||||||
[server]
|
[server]
|
||||||
hostname = "'oidc.example.org'"
|
hostname = "'oidc.example.org'"
|
||||||
http.url = "'https://127.0.0.1:9090'"
|
|
||||||
|
[http]
|
||||||
|
url = "'https://127.0.0.1:9090'"
|
||||||
|
|
||||||
[server.listener.jmap]
|
[server.listener.jmap]
|
||||||
bind = ['127.0.0.1:9090']
|
bind = ['127.0.0.1:9090']
|
||||||
|
|
|
||||||
|
|
@ -79,19 +79,8 @@ pub mod vacation_response;
|
||||||
pub mod webhooks;
|
pub mod webhooks;
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
|
||||||
#[test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
fn jmap_tests() {
|
async fn jmap_tests() {
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.thread_stack_size(3 * 1024 * 1024)
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
.block_on(async {
|
|
||||||
jmap_tests_().await;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn jmap_tests_() {
|
|
||||||
let delete = true;
|
let delete = true;
|
||||||
let mut params = init_jmap_tests(
|
let mut params = init_jmap_tests(
|
||||||
&std::env::var("STORE")
|
&std::env::var("STORE")
|
||||||
|
|
@ -100,8 +89,8 @@ async fn jmap_tests_() {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
/*webhooks::test(&mut params).await;
|
webhooks::test(&mut params).await;
|
||||||
email_query::test(&mut params, delete).await;
|
/*email_query::test(&mut params, delete).await;
|
||||||
email_get::test(&mut params).await;
|
email_get::test(&mut params).await;
|
||||||
email_set::test(&mut params).await;
|
email_set::test(&mut params).await;
|
||||||
email_parse::test(&mut params).await;
|
email_parse::test(&mut params).await;
|
||||||
|
|
@ -113,11 +102,11 @@ async fn jmap_tests_() {
|
||||||
thread_merge::test(&mut params).await;
|
thread_merge::test(&mut params).await;
|
||||||
mailbox::test(&mut params).await;
|
mailbox::test(&mut params).await;
|
||||||
delivery::test(&mut params).await;
|
delivery::test(&mut params).await;
|
||||||
auth_acl::test(&mut params).await;
|
auth_acl::test(&mut params).await;*/
|
||||||
auth_limits::test(&mut params).await;
|
auth_limits::test(&mut params).await;
|
||||||
auth_oauth::test(&mut params).await;
|
auth_oauth::test(&mut params).await;
|
||||||
event_source::test(&mut params).await;
|
event_source::test(&mut params).await;
|
||||||
push_subscription::test(&mut params).await;*/
|
push_subscription::test(&mut params).await;
|
||||||
sieve_script::test(&mut params).await;
|
sieve_script::test(&mut params).await;
|
||||||
vacation_response::test(&mut params).await;
|
vacation_response::test(&mut params).await;
|
||||||
email_submission::test(&mut params).await;
|
email_submission::test(&mut params).await;
|
||||||
|
|
@ -736,7 +725,9 @@ impl<T: Debug> Response<T> {
|
||||||
const SERVER: &str = r#"
|
const SERVER: &str = r#"
|
||||||
[server]
|
[server]
|
||||||
hostname = "'jmap.example.org'"
|
hostname = "'jmap.example.org'"
|
||||||
http.url = "'https://127.0.0.1:8899'"
|
|
||||||
|
[http]
|
||||||
|
url = "'https://127.0.0.1:8899'"
|
||||||
|
|
||||||
[server.listener.jmap]
|
[server.listener.jmap]
|
||||||
bind = ["127.0.0.1:8899"]
|
bind = ["127.0.0.1:8899"]
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,9 @@ use super::JMAPTest;
|
||||||
const SERVER: &str = r#"
|
const SERVER: &str = r#"
|
||||||
[server]
|
[server]
|
||||||
hostname = "'jmap-push.example.org'"
|
hostname = "'jmap-push.example.org'"
|
||||||
http.url = "'https://127.0.0.1:9000'"
|
|
||||||
|
[http]
|
||||||
|
url = "'https://127.0.0.1:9000'"
|
||||||
|
|
||||||
[server.listener.jmap]
|
[server.listener.jmap]
|
||||||
bind = ['127.0.0.1:9000']
|
bind = ['127.0.0.1:9000']
|
||||||
|
|
|
||||||
|
|
@ -966,7 +966,9 @@ fn generate_random_name(length: usize) -> String {
|
||||||
const SERVER: &str = r#"
|
const SERVER: &str = r#"
|
||||||
[server]
|
[server]
|
||||||
hostname = "webdav.example.org"
|
hostname = "webdav.example.org"
|
||||||
http.url = "'https://127.0.0.1:8899'"
|
|
||||||
|
[http]
|
||||||
|
url = "'https://127.0.0.1:8899'"
|
||||||
|
|
||||||
[server.listener.webdav]
|
[server.listener.webdav]
|
||||||
bind = ["127.0.0.1:8899"]
|
bind = ["127.0.0.1:8899"]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue