From 5f61607419fb329442ebbdd98832cb14349d33ab Mon Sep 17 00:00:00 2001 From: BlackDex Date: Wed, 26 Feb 2020 11:02:22 +0100 Subject: [PATCH 1/3] Added SMTP test button in the admin gui - Added a test button for checking the e-mail settings. - Fixed a bug with the _post JavaScript function: A function was overwriten with a variable and errors were not handled correctly like a 500 for example. --- src/api/admin.rs | 13 ++ src/config.rs | 1 + src/mail.rs | 11 ++ src/static/templates/admin/page.hbs | 47 +++++-- src/static/templates/email/smtp_test.hbs | 8 ++ src/static/templates/email/smtp_test.html.hbs | 129 ++++++++++++++++++ 6 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 src/static/templates/email/smtp_test.hbs create mode 100644 src/static/templates/email/smtp_test.html.hbs diff --git a/src/api/admin.rs b/src/api/admin.rs index c4fad117..19a18f9c 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -34,6 +34,7 @@ pub fn routes() -> Vec { post_config, delete_config, backup_db, + test_smtp, ] } @@ -164,6 +165,18 @@ fn invite_user(data: Json, _token: AdminToken, conn: DbConn) -> Empt } } +#[post("/test/smtp", data = "")] +fn test_smtp(data: Json, _token: AdminToken) -> EmptyResult { + let data: InviteData = data.into_inner(); + let email = data.email.clone(); + + if CONFIG.mail_enabled() { + mail::send_test(&email) + } else { + err!("Mail is not enabled") + } +} + #[get("/logout")] fn logout(mut cookies: Cookies) -> Result { cookies.remove(Cookie::named(COOKIE_NAME)); diff --git a/src/config.rs b/src/config.rs index 2c53a342..34f7f3af 100644 --- a/src/config.rs +++ b/src/config.rs @@ -634,6 +634,7 @@ where reg!("email/verify_email", ".html"); reg!("email/welcome", ".html"); reg!("email/welcome_must_verify", ".html"); + reg!("email/smtp_test", ".html"); reg!("admin/base"); reg!("admin/login"); diff --git a/src/mail.rs b/src/mail.rs index 6e49f8f5..77eb2ac1 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -258,6 +258,17 @@ pub fn send_change_email(address: &str, token: &str) -> EmptyResult { send_email(&address, &subject, &body_html, &body_text) } +pub fn send_test(address: &str) -> EmptyResult { + let (subject, body_html, body_text) = get_text( + "email/smtp_test", + json!({ + "url": CONFIG.domain(), + }), + )?; + + send_email(&address, &subject, &body_html, &body_text) +} + fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) -> EmptyResult { let address_split: Vec<&str> = address.rsplitn(2, '@').collect(); if address_split.len() != 2 { diff --git a/src/static/templates/admin/page.hbs b/src/static/templates/admin/page.hbs index 1001c707..6136f4af 100644 --- a/src/static/templates/admin/page.hbs +++ b/src/static/templates/admin/page.hbs @@ -71,6 +71,17 @@ them to avoid confusion. This does not apply to the read-only section, which can only be set through the environment. + +
+
SMTP Test
+ Email: + +
+ + +
+
+
{{#each config}} {{#if groupdoc}} @@ -213,13 +224,24 @@ mode: "same-origin", credentials: "same-origin", headers: { "Content-Type": "application/json" } - }).then(e => { - if (e.ok) { return msg(successMsg); } - e.json().then(json => { - const msg = json ? json.ErrorModel.Message : "Unknown error"; - msg(errMsg + ": " + msg); - }); - }).catch(e => { msg(errMsg + ": Unknown error") }); + }).then( resp => { + if (resp.ok) { msg(successMsg); return Promise.reject({error: false}); } + respStatus = resp.status; + respStatusText = resp.statusText; + return resp.text(); + }).then( respText => { + try { + const respJson = JSON.parse(respText); + return respJson ? respJson.ErrorModel.Message : "Unknown error"; + } catch (e) { + return Promise.reject({body:respStatus + ' - ' + respStatusText, error: true}); + } + }).then( apiMsg => { + msg(errMsg + "\n" + apiMsg); + }).catch( e => { + if (e.error === false) { return true; } + else { msg(errMsg + "\n" + e.body); } + }); } function deleteUser(id, mail) { var input_mail = prompt("To delete user '" + mail + "', please type the email below") @@ -260,6 +282,15 @@ "Error inviting user", data); return false; } + function smtpTest() { + inv = document.getElementById("smtp-test-email"); + data = JSON.stringify({ "email": inv.value }); + inv.value = ""; + _post("/admin/test/smtp/", + "SMTP Test email sent correctly", + "Error sending SMTP test email", data); + return false; + } function getFormData() { let data = {}; @@ -331,7 +362,7 @@ e.title = orgtype.name; }); - // These are formatted because otherwise the + // These are formatted because otherwise the // VSCode formatter breaks But they still work // {{#each config}} {{#if grouptoggle}} masterCheck("input_{{grouptoggle}}", "#g_{{group}} input"); diff --git a/src/static/templates/email/smtp_test.hbs b/src/static/templates/email/smtp_test.hbs new file mode 100644 index 00000000..9d16d223 --- /dev/null +++ b/src/static/templates/email/smtp_test.hbs @@ -0,0 +1,8 @@ +Bitwarden_rs SMTP Test + + +

+This is a test email to verify the SMTP configuration for {{url}}. +

+

When you can read this email it is probably configured correctly.

+ diff --git a/src/static/templates/email/smtp_test.html.hbs b/src/static/templates/email/smtp_test.html.hbs new file mode 100644 index 00000000..154bda0c --- /dev/null +++ b/src/static/templates/email/smtp_test.html.hbs @@ -0,0 +1,129 @@ +Bitwarden_rs SMTP Test + + + + + + Bitwarden_rs + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + +
+ This is a test email to verify the SMTP configuration for {{url}}. +
+ When you can read this email it is probably configured correctly. +
+
+ + + + + +
+
+ + From 5a974c7b944a66adf72d4615004b894ba16ea6bd Mon Sep 17 00:00:00 2001 From: BlackDex Date: Wed, 26 Feb 2020 11:02:22 +0100 Subject: [PATCH 2/3] Added SMTP test button in the admin gui - Added a test button for checking the e-mail settings. - Fixed a bug with the _post JavaScript function: A function was overwriten with a variable and errors were not handled correctly like a 500 for example. --- src/api/admin.rs | 13 ++ src/config.rs | 1 + src/mail.rs | 11 ++ src/static/templates/admin/page.hbs | 47 +++++-- src/static/templates/email/smtp_test.hbs | 8 ++ src/static/templates/email/smtp_test.html.hbs | 129 ++++++++++++++++++ 6 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 src/static/templates/email/smtp_test.hbs create mode 100644 src/static/templates/email/smtp_test.html.hbs diff --git a/src/api/admin.rs b/src/api/admin.rs index 937783f2..03e62700 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -34,6 +34,7 @@ pub fn routes() -> Vec { post_config, delete_config, backup_db, + test_smtp, ] } @@ -170,6 +171,18 @@ fn invite_user(data: Json, _token: AdminToken, conn: DbConn) -> Empt } } +#[post("/test/smtp", data = "")] +fn test_smtp(data: Json, _token: AdminToken) -> EmptyResult { + let data: InviteData = data.into_inner(); + let email = data.email.clone(); + + if CONFIG.mail_enabled() { + mail::send_test(&email) + } else { + err!("Mail is not enabled") + } +} + #[get("/logout")] fn logout(mut cookies: Cookies) -> Result { cookies.remove(Cookie::named(COOKIE_NAME)); diff --git a/src/config.rs b/src/config.rs index 11f63aaf..12e04d65 100644 --- a/src/config.rs +++ b/src/config.rs @@ -668,6 +668,7 @@ where reg!("email/verify_email", ".html"); reg!("email/welcome", ".html"); reg!("email/welcome_must_verify", ".html"); + reg!("email/smtp_test", ".html"); reg!("admin/base"); reg!("admin/login"); diff --git a/src/mail.rs b/src/mail.rs index 6e49f8f5..77eb2ac1 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -258,6 +258,17 @@ pub fn send_change_email(address: &str, token: &str) -> EmptyResult { send_email(&address, &subject, &body_html, &body_text) } +pub fn send_test(address: &str) -> EmptyResult { + let (subject, body_html, body_text) = get_text( + "email/smtp_test", + json!({ + "url": CONFIG.domain(), + }), + )?; + + send_email(&address, &subject, &body_html, &body_text) +} + fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) -> EmptyResult { let address_split: Vec<&str> = address.rsplitn(2, '@').collect(); if address_split.len() != 2 { diff --git a/src/static/templates/admin/page.hbs b/src/static/templates/admin/page.hbs index fd26ce16..31c45862 100644 --- a/src/static/templates/admin/page.hbs +++ b/src/static/templates/admin/page.hbs @@ -71,6 +71,17 @@ them to avoid confusion. This does not apply to the read-only section, which can only be set through the environment. + +
+
SMTP Test
+ Email: + + + + + +
+
{{#each config}} {{#if groupdoc}} @@ -213,13 +224,24 @@ mode: "same-origin", credentials: "same-origin", headers: { "Content-Type": "application/json" } - }).then(e => { - if (e.ok) { return msg(successMsg); } - e.json().then(json => { - const msg = json ? json.ErrorModel.Message : "Unknown error"; - msg(errMsg + ": " + msg); - }); - }).catch(e => { msg(errMsg + ": Unknown error") }); + }).then( resp => { + if (resp.ok) { msg(successMsg); return Promise.reject({error: false}); } + respStatus = resp.status; + respStatusText = resp.statusText; + return resp.text(); + }).then( respText => { + try { + const respJson = JSON.parse(respText); + return respJson ? respJson.ErrorModel.Message : "Unknown error"; + } catch (e) { + return Promise.reject({body:respStatus + ' - ' + respStatusText, error: true}); + } + }).then( apiMsg => { + msg(errMsg + "\n" + apiMsg); + }).catch( e => { + if (e.error === false) { return true; } + else { msg(errMsg + "\n" + e.body); } + }); } function deleteUser(id, mail) { var input_mail = prompt("To delete user '" + mail + "', please type the email below") @@ -260,6 +282,15 @@ "Error inviting user", data); return false; } + function smtpTest() { + inv = document.getElementById("smtp-test-email"); + data = JSON.stringify({ "email": inv.value }); + inv.value = ""; + _post("/admin/test/smtp/", + "SMTP Test email sent correctly", + "Error sending SMTP test email", data); + return false; + } function getFormData() { let data = {}; @@ -331,7 +362,7 @@ e.title = orgtype.name; }); - // These are formatted because otherwise the + // These are formatted because otherwise the // VSCode formatter breaks But they still work // {{#each config}} {{#if grouptoggle}} masterCheck("input_{{grouptoggle}}", "#g_{{group}} input"); diff --git a/src/static/templates/email/smtp_test.hbs b/src/static/templates/email/smtp_test.hbs new file mode 100644 index 00000000..9d16d223 --- /dev/null +++ b/src/static/templates/email/smtp_test.hbs @@ -0,0 +1,8 @@ +Bitwarden_rs SMTP Test + + +

+This is a test email to verify the SMTP configuration for {{url}}. +

+

When you can read this email it is probably configured correctly.

+ diff --git a/src/static/templates/email/smtp_test.html.hbs b/src/static/templates/email/smtp_test.html.hbs new file mode 100644 index 00000000..154bda0c --- /dev/null +++ b/src/static/templates/email/smtp_test.html.hbs @@ -0,0 +1,129 @@ +Bitwarden_rs SMTP Test + + + + + + Bitwarden_rs + + + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + + +
+ This is a test email to verify the SMTP configuration for {{url}}. +
+ When you can read this email it is probably configured correctly. +
+
+ + + + + +
+
+ + From 97fb7b5b96b66ee1b476cb9f74c8be0742c57c50 Mon Sep 17 00:00:00 2001 From: BlackDex Date: Wed, 26 Feb 2020 16:58:57 +0100 Subject: [PATCH 3/3] Added urlpath to smtpTest function --- src/static/templates/admin/page.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/templates/admin/page.hbs b/src/static/templates/admin/page.hbs index 31c45862..f3263977 100644 --- a/src/static/templates/admin/page.hbs +++ b/src/static/templates/admin/page.hbs @@ -286,7 +286,7 @@ inv = document.getElementById("smtp-test-email"); data = JSON.stringify({ "email": inv.value }); inv.value = ""; - _post("/admin/test/smtp/", + _post("{{urlpath}}/admin/test/smtp/", "SMTP Test email sent correctly", "Error sending SMTP test email", data); return false;