diff --git a/Cargo.lock b/Cargo.lock index 22d759f..95beaac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -541,10 +541,12 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8033576bf9f051fce6cb92b6264114b4340896c352a9ff38b67bd4cde924635" dependencies = [ + "async-trait", "base64 0.21.0", "email-encoding", "email_address", "fastrand", + "futures-io", "futures-util", "hostname", "httpdate", @@ -557,6 +559,7 @@ dependencies = [ "rustls-pemfile", "socket2", "tokio", + "tokio-rustls", "webpki-roots", ] @@ -1087,6 +1090,17 @@ dependencies = [ "syn", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + [[package]] name = "tokio-util" version = "0.7.7" diff --git a/Cargo.toml b/Cargo.toml index 4e3b5dd..de92207 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ askama = { git = "https://github.com/djc/askama.git" } askama_axum = { git = "https://github.com/djc/askama.git", package = "askama_axum" } axum = { version = "0.6", default-features = false, features = ["http1", "form", "tokio", "macros"] } captcha = { version = "0.0.9", default-features = false } -lettre = { version = "0.10", default-features = false, features = ["smtp-transport", "hostname", "rustls-tls", "pool", "builder"] } +lettre = { version = "0.10", default-features = false, features = ["smtp-transport", "hostname", "tokio1-rustls-tls", "pool", "builder"] } serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" time = "0.3" diff --git a/src/mailer.rs b/src/mailer.rs index 576ab1d..ecaa016 100644 --- a/src/mailer.rs +++ b/src/mailer.rs @@ -1,29 +1,39 @@ use anyhow::{Context, Result}; use lettre::{ - message::{Mailbox, MessageBuilder}, - transport::smtp::authentication::Credentials, - Message, SmtpTransport, Transport, + message::{Mailbox, Message, MessageBuilder}, + transport::{ + smtp::{authentication::Credentials, AsyncSmtpTransport}, + AsyncTransport, + }, + Tokio1Executor, }; use crate::config::Config; +type ASmtpTransport = AsyncSmtpTransport; + +/// Mail sender. pub struct Mailer { - mailer: SmtpTransport, + mailer: ASmtpTransport, message_builder: MessageBuilder, } impl Mailer { + /// Tries to initialize the mailer. pub fn build(config: &Config) -> Result { - let creds = Credentials::new( + // Mail server credentials for login. + let credentials = Credentials::new( config.email_server.email.clone(), config.email_server.password.clone(), ); - let mailer = SmtpTransport::relay(&config.email_server.server_name) + // Establish the connection. + let mailer = ASmtpTransport::relay(&config.email_server.server_name) .context("Failed to connect to the email server!")? - .credentials(creds) + .credentials(credentials) .build(); + // Set the From and To mailboxes for every sent mail. let message_builder = Message::builder() .from( config @@ -42,13 +52,19 @@ impl Mailer { }) } - pub fn send(&self, name: &str, email: &str, telefon: &str, message: &str) -> Result<()> { + /// Sends a mail with data from the contact form. + pub async fn send(&self, name: &str, email: &str, telefon: &str, message: &str) -> Result<()> { let name = name.trim().to_string(); + let subject = "Message from ".to_string() + &name; + let reply_to = Mailbox::new( + Some(name), + email + .parse() + .context("Failed to parse the email from the form to an address!")?, + ); + let telefon = telefon.trim(); let message = message.trim().to_string(); - - let subject = "Message from ".to_string() + &name; - let body = if !telefon.is_empty() { message + "\n\nTelefon: " + telefon } else { @@ -58,17 +74,15 @@ impl Mailer { let email = self .message_builder .clone() - .reply_to(Mailbox::new( - Some(name), - email - .parse() - .context("Failed to parse the email from the form to an address!")?, - )) + .reply_to(reply_to) .subject(subject) .body(body) .context("Failed to build email!")?; - self.mailer.send(&email).context("Failed to send email!")?; + self.mailer + .send(email) + .await + .context("Failed to send email!")?; Ok(()) } diff --git a/src/routes.rs b/src/routes.rs index e061f47..df077cc 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -112,7 +112,10 @@ pub async fn submit( .await; } - match mailer.send(&form.name, &form.email, &form.telefon, &form.message) { + match mailer + .send(&form.name, &form.email, &form.telefon, &form.message) + .await + { Ok(_) => (), Err(e) => { error!("{e:?}");