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}