82 lines
2.1 KiB
Rust
82 lines
2.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
use lettre::{
|
|
AsyncTransport, Message, Tokio1Executor,
|
|
transport::smtp::{AsyncSmtpTransport, authentication::Credentials},
|
|
};
|
|
|
|
use crate::consts;
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum Error {
|
|
#[error("Parse error: {0}")]
|
|
Parse(#[from] lettre::address::AddressError),
|
|
|
|
#[error("SMTP error: {0}")]
|
|
Smtp(#[from] lettre::transport::smtp::Error),
|
|
|
|
#[error("Email error: {0}")]
|
|
Email(#[from] lettre::error::Error),
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
pub trait EmailServiceTrait: Send + Sync {
|
|
async fn send_email(
|
|
&self,
|
|
email_sender: &str,
|
|
email_receiver: &str,
|
|
title: &str,
|
|
message: &str,
|
|
) -> Result<(), Error>;
|
|
}
|
|
|
|
pub struct EmailService {
|
|
smtp_relay_address: String,
|
|
smtp_login: String,
|
|
smtp_password: String,
|
|
}
|
|
|
|
impl EmailService {
|
|
pub fn create_service(
|
|
smtp_relay_address: &str,
|
|
smtp_login: &str,
|
|
smtp_password: &str,
|
|
) -> Arc<dyn EmailServiceTrait> {
|
|
Arc::new(Self {
|
|
smtp_relay_address: smtp_relay_address.to_string(),
|
|
smtp_login: smtp_login.to_string(),
|
|
smtp_password: smtp_password.to_string(),
|
|
})
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl EmailServiceTrait for EmailService {
|
|
/// A function to send an email using the given SMTP address.
|
|
/// It may timeout if the SMTP server is not reachable, see [consts::SEND_EMAIL_TIMEOUT].
|
|
async fn send_email(
|
|
&self,
|
|
email_sender: &str,
|
|
email_receiver: &str,
|
|
title: &str,
|
|
message: &str,
|
|
) -> Result<(), Error> {
|
|
let email = Message::builder()
|
|
.message_id(None)
|
|
.from(email_sender.parse()?)
|
|
.to(email_receiver.parse()?)
|
|
.subject(title)
|
|
.body(message.to_string())?;
|
|
|
|
let credentials = Credentials::new(self.smtp_login.clone(), self.smtp_password.clone());
|
|
|
|
let mailer = AsyncSmtpTransport::<Tokio1Executor>::relay(&self.smtp_relay_address)?
|
|
.credentials(credentials)
|
|
.timeout(Some(consts::SEND_EMAIL_TIMEOUT))
|
|
.build();
|
|
|
|
mailer.send(email).await?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|