refactor: use async email sending
This commit is contained in:
parent
8b470f2d4f
commit
b696aa4fe0
161
Cargo.lock
generated
161
Cargo.lock
generated
@ -1038,16 +1038,6 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
@ -1447,21 +1437,6 @@ version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.1"
|
||||
@ -1554,6 +1529,17 @@ dependencies = [
|
||||
"syn 2.0.96",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-rustls"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb"
|
||||
dependencies = [
|
||||
"futures-io",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.31"
|
||||
@ -1769,17 +1755,6 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.12"
|
||||
@ -2115,23 +2090,29 @@ version = "0.11.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab4c9a167ff73df98a5ecc07e8bf5ce90b583665da3d1762eb1f775ad4d0d6f5"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
"chumsky",
|
||||
"email-encoding",
|
||||
"email_address",
|
||||
"fastrand 2.3.0",
|
||||
"futures-io",
|
||||
"futures-rustls",
|
||||
"futures-util",
|
||||
"hostname",
|
||||
"httpdate",
|
||||
"idna",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"nom",
|
||||
"percent-encoding",
|
||||
"quoted_printable",
|
||||
"rustls",
|
||||
"rustls-pemfile",
|
||||
"rustls-pki-types",
|
||||
"socket2 0.5.8",
|
||||
"tokio",
|
||||
"url",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2306,23 +2287,6 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@ -2413,50 +2377,6 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.96",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.2.1"
|
||||
@ -2955,6 +2875,7 @@ version = "0.23.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
@ -3001,44 +2922,12 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"core-foundation",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"security-framework-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.25"
|
||||
@ -3939,16 +3828,6 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
|
@ -22,7 +22,7 @@ serde_json = "1.0.114"
|
||||
pico-args = "0.5.0"
|
||||
rand = { version = "0.8.5", features = ["getrandom"] }
|
||||
async-trait = "0.1.79"
|
||||
lettre = "0.11.11"
|
||||
lettre = { version = "0.11.11", default-features = false, features = ["builder", "smtp-transport", "async-std1-rustls-tls"] }
|
||||
quick-xml = { version = "0.37", features = ["serde", "serialize"] }
|
||||
actix-web-static-files = "4.0"
|
||||
static-files = "0.2.1"
|
||||
|
@ -49,7 +49,7 @@ pub async fn post_new(
|
||||
|
||||
let registration = Registration::insert_new_for_user(pool.get_ref(), id).await?;
|
||||
let new_user = User::read_by_id(pool.get_ref(), id).await?.unwrap();
|
||||
mailer.send_registration_mail(&new_user, ®istration.token)?;
|
||||
mailer.send_registration_mail(&new_user, ®istration.token).await?;
|
||||
|
||||
Ok(HttpResponse::Found()
|
||||
.insert_header((LOCATION, "/users"))
|
||||
|
@ -31,7 +31,7 @@ async fn post(
|
||||
{
|
||||
if let Ok(user) = User::read_for_login(pool.get_ref(), form.email.as_ref().unwrap()).await {
|
||||
let reset = PasswordReset::insert_new_for_user(pool.get_ref(), user.id).await?;
|
||||
mailer.send_forgot_password_mail(&user, &reset.token)?;
|
||||
mailer.send_forgot_password_mail(&user, &reset.token).await?;
|
||||
}
|
||||
|
||||
return Ok(HttpResponse::Ok().body("E-Mail versandt!"));
|
||||
|
@ -1,6 +1,6 @@
|
||||
use lettre::{
|
||||
message::{Mailbox, MultiPart, SinglePart},
|
||||
Message, Transport,
|
||||
AsyncTransport, Message,
|
||||
};
|
||||
use rinja::Template;
|
||||
|
||||
@ -9,13 +9,13 @@ use crate::{models::User, utils::ApplicationError};
|
||||
use super::Mailer;
|
||||
|
||||
impl Mailer {
|
||||
pub fn send_forgot_password_mail(
|
||||
pub async fn send_forgot_password_mail(
|
||||
&self,
|
||||
user: &User,
|
||||
token: &str,
|
||||
) -> Result<(), ApplicationError> {
|
||||
let message = build(&self.hostname, &user.name, &user.email, token)?;
|
||||
self.transport.send(&message)?;
|
||||
self.transport.send(message).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -74,7 +74,7 @@ fn build(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::utils::test_helper::assert_mail_snapshot;
|
||||
use lettre::transport::stub::StubTransport;
|
||||
use lettre::{transport::stub::StubTransport, Transport};
|
||||
|
||||
#[test]
|
||||
fn build_mail_snapshot() {
|
||||
|
@ -1,10 +1,11 @@
|
||||
use brass_config::{Config, SmtpTlsType};
|
||||
use lettre::{
|
||||
address::Envelope,
|
||||
transport::{
|
||||
smtp::{authentication::Credentials, extension::ClientId},
|
||||
stub::StubTransport,
|
||||
stub::AsyncStubTransport,
|
||||
},
|
||||
SmtpTransport, Transport,
|
||||
AsyncSmtpTransport, AsyncStd1Executor, AsyncTransport,
|
||||
};
|
||||
|
||||
use crate::utils::ApplicationError;
|
||||
@ -21,30 +22,46 @@ pub struct Mailer {
|
||||
|
||||
#[derive(Clone)]
|
||||
enum Transports {
|
||||
SmtpTransport(SmtpTransport),
|
||||
SmtpTransport(AsyncSmtpTransport<AsyncStd1Executor>),
|
||||
#[allow(unused)]
|
||||
StubTransport(StubTransport),
|
||||
StubTransport(AsyncStubTransport),
|
||||
}
|
||||
|
||||
impl Transport for Transports {
|
||||
impl AsyncTransport for Transports {
|
||||
type Ok = ();
|
||||
type Error = ApplicationError;
|
||||
|
||||
fn send_raw(
|
||||
&self,
|
||||
envelope: &lettre::address::Envelope,
|
||||
email: &[u8],
|
||||
) -> Result<Self::Ok, Self::Error> {
|
||||
match self {
|
||||
Transports::SmtpTransport(smtp_transport) => smtp_transport
|
||||
.send_raw(envelope, email)
|
||||
.map(|_| ())
|
||||
.map_err(|err| ApplicationError::EmailTransport(err)),
|
||||
Transports::StubTransport(stub_transport) => stub_transport
|
||||
.send_raw(envelope, email)
|
||||
.map(|_| ())
|
||||
.map_err(|err| ApplicationError::EmailStubTransport(err)),
|
||||
}
|
||||
fn send_raw<'life0, 'life1, 'life2, 'async_trait>(
|
||||
&'life0 self,
|
||||
envelope: &'life1 Envelope,
|
||||
email: &'life2 [u8],
|
||||
) -> ::core::pin::Pin<
|
||||
Box<
|
||||
dyn ::core::future::Future<Output = Result<Self::Ok, Self::Error>>
|
||||
+ ::core::marker::Send
|
||||
+ 'async_trait,
|
||||
>,
|
||||
>
|
||||
where
|
||||
'life0: 'async_trait,
|
||||
'life1: 'async_trait,
|
||||
'life2: 'async_trait,
|
||||
Self: 'async_trait,
|
||||
{
|
||||
return Box::pin(async move {
|
||||
match self {
|
||||
Transports::SmtpTransport(smtp_transport) => smtp_transport
|
||||
.send_raw(envelope, email)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(|err| ApplicationError::EmailTransport(err)),
|
||||
Transports::StubTransport(stub_transport) => stub_transport
|
||||
.send_raw(envelope, email)
|
||||
.await
|
||||
.map(|_| ())
|
||||
.map_err(|err| ApplicationError::EmailStubTransport(err)),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,11 +69,16 @@ impl Mailer {
|
||||
pub fn new(config: &Config) -> anyhow::Result<Self> {
|
||||
let mut builder = match config.smtp_tlstype {
|
||||
SmtpTlsType::StartTLS => {
|
||||
SmtpTransport::starttls_relay(&config.smtp_server)?.port(config.smtp_port)
|
||||
AsyncSmtpTransport::<AsyncStd1Executor>::starttls_relay(&config.smtp_server)?
|
||||
.port(config.smtp_port)
|
||||
}
|
||||
SmtpTlsType::TLS => {
|
||||
AsyncSmtpTransport::<AsyncStd1Executor>::relay(&config.smtp_server)?
|
||||
.port(config.smtp_port)
|
||||
}
|
||||
SmtpTlsType::TLS => SmtpTransport::relay(&config.smtp_server)?.port(config.smtp_port),
|
||||
SmtpTlsType::NoTLS => {
|
||||
SmtpTransport::builder_dangerous(&config.smtp_server).port(config.smtp_port)
|
||||
AsyncSmtpTransport::<AsyncStd1Executor>::builder_dangerous(&config.smtp_server)
|
||||
.port(config.smtp_port)
|
||||
}
|
||||
};
|
||||
|
||||
@ -80,13 +102,12 @@ impl Mailer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
impl Mailer {
|
||||
pub fn new_stub() -> Self {
|
||||
Mailer {
|
||||
transport: Transports::StubTransport(StubTransport::new_ok()),
|
||||
hostname: String::from("testhostname")
|
||||
transport: Transports::StubTransport(AsyncStubTransport::new_ok()),
|
||||
hostname: String::from("testhostname"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use lettre::{
|
||||
message::{Mailbox, MultiPart, SinglePart},
|
||||
Message, Transport,
|
||||
AsyncTransport, Message,
|
||||
};
|
||||
use rinja::Template;
|
||||
|
||||
@ -9,9 +9,13 @@ use crate::{models::User, utils::ApplicationError};
|
||||
use super::Mailer;
|
||||
|
||||
impl Mailer {
|
||||
pub fn send_registration_mail(&self, user: &User, token: &str) -> Result<(), ApplicationError> {
|
||||
pub async fn send_registration_mail(
|
||||
&self,
|
||||
user: &User,
|
||||
token: &str,
|
||||
) -> Result<(), ApplicationError> {
|
||||
let message = build(&self.hostname, &user.name, &user.email, token)?;
|
||||
self.transport.send(&message)?;
|
||||
self.transport.send(message).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -73,7 +77,7 @@ fn build(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::utils::test_helper::assert_mail_snapshot;
|
||||
use lettre::transport::stub::StubTransport;
|
||||
use lettre::{transport::stub::StubTransport, Transport};
|
||||
|
||||
#[test]
|
||||
fn build_mail_snapshot() {
|
||||
|
@ -1,11 +1,11 @@
|
||||
use lettre::{message::SinglePart, Message, Transport};
|
||||
use lettre::{message::SinglePart, AsyncTransport, Message};
|
||||
|
||||
use crate::utils::ApplicationError;
|
||||
|
||||
use super::Mailer;
|
||||
|
||||
impl Mailer {
|
||||
pub fn send_test_mail(&self, to: &str) -> Result<(), ApplicationError> {
|
||||
pub async fn send_test_mail(&self, to: &str) -> Result<(), ApplicationError> {
|
||||
let message = Message::builder()
|
||||
.from("noreply <noreply@brasiwa-leipzig.de>".parse()?)
|
||||
.reply_to("noreply <noreply@brasiwa-leipzig.de>".parse()?)
|
||||
@ -15,7 +15,7 @@ impl Mailer {
|
||||
"Testmail von Brass. E-Mail Versand funktioniert!".to_string(),
|
||||
))?;
|
||||
|
||||
self.transport.send(&message)?;
|
||||
self.transport.send(message).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ pub async fn handle_command(
|
||||
exit(0);
|
||||
}
|
||||
Some(Command::TestMail(to)) => {
|
||||
match mailer.send_test_mail(&to) {
|
||||
match mailer.send_test_mail(&to).await {
|
||||
Ok(_) => println!("Successfully sent mail to {to}."),
|
||||
Err(e) => {
|
||||
if let Some(source) = e.source() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user