2024-10-02 12:41:25 -04:00
|
|
|
use std::{
|
|
|
|
fs::File,
|
|
|
|
io::Read,
|
|
|
|
path::Path,
|
|
|
|
sync::{mpsc::Receiver, LazyLock},
|
|
|
|
thread,
|
|
|
|
};
|
2024-08-06 11:08:15 -04:00
|
|
|
|
|
|
|
use lettre::{
|
|
|
|
message::{header::ContentType, Mailbox},
|
|
|
|
transport::smtp::{
|
|
|
|
authentication::{Credentials, Mechanism},
|
|
|
|
PoolConfig,
|
|
|
|
},
|
|
|
|
AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor,
|
|
|
|
};
|
|
|
|
use tokio::runtime::Handle;
|
|
|
|
|
|
|
|
use super::UserConfirmationMessage;
|
|
|
|
|
2024-10-02 12:41:25 -04:00
|
|
|
static CREDENTIALS: LazyLock<Credentials> = LazyLock::new(|| {
|
2024-08-06 11:08:15 -04:00
|
|
|
Credentials::new(
|
|
|
|
"donotreply@mail.dziura.cloud".to_owned(),
|
|
|
|
"hunter2".to_owned(),
|
|
|
|
)
|
|
|
|
});
|
|
|
|
|
2024-10-02 12:41:25 -04:00
|
|
|
static NUM_CPUS: LazyLock<u32> = LazyLock::new(|| num_cpus::get() as u32);
|
2024-08-06 11:08:15 -04:00
|
|
|
|
2024-10-02 12:41:25 -04:00
|
|
|
static FROM_MAILBOX: LazyLock<Mailbox> = LazyLock::new(|| {
|
2024-08-06 11:08:15 -04:00
|
|
|
"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,
|
2024-11-15 22:17:09 -05:00
|
|
|
user_id,
|
2024-10-03 15:27:30 -04:00
|
|
|
verification_token,
|
2024-08-06 11:08:15 -04:00
|
|
|
} = message;
|
|
|
|
|
|
|
|
runtime.spawn(async move {
|
|
|
|
send_new_user_confirmation_email(
|
|
|
|
recipient_email.as_str(),
|
|
|
|
new_user_confirmation_template_text.as_str(),
|
|
|
|
name.as_str(),
|
2024-11-15 22:17:09 -05:00
|
|
|
user_id,
|
2024-10-03 15:27:30 -04:00
|
|
|
verification_token.as_str(),
|
2024-08-06 11:08:15 -04:00
|
|
|
)
|
|
|
|
.await;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn send_new_user_confirmation_email(
|
|
|
|
recipient_email: &str,
|
|
|
|
new_user_confirmation_template_text: &str,
|
|
|
|
name: &str,
|
2024-11-15 22:17:09 -05:00
|
|
|
user_id: i32,
|
2024-10-03 15:27:30 -04:00
|
|
|
verification_token: &str,
|
2024-08-06 11:08:15 -04:00
|
|
|
) {
|
|
|
|
let body = new_user_confirmation_template_text
|
|
|
|
.replace("$NAME", name)
|
2024-11-15 22:17:09 -05:00
|
|
|
.replace("$USER_ID", user_id.to_string().as_str())
|
2024-10-03 15:27:30 -04:00
|
|
|
.replace("$VERIFICATION_TOKEN", verification_token);
|
2024-08-06 11:08:15 -04:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|