use crate::error::ApiResult; use handlebars::Handlebars; use lettre::message::header::ContentType; use lettre::message::{Mailbox, MultiPart, SinglePart}; use lettre::transport::smtp::AsyncSmtpTransportBuilder; use lettre::transport::smtp::authentication::Credentials; use lettre::{Address, AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor}; use std::env; use std::sync::OnceLock; use std::time::Duration; static MAILER: OnceLock> = OnceLock::new(); static FROM_ADDRESS: OnceLock = OnceLock::new(); static REGISTRY: OnceLock = OnceLock::new(); fn mailer() -> &'static AsyncSmtpTransport { MAILER.get_or_init(|| { let server = env::var("SMTP_SERVER").expect("SMTP_SERVER missing"); let username = env::var("SMTP_USERNAME").expect("SMTP_USERNAME missing"); let password = env::var("SMTP_PASSWORD").expect("SMTP_PASSWORD missing"); let port = env::var("SMTP_PORT").expect("SMTP_PORT missing"); let creds = Credentials::new(username, password); let builder: AsyncSmtpTransportBuilder; if server == "localhost" || server == "127.0.0.1" { builder = AsyncSmtpTransport::::builder_dangerous(&server); log::warn!("Using a local SMTP server: {}", server); } else { builder = AsyncSmtpTransport::::relay(&server).expect("invalid SMTP_SERVER"); } builder .credentials(creds) .port(port.parse().expect("SMTP_PORT invalid")) .timeout(Some(Duration::from_secs(10))) .build() }) } fn from_address() -> &'static Mailbox { FROM_ADDRESS.get_or_init(|| { let raw = env::var("SMTP_FROM").expect("SMTP_FROM missing"); let addr = raw.parse().expect("SMTP_FROM invalid"); Mailbox::new(Some("Aviation Data".into()), addr) }) } pub fn registry() -> &'static Handlebars<'static> { REGISTRY.get_or_init(|| Handlebars::new()) } pub async fn send_email(to: &str, subject: &str, header: String, html: String) -> ApiResult<()> { let to_address = to.parse::
()?; let to_mailbox = Mailbox::new(None, to_address); // Build the email let email = Message::builder() .from(from_address().clone()) .to(to_mailbox) .subject(subject) .multipart( MultiPart::alternative() .singlepart( SinglePart::builder() .header(ContentType::TEXT_PLAIN) .body(header), ) .singlepart( SinglePart::builder() .header(ContentType::TEXT_HTML) .body(html), ), )?; // Send the email mailer().send(email).await?; Ok(()) }