97 lines
3 KiB
Rust
97 lines
3 KiB
Rust
|
use std::{fs::File, io::Read, path::Path, sync::mpsc::Receiver, thread};
|
||
|
|
||
|
use lettre::{
|
||
|
message::{header::ContentType, Mailbox},
|
||
|
transport::smtp::{
|
||
|
authentication::{Credentials, Mechanism},
|
||
|
PoolConfig,
|
||
|
},
|
||
|
AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor,
|
||
|
};
|
||
|
use once_cell::sync::Lazy;
|
||
|
use tokio::runtime::Handle;
|
||
|
|
||
|
use super::UserConfirmationMessage;
|
||
|
|
||
|
static CREDENTIALS: Lazy<Credentials> = Lazy::new(|| {
|
||
|
Credentials::new(
|
||
|
"donotreply@mail.dziura.cloud".to_owned(),
|
||
|
"hunter2".to_owned(),
|
||
|
)
|
||
|
});
|
||
|
|
||
|
static NUM_CPUS: Lazy<u32> = Lazy::new(|| num_cpus::get() as u32);
|
||
|
|
||
|
static FROM_MAILBOX: Lazy<Mailbox> = Lazy::new(|| {
|
||
|
"No Not Reply Auth-Test <donotreply@mail.dziura.cloud>"
|
||
|
.parse()
|
||
|
.unwrap()
|
||
|
});
|
||
|
|
||
|
pub fn start_emailer_service(
|
||
|
runtime: Handle,
|
||
|
assets_dir: &Path,
|
||
|
email_message_rx: Receiver<UserConfirmationMessage>,
|
||
|
) {
|
||
|
let new_user_confirmation_template_path = assets_dir.join("new-user-confirmation.html");
|
||
|
// TODO: Validate that the new user confirmation template exists
|
||
|
|
||
|
let mut new_user_confirmation_template_text = String::with_capacity(8000);
|
||
|
File::open(new_user_confirmation_template_path)
|
||
|
.and_then(|mut file| file.read_to_string(&mut new_user_confirmation_template_text))
|
||
|
.unwrap();
|
||
|
|
||
|
thread::spawn(move || {
|
||
|
while let Some(message) = email_message_rx.iter().next() {
|
||
|
let new_user_confirmation_template_text = new_user_confirmation_template_text.clone();
|
||
|
let UserConfirmationMessage {
|
||
|
email: recipient_email,
|
||
|
name,
|
||
|
auth_token,
|
||
|
} = message;
|
||
|
|
||
|
runtime.spawn(async move {
|
||
|
send_new_user_confirmation_email(
|
||
|
recipient_email.as_str(),
|
||
|
new_user_confirmation_template_text.as_str(),
|
||
|
name.as_str(),
|
||
|
auth_token.as_str(),
|
||
|
)
|
||
|
.await;
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
async fn send_new_user_confirmation_email(
|
||
|
recipient_email: &str,
|
||
|
new_user_confirmation_template_text: &str,
|
||
|
name: &str,
|
||
|
auth_token: &str,
|
||
|
) {
|
||
|
let body = new_user_confirmation_template_text
|
||
|
.replace("$NAME", name)
|
||
|
.replace("$AUTH_TOKEN", auth_token);
|
||
|
|
||
|
let message = Message::builder()
|
||
|
.from(FROM_MAILBOX.clone())
|
||
|
.reply_to(FROM_MAILBOX.clone())
|
||
|
.to(recipient_email.parse().unwrap())
|
||
|
.subject(format!(
|
||
|
"You're registered, {name}, please confirm your email address"
|
||
|
))
|
||
|
.header(ContentType::TEXT_HTML)
|
||
|
.body(body)
|
||
|
.unwrap();
|
||
|
|
||
|
let sender: AsyncSmtpTransport<Tokio1Executor> =
|
||
|
AsyncSmtpTransport::<Tokio1Executor>::starttls_relay("mail.dziura.cloud")
|
||
|
.unwrap()
|
||
|
.credentials(CREDENTIALS.clone())
|
||
|
.authentication(vec![Mechanism::Plain])
|
||
|
.pool_config(PoolConfig::new().max_size(*NUM_CPUS))
|
||
|
.build();
|
||
|
|
||
|
let _ = sender.send(message).await;
|
||
|
}
|