mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-09-10 10:45:57 +03: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:
@@ -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 {}
|
||||
|
66
src/mail.rs
66
src/mail.rs
@@ -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