mod drivers;
mod mail;
pub mod config;
pub mod error;
pub mod errors;
pub mod mailable;
#[cfg(feature = "axum")]
pub mod mail_layer;
#[cfg(feature = "queue")]
pub mod queue_job;
pub use config::MailConfig;
pub use error::MailError;
pub use mail::{global_config, set_global_config, Mail};
pub use mailable::Mailable;
#[cfg(feature = "markdown")]
pub use mailable::MarkdownMailable;
#[cfg(feature = "axum")]
pub use mail_layer::MailLayer;
#[cfg(test)]
mod tests {
use crate::{Mail, MailConfig, MailError, Mailable};
struct Welcome {
name: String,
}
impl Mailable for Welcome {
fn subject(&self) -> &str {
"Welcome!"
}
fn body(&self) -> String {
format!("Hi, {}!", self.name)
}
fn html_body(&self) -> Option<String> {
Some(format!("<p>Hi, <b>{}</b>!</p>", self.name))
}
}
fn log_config() -> MailConfig {
MailConfig {
driver: "log".into(),
..MailConfig::default()
}
}
#[test]
fn mailable_subject_and_body() {
let m = Welcome {
name: "Alice".into(),
};
assert_eq!(m.subject(), "Welcome!");
assert!(m.body().contains("Alice"));
assert!(m.html_body().unwrap().contains("Alice"));
}
#[test]
fn mail_config_defaults() {
let c = MailConfig::default();
assert_eq!(c.driver, "log");
assert_eq!(c.from_address, "noreply@rok-app.com");
assert_eq!(c.smtp_port, 587);
assert_eq!(c.smtp_encryption, "starttls");
assert!(c.postmark_api_key.is_none());
assert!(c.resend_api_key.is_none());
}
#[tokio::test]
async fn send_with_log_driver_succeeds() {
let result = Mail::send_with(
Welcome { name: "Bob".into() },
"bob@example.com",
&log_config(),
)
.await;
assert!(result.is_ok());
}
#[tokio::test]
async fn send_with_unknown_driver_returns_error() {
let config = MailConfig {
driver: "carrier_pigeon".into(),
..MailConfig::default()
};
let result = Mail::send_with(
Welcome {
name: "Carol".into(),
},
"carol@example.com",
&config,
)
.await;
assert!(matches!(result, Err(MailError::UnknownDriver(d)) if d == "carrier_pigeon"));
}
#[tokio::test]
async fn send_without_layer_returns_not_configured() {
let result = Mail::send(
Welcome {
name: "Dave".into(),
},
"dave@example.com",
)
.await;
assert!(matches!(result, Err(MailError::NotConfigured)));
}
}