Bump to smtp-proto 0.2

This commit is contained in:
mdecimus
2025-09-14 11:32:14 +02:00
parent dde4663efc
commit 7b48d9022f
22 changed files with 341 additions and 210 deletions

View File

@@ -4,32 +4,33 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use std::time::{Duration, Instant, SystemTime};
use crate::{core::Session, scripts::ScriptResult};
use common::{
config::smtp::session::{Mechanism, Stage},
listener::SessionStream,
};
use mail_auth::{
SpfResult,
spf::verify::{HasValidLabels, SpfParameters},
};
use smtp_proto::*;
use std::{
borrow::Cow,
time::{Duration, Instant, SystemTime},
};
use trc::SmtpEvent;
impl<T: SessionStream> Session<T> {
pub async fn handle_ehlo(&mut self, domain: String, is_extended: bool) -> Result<(), ()> {
pub async fn handle_ehlo(&mut self, domain: Cow<'_, str>, is_extended: bool) -> Result<(), ()> {
// Set EHLO domain
if domain != self.data.helo_domain {
// Reject non-FQDN EHLO domains - simply checks that the hostname has at least one dot
if self.params.ehlo_reject_non_fqdn && !domain.as_str().has_valid_labels() {
if self.params.ehlo_reject_non_fqdn && !domain.as_ref().has_valid_labels() {
trc::event!(
Smtp(SmtpEvent::InvalidEhlo),
SpanId = self.data.session_id,
Domain = domain,
Domain = domain.as_ref().to_string(),
);
return self.write(b"550 5.5.0 Invalid EHLO domain.\r\n").await;
@@ -38,11 +39,12 @@ impl<T: SessionStream> Session<T> {
trc::event!(
Smtp(SmtpEvent::Ehlo),
SpanId = self.data.session_id,
Domain = domain.clone(),
Domain = domain.as_ref().to_string(),
);
// SPF check
let prev_helo_domain = std::mem::replace(&mut self.data.helo_domain, domain);
let prev_helo_domain =
std::mem::replace(&mut self.data.helo_domain, domain.into_owned());
if self.params.spf_ehlo.verify() {
let time = Instant::now();
let spf_output = self

View File

@@ -4,23 +4,23 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use std::time::{Duration, Instant, SystemTime};
use common::{config::smtp::session::Stage, listener::SessionStream, scripts::ScriptModification};
use mail_auth::{IprevOutput, IprevResult, SpfOutput, SpfResult, spf::verify::SpfParameters};
use smtp_proto::{MAIL_BY_NOTIFY, MAIL_BY_RETURN, MAIL_REQUIRETLS, MailFrom, MtPriority};
use trc::SmtpEvent;
use utils::config::Rate;
use crate::{
core::{Session, SessionAddress},
queue::DomainPart,
scripts::ScriptResult,
};
use common::{config::smtp::session::Stage, listener::SessionStream, scripts::ScriptModification};
use mail_auth::{IprevOutput, IprevResult, SpfOutput, SpfResult, spf::verify::SpfParameters};
use smtp_proto::{MAIL_BY_NOTIFY, MAIL_BY_RETURN, MAIL_REQUIRETLS, MailFrom, MtPriority};
use std::{
borrow::Cow,
time::{Duration, Instant, SystemTime},
};
use trc::SmtpEvent;
use utils::config::Rate;
impl<T: SessionStream> Session<T> {
pub async fn handle_mail_from(&mut self, from: MailFrom<String>) -> Result<(), ()> {
pub async fn handle_mail_from(&mut self, from: MailFrom<Cow<'_, str>>) -> Result<(), ()> {
if self.data.helo_domain.is_empty()
&& (self.params.ehlo_require
|| self.params.spf_ehlo.verify()
@@ -111,7 +111,7 @@ impl<T: SessionStream> Session<T> {
let (address, address_lcase, domain) = if !from.address.is_empty() {
let address_lcase = from.address.to_lowercase();
let domain = address_lcase.domain_part().into();
(from.address, address_lcase, domain)
(from.address.into_owned(), address_lcase, domain)
} else {
(String::new(), String::new(), String::new())
};
@@ -122,7 +122,7 @@ impl<T: SessionStream> Session<T> {
address_lcase,
domain,
flags: from.flags,
dsn_info: from.env_id,
dsn_info: from.env_id.map(|e| e.into_owned()),
}
.into();

View File

@@ -316,11 +316,11 @@ impl SessionData {
if !args.is_empty() {
args.push('\n');
match Rfc5321Parser::new(&mut args.as_bytes().iter())
.mail_from_parameters(String::new())
.mail_from_parameters(Cow::Borrowed(""))
{
Ok(addr) => {
mail_from.flags = addr.flags;
mail_from.dsn_info = addr.env_id;
mail_from.dsn_info = addr.env_id.map(|e| e.into_owned());
}
Err(err) => {
trc::event!(
@@ -352,11 +352,11 @@ impl SessionData {
if !args.is_empty() {
args.push('\n');
match Rfc5321Parser::new(&mut args.as_bytes().iter())
.rcpt_to_parameters(String::new())
.rcpt_to_parameters(Cow::Borrowed(""))
{
Ok(addr) => {
rcpt.flags = addr.flags;
rcpt.dsn_info = addr.orcpt;
rcpt.dsn_info = addr.orcpt.map(|e| e.into_owned());
}
Err(err) => {
trc::event!(

View File

@@ -4,6 +4,8 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use std::borrow::Cow;
use common::{
KV_GREYLIST, config::smtp::session::Stage, listener::SessionStream, scripts::ScriptModification,
};
@@ -22,7 +24,7 @@ use crate::{
};
impl<T: SessionStream> Session<T> {
pub async fn handle_rcpt_to(&mut self, to: RcptTo<String>) -> Result<(), ()> {
pub async fn handle_rcpt_to(&mut self, to: RcptTo<Cow<'_, str>>) -> Result<(), ()> {
#[cfg(feature = "test_mode")]
if self.instance.id.ends_with("-debug") {
if to.address.contains("fail@") {
@@ -72,9 +74,9 @@ impl<T: SessionStream> Session<T> {
let rcpt = SessionAddress {
domain: address_lcase.domain_part().into(),
address_lcase,
address: to.address,
address: to.address.into_owned(),
flags: to.flags,
dsn_info: to.orcpt,
dsn_info: to.orcpt.map(|e| e.into_owned()),
};
if self.data.rcpt_to.contains(&rcpt) {

View File

@@ -33,7 +33,7 @@ impl<T: SessionStream> Session<T> {
'outer: loop {
match &mut state {
State::Request(receiver) => loop {
match receiver.ingest(&mut iter, bytes) {
match receiver.ingest(&mut iter) {
Ok(request) => match request {
Request::Rcpt { to } => {
self.handle_rcpt_to(to).await?;
@@ -301,7 +301,7 @@ impl<T: SessionStream> Session<T> {
if !self.params.ehlo_reject_non_fqdn && syntax.starts_with("EHLO ")
{
self.handle_ehlo("null".to_string(), true).await?
self.handle_ehlo("null".into(), true).await?
} else {
self.write(
format!("501 5.5.2 Syntax error, expected: {syntax}\r\n")

View File

@@ -4,15 +4,13 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use crate::core::Session;
use common::listener::SessionStream;
use std::{borrow::Cow, fmt::Write};
use trc::SmtpEvent;
use crate::core::Session;
use std::fmt::Write;
impl<T: SessionStream> Session<T> {
pub async fn handle_vrfy(&mut self, address: String) -> Result<(), ()> {
pub async fn handle_vrfy(&mut self, address: Cow<'_, str>) -> Result<(), ()> {
match self
.server
.eval_if::<String, _>(
@@ -43,7 +41,7 @@ impl<T: SessionStream> Session<T> {
trc::event!(
Smtp(SmtpEvent::Vrfy),
SpanId = self.data.session_id,
To = address,
To = address.as_ref().to_string(),
Result = values,
);
@@ -53,7 +51,7 @@ impl<T: SessionStream> Session<T> {
trc::event!(
Smtp(SmtpEvent::VrfyNotFound),
SpanId = self.data.session_id,
To = address,
To = address.as_ref().to_string(),
);
self.write(b"550 5.1.2 Address not found.\r\n").await
@@ -77,7 +75,7 @@ impl<T: SessionStream> Session<T> {
trc::event!(
Smtp(SmtpEvent::VrfyDisabled),
SpanId = self.data.session_id,
To = address,
To = address.as_ref().to_string(),
);
self.write(b"252 2.5.1 VRFY is disabled.\r\n").await
@@ -85,7 +83,7 @@ impl<T: SessionStream> Session<T> {
}
}
pub async fn handle_expn(&mut self, address: String) -> Result<(), ()> {
pub async fn handle_expn(&mut self, address: Cow<'_, str>) -> Result<(), ()> {
match self
.server
.eval_if::<String, _>(
@@ -116,7 +114,7 @@ impl<T: SessionStream> Session<T> {
trc::event!(
Smtp(SmtpEvent::Expn),
SpanId = self.data.session_id,
To = address,
To = address.as_ref().to_string(),
Result = values,
);
@@ -126,7 +124,7 @@ impl<T: SessionStream> Session<T> {
trc::event!(
Smtp(SmtpEvent::ExpnNotFound),
SpanId = self.data.session_id,
To = address,
To = address.as_ref().to_string(),
);
self.write(b"550 5.1.2 Mailing list not found.\r\n").await
@@ -150,7 +148,7 @@ impl<T: SessionStream> Session<T> {
trc::event!(
Smtp(SmtpEvent::ExpnDisabled),
SpanId = self.data.session_id,
To = address,
To = address.as_ref().to_string(),
);
self.write(b"252 2.5.1 EXPN is disabled.\r\n").await