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..731f7bb4 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, "url": CONFIG.domain() }))?; + + 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()))?; diff --git a/src/static/templates/email/invite_accepted.html.hbs b/src/static/templates/email/invite_accepted.html.hbs new file mode 100644 index 00000000..71b8d174 --- /dev/null +++ b/src/static/templates/email/invite_accepted.html.hbs @@ -0,0 +1,138 @@ +Invitation accepted + + + + + + Bitwarden_rs + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + +
+ This email is to notify you that {{email}} has accepted your invitation to join {{org_name}}. +
+ Please log in to the bitwarden_rs server and confirm them from the organization management page. +
+ If you do not wish to confirm this user, you can also remove them from the organization on the same page. +
+
+ + + + + +
+
+ + diff --git a/src/static/templates/email/invite_confirmed.hbs b/src/static/templates/email/invite_confirmed.hbs index 7fc7db78..26704bba 100644 --- a/src/static/templates/email/invite_confirmed.hbs +++ b/src/static/templates/email/invite_confirmed.hbs @@ -5,4 +5,4 @@ Invitation to {{org_name}} confirmed Your invitation to join {{org_name}} was confirmed. It will now appear under the Organizations the next time you log in to the web vault.

- \ No newline at end of file + diff --git a/src/static/templates/email/invite_confirmed.html.hbs b/src/static/templates/email/invite_confirmed.html.hbs new file mode 100644 index 00000000..746f96ed --- /dev/null +++ b/src/static/templates/email/invite_confirmed.html.hbs @@ -0,0 +1,134 @@ +Invitation to {{org_name}} confirmed + + + + + + Bitwarden_rs + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + +
+ This email is to notify you that you have been confirmed as a user of {{org_name}}. +
+ Any collections and logins being shared with you by this organization will now appear in your Bitwarden vault.
+ Log in +
+
+ + + + + +
+
+ + diff --git a/src/static/templates/email/pw_hint_none.html.hbs b/src/static/templates/email/pw_hint_none.html.hbs new file mode 100644 index 00000000..4b97e57f --- /dev/null +++ b/src/static/templates/email/pw_hint_none.html.hbs @@ -0,0 +1,133 @@ +Sorry, you have no password hint... + + + + + + Bitwarden_rs + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + +
+ You (or someone) recently requested your master password hint. Unfortunately, your account does not have a master password hint.
+
+ If you did not request your master password hint you can safely ignore this email. +
+
+ + + + + +
+
+ + diff --git a/src/static/templates/email/pw_hint_some.html.hbs b/src/static/templates/email/pw_hint_some.html.hbs new file mode 100644 index 00000000..44cb3856 --- /dev/null +++ b/src/static/templates/email/pw_hint_some.html.hbs @@ -0,0 +1,139 @@ +Your master password hint + + + + + + Bitwarden_rs + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + +
+ You (or someone) recently requested your master password hint. +
+ Your hint is: "{{hint}}"
+ Log in: Web Vault +
+ If you did not request your master password hint you can safely ignore this email. +
+
+ + + + + +
+
+ + diff --git a/src/static/templates/email/send_org_invite.html.hbs b/src/static/templates/email/send_org_invite.html.hbs new file mode 100644 index 00000000..0d8f32a1 --- /dev/null +++ b/src/static/templates/email/send_org_invite.html.hbs @@ -0,0 +1,140 @@ +Join {{org_name}} + + + + + + Bitwarden_rs + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + +
+ You have been invited to join the {{org_name}} organization. +
+ + Join Organization Now + +
+ If you do not wish to join this organization, you can safely ignore this email. +
+
+ + + + + +
+
+ +