mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-09-10 10:45:57 +03:00
Updated email processing.
- Added an option to enable smtp debugging via SMTP_DEBUG. This will trigger a trace of the smtp commands sent/received to/from the mail server. Useful when troubleshooting. - Added two options to ignore invalid certificates which either do not match at all, or only doesn't match the hostname. - Updated lettre to the latest alpha.4 version.
This commit is contained in:
@@ -413,29 +413,35 @@ make_config! {
|
||||
/// SMTP Email Settings
|
||||
smtp: _enable_smtp {
|
||||
/// Enabled
|
||||
_enable_smtp: bool, true, def, true;
|
||||
_enable_smtp: bool, true, def, true;
|
||||
/// Host
|
||||
smtp_host: String, true, option;
|
||||
smtp_host: String, true, option;
|
||||
/// Enable Secure SMTP |> (Explicit) - Enabling this by default would use STARTTLS (Standard ports 587 or 25)
|
||||
smtp_ssl: bool, true, def, true;
|
||||
smtp_ssl: bool, true, def, true;
|
||||
/// Force TLS |> (Implicit) - Enabling this would force the use of an SSL/TLS connection, instead of upgrading an insecure one with STARTTLS (Standard port 465)
|
||||
smtp_explicit_tls: bool, true, def, false;
|
||||
smtp_explicit_tls: bool, true, def, false;
|
||||
/// Port
|
||||
smtp_port: u16, true, auto, |c| if c.smtp_explicit_tls {465} else if c.smtp_ssl {587} else {25};
|
||||
smtp_port: u16, true, auto, |c| if c.smtp_explicit_tls {465} else if c.smtp_ssl {587} else {25};
|
||||
/// From Address
|
||||
smtp_from: String, true, def, String::new();
|
||||
smtp_from: String, true, def, String::new();
|
||||
/// From Name
|
||||
smtp_from_name: String, true, def, "Bitwarden_RS".to_string();
|
||||
smtp_from_name: String, true, def, "Bitwarden_RS".to_string();
|
||||
/// Username
|
||||
smtp_username: String, true, option;
|
||||
smtp_username: String, true, option;
|
||||
/// Password
|
||||
smtp_password: Pass, true, option;
|
||||
smtp_password: Pass, true, option;
|
||||
/// SMTP Auth mechanism |> Defaults for SSL is "Plain" and "Login" and nothing for Non-SSL connections. Possible values: ["Plain", "Login", "Xoauth2"]. Multiple options need to be separated by a comma ','.
|
||||
smtp_auth_mechanism: String, true, option;
|
||||
smtp_auth_mechanism: String, true, option;
|
||||
/// SMTP connection timeout |> Number of seconds when to stop trying to connect to the SMTP server
|
||||
smtp_timeout: u64, true, def, 15;
|
||||
smtp_timeout: u64, true, def, 15;
|
||||
/// Server name sent during HELO |> By default this value should be is on the machine's hostname, but might need to be changed in case it trips some anti-spam filters
|
||||
helo_name: String, true, option;
|
||||
helo_name: String, true, option;
|
||||
/// Enable SMTP debugging (Know the risks!) |> DANGEROUS: Enabling this will output very detailed SMTP messages. This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting!
|
||||
smtp_debug: bool, true, def, false;
|
||||
/// Accept Invalid Certs (Know the risks!) |> DANGEROUS: Allow invalid certificates. This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
||||
smtp_accept_invalid_certs: bool, true, def, false;
|
||||
/// Accept Invalid Hostnames (Know the risks!) |> DANGEROUS: Allow invalid hostnames. This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
||||
smtp_accept_invalid_hostnames: bool, true, def, false;
|
||||
},
|
||||
|
||||
/// Email 2FA Settings
|
||||
|
41
src/mail.rs
41
src/mail.rs
@@ -7,6 +7,7 @@ use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||
use lettre::{
|
||||
message::{header, Mailbox, Message, MultiPart, SinglePart},
|
||||
transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism},
|
||||
transport::smtp::client::{Tls, TlsParameters},
|
||||
transport::smtp::extension::ClientId,
|
||||
Address, SmtpTransport, Transport,
|
||||
};
|
||||
@@ -22,21 +23,30 @@ fn mailer() -> SmtpTransport {
|
||||
use std::time::Duration;
|
||||
let host = CONFIG.smtp_host().unwrap();
|
||||
|
||||
// Determine security
|
||||
let smtp_client = if CONFIG.smtp_ssl() {
|
||||
if CONFIG.smtp_explicit_tls() {
|
||||
SmtpTransport::relay(host.as_str())
|
||||
} else {
|
||||
SmtpTransport::starttls_relay(host.as_str())
|
||||
}
|
||||
} else {
|
||||
Ok(SmtpTransport::builder_dangerous(host.as_str()))
|
||||
};
|
||||
|
||||
let smtp_client = smtp_client.unwrap()
|
||||
let smtp_client = SmtpTransport::builder_dangerous(host.as_str())
|
||||
.port(CONFIG.smtp_port())
|
||||
.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())));
|
||||
|
||||
// Determine security
|
||||
let smtp_client = if CONFIG.smtp_ssl() {
|
||||
let mut tls_parameters = TlsParameters::builder(host);
|
||||
if CONFIG.smtp_accept_invalid_hostnames() {
|
||||
tls_parameters.dangerous_accept_invalid_hostnames(true);
|
||||
}
|
||||
if CONFIG.smtp_accept_invalid_certs() {
|
||||
tls_parameters.dangerous_accept_invalid_certs(true);
|
||||
}
|
||||
let tls_parameters = tls_parameters.build().unwrap();
|
||||
|
||||
if CONFIG.smtp_explicit_tls() {
|
||||
smtp_client.tls(Tls::Wrapper(tls_parameters))
|
||||
} else {
|
||||
smtp_client.tls(Tls::Required(tls_parameters))
|
||||
}
|
||||
} else {
|
||||
smtp_client
|
||||
};
|
||||
|
||||
let smtp_client = match (CONFIG.smtp_username(), CONFIG.smtp_password()) {
|
||||
(Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user, pass)),
|
||||
_ => smtp_client,
|
||||
@@ -318,14 +328,17 @@ fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) ->
|
||||
|
||||
// The boundary generated by Lettre it self is mostly too large based on the RFC822, so we generate one our selfs.
|
||||
use uuid::Uuid;
|
||||
let boundary = format!("_Part_{}_", Uuid::new_v4().to_simple());
|
||||
let unique_id = Uuid::new_v4().to_simple();
|
||||
let boundary = format!("_Part_{}_", unique_id);
|
||||
let alternative = MultiPart::alternative().boundary(boundary).singlepart(text).singlepart(html);
|
||||
let smtp_from = &CONFIG.smtp_from();
|
||||
|
||||
let email = Message::builder()
|
||||
.message_id(Some(format!("<{}.{}>", unique_id, smtp_from)))
|
||||
.to(Mailbox::new(None, Address::from_str(&address)?))
|
||||
.from(Mailbox::new(
|
||||
Some(CONFIG.smtp_from_name()),
|
||||
Address::from_str(&CONFIG.smtp_from())?,
|
||||
Address::from_str(smtp_from)?,
|
||||
))
|
||||
.subject(subject)
|
||||
.multipart(alternative)?;
|
||||
|
10
src/main.rs
10
src/main.rs
@@ -115,6 +115,16 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> {
|
||||
.level_for("rocket::fairing", log::LevelFilter::Off)
|
||||
.chain(std::io::stdout());
|
||||
|
||||
// Enable smtp debug logging only specifically for smtp when need.
|
||||
// This can contain sensitive information we do not want in the default debug/trace logging.
|
||||
if CONFIG.smtp_debug() {
|
||||
println!("[WARNING] SMTP Debugging is enabled (SMTP_DEBUG=true). Sensitive information could be disclosed via logs!");
|
||||
println!("[WARNING] Only enable SMTP_DEBUG during troubleshooting!\n");
|
||||
logger = logger.level_for("lettre::transport::smtp", log::LevelFilter::Debug)
|
||||
} else {
|
||||
logger = logger.level_for("lettre::transport::smtp", log::LevelFilter::Off)
|
||||
}
|
||||
|
||||
if CONFIG.extended_logging() {
|
||||
logger = logger.format(|out, message, record| {
|
||||
out.finish(format_args!(
|
||||
|
Reference in New Issue
Block a user