From 7aaa41cf0d8767d74eefc9fac6e66254503f1507 Mon Sep 17 00:00:00 2001 From: Stefan Melmuk Date: Sun, 2 Oct 2022 09:21:20 +0200 Subject: [PATCH] attach images in email --- .env.template | 5 +++ src/api/web.rs | 4 +-- src/config.rs | 2 ++ src/mail.rs | 38 ++++++++++++--------- src/static/templates/email/email_header.hbs | 2 +- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/.env.template b/.env.template index 66a04343cb9..51786e22744 100644 --- a/.env.template +++ b/.env.template @@ -363,6 +363,11 @@ ## but might need to be changed in case it trips some anti-spam filters # HELO_NAME= +## Embed images as email attachments +## When set to false without adapting the templates `email_header.hbs` and `email_footer.hbs` +## the mails will be missing their attachments. +# SMTP_EMBED_IMAGES=false + ## SMTP debugging ## When set to true this will output very detailed SMTP messages. ## WARNING: This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting! diff --git a/src/api/web.rs b/src/api/web.rs index 2ad94db8acd..35f54bd74f3 100644 --- a/src/api/web.rs +++ b/src/api/web.rs @@ -91,8 +91,8 @@ fn alive(_conn: DbConn) -> Json { #[get("/vw_static/")] fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Error> { match filename.as_ref() { - "mail-github.png" => Ok((ContentType::PNG, include_bytes!("../static/images/mail-github.png"))), - "logo-gray.png" => Ok((ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))), + "mail-github.png" => Ok((ContentType::PNG, crate::mail::MAIL_GITHUB)), + "logo-gray.png" => Ok((ContentType::PNG, crate::mail::LOGO_GRAY)), "error-x.svg" => Ok((ContentType::SVG, include_bytes!("../static/images/error-x.svg"))), "hibp.png" => Ok((ContentType::PNG, include_bytes!("../static/images/hibp.png"))), "vaultwarden-icon.png" => Ok((ContentType::PNG, include_bytes!("../static/images/vaultwarden-icon.png"))), diff --git a/src/config.rs b/src/config.rs index b8f3246ba31..4d80b81c6cb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -599,6 +599,8 @@ make_config! { smtp_timeout: u64, true, def, 15; /// Server name sent during HELO |> By default this value should be is on the machine's hostname, but might need to be changed in case it trips some anti-spam filters helo_name: String, true, option; + /// Embed images as email attachments.|> When set to false without adapting the templates `email_header.hbs` and `email_footer.hbs` the mails will be missing their attachments. + smtp_embed_images: bool, true, def, true; /// Enable SMTP debugging (Know the risks!) |> DANGEROUS: Enabling this will output very detailed SMTP messages. This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting! smtp_debug: bool, false, def, false; /// Accept Invalid Certs (Know the risks!) |> DANGEROUS: Allow invalid certificates. This option introduces significant vulnerabilities to man-in-the-middle attacks! diff --git a/src/mail.rs b/src/mail.rs index 6e293eafb4f..4f53bd80777 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -466,31 +466,37 @@ pub async fn send_test(address: &str) -> EmptyResult { send_email(address, &subject, body_html, body_text).await } +pub const MAIL_GITHUB: &[u8] = include_bytes!("static/images/mail-github.png"); +pub const LOGO_GRAY: &[u8] = include_bytes!("static/images/logo-gray.png"); + async fn send_email(address: &str, subject: &str, body_html: String, body_text: String) -> EmptyResult { - const LOGO_GRAY: &[u8] = include_bytes!("static/images/logo-gray.png"); - const MAIL_GITHUB: &[u8] = include_bytes!("static/images/mail-github.png"); let logo_gray_body = Body::new(LOGO_GRAY.to_vec()); let mail_github_body = Body::new(MAIL_GITHUB.to_vec()); let smtp_from = &CONFIG.smtp_from(); + + let body = if CONFIG.smtp_embed_images() { + MultiPart::alternative().singlepart(SinglePart::plain(body_text)).multipart( + MultiPart::related() + .singlepart(SinglePart::html(body_html)) + .singlepart( + Attachment::new_inline(String::from("logo-gray")) + .body(logo_gray_body, "image/png".parse().unwrap()), + ) + .singlepart( + Attachment::new_inline(String::from("mail-github")) + .body(mail_github_body, "image/png".parse().unwrap()), + ), + ) + } else { + MultiPart::alternative_plain_html(body_text, body_html) + }; + let email = Message::builder() .message_id(Some(format!("<{}@{}>", crate::util::get_uuid(), smtp_from.split('@').collect::>()[1]))) .to(Mailbox::new(None, Address::from_str(address)?)) .from(Mailbox::new(Some(CONFIG.smtp_from_name()), Address::from_str(smtp_from)?)) .subject(subject) - .multipart( - MultiPart::alternative().singlepart(SinglePart::plain(body_text)).multipart( - MultiPart::related() - .singlepart(SinglePart::html(body_html)) - .singlepart( - Attachment::new_inline(String::from("logo-gray")) - .body(logo_gray_body, "image/png".parse().unwrap()), - ) - .singlepart( - Attachment::new_inline(String::from("github-logo")) - .body(mail_github_body, "image/png".parse().unwrap()), - ), - ), - )?; + .multipart(body)?; match mailer().send(email).await { Ok(_) => Ok(()), diff --git a/src/static/templates/email/email_header.hbs b/src/static/templates/email/email_header.hbs index 4e826466d68..68486e188bd 100644 --- a/src/static/templates/email/email_header.hbs +++ b/src/static/templates/email/email_header.hbs @@ -81,7 +81,7 @@