armature_mail/
lib.rs

1//! # Armature Mail
2//!
3//! Email sending with SMTP, templates, and cloud provider integrations.
4//!
5//! ## Features
6//!
7//! - **SMTP Transport**: Direct SMTP email sending with TLS support
8//! - **Email Templates**: HTML and text templates with Handlebars, Tera, or MiniJinja
9//! - **Cloud Providers**: SendGrid, Mailgun, AWS SES integrations
10//! - **Attachments**: File and inline attachments
11//! - **Async Queue**: Non-blocking email sending with retries
12//!
13//! ## Quick Start
14//!
15//! ```rust,ignore
16//! use armature_mail::{Mailer, SmtpConfig, Email};
17//!
18//! #[tokio::main]
19//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
20//!     // Configure SMTP
21//!     let config = SmtpConfig::new("smtp.example.com")
22//!         .credentials("user@example.com", "password")
23//!         .port(587)
24//!         .starttls();
25//!
26//!     let mailer = Mailer::smtp(config).await?;
27//!
28//!     // Send an email
29//!     let email = Email::new()
30//!         .from("sender@example.com")
31//!         .to("recipient@example.com")
32//!         .subject("Hello from Armature!")
33//!         .text("This is a test email.")
34//!         .html("<h1>Hello!</h1><p>This is a test email.</p>");
35//!
36//!     mailer.send(email).await?;
37//!     Ok(())
38//! }
39//! ```
40//!
41//! ## With Templates
42//!
43//! ```rust,ignore
44//! use armature_mail::{Mailer, SmtpConfig, TemplateEngine};
45//! use serde_json::json;
46//!
47//! let mailer = Mailer::smtp(config).await?
48//!     .with_templates("./templates")?;
49//!
50//! // Send using a template
51//! mailer.send_template(
52//!     "welcome",
53//!     "user@example.com",
54//!     json!({
55//!         "name": "John",
56//!         "activation_link": "https://example.com/activate/abc123"
57//!     }),
58//! ).await?;
59//! ```
60
61mod address;
62mod attachment;
63mod email;
64mod error;
65mod mailer;
66mod transport;
67
68#[cfg(feature = "handlebars")]
69mod template_handlebars;
70
71#[cfg(feature = "tera")]
72mod template_tera;
73
74#[cfg(feature = "minijinja")]
75mod template_minijinja;
76
77#[cfg(feature = "sendgrid")]
78mod sendgrid;
79
80#[cfg(feature = "ses")]
81mod ses;
82
83#[cfg(feature = "mailgun")]
84mod mailgun;
85
86#[cfg(feature = "queue")]
87mod queue;
88
89pub use address::{Address, IntoAddress, Mailbox};
90pub use attachment::{Attachment, ContentDisposition};
91pub use email::{Email, EmailBuilder};
92pub use error::{MailError, Result};
93pub use mailer::{Mailer, MailerConfig};
94pub use transport::{SmtpConfig, SmtpSecurity, SmtpTransport, Transport};
95
96#[cfg(feature = "handlebars")]
97pub use template_handlebars::HandlebarsEngine;
98
99#[cfg(feature = "tera")]
100pub use template_tera::TeraEngine;
101
102#[cfg(feature = "minijinja")]
103pub use template_minijinja::MiniJinjaEngine;
104
105#[cfg(feature = "sendgrid")]
106pub use sendgrid::{SendGridConfig, SendGridTransport};
107
108#[cfg(feature = "ses")]
109pub use ses::{SesConfig, SesTransport};
110
111#[cfg(feature = "mailgun")]
112pub use mailgun::{MailgunConfig, MailgunTransport};
113
114#[cfg(feature = "queue")]
115pub use queue::{
116    EmailJob, EmailQueue, EmailQueueBackend, EmailQueueConfig, EmailQueueWorker, InMemoryBackend,
117    MailerQueueExt, QueueStats,
118};
119
120#[cfg(feature = "redis")]
121pub use queue::RedisBackend;
122
123/// Template engine trait for rendering email templates.
124pub trait TemplateEngine: Send + Sync {
125    /// Render a template with the given name and context.
126    fn render(&self, name: &str, context: &serde_json::Value) -> Result<RenderedTemplate>;
127
128    /// Check if a template exists.
129    fn has_template(&self, name: &str) -> bool;
130
131    /// Register a template from a string.
132    fn register_template(&mut self, name: &str, content: &str) -> Result<()>;
133}
134
135/// Rendered template output.
136#[derive(Debug, Clone)]
137pub struct RenderedTemplate {
138    /// HTML content (if available).
139    pub html: Option<String>,
140    /// Plain text content (if available).
141    pub text: Option<String>,
142    /// Subject line (if available).
143    pub subject: Option<String>,
144}
145
146impl RenderedTemplate {
147    /// Create a new rendered template with HTML content.
148    pub fn html(html: impl Into<String>) -> Self {
149        Self {
150            html: Some(html.into()),
151            text: None,
152            subject: None,
153        }
154    }
155
156    /// Create a new rendered template with text content.
157    pub fn text(text: impl Into<String>) -> Self {
158        Self {
159            html: None,
160            text: Some(text.into()),
161            subject: None,
162        }
163    }
164
165    /// Create a new rendered template with both HTML and text.
166    pub fn both(html: impl Into<String>, text: impl Into<String>) -> Self {
167        Self {
168            html: Some(html.into()),
169            text: Some(text.into()),
170            subject: None,
171        }
172    }
173
174    /// Set the subject.
175    pub fn with_subject(mut self, subject: impl Into<String>) -> Self {
176        self.subject = Some(subject.into());
177        self
178    }
179}
180
181/// Prelude for common imports.
182///
183/// ```
184/// use armature_mail::prelude::*;
185/// ```
186pub mod prelude {
187    pub use crate::address::{Address, IntoAddress, Mailbox};
188    pub use crate::attachment::{Attachment, ContentDisposition};
189    pub use crate::email::{Email, EmailBuilder};
190    pub use crate::error::{MailError, Result};
191    pub use crate::mailer::{Mailer, MailerConfig};
192    pub use crate::transport::{SmtpConfig, SmtpSecurity, SmtpTransport, Transport};
193    pub use crate::{RenderedTemplate, TemplateEngine};
194
195    #[cfg(feature = "handlebars")]
196    pub use crate::HandlebarsEngine;
197
198    #[cfg(feature = "sendgrid")]
199    pub use crate::sendgrid::{SendGridConfig, SendGridTransport};
200
201    #[cfg(feature = "ses")]
202    pub use crate::ses::{SesConfig, SesTransport};
203
204    #[cfg(feature = "mailgun")]
205    pub use crate::mailgun::{MailgunConfig, MailgunTransport};
206
207    #[cfg(feature = "queue")]
208    pub use crate::queue::{EmailJob, EmailQueue, EmailQueueBackend, EmailQueueConfig};
209}