commit
5379329ef7
|
@ -242,9 +242,9 @@
|
||||||
# SMTP_HOST=smtp.domain.tld
|
# SMTP_HOST=smtp.domain.tld
|
||||||
# SMTP_FROM=bitwarden-rs@domain.tld
|
# SMTP_FROM=bitwarden-rs@domain.tld
|
||||||
# SMTP_FROM_NAME=Bitwarden_RS
|
# SMTP_FROM_NAME=Bitwarden_RS
|
||||||
# SMTP_PORT=587
|
# SMTP_PORT=587 # Ports 587 (submission) and 25 (smtp) are standard without encryption and with encryption via STARTTLS (Explicit TLS). Port 465 is outdated and used with Implicit TLS.
|
||||||
# SMTP_SSL=true # (Explicit) - This variable by default configures Explicit STARTTLS, it will upgrade an insecure connection to a secure one. Unless SMTP_EXPLICIT_TLS is set to true.
|
# SMTP_SSL=true # (Explicit) - This variable by default configures Explicit STARTTLS, it will upgrade an insecure connection to a secure one. Unless SMTP_EXPLICIT_TLS is set to true. Either port 587 or 25 are default.
|
||||||
# SMTP_EXPLICIT_TLS=true # (Implicit) - N.B. This variable configures Implicit TLS. It's currently mislabelled (see bug #851) - SMTP_SSL Needs to be set to true for this option to work.
|
# SMTP_EXPLICIT_TLS=true # (Implicit) - N.B. This variable configures Implicit TLS. It's currently mislabelled (see bug #851) - SMTP_SSL Needs to be set to true for this option to work. Usually port 465 is used here.
|
||||||
# SMTP_USERNAME=username
|
# SMTP_USERNAME=username
|
||||||
# SMTP_PASSWORD=password
|
# SMTP_PASSWORD=password
|
||||||
# SMTP_TIMEOUT=15
|
# SMTP_TIMEOUT=15
|
||||||
|
@ -259,6 +259,22 @@
|
||||||
## but might need to be changed in case it trips some anti-spam filters
|
## but might need to be changed in case it trips some anti-spam filters
|
||||||
# HELO_NAME=
|
# HELO_NAME=
|
||||||
|
|
||||||
|
## SMTP debugging
|
||||||
|
## When set to true this will output very detailed SMTP messages.
|
||||||
|
## WARNING: This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting!
|
||||||
|
# SMTP_DEBUG=false
|
||||||
|
|
||||||
|
## Accept Invalid Hostnames
|
||||||
|
## DANGEROUS: This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
||||||
|
## Only use this as a last resort if you are not able to use a valid certificate.
|
||||||
|
# SMTP_ACCEPT_INVALID_HOSTNAMES=false
|
||||||
|
|
||||||
|
## Accept Invalid Certificates
|
||||||
|
## DANGEROUS: This option introduces significant vulnerabilities to man-in-the-middle attacks!
|
||||||
|
## Only use this as a last resort if you are not able to use a valid certificate.
|
||||||
|
## If the Certificate is valid but the hostname doesn't match, please use SMTP_ACCEPT_INVALID_HOSTNAMES instead.
|
||||||
|
# SMTP_ACCEPT_INVALID_CERTS=false
|
||||||
|
|
||||||
## Require new device emails. When a user logs in an email is required to be sent.
|
## Require new device emails. When a user logs in an email is required to be sent.
|
||||||
## If sending the email fails the login attempt will fail!!
|
## If sending the email fails the login attempt will fail!!
|
||||||
# REQUIRE_DEVICE_EMAIL=false
|
# REQUIRE_DEVICE_EMAIL=false
|
||||||
|
|
|
@ -33,12 +33,6 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayvec"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -131,6 +125,18 @@ version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitvec"
|
||||||
|
version = "0.19.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81"
|
||||||
|
dependencies = [
|
||||||
|
"funty",
|
||||||
|
"radium",
|
||||||
|
"tap",
|
||||||
|
"wyz",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitwarden_rs"
|
name = "bitwarden_rs"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -638,6 +644,12 @@ version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "funty"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ba62103ce691c2fd80fbae2213dfdda9ce60804973ac6b6e97de818ea7f52c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futf"
|
name = "futf"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
@ -1144,9 +1156,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
version = "0.10.0-alpha.3"
|
version = "0.10.0-alpha.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e422b6c03563bc47db09bb61a8ece4f1462de131455beb96c091e2998fa316a2"
|
checksum = "dc8c2fc7873920aca23647e5e86d44ff3f40bbc5a5efaab445c9eb0e001c9f71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.0",
|
"base64 0.13.0",
|
||||||
"hostname",
|
"hostname",
|
||||||
|
@ -1160,22 +1172,10 @@ dependencies = [
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
"tracing",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lexical-core"
|
|
||||||
version = "0.7.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
|
|
||||||
dependencies = [
|
|
||||||
"arrayvec",
|
|
||||||
"bitflags",
|
|
||||||
"cfg-if 0.1.10",
|
|
||||||
"ryu",
|
|
||||||
"static_assertions",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.80"
|
version = "0.2.80"
|
||||||
|
@ -1448,11 +1448,11 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "5.1.2"
|
version = "6.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
checksum = "4489ccc7d668957ddf64af7cd027c081728903afa6479d35da7e99bf5728f75f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lexical-core",
|
"bitvec",
|
||||||
"memchr",
|
"memchr",
|
||||||
"version_check 0.9.2",
|
"version_check 0.9.2",
|
||||||
]
|
]
|
||||||
|
@ -1978,6 +1978,12 @@ dependencies = [
|
||||||
"scheduled-thread-pool",
|
"scheduled-thread-pool",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radium"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
@ -2617,12 +2623,6 @@ version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
|
checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_assertions"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stdweb"
|
name = "stdweb"
|
||||||
version = "0.4.20"
|
version = "0.4.20"
|
||||||
|
@ -2782,6 +2782,12 @@ dependencies = [
|
||||||
"time 0.1.44",
|
"time 0.1.44",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tap"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
|
@ -3371,6 +3377,12 @@ dependencies = [
|
||||||
"winapi-build",
|
"winapi-build",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyz"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yansi"
|
name = "yansi"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
|
|
@ -100,7 +100,7 @@ num-traits = "0.2.14"
|
||||||
num-derive = "0.3.3"
|
num-derive = "0.3.3"
|
||||||
|
|
||||||
# Email libraries
|
# Email libraries
|
||||||
lettre = { version = "0.10.0-alpha.3", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname"], default-features = false }
|
lettre = { version = "0.10.0-alpha.4", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname", "tracing"], default-features = false }
|
||||||
newline-converter = "0.1.0"
|
newline-converter = "0.1.0"
|
||||||
|
|
||||||
# Template library
|
# Template library
|
||||||
|
|
|
@ -413,29 +413,35 @@ make_config! {
|
||||||
/// SMTP Email Settings
|
/// SMTP Email Settings
|
||||||
smtp: _enable_smtp {
|
smtp: _enable_smtp {
|
||||||
/// Enabled
|
/// Enabled
|
||||||
_enable_smtp: bool, true, def, true;
|
_enable_smtp: bool, true, def, true;
|
||||||
/// Host
|
/// 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)
|
/// 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)
|
/// 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
|
/// 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
|
/// From Address
|
||||||
smtp_from: String, true, def, String::new();
|
smtp_from: String, true, def, String::new();
|
||||||
/// From Name
|
/// From Name
|
||||||
smtp_from_name: String, true, def, "Bitwarden_RS".to_string();
|
smtp_from_name: String, true, def, "Bitwarden_RS".to_string();
|
||||||
/// Username
|
/// Username
|
||||||
smtp_username: String, true, option;
|
smtp_username: String, true, option;
|
||||||
/// Password
|
/// 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 |> 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 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
|
/// 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
|
/// Email 2FA Settings
|
||||||
|
|
41
src/mail.rs
41
src/mail.rs
|
@ -7,6 +7,7 @@ use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||||
use lettre::{
|
use lettre::{
|
||||||
message::{header, Mailbox, Message, MultiPart, SinglePart},
|
message::{header, Mailbox, Message, MultiPart, SinglePart},
|
||||||
transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism},
|
transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism},
|
||||||
|
transport::smtp::client::{Tls, TlsParameters},
|
||||||
transport::smtp::extension::ClientId,
|
transport::smtp::extension::ClientId,
|
||||||
Address, SmtpTransport, Transport,
|
Address, SmtpTransport, Transport,
|
||||||
};
|
};
|
||||||
|
@ -22,21 +23,30 @@ fn mailer() -> SmtpTransport {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
let host = CONFIG.smtp_host().unwrap();
|
let host = CONFIG.smtp_host().unwrap();
|
||||||
|
|
||||||
// Determine security
|
let smtp_client = SmtpTransport::builder_dangerous(host.as_str())
|
||||||
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()
|
|
||||||
.port(CONFIG.smtp_port())
|
.port(CONFIG.smtp_port())
|
||||||
.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())));
|
.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()) {
|
let smtp_client = match (CONFIG.smtp_username(), CONFIG.smtp_password()) {
|
||||||
(Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user, pass)),
|
(Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user, pass)),
|
||||||
_ => smtp_client,
|
_ => 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.
|
// The boundary generated by Lettre it self is mostly too large based on the RFC822, so we generate one our selfs.
|
||||||
use uuid::Uuid;
|
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 alternative = MultiPart::alternative().boundary(boundary).singlepart(text).singlepart(html);
|
||||||
|
let smtp_from = &CONFIG.smtp_from();
|
||||||
|
|
||||||
let email = Message::builder()
|
let email = Message::builder()
|
||||||
|
.message_id(Some(format!("<{}.{}>", unique_id, smtp_from)))
|
||||||
.to(Mailbox::new(None, Address::from_str(&address)?))
|
.to(Mailbox::new(None, Address::from_str(&address)?))
|
||||||
.from(Mailbox::new(
|
.from(Mailbox::new(
|
||||||
Some(CONFIG.smtp_from_name()),
|
Some(CONFIG.smtp_from_name()),
|
||||||
Address::from_str(&CONFIG.smtp_from())?,
|
Address::from_str(smtp_from)?,
|
||||||
))
|
))
|
||||||
.subject(subject)
|
.subject(subject)
|
||||||
.multipart(alternative)?;
|
.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)
|
.level_for("rocket::fairing", log::LevelFilter::Off)
|
||||||
.chain(std::io::stdout());
|
.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() {
|
if CONFIG.extended_logging() {
|
||||||
logger = logger.format(|out, message, record| {
|
logger = logger.format(|out, message, record| {
|
||||||
out.finish(format_args!(
|
out.finish(format_args!(
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<div id="g_{{group}}" class="card-body collapse" data-parent="#config-form">
|
<div id="g_{{group}}" class="card-body collapse" data-parent="#config-form">
|
||||||
{{#each elements}}
|
{{#each elements}}
|
||||||
{{#if editable}}
|
{{#if editable}}
|
||||||
<div class="form-group row" title="[{{name}}] {{doc.description}}">
|
<div class="form-group row align-items-center" title="[{{name}}] {{doc.description}}">
|
||||||
{{#case type "text" "number" "password"}}
|
{{#case type "text" "number" "password"}}
|
||||||
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
|
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
|
||||||
<div class="col-sm-8 input-group">
|
<div class="col-sm-8 input-group">
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{/case}}
|
{{/case}}
|
||||||
{{#case type "checkbox"}}
|
{{#case type "checkbox"}}
|
||||||
<div class="col-sm-3">{{doc.name}}</div>
|
<div class="col-sm-3 col-form-label">{{doc.name}}</div>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input conf-{{type}}" type="checkbox" id="input_{{name}}"
|
<input class="form-check-input conf-{{type}}" type="checkbox" id="input_{{name}}"
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#case group "smtp"}}
|
{{#case group "smtp"}}
|
||||||
<div class="form-group row pt-3 border-top" title="Send a test email to given email address">
|
<div class="form-group row align-items-center pt-3 border-top" title="Send a test email to given email address">
|
||||||
<label for="smtp-test-email" class="col-sm-3 col-form-label">Test SMTP</label>
|
<label for="smtp-test-email" class="col-sm-3 col-form-label">Test SMTP</label>
|
||||||
<div class="col-sm-8 input-group">
|
<div class="col-sm-8 input-group">
|
||||||
<input class="form-control" id="smtp-test-email" type="email" placeholder="Enter test email">
|
<input class="form-control" id="smtp-test-email" type="email" placeholder="Enter test email">
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
{{#each config}}
|
{{#each config}}
|
||||||
{{#each elements}}
|
{{#each elements}}
|
||||||
{{#unless editable}}
|
{{#unless editable}}
|
||||||
<div class="form-group row" title="[{{name}}] {{doc.description}}">
|
<div class="form-group row align-items-center" title="[{{name}}] {{doc.description}}">
|
||||||
{{#case type "text" "number" "password"}}
|
{{#case type "text" "number" "password"}}
|
||||||
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
|
<label for="input_{{name}}" class="col-sm-3 col-form-label">{{doc.name}}</label>
|
||||||
<div class="col-sm-8 input-group">
|
<div class="col-sm-8 input-group">
|
||||||
|
@ -92,9 +92,9 @@
|
||||||
</div>
|
</div>
|
||||||
{{/case}}
|
{{/case}}
|
||||||
{{#case type "checkbox"}}
|
{{#case type "checkbox"}}
|
||||||
<div class="col-sm-3">{{doc.name}}</div>
|
<div class="col-sm-3 col-form-label">{{doc.name}}</div>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<div class="form-check">
|
<div class="form-check align-middle">
|
||||||
<input disabled class="form-check-input" type="checkbox" id="input_{{name}}"
|
<input disabled class="form-check-input" type="checkbox" id="input_{{name}}"
|
||||||
{{#if value}} checked {{/if}}>
|
{{#if value}} checked {{/if}}>
|
||||||
|
|
||||||
|
@ -139,6 +139,10 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function smtpTest() {
|
function smtpTest() {
|
||||||
|
if (formHasChanges(config_form)) {
|
||||||
|
alert("Config has been changed but not yet saved.\nPlease save the changes first before sending a test email.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
test_email = document.getElementById("smtp-test-email");
|
test_email = document.getElementById("smtp-test-email");
|
||||||
data = JSON.stringify({ "email": test_email.value });
|
data = JSON.stringify({ "email": test_email.value });
|
||||||
_post("{{urlpath}}/admin/test/smtp/",
|
_post("{{urlpath}}/admin/test/smtp/",
|
||||||
|
@ -205,4 +209,35 @@
|
||||||
// {{#each config}} {{#if grouptoggle}}
|
// {{#each config}} {{#if grouptoggle}}
|
||||||
masterCheck("input_{{grouptoggle}}", "#g_{{group}} input");
|
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
|
||||||
|
function initChangeDetection(form) {
|
||||||
|
const ignore_fields = ["smtp-test-email"];
|
||||||
|
Array.from(form).forEach((el) => {
|
||||||
|
if (! ignore_fields.includes(el.id)) {
|
||||||
|
el.dataset.origValue = el.value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function formHasChanges(form) {
|
||||||
|
return Array.from(form).some(el => 'origValue' in el.dataset && ( el.dataset.origValue !== el.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger Form Change Detection
|
||||||
|
const config_form = document.getElementById('config-form');
|
||||||
|
initChangeDetection(config_form);
|
||||||
|
|
||||||
|
// Colorize some settings which are high risk
|
||||||
|
const risk_items = document.getElementsByClassName('col-form-label');
|
||||||
|
function colorRiskSettings(risk_el) {
|
||||||
|
Array.from(risk_el).forEach((el) => {
|
||||||
|
if (el.innerText.toLowerCase().includes('risks') ) {
|
||||||
|
el.parentElement.className += ' alert-danger'
|
||||||
|
console.log(el)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
colorRiskSettings(risk_items);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
Your Email Change
|
Your Email Change
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
To finalize changing your email address enter the following code in web vault: {{token}}
|
||||||
<p>To finalize changing your email address enter the following code in web vault: <b>{{token}}</b></p>
|
|
||||||
<p>If you did not try to change an email address, you can safely ignore this email.</p>
|
If you did not try to change an email address, you can safely ignore this email.
|
||||||
</html>
|
|
||||||
|
===
|
||||||
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
Delete Your Account
|
Delete Your Account
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
Click the link below to delete your account.
|
||||||
<p>
|
|
||||||
click the link below to delete your account.
|
Delete Your Account: {{url}}/#/verify-recover-delete?userId={{user_id}}&token={{token}}&email={{email}}
|
||||||
<br>
|
|
||||||
<br>
|
If you did not request this email to delete your account, you can safely ignore this email.
|
||||||
<a href="{{url}}/#/verify-recover-delete?userId={{user_id}}&token={{token}}&email={{email}}">
|
|
||||||
Delete Your Account</a>
|
===
|
||||||
</p>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
<p>If you did not request this email to delete your account, you can safely ignore this email.</p>
|
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
Invitation to {{{org_name}}} accepted
|
Invitation to {{{org_name}}} accepted
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
Your invitation for *{{email}}* to join *{{org_name}}* was accepted.
|
||||||
<p>
|
Please log in via {{url}} to the bitwarden_rs server and confirm them from the organization management page.
|
||||||
Your invitation for <b>{{email}}</b> to join <b>{{org_name}}</b> was accepted.
|
|
||||||
Please <a href="{{url}}/">log in</a> to the bitwarden_rs server and confirm them from the organization management page.
|
===
|
||||||
</p>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
Invitation to {{{org_name}}} confirmed
|
Invitation to {{{org_name}}} confirmed
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
Your invitation to join *{{org_name}}* was confirmed.
|
||||||
<p>
|
It will now appear under the Organizations the next time you log in to the web vault at {{url}}.
|
||||||
Your invitation to join <b>{{org_name}}</b> was confirmed.
|
|
||||||
It will now appear under the Organizations the next time you <a href="{{url}}/">log in</a> to the web vault.
|
===
|
||||||
</p>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
New Device Logged In From {{{device}}}
|
New Device Logged In From {{{device}}}
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
Your account was just logged into from a new device.
|
||||||
<p>
|
|
||||||
Your account was just logged into from a new device.
|
|
||||||
|
|
||||||
Date: {{datetime}}
|
* Date: {{datetime}}
|
||||||
IP Address: {{ip}}
|
* IP Address: {{ip}}
|
||||||
Device Type: {{device}}
|
* Device Type: {{device}}
|
||||||
|
|
||||||
You can deauthorize all devices that have access to your account from the
|
You can deauthorize all devices that have access to your account from the web vault ( {{url}} ) under Settings > My Account > Deauthorize Sessions.
|
||||||
<a href="{{url}}/">web vault</a> under Settings > My Account > Deauthorize Sessions.
|
|
||||||
</p>
|
===
|
||||||
</html>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -2,6 +2,9 @@ Your master password hint
|
||||||
<!---------------->
|
<!---------------->
|
||||||
You (or someone) recently requested your master password hint. Unfortunately, your account does not have a master password hint.
|
You (or someone) recently requested your master password hint. Unfortunately, your account does not have a master password hint.
|
||||||
|
|
||||||
If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to <a href="{{url}}/#/recover-delete">delete the account</a> so that you can register again and start over. All data associated with your account will be deleted.
|
If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to delete the account ( {{url}}/#/recover-delete ) so that you can register again and start over. All data associated with your account will be deleted.
|
||||||
|
|
||||||
If you did not request your master password hint you can safely ignore this email.
|
If you did not request your master password hint you can safely ignore this email.
|
||||||
|
|
||||||
|
===
|
||||||
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -2,9 +2,12 @@ Your master password hint
|
||||||
<!---------------->
|
<!---------------->
|
||||||
You (or someone) recently requested your master password hint.
|
You (or someone) recently requested your master password hint.
|
||||||
|
|
||||||
Your hint is: "{{hint}}"
|
Your hint is: *{{hint}}*
|
||||||
Log in: <a href="{{url}}/">Web Vault</a>
|
Log in to the web vault: {{url}}
|
||||||
|
|
||||||
If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to <a href="{{url}}/#/recover-delete">delete the account</a> so that you can register again and start over. All data associated with your account will be deleted.
|
If you cannot remember your master password, there is no way to recover your data. The only option to gain access to your account again is to delete the account ( {{url}}/#/recover-delete ) so that you can register again and start over. All data associated with your account will be deleted.
|
||||||
|
|
||||||
If you did not request your master password hint you can safely ignore this email.
|
If you did not request your master password hint you can safely ignore this email.
|
||||||
|
|
||||||
|
===
|
||||||
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
Join {{{org_name}}}
|
Join {{{org_name}}}
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
You have been invited to join the *{{org_name}}* organization.
|
||||||
<p>
|
|
||||||
You have been invited to join the <b>{{org_name}}</b> organization.
|
|
||||||
<br>
|
Click here to join: {{url}}/#/accept-organization/?organizationId={{org_id}}&organizationUserId={{org_user_id}}&email={{email}}&organizationName={{org_name}}&token={{token}}
|
||||||
<br>
|
|
||||||
<a href="{{url}}/#/accept-organization/?organizationId={{org_id}}&organizationUserId={{org_user_id}}&email={{email}}&organizationName={{org_name}}&token={{token}}">
|
|
||||||
Click here to join</a>
|
If you do not wish to join this organization, you can safely ignore this email.
|
||||||
</p>
|
|
||||||
<p>If you do not wish to join this organization, you can safely ignore this email.</p>
|
===
|
||||||
</html>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Bitwarden_rs SMTP Test
|
Bitwarden_rs SMTP Test
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
This is a test email to verify the SMTP configuration for {{url}}.
|
||||||
<p>
|
|
||||||
This is a test email to verify the SMTP configuration for <a href="{{url}}">{{url}}</a>.
|
When you can read this email it is probably configured correctly.
|
||||||
</p>
|
|
||||||
<p>When you can read this email it is probably configured correctly.</p>
|
===
|
||||||
</html>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
Your Two-step Login Verification Code
|
Your Two-step Login Verification Code
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
Your two-step verification code is: {{token}}
|
||||||
<p>
|
|
||||||
Your two-step verification code is: <b>{{token}}</b>
|
|
||||||
|
|
||||||
Use this code to complete logging in with Bitwarden.
|
Use this code to complete logging in with Bitwarden.
|
||||||
</p>
|
|
||||||
</html>
|
===
|
||||||
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
Verify Your Email
|
Verify Your Email
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
|
||||||
<p>
|
|
||||||
Verify this email address for your account by clicking the link below.
|
Verify this email address for your account by clicking the link below.
|
||||||
<br>
|
|
||||||
<br>
|
Verify Email Address Now: {{url}}/#/verify-email/?userId={{user_id}}&token={{token}}
|
||||||
<a href="{{url}}/#/verify-email/?userId={{user_id}}&token={{token}}">
|
|
||||||
Verify Email Address Now</a>
|
If you did not request to verify your account, you can safely ignore this email.
|
||||||
</p>
|
|
||||||
<p>If you did not request to verify your account, you can safely ignore this email.</p>
|
===
|
||||||
</html>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Welcome
|
Welcome
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
Thank you for creating an account at {{url}}. You may now log in with your new account.
|
||||||
<p>
|
|
||||||
Thank you for creating an account at <a href="{{url}}/">{{url}}</a>. You may now log in with your new account.
|
If you did not request to create an account, you can safely ignore this email.
|
||||||
</p>
|
|
||||||
<p>If you did not request to create an account, you can safely ignore this email.</p>
|
===
|
||||||
</html>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
Welcome
|
Welcome
|
||||||
<!---------------->
|
<!---------------->
|
||||||
<html>
|
Thank you for creating an account at {{url}}. Before you can login with your new account, you must verify this email address by clicking the link below.
|
||||||
<p>
|
|
||||||
Thank you for creating an account at <a href="{{url}}/">{{url}}</a>. Before you can login with your new account, you must verify this email address by clicking the link below.
|
Verify Email Address Now: {{url}}/#/verify-email/?userId={{user_id}}&token={{token}}
|
||||||
<br>
|
|
||||||
<br>
|
If you did not request to create an account, you can safely ignore this email.
|
||||||
<a href="{{url}}/#/verify-email/?userId={{user_id}}&token={{token}}">
|
|
||||||
Verify Email Address Now</a>
|
===
|
||||||
</p>
|
Github: https://github.com/dani-garcia/bitwarden_rs
|
||||||
<p>If you did not request to create an account, you can safely ignore this email.</p>
|
|
||||||
</html>
|
|
||||||
|
|
Loading…
Reference in New Issue