mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-03-05 05:19:25 +00:00
Updated lettre (and other crates) and workflow.
General: - Updated several dependancies Lettre: - Updateded lettere and the workflow - Changed encoding to base64 - Convert unix newlines to dos newlines for e-mails. - Created custom e-mail boundary (auto generated could cause errors) Tested the e-mails sent using several clients (Linux, Windows, MacOS, Web). Run msglint (https://tools.ietf.org/tools/msglint/) on the generated e-mails until all errors were gone. Lettre has changed quite some stuff compared between alpha.1 and alpha.2, i haven't noticed any issues sending e-mails during my tests.
This commit is contained in:
Generated
+98
-119
File diff suppressed because it is too large
Load Diff
+13
-13
@@ -18,7 +18,7 @@ postgresql = ["diesel/postgres", "diesel_migrations/postgres"]
|
||||
sqlite = ["diesel/sqlite", "diesel_migrations/sqlite", "libsqlite3-sys"]
|
||||
|
||||
# Enable unstable features, requires nightly
|
||||
# Currently only used to enable rusts official ip support
|
||||
# Currently only used to enable rusts official ip support
|
||||
unstable = []
|
||||
|
||||
[target."cfg(not(windows))".dependencies]
|
||||
@@ -30,7 +30,7 @@ rocket = { version = "0.5.0-dev", features = ["tls"], default-features = false }
|
||||
rocket_contrib = "0.5.0-dev"
|
||||
|
||||
# HTTP client
|
||||
reqwest = { version = "0.10.7", features = ["blocking", "json"] }
|
||||
reqwest = { version = "0.10.8", features = ["blocking", "json"] }
|
||||
|
||||
# multipart/form-data support
|
||||
multipart = { version = "0.17.0", features = ["server"], default-features = false }
|
||||
@@ -45,8 +45,8 @@ rmpv = "0.4.5"
|
||||
chashmap = "2.2.2"
|
||||
|
||||
# A generic serialization/deserialization framework
|
||||
serde = "1.0.115"
|
||||
serde_derive = "1.0.115"
|
||||
serde = "1.0.116"
|
||||
serde_derive = "1.0.116"
|
||||
serde_json = "1.0.57"
|
||||
|
||||
# Logging
|
||||
@@ -68,9 +68,9 @@ ring = "0.16.15"
|
||||
uuid = { version = "0.8.1", features = ["v4"] }
|
||||
|
||||
# Date and time libraries
|
||||
chrono = "0.4.13"
|
||||
chrono-tz = "0.5.2"
|
||||
time = "0.2.16"
|
||||
chrono = "0.4.15"
|
||||
chrono-tz = "0.5.3"
|
||||
time = "0.2.18"
|
||||
|
||||
# TOTP library
|
||||
oath = "0.10.2"
|
||||
@@ -91,18 +91,18 @@ yubico = { version = "0.9.1", features = ["online-tokio"], default-features = fa
|
||||
dotenv = { version = "0.15.0", default-features = false }
|
||||
|
||||
# Lazy initialization
|
||||
once_cell = "1.4.0"
|
||||
once_cell = "1.4.1"
|
||||
|
||||
# Numerical libraries
|
||||
num-traits = "0.2.12"
|
||||
num-derive = "0.3.1"
|
||||
num-derive = "0.3.2"
|
||||
|
||||
# Email libraries
|
||||
lettre = { version = "0.10.0-alpha.1", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname"], default-features = false }
|
||||
native-tls = "0.2.4"
|
||||
lettre = { version = "0.10.0-alpha.2", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname"], default-features = false }
|
||||
newline-converter = "0.1.0"
|
||||
|
||||
# Template library
|
||||
handlebars = { version = "3.3.0", features = ["dir_source"] }
|
||||
handlebars = { version = "3.4.0", features = ["dir_source"] }
|
||||
|
||||
# For favicon extraction from main website
|
||||
soup = "0.5.0"
|
||||
@@ -118,7 +118,7 @@ percent-encoding = "2.1.0"
|
||||
idna = "0.2.0"
|
||||
|
||||
# CLI argument parsing
|
||||
structopt = "0.3.16"
|
||||
structopt = "0.3.17"
|
||||
|
||||
# Logging panics to logfile instead stderr only
|
||||
backtrace = "0.3.50"
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ use yubico::yubicoerror::YubicoError as YubiErr;
|
||||
use lettre::address::AddressError as AddrErr;
|
||||
use lettre::error::Error as LettreErr;
|
||||
use lettre::message::mime::FromStrError as FromStrErr;
|
||||
use lettre::transport::smtp::error::Error as SmtpErr;
|
||||
use lettre::transport::smtp::Error as SmtpErr;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Empty {}
|
||||
|
||||
+27
-39
@@ -2,14 +2,13 @@ use std::{env, str::FromStr};
|
||||
|
||||
use chrono::{DateTime, Local};
|
||||
use chrono_tz::Tz;
|
||||
use native_tls::{Protocol, TlsConnector};
|
||||
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
|
||||
|
||||
use lettre::{
|
||||
message::{header, Mailbox, Message, MultiPart, SinglePart},
|
||||
transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism},
|
||||
transport::smtp::extension::ClientId,
|
||||
Address, SmtpTransport, Tls, TlsParameters, Transport,
|
||||
Address, SmtpTransport, Transport,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -20,28 +19,23 @@ use crate::{
|
||||
};
|
||||
|
||||
fn mailer() -> SmtpTransport {
|
||||
use std::time::Duration;
|
||||
let host = CONFIG.smtp_host().unwrap();
|
||||
|
||||
let client_security = if CONFIG.smtp_ssl() {
|
||||
let tls = TlsConnector::builder()
|
||||
.min_protocol_version(Some(Protocol::Tlsv11))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let params = TlsParameters::new(host.clone(), tls);
|
||||
|
||||
// Determine security
|
||||
let smtp_client = if CONFIG.smtp_ssl() {
|
||||
if CONFIG.smtp_explicit_tls() {
|
||||
Tls::Wrapper(params)
|
||||
SmtpTransport::relay(host.as_str())
|
||||
} else {
|
||||
Tls::Required(params)
|
||||
SmtpTransport::starttls_relay(host.as_str())
|
||||
}
|
||||
} else {
|
||||
Tls::None
|
||||
Ok(SmtpTransport::builder_dangerous(host.as_str()))
|
||||
};
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
let smtp_client = SmtpTransport::builder(host).port(CONFIG.smtp_port()).tls(client_security);
|
||||
let smtp_client = smtp_client.unwrap()
|
||||
.port(CONFIG.smtp_port())
|
||||
.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())));
|
||||
|
||||
let smtp_client = match (CONFIG.smtp_username(), CONFIG.smtp_password()) {
|
||||
(Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user, pass)),
|
||||
@@ -49,7 +43,7 @@ fn mailer() -> SmtpTransport {
|
||||
};
|
||||
|
||||
let smtp_client = match CONFIG.helo_name() {
|
||||
Some(helo_name) => smtp_client.hello_name(ClientId::new(helo_name)),
|
||||
Some(helo_name) => smtp_client.hello_name(ClientId::Domain(helo_name)),
|
||||
None => smtp_client,
|
||||
};
|
||||
|
||||
@@ -66,7 +60,7 @@ fn mailer() -> SmtpTransport {
|
||||
_ => smtp_client,
|
||||
};
|
||||
|
||||
smtp_client.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout()))).build()
|
||||
smtp_client.build()
|
||||
}
|
||||
|
||||
fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> {
|
||||
@@ -84,8 +78,9 @@ fn get_template(template_name: &str, data: &serde_json::Value) -> Result<(String
|
||||
None => err!("Template doesn't contain subject"),
|
||||
};
|
||||
|
||||
use newline_converter::unix2dos;
|
||||
let body = match text_split.next() {
|
||||
Some(s) => s.trim().to_string(),
|
||||
Some(s) => unix2dos(s.trim()).to_string(),
|
||||
None => err!("Template doesn't contain body"),
|
||||
};
|
||||
|
||||
@@ -303,25 +298,18 @@ fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) ->
|
||||
|
||||
let address = format!("{}@{}", address_split[1], domain_puny);
|
||||
|
||||
let data = MultiPart::mixed()
|
||||
.multipart(
|
||||
MultiPart::alternative()
|
||||
.singlepart(
|
||||
SinglePart::quoted_printable()
|
||||
.header(header::ContentType("text/plain; charset=utf-8".parse()?))
|
||||
.body(body_text),
|
||||
)
|
||||
.multipart(
|
||||
MultiPart::related().singlepart(
|
||||
SinglePart::quoted_printable()
|
||||
.header(header::ContentType("text/html; charset=utf-8".parse()?))
|
||||
.body(body_html),
|
||||
)
|
||||
// .singlepart(SinglePart::base64() -- Inline files would go here
|
||||
),
|
||||
)
|
||||
// .singlepart(SinglePart::base64() -- Attachments would go here
|
||||
;
|
||||
let html = SinglePart::base64()
|
||||
.header(header::ContentType("text/html; charset=utf-8".parse()?))
|
||||
.body(body_html);
|
||||
|
||||
let text = SinglePart::base64()
|
||||
.header(header::ContentType("text/plain; charset=utf-8".parse()?))
|
||||
.body(body_text);
|
||||
|
||||
// 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 alternative = MultiPart::alternative().boundary(boundary).singlepart(text).singlepart(html);
|
||||
|
||||
let email = Message::builder()
|
||||
.to(Mailbox::new(None, Address::from_str(&address)?))
|
||||
@@ -330,7 +318,7 @@ fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) ->
|
||||
Address::from_str(&CONFIG.smtp_from())?,
|
||||
))
|
||||
.subject(subject)
|
||||
.multipart(data)?;
|
||||
.multipart(alternative)?;
|
||||
|
||||
let _ = mailer().send(&email)?;
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user