use tracing::{info, warn};
use crate::{
handler::{HandlerError, HandlerFuture, MessageHandler},
EmailMessage,
};
pub struct RejectHandler {
code: u16,
message: String,
}
impl RejectHandler {
pub fn new(code: u16, message: String) -> Self {
info!(
code = code,
message = %message,
"Reject handler initialized"
);
Self { code, message }
}
pub fn code(&self) -> u16 {
self.code
}
pub fn message(&self) -> &str {
&self.message
}
}
impl MessageHandler for RejectHandler {
fn handle<'a>(&'a self, message: &'a EmailMessage) -> HandlerFuture<'a> {
Box::pin(async move {
warn!(
message_id = %message.message_id,
to = %message.to,
code = self.code,
"Rejecting message"
);
Err(HandlerError::Rejected(self.message.clone()))
})
}
fn name(&self) -> &str {
"reject"
}
fn reject_reply(&self) -> Option<(u16, String)> {
Some((self.code, self.message.clone()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_reject_handler_returns_rejected_error() {
let handler = RejectHandler::new(550, "Relay access denied".to_string());
let message = EmailMessage::from_raw("sender@example.com", "rcpt@example.com", "Hi");
let result = handler.handle(&message).await;
match result {
Err(HandlerError::Rejected(msg)) => {
assert_eq!(msg, "Relay access denied");
}
other => panic!("Expected Rejected error, got {other:?}"),
}
assert_eq!(
handler.reject_reply(),
Some((550, "Relay access denied".to_string()))
);
}
#[test]
fn test_reject_handler_name() {
let handler = RejectHandler::new(550, "Relay access denied".to_string());
assert_eq!(handler.name(), "reject");
}
#[test]
fn test_reject_handler_accessors() {
let handler = RejectHandler::new(521, "No mail accepted here".to_string());
assert_eq!(handler.code(), 521);
assert_eq!(handler.message(), "No mail accepted here");
}
}