77 lines
2.6 KiB
Rust
77 lines
2.6 KiB
Rust
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<AsyncSmtpTransport<Tokio1Executor>> = OnceLock::new();
|
|
static FROM_ADDRESS: OnceLock<Mailbox> = OnceLock::new();
|
|
static REGISTRY: OnceLock<Handlebars> = OnceLock::new();
|
|
|
|
fn mailer() -> &'static AsyncSmtpTransport<Tokio1Executor> {
|
|
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::<Tokio1Executor>::builder_dangerous(&server);
|
|
log::warn!("Using a local SMTP server: {}", server);
|
|
} else {
|
|
builder = AsyncSmtpTransport::<Tokio1Executor>::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::<Address>()?;
|
|
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(())
|
|
}
|