From 7395f76bbad293e0c666a3da8caf8f8371b86ccb Mon Sep 17 00:00:00 2001 From: mdecimus Date: Sat, 23 Aug 2025 20:31:57 +0200 Subject: [PATCH] SMTP: Do no send EHLO twice when STARTTLS is unavailable (fixes #2050) --- crates/smtp/src/outbound/delivery.rs | 4 ++- crates/smtp/src/outbound/session.rs | 51 +++++++++++++++------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/crates/smtp/src/outbound/delivery.rs b/crates/smtp/src/outbound/delivery.rs index b21f50ef..5a2a02a3 100644 --- a/crates/smtp/src/outbound/delivery.rs +++ b/crates/smtp/src/outbound/delivery.rs @@ -926,7 +926,7 @@ impl QueuedMessage { .and_then(|ip| ip.host.as_deref()) .or(conn_strategy.ehlo_hostname.as_deref()) .unwrap_or(server.core.network.server_name.as_str()); - let params = SessionParams { + let mut params = SessionParams { session_id: message.span_id, server: &server, credentials: remote_host.credentials(), @@ -934,6 +934,7 @@ impl QueuedMessage { hostname: envelope.mx, local_hostname, conn_strategy, + capabilities: None, }; // Prepare TLS connector @@ -1132,6 +1133,7 @@ impl QueuedMessage { continue 'next_host; } else { // TLS is not required, proceed in plain-text + params.capabilities = Some(capabilities); message .deliver( smtp_client, diff --git a/crates/smtp/src/outbound/session.rs b/crates/smtp/src/outbound/session.rs index 54f6343e..b47589e7 100644 --- a/crates/smtp/src/outbound/session.rs +++ b/crates/smtp/src/outbound/session.rs @@ -25,6 +25,7 @@ pub struct SessionParams<'x> { pub server: &'x Server, pub hostname: &'x str, pub credentials: Option<&'x Credentials>, + pub capabilities: Option>, pub is_smtp: bool, pub local_hostname: &'x str, pub conn_strategy: &'x ConnectionStrategy, @@ -37,33 +38,37 @@ impl MessageWrapper { mut smtp_client: SmtpClient, rcpt_idxs: Vec, statuses: &mut Vec, - params: SessionParams<'_>, + mut params: SessionParams<'_>, ) { // Obtain capabilities let time = Instant::now(); - let capabilities = match smtp_client.say_helo(¶ms).await { - Ok(capabilities) => { - trc::event!( - Delivery(DeliveryEvent::Ehlo), - SpanId = params.session_id, - Hostname = params.hostname.to_string(), - Details = capabilities.capabilities(), - Elapsed = time.elapsed(), - ); + let capabilities = if let Some(capabilities) = params.capabilities.take() { + capabilities + } else { + match smtp_client.say_helo(¶ms).await { + Ok(capabilities) => { + trc::event!( + Delivery(DeliveryEvent::Ehlo), + SpanId = params.session_id, + Hostname = params.hostname.to_string(), + Details = capabilities.capabilities(), + Elapsed = time.elapsed(), + ); - capabilities - } - Err(status) => { - trc::event!( - Delivery(DeliveryEvent::EhloRejected), - SpanId = params.session_id, - Hostname = params.hostname.to_string(), - CausedBy = from_error_status(&status), - Elapsed = time.elapsed(), - ); - smtp_client.quit().await; - statuses.push(DeliveryResult::domain(status, rcpt_idxs)); - return; + capabilities + } + Err(status) => { + trc::event!( + Delivery(DeliveryEvent::EhloRejected), + SpanId = params.session_id, + Hostname = params.hostname.to_string(), + CausedBy = from_error_status(&status), + Elapsed = time.elapsed(), + ); + smtp_client.quit().await; + statuses.push(DeliveryResult::domain(status, rcpt_idxs)); + return; + } } };