1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! # modo::email
//!
//! Transactional email with Markdown templates, layouts, and SMTP delivery.
//!
//! Templates are Markdown files with a YAML frontmatter block that specifies
//! the subject line and optional layout. Variable substitution uses
//! `{{var_name}}` placeholders throughout both frontmatter and body.
//!
//! Provides:
//! - [`Mailer`] — renders templates and delivers email over SMTP (cheap
//! `Clone` via `Arc`).
//! - [`EmailConfig`] — top-level configuration (deserializes from YAML).
//! - [`SmtpConfig`] — SMTP connection settings.
//! - [`SmtpSecurity`] — TLS mode (`StartTls` / `Tls` / `None`).
//! - [`SendEmail`] — builder for composing an outgoing email.
//! - [`SenderProfile`] — per-message `From` / `Reply-To` override.
//! - [`RenderedEmail`] — output of [`Mailer::render`] (subject, HTML, text).
//! - [`TemplateSource`] — trait for pluggable template loaders.
//! - [`FileSource`] — filesystem loader with locale fallback.
//! - [`CachedSource`] — LRU-caching wrapper around any [`TemplateSource`].
//! - [`ButtonType`] — colour variants rendered by the `[button|…]` Markdown
//! syntax.
//!
//! ## Custom elements
//!
//! Two custom Markdown elements extend the standard syntax:
//!
//! - `[button|Label](url)` / `[button:TYPE|Label](url)` — styled
//! call-to-action button (`TYPE`: `danger`, `warning`, `info`, `success`).
//! - `[otp|CODE]` — styled one-time-code pill (monospace, letter-spaced,
//! rounded background). `CODE` must match `[A-Za-z0-9-]{1,32}`.
//!
//! Both elements are inert inside code spans, fenced code blocks, and after a
//! backslash escape.
//!
//! ## Quick start
//!
//! ```rust,no_run
//! use modo::email::{EmailConfig, Mailer, SendEmail};
//!
//! # async fn run() -> modo::Result<()> {
//! let mut config = EmailConfig::default();
//! config.default_from_email = "noreply@example.com".into();
//! config.smtp.host = "smtp.example.com".into();
//! let mailer = Mailer::new(&config)?;
//!
//! mailer.send(
//! SendEmail::new("welcome", "user@example.com")
//! .var("name", "Dmytro"),
//! ).await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Template format
//!
//! ```text
//! ---
//! subject: Welcome to {{app_name}}!
//! layout: base
//! ---
//!
//! Hi {{name}},
//!
//! Your verification code:
//!
//! [otp|{{code}}]
//!
//! [button|Get started](https://example.com/start)
//! ```
pub use ButtonType;
pub use CachedSource;
pub use ;
pub use Mailer;
pub use ;
pub use ;