Skip to main content

mailsis_utils/
handler.rs

1//! Delivery backend abstraction for incoming email messages.
2//!
3//! Every destination that can receive an email - filesystem storage, a Redis
4//! queue, etc. - implements the [`MessageHandler`] trait defined here.
5//! The trait is object-safe so that the router can dispatch dynamically.
6
7use std::{error::Error, fmt::Display, future::Future, pin::Pin};
8
9/// Result type for handler operations.
10pub type HandlerResult<T> = Result<T, HandlerError>;
11
12/// Boxed future type for handler operations, enabling object safety.
13pub type HandlerFuture<'a> = Pin<Box<dyn Future<Output = HandlerResult<()>> + Send + 'a>>;
14
15/// Errors that can occur during message handling.
16#[derive(Debug)]
17pub enum HandlerError {
18    /// A storage error occurred.
19    Storage(String),
20    /// A connection error occurred.
21    Connection(String),
22    /// A serialization error occurred.
23    Serialization(String),
24}
25
26impl Display for HandlerError {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        match self {
29            HandlerError::Storage(msg) => write!(f, "Storage error: {msg}"),
30            HandlerError::Connection(msg) => write!(f, "Connection error: {msg}"),
31            HandlerError::Serialization(msg) => write!(f, "Serialization error: {msg}"),
32        }
33    }
34}
35
36impl Error for HandlerError {}
37
38/// Trait for message handlers that process incoming emails.
39///
40/// Unlike [`StorageEngine`], this trait only handles the inbound direction
41/// (receiving/storing), making it suitable for both storage backends
42/// and queue-based destinations like Redis.
43pub trait MessageHandler: Send + Sync {
44    /// Handles an incoming email message.
45    fn handle<'a>(&'a self, message: &'a crate::EmailMessage) -> HandlerFuture<'a>;
46
47    /// Returns the name of this handler.
48    fn name(&self) -> &str;
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_handler_error_display() {
57        assert_eq!(
58            HandlerError::Storage("test".to_string()).to_string(),
59            "Storage error: test"
60        );
61        assert_eq!(
62            HandlerError::Connection("test".to_string()).to_string(),
63            "Connection error: test"
64        );
65        assert_eq!(
66            HandlerError::Serialization("test".to_string()).to_string(),
67            "Serialization error: test"
68        );
69    }
70}