acton_htmx/email/
sender.rs

1//! Email sender trait abstraction
2//!
3//! This module defines the core `EmailSender` trait that all email backends implement.
4
5use async_trait::async_trait;
6
7use super::{Email, EmailError};
8
9/// Trait for sending emails
10///
11/// Implemented by all email backends (SMTP, AWS SES, console, etc.)
12///
13/// # Examples
14///
15/// ```rust,no_run
16/// use acton_htmx::email::{Email, EmailSender, SmtpBackend};
17///
18/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
19/// let sender = SmtpBackend::from_env()?;
20///
21/// let email = Email::new()
22///     .to("user@example.com")
23///     .from("noreply@myapp.com")
24///     .subject("Hello!")
25///     .text("Hello, World!");
26///
27/// sender.send(email).await?;
28/// # Ok(())
29/// # }
30/// ```
31#[cfg_attr(test, mockall::automock)]
32#[async_trait]
33pub trait EmailSender: Send + Sync {
34    /// Send an email
35    ///
36    /// # Errors
37    ///
38    /// Returns `EmailError` if the email cannot be sent or is invalid
39    async fn send(&self, email: Email) -> Result<(), EmailError>;
40
41    /// Send multiple emails in batch
42    ///
43    /// Default implementation sends emails sequentially. Backends can override
44    /// for more efficient batch sending.
45    ///
46    /// # Errors
47    ///
48    /// Returns `EmailError` if any email fails to send
49    async fn send_batch(&self, emails: Vec<Email>) -> Result<(), EmailError> {
50        for email in emails {
51            self.send(email).await?;
52        }
53        Ok(())
54    }
55}