commit a1c1b9ab3bcfb89b92264ae7b903760ce1afd4a2
parent 395979e834ff3bccbedf87fb386607bbc9ad8557
Author: Daniel GarcĂa <dani-garcia@users.noreply.github.com>
Date:   Fri,  8 Oct 2021 22:28:46 +0200
Merge branch 'mail-errors' of https://github.com/BlackDex/vaultwarden into BlackDex-mail-errors
Diffstat:
8 files changed, 52 insertions(+), 24 deletions(-)
diff --git a/src/api/admin.rs b/src/api/admin.rs
@@ -18,7 +18,9 @@ use crate::{
     db::{backup_database, get_sql_server_version, models::*, DbConn, DbConnType},
     error::{Error, MapResult},
     mail,
-    util::{format_naive_datetime_local, get_display_size, get_reqwest_client, is_running_in_docker},
+    util::{
+        docker_base_image, format_naive_datetime_local, get_display_size, get_reqwest_client, is_running_in_docker,
+    },
     CONFIG,
 };
 
@@ -492,6 +494,7 @@ fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> ApiResu
 
     // Execute some environment checks
     let running_within_docker = is_running_in_docker();
+    let docker_base_image = docker_base_image();
     let has_http_access = has_http_access();
     let uses_proxy = env::var_os("HTTP_PROXY").is_some()
         || env::var_os("http_proxy").is_some()
@@ -549,6 +552,7 @@ fn diagnostics(_token: AdminToken, ip_header: IpHeader, conn: DbConn) -> ApiResu
         "web_vault_version": web_vault_version.version,
         "latest_web_build": latest_web_build,
         "running_within_docker": running_within_docker,
+        "docker_base_image": docker_base_image,
         "has_http_access": has_http_access,
         "ip_header_exists": &ip_header.0.is_some(),
         "ip_header_match": ip_header_name == CONFIG.ip_header(),
diff --git a/src/mail.rs b/src/mail.rs
@@ -485,15 +485,28 @@ fn send_email(address: &str, subject: &str, body_html: String, body_text: String
         // Match some common errors and make them more user friendly
         Err(e) => {
             if e.is_client() {
-                err!(format!("SMTP Client error: {}", e));
+                debug!("SMTP Client error: {:#?}", e);
+                err!(format!("SMTP Client error: {}", e.to_string()));
             } else if e.is_transient() {
-                err!(format!("SMTP 4xx error: {:?}", e));
+                debug!("SMTP 4xx error: {:#?}", e);
+                err!(format!("SMTP 4xx error: {}", e.to_string()));
             } else if e.is_permanent() {
-                err!(format!("SMTP 5xx error: {:?}", e));
+                debug!("SMTP 5xx error: {:#?}", e);
+                let mut msg = e.to_string();
+                // Add a special check for 535 to add a more descriptive message
+                if msg.contains("(535)") {
+                    msg = format!("{} - Authentication credentials invalid", msg);
+                }
+                err!(format!("SMTP 5xx error: {}", msg));
             } else if e.is_timeout() {
-                err!(format!("SMTP timeout error: {:?}", e));
+                debug!("SMTP timeout error: {:#?}", e);
+                err!(format!("SMTP timeout error: {}", e.to_string()));
+            } else if e.is_tls() {
+                debug!("SMTP Encryption error: {:#?}", e);
+                err!(format!("SMTP Encryption error: {}", e.to_string()));
             } else {
-                Err(e.into())
+                debug!("SMTP {:#?}", e);
+                err!(format!("SMTP {}", e.to_string()));
             }
         }
     }
diff --git a/src/static/templates/admin/base.hbs b/src/static/templates/admin/base.hbs
@@ -62,8 +62,8 @@
                 headers: { "Content-Type": "application/json" }
             }).then( resp => {
                 if (resp.ok) { msg(successMsg, reload_page); return Promise.reject({error: false}); }
-                respStatus = resp.status;
-                respStatusText = resp.statusText;
+                const respStatus = resp.status;
+                const respStatusText = resp.statusText;
                 return resp.text();
             }).then( respText => {
                 try {
@@ -126,9 +126,9 @@
 
         // get current URL path and assign 'active' class to the correct nav-item
         (() => {
-            var pathname = window.location.pathname;
+            const pathname = window.location.pathname;
             if (pathname === "") return;
-            var navItem = document.querySelectorAll('.navbar-nav .nav-item a[href="'+pathname+'"]');
+            let navItem = document.querySelectorAll('.navbar-nav .nav-item a[href="'+pathname+'"]');
             if (navItem.length === 1) {
                 navItem[0].className = navItem[0].className + ' active';
                 navItem[0].setAttribute('aria-current', 'page');
diff --git a/src/static/templates/admin/diagnostics.hbs b/src/static/templates/admin/diagnostics.hbs
@@ -58,7 +58,7 @@
                     <dt class="col-sm-5">Running within Docker</dt>
                     <dd class="col-sm-7">
                     {{#if page_data.running_within_docker}}
-                        <span class="d-block"><b>Yes</b></span>
+                        <span class="d-block"><b>Yes (Base: {{ page_data.docker_base_image }})</b></span>
                     {{/if}}
                     {{#unless page_data.running_within_docker}}
                         <span class="d-block"><b>No</b></span>
@@ -329,7 +329,7 @@
 
         supportString += "* Vaultwarden version: v{{ version }}\n";
         supportString += "* Web-vault version: v{{ page_data.web_vault_version }}\n";
-        supportString += "* Running within Docker: {{ page_data.running_within_docker }}\n";
+        supportString += "* Running within Docker: {{ page_data.running_within_docker }} (Base: {{ page_data.docker_base_image }})\n";
         supportString += "* Environment settings overridden: ";
         {{#if page_data.overrides}}
             supportString += "true\n"
diff --git a/src/static/templates/admin/organizations.hbs b/src/static/templates/admin/organizations.hbs
@@ -37,8 +37,8 @@
                             <span class="d-block"><strong>Size:</strong> {{attachment_size}}</span>
                             {{/if}}
                         </td>
-                        <td class="text-end pe-2 small">
-                            <a class="d-block" href="#" onclick='deleteOrganization({{jsesc Id}}, {{jsesc Name}}, {{jsesc BillingEmail}})'>Delete Organization</a>
+                        <td class="text-end px-0 small">
+                            <button type="button" class="btn btn-sm btn-link p-0 border-0" onclick='deleteOrganization({{jsesc Id}}, {{jsesc Name}}, {{jsesc BillingEmail}})'>Delete Organization</button>
                         </td>
                     </tr>
                     {{/each}}
diff --git a/src/static/templates/admin/settings.hbs b/src/static/templates/admin/settings.hbs
@@ -219,11 +219,10 @@
         onChange(); // Trigger the event initially
         checkbox.addEventListener("change", onChange);
     }
-    // These are formatted because otherwise the
-    // VSCode formatter breaks But they still work
-    // {{#each config}} {{#if grouptoggle}}
+
+    {{#each config}} {{#if grouptoggle}}
     masterCheck("input_{{grouptoggle}}", "#g_{{group}} input");
-    // {{/if}} {{/each}}
+    {{/if}} {{/each}}
 
     // Two functions to help check if there were changes to the form fields
     // Useful for example during the smtp test to prevent people from clicking save before testing there new settings
diff --git a/src/static/templates/admin/users.hbs b/src/static/templates/admin/users.hbs
@@ -61,16 +61,16 @@
                             {{/each}}
                             </div>
                         </td>
-                        <td class="text-end pe-2 small">
+                        <td class="text-end px-0 small">
                             {{#if TwoFactorEnabled}}
-                            <a class="d-block" href="#" onclick='remove2fa({{jsesc Id}})'>Remove all 2FA</a>
+                            <button type="button" class="btn btn-sm btn-link p-0 border-0" onclick='remove2fa({{jsesc Id}})'>Remove all 2FA</button>
                             {{/if}}
-                            <a class="d-block" href="#" onclick='deauthUser({{jsesc Id}})'>Deauthorize sessions</a>
-                            <a class="d-block" href="#" onclick='deleteUser({{jsesc Id}}, {{jsesc Email}})'>Delete User</a>
+                            <button type="button" class="btn btn-sm btn-link p-0 border-0" onclick='deauthUser({{jsesc Id}})'>Deauthorize sessions</button>
+                            <button type="button" class="btn btn-sm btn-link p-0 border-0" onclick='deleteUser({{jsesc Id}}, {{jsesc Email}})'>Delete User</button>
                             {{#if user_enabled}}
-                            <a class="d-block" href="#" onclick='disableUser({{jsesc Id}}, {{jsesc Email}})'>Disable User</a>
+                            <button type="button" class="btn btn-sm btn-link p-0 border-0" onclick='disableUser({{jsesc Id}}, {{jsesc Email}})'>Disable User</button>
                             {{else}}
-                            <a class="d-block" href="#" onclick='enableUser({{jsesc Id}}, {{jsesc Email}})'>Enable User</a>
+                            <button type="button" class="btn btn-sm btn-link p-0 border-0" onclick='enableUser({{jsesc Id}}, {{jsesc Email}})'>Enable User</button>
                             {{/if}}
                         </td>
                     </tr>
diff --git a/src/util.rs b/src/util.rs
@@ -419,6 +419,18 @@ pub fn is_running_in_docker() -> bool {
     Path::new("/.dockerenv").exists() || Path::new("/run/.containerenv").exists()
 }
 
+/// Simple check to determine on which docker base image vaultwarden is running.
+/// We build images based upon Debian or Alpine, so these we check here.
+pub fn docker_base_image() -> String {
+    if Path::new("/etc/debian_version").exists() {
+        "Debian".to_string()
+    } else if Path::new("/etc/alpine-release").exists() {
+        "Alpine".to_string()
+    } else {
+        "Unknown".to_string()
+    }
+}
+
 //
 // Deserialization methods
 //