{"record":{"id":"36cd5fdcbf472dee","repo":"dani-garcia/vaultwarden","slug":"error-on-sending-email","errorCode":null,"errorMessage":"Error on sending email","messagePattern":"Error on sending email","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/api/core/emergency_access.rs","lineNumber":764,"sourceCode":"\n                if CONFIG.mail_enabled() {\n                    // get grantor user to send Accepted email\n                    let grantor_user =\n                        User::find_by_uuid(&emer.grantor_uuid, &conn).await.expect(\"Grantor user not found\");\n\n                    // get grantee user to send Accepted email\n                    let grantee_user =\n                        User::find_by_uuid(&emer.grantee_uuid.clone().expect(\"Grantee user invalid\"), &conn)\n                            .await\n                            .expect(\"Grantee user not found\");\n\n                    mail::send_emergency_access_recovery_timed_out(\n                        &grantor_user.email,\n                        &grantee_user.name,\n                        emer.get_type_as_str(),\n                    )\n                    .await\n                    .expect(\"Error on sending email\");\n\n                    mail::send_emergency_access_recovery_approved(&grantee_user.email, &grantor_user.name)\n                        .await\n                        .expect(\"Error on sending email\");\n                }\n            }\n        }\n    } else {\n        error!(\"Failed to get DB connection while searching emergency request timed out\");\n    }\n}\n\npub async fn emergency_notification_reminder_job(pool: DbPool) {\n    debug!(\"Start emergency_notification_reminder_job\");\n    if !CONFIG.emergency_access_allowed() {\n        return;\n    }\n","sourceCodeStart":746,"sourceCodeEnd":782,"githubUrl":"https://github.com/dani-garcia/vaultwarden/blob/0cefa4cca7c9f2a5579dd290f78193b543818c51/src/api/core/emergency_access.rs#L746-L782","documentation":"After the timeout job approves a recovery and mail is enabled, mail::send_emergency_access_recovery_timed_out(...).expect(\"Error on sending email\") panics the job task on any SMTP failure (connection refused, auth rejected, TLS problem). The DB status update has already committed, so a later rerun will not re-send this notification — the mail is lost even after SMTP is fixed.","triggerScenarios":"EMERGENCY_REQUEST_TIMEOUT job firing while SMTP is misconfigured or unreachable: wrong SMTP_HOST/PORT/SECURITY, expired credentials, DNS or firewall issues.","commonSituations":"SMTP provider credentials rotated; mail settings changed but untested; SMTP enabled after recoveries had already started; provider outages.","solutions":["Fix SMTP config (SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_USERNAME/SMTP_PASSWORD) and verify with the 'Test SMTP' button on /admin/diagnostics","Restart Vaultwarden to respawn the panicked job task","Accept that this particular notification was lost; inform the affected user manually if needed","Code fix: log mail failures instead of expect"],"exampleFix":"// before\nmail::send_emergency_access_recovery_timed_out(&grantor_user.email, &grantee_user.name, emer.get_type_as_str())\n    .await\n    .expect(\"Error on sending email\");\n// after\nif let Err(e) = mail::send_emergency_access_recovery_timed_out(&grantor_user.email, &grantee_user.name, emer.get_type_as_str()).await {\n    error!(\"Failed to send recovery timed out mail for {}: {e}\", emer.uuid);\n}","handlingStrategy":"try-catch","validationCode":"# Probe SMTP reachability with the same host/port/security Vaultwarden uses\nopenssl s_client -connect ${SMTP_HOST}:${SMTP_PORT} -starttls smtp < /dev/null\n# for implicit TLS (SMTP_SECURITY=starttls vs secure) use without -starttls:\n# openssl s_client -connect ${SMTP_HOST}:${SMTP_PORT} < /dev/null","typeGuard":null,"tryCatchPattern":"// Mail failures in jobs: log and continue, never panic\nlet mail_res = mail::send_emergency_access_recovery_timed_out(&grantor_user.email, &grantee_user.name, emer.get_type_as_str()).await;\nif let Err(e) = mail_res {\n    error!(\"emergency timeout job: mail send failed for {}: {e}\", emer.uuid);\n}","preventionTips":["Run 'Test SMTP' from /admin/diagnostics after any mail config change","Keep SMTP credentials current and monitor provider expiry","Treat job panics as alerts: one dead task stops future runs until restart"],"tags":["rust","emergency-access","email","smtp","panic"],"backgroundTag":null,"analyzedSha":"0cefa4cca7c9f2a5579dd290f78193b543818c51","analyzedAt":"2026-08-16T07:44:56.102Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}