From d086a99e5bf6cb4f3c27f82904c5619f8325d53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Sun, 10 Feb 2019 19:12:34 +0100 Subject: [PATCH] Implemented HTML emails with text alternative --- src/config.rs | 14 +++++++++----- src/mail.rs | 33 +++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/config.rs b/src/config.rs index c6c0e18e..d7839a8e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -426,14 +426,18 @@ fn load_templates(path: &str) -> Handlebars { let template = include_str!(concat!("static/templates/", $name, ".hbs")); hb.register_template_string($name, template).unwrap(); }}; + ($name:expr, $ext:expr) => {{ + reg!($name); + reg!(concat!($name, $ext)); + }}; } // First register default templates here - reg!("email/invite_accepted"); - reg!("email/invite_confirmed"); - reg!("email/pw_hint_none"); - reg!("email/pw_hint_some"); - reg!("email/send_org_invite"); + reg!("email/invite_accepted", ".html"); + reg!("email/invite_confirmed", ".html"); + reg!("email/pw_hint_none", ".html"); + reg!("email/pw_hint_some", ".html"); + reg!("email/send_org_invite", ".html"); reg!("admin/base"); reg!("admin/login"); diff --git a/src/mail.rs b/src/mail.rs index 468fa37d..fb4cb9c4 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -36,8 +36,14 @@ fn mailer() -> SmtpTransport { .transport() } -fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String), Error> { - let text = CONFIG.render_template(template_name, &data)?; +fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> { + let (subject_html, body_html) = get_template(&format!("{}.html", template_name), &data)?; + let (_subject_text, body_text) = get_template(template_name, &data)?; + Ok((subject_html, body_html, body_text)) +} + +fn get_template(template_name: &str, data: &serde_json::Value) -> Result<(String, String), Error> { + let text = CONFIG.render_template(template_name, data)?; let mut text_split = text.split(""); let subject = match text_split.next() { @@ -60,9 +66,9 @@ pub fn send_password_hint(address: &str, hint: Option) -> EmptyResult { "email/pw_hint_none" }; - let (subject, body) = get_text(template_name, json!({ "hint": hint }))?; - - send_email(&address, &subject, &body) + let (subject, body_html, body_text) = get_text(template_name, json!({ "hint": hint }))?; + + send_email(&address, &subject, &body_html, &body_text) } pub fn send_invite( @@ -82,7 +88,7 @@ pub fn send_invite( ); let invite_token = encode_jwt(&claims); - let (subject, body) = get_text( + let (subject, body_html, body_text) = get_text( "email/send_org_invite", json!({ "url": CONFIG.domain(), @@ -94,11 +100,11 @@ pub fn send_invite( }), )?; - send_email(&address, &subject, &body) + send_email(&address, &subject, &body_html, &body_text) } pub fn send_invite_accepted(new_user_email: &str, address: &str, org_name: &str) -> EmptyResult { - let (subject, body) = get_text( + let (subject, body_html, body_text) = get_text( "email/invite_accepted", json!({ "url": CONFIG.domain(), @@ -107,11 +113,11 @@ pub fn send_invite_accepted(new_user_email: &str, address: &str, org_name: &str) }), )?; - send_email(&address, &subject, &body) + send_email(&address, &subject, &body_html, &body_text) } pub fn send_invite_confirmed(address: &str, org_name: &str) -> EmptyResult { - let (subject, body) = get_text( + let (subject, body_html, body_text) = get_text( "email/invite_confirmed", json!({ "url": CONFIG.domain(), @@ -119,16 +125,15 @@ pub fn send_invite_confirmed(address: &str, org_name: &str) -> EmptyResult { }), )?; - send_email(&address, &subject, &body) + send_email(&address, &subject, &body_html, &body_text) } -fn send_email(address: &str, subject: &str, body: &str) -> EmptyResult { +fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) -> EmptyResult { let email = EmailBuilder::new() .to(address) .from((CONFIG.smtp_from().as_str(), CONFIG.smtp_from_name().as_str())) .subject(subject) - .header(("Content-Type", "text/html")) - .body(body) + .alternative(body_html, body_text) .build() .map_err(|e| Error::new("Error building email", e.to_string()))?;