/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use mail_auth::{DkimResult, DmarcResult, IprevResult, SpfResult, dmarc::Policy}; use std::borrow::Cow; pub mod auth; pub mod data; pub mod dkim; pub mod ehlo; pub mod hooks; pub mod mail; pub mod milter; pub mod rcpt; pub mod session; pub mod spam; pub mod spawn; pub mod vrfy; #[derive(Debug, Default)] pub struct FilterResponse { pub message: Cow<'static, str>, pub disconnect: bool, } pub trait AuthResult { fn as_str(&self) -> &'static str; } impl AuthResult for SpfResult { fn as_str(&self) -> &'static str { match self { SpfResult::Pass => "pass", SpfResult::Fail => "fail", SpfResult::SoftFail => "softfail", SpfResult::Neutral => "neutral", SpfResult::None => "none", SpfResult::TempError => "temperror", SpfResult::PermError => "permerror", } } } impl AuthResult for IprevResult { fn as_str(&self) -> &'static str { match self { IprevResult::Pass => "pass", IprevResult::Fail(_) => "fail", IprevResult::TempError(_) => "temperror", IprevResult::PermError(_) => "permerror", IprevResult::None => "none", } } } impl AuthResult for DkimResult { fn as_str(&self) -> &'static str { match self { DkimResult::Pass => "pass", DkimResult::None => "none", DkimResult::Neutral(_) => "neutral", DkimResult::Fail(_) => "fail", DkimResult::PermError(_) => "permerror", DkimResult::TempError(_) => "temperror", } } } impl AuthResult for DmarcResult { fn as_str(&self) -> &'static str { match self { DmarcResult::Pass => "pass", DmarcResult::Fail(_) => "fail", DmarcResult::TempError(_) => "temperror", DmarcResult::PermError(_) => "permerror", DmarcResult::None => "none", } } } impl AuthResult for Policy { fn as_str(&self) -> &'static str { match self { Policy::Reject => "reject", Policy::Quarantine => "quarantine", Policy::None | Policy::Unspecified => "none", } } } impl FilterResponse { pub fn accept() -> Self { Self { message: Cow::Borrowed("250 2.0.0 Message queued for delivery.\r\n"), disconnect: false, } } pub fn reject() -> Self { Self { message: Cow::Borrowed("503 5.5.3 Message rejected.\r\n"), disconnect: false, } } pub fn temp_fail() -> Self { Self { message: Cow::Borrowed("451 4.3.5 Unable to accept message at this time.\r\n"), disconnect: false, } } pub fn shutdown() -> Self { Self { message: Cow::Borrowed("421 4.3.0 Server shutting down.\r\n"), disconnect: true, } } pub fn server_failure() -> Self { Self { message: Cow::Borrowed("451 4.3.5 Unable to accept message at this time.\r\n"), disconnect: false, } } pub fn disconnect(self) -> Self { Self { disconnect: true, ..self } } pub fn into_bytes(self) -> Cow<'static, [u8]> { match self.message { Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()), Cow::Owned(s) => Cow::Owned(s.into_bytes()), } } }