use derive_more::Display; use lettre::{ transport::smtp::{authentication::Credentials, AsyncSmtpTransport}, AsyncTransport, Message, Tokio1Executor, }; use tracing::{event, Level}; use crate::consts; #[derive(Debug, Display)] pub enum Error { ParseError(lettre::address::AddressError), SmtpError(lettre::transport::smtp::Error), Email(lettre::error::Error), } impl From for Error { fn from(error: lettre::address::AddressError) -> Self { Error::ParseError(error) } } impl From for Error { fn from(error: lettre::transport::smtp::Error) -> Self { Error::SmtpError(error) } } impl From for Error { fn from(error: lettre::error::Error) -> Self { Error::Email(error) } } pub async fn send_email( email: &str, message: &str, smtp_relay_address: &str, smtp_login: &str, smtp_password: &str, ) -> Result<(), Error> { let email = Message::builder() .message_id(None) .from("recipes@gburri.org".parse()?) .to(email.parse()?) .subject("recipes.gburri.org account validation") .body(message.to_string())?; let credentials = Credentials::new(smtp_login.to_string(), smtp_password.to_string()); let mailer = AsyncSmtpTransport::::relay(smtp_relay_address)? .credentials(credentials) .timeout(Some(consts::SEND_EMAIL_TIMEOUT)) .build(); if let Err(error) = mailer.send(email).await { event!(Level::ERROR, "Error when sending E-mail: {}", &error); } Ok(()) }