recipes/backend/src/email.rs

61 lines
1.6 KiB
Rust

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 {
Parse(lettre::address::AddressError),
Smtp(lettre::transport::smtp::Error),
Email(lettre::error::Error),
}
impl From<lettre::address::AddressError> for Error {
fn from(error: lettre::address::AddressError) -> Self {
Error::Parse(error)
}
}
impl From<lettre::transport::smtp::Error> for Error {
fn from(error: lettre::transport::smtp::Error) -> Self {
Error::Smtp(error)
}
}
impl From<lettre::error::Error> 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::<Tokio1Executor>::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(())
}