vw_small

Hardened fork of Vaultwarden (https://github.com/dani-garcia/vaultwarden) with fewer features.
git clone https://git.philomathiclife.com/repos/vw_small
Log | Files | Refs | README

commit 5a974c7b944a66adf72d4615004b894ba16ea6bd
parent cd8907542a5d128d36309a4c9218ea3f4bd07df3
Author: BlackDex <black.dex@gmail.com>
Date:   Wed, 26 Feb 2020 11:02:22 +0100

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.

Diffstat:
Msrc/api/admin.rs | 13+++++++++++++
Msrc/config.rs | 1+
Msrc/mail.rs | 11+++++++++++
Msrc/static/templates/admin/page.hbs | 47+++++++++++++++++++++++++++++++++++++++--------
Asrc/static/templates/email/smtp_test.hbs | 8++++++++
Asrc/static/templates/email/smtp_test.html.hbs | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 201 insertions(+), 8 deletions(-)

diff --git a/src/api/admin.rs b/src/api/admin.rs @@ -34,6 +34,7 @@ pub fn routes() -> Vec<Route> { post_config, delete_config, backup_db, + test_smtp, ] } @@ -170,6 +171,18 @@ fn invite_user(data: Json<InviteData>, _token: AdminToken, conn: DbConn) -> Empt } } +#[post("/test/smtp", data = "<data>")] +fn test_smtp(data: Json<InviteData>, _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<Redirect, ()> { cookies.remove(Cookie::named(COOKIE_NAME)); diff --git 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 @@ -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 @@ -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. </div> + + <div id="smtp-test-form-block" class="align-items-center mb-3 text-white-50 bg-secondary"> + <h6 class="mb-0 text-white">SMTP Test</h6> + <small>Email:</small> + + <form class="form-inline" id="smtp-test-form" onsubmit="smtpTest(); return false;"> + <input type="email" class="form-control w-50 mr-2" id="smtp-test-email" placeholder="Enter email"> + <button type="submit" class="btn btn-primary">Send test email</button> + </form> + </div> + <form class="form accordion" id="config-form" onsubmit="saveConfig(); return false;"> {{#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 @@ -0,0 +1,8 @@ +Bitwarden_rs SMTP Test +<!----------------> +<html> +<p> +This is a test email to verify the SMTP configuration for <a href="{{url}}">{{url}}</a>. +</p> +<p>When you can read this email it is probably configured correctly.</p> +</html> diff --git a/src/static/templates/email/smtp_test.html.hbs b/src/static/templates/email/smtp_test.html.hbs @@ -0,0 +1,129 @@ +Bitwarden_rs SMTP Test +<!----------------> +<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> + <head> + <meta name="viewport" content="width=device-width" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>Bitwarden_rs</title> + </head> + <body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; height: 100%; line-height: 25px; width: 100% !important;" bgcolor="#f6f6f6"> + <style type="text/css"> +  body { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + box-sizing: border-box; + font-size: 16px; + color: #333; + line-height: 25px; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: none; + } + body * { + margin: 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + box-sizing: border-box; + font-size: 16px; + color: #333; + line-height: 25px; + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: none; + } + img { + max-width: 100%; + border: none; + } + body { + -webkit-font-smoothing: antialiased; + -webkit-text-size-adjust: none; + width: 100% !important; + height: 100%; + line-height: 25px; + } + body { + background-color: #f6f6f6; + } + @media only screen and (max-width: 600px) { + body { + padding: 0 !important; + } + .container { + padding: 0 !important; + width: 100% !important; + } + .container-table { + padding: 0 !important; + width: 100% !important; + } + .content { + padding: 0 0 10px 0 !important; + } + .content-wrap { + padding: 10px !important; + } + .invoice { + width: 100% !important; + } + .main { + border-right: none !important; + border-left: none !important; + border-radius: 0 !important; + } + .logo { + padding-top: 10px !important; + } + .footer { + margin-top: 10px !important; + } + .indented { + padding-left: 10px; + } + } + </style> + <table class="body-wrap" cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; width: 100%;" bgcolor="#f6f6f6"> + <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> + <td valign="middle" class="aligncenter middle logo" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; padding: 20px 0 10px;" align="center"> + <img src="{{url}}/bwrs_static/logo-gray.png" alt="" width="250" height="39" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /> + </td> + </tr> + <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> + <td class="container" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;" valign="top"> + <table cellpadding="0" cellspacing="0" class="container-table" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both !important; color: #333; display: block !important; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto; max-width: 600px !important; width: 600px;"> + <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> + <td class="content" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; display: block; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 0; line-height: 0; margin: 0 auto; max-width: 600px; padding-bottom: 20px;" valign="top"> + <table class="main" width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; margin: 0; -webkit-text-size-adjust: none; border: 1px solid #e9e9e9; border-radius: 3px;" bgcolor="white"> + <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> + <td class="content-wrap" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 20px; -webkit-text-size-adjust: none;" valign="top"> + <table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> + <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> + <td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> + This is a test email to verify the SMTP configuration for <a href="{{url}}">{{url}}</a>. + </td> + </tr> + <tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"> + <td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none; text-align: center;" valign="top" align="center"> + When you can read this email it is probably configured correctly. + </td> + </tr> + </table> + </td> + </tr> + </table> + <table class="footer" cellpadding="0" cellspacing="0" width="100%" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; clear: both; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; width: 100%;"> + <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> + <td class="aligncenter social-icons" align="center" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 15px 0 0 0;" valign="top"> + <table cellpadding="0" cellspacing="0" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0 auto;"> + <tr style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0;"> + <td style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; padding: 0 10px;" valign="top"><a href="https://github.com/dani-garcia/bitwarden_rs" target="_blank" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #999; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 12px; line-height: 20px; margin: 0; text-decoration: underline;"><img src="{{url}}/bwrs_static/mail-github.png" alt="GitHub" width="30" height="30" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; border: none; box-sizing: border-box; color: #333; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; max-width: 100%;" /></a></td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </body> +</html>