Update lettre to latest master

pull/987/head
Daniel García 5 years ago
parent 9cca64003a
commit 63cbd9ef9c
No known key found for this signature in database
GPG Key ID: FC8A7D14C3CD543A

175
Cargo.lock generated

@ -27,12 +27,6 @@ dependencies = [
"nodrop", "nodrop",
] ]
[[package]]
name = "ascii_utils"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -109,6 +103,12 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
[[package]]
name = "base64"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
[[package]] [[package]]
name = "binascii" name = "binascii"
version = "0.1.4" version = "0.1.4"
@ -148,7 +148,6 @@ dependencies = [
"once_cell", "once_cell",
"openssl", "openssl",
"percent-encoding 2.1.0", "percent-encoding 2.1.0",
"quoted_printable",
"regex", "regex",
"reqwest", "reqwest",
"ring", "ring",
@ -482,85 +481,6 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
[[package]]
name = "email"
version = "0.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91549a51bb0241165f13d57fc4c72cef063b4088fb078b019ecbf464a45f22e4"
dependencies = [
"base64 0.9.3",
"chrono",
"encoding",
"lazy_static",
"rand 0.4.6",
"time 0.1.43",
"version_check 0.1.5",
]
[[package]]
name = "encoding"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
dependencies = [
"encoding-index-japanese",
"encoding-index-korean",
"encoding-index-simpchinese",
"encoding-index-singlebyte",
"encoding-index-tradchinese",
]
[[package]]
name = "encoding-index-japanese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-korean"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-simpchinese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-singlebyte"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-tradchinese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding_index_tests"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.22" version = "0.8.22"
@ -585,15 +505,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fast_chemail"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "495a39d30d624c2caabe6312bfead73e7717692b44e0b32df168c275a2e8e9e4"
dependencies = [
"ascii_utils",
]
[[package]] [[package]]
name = "fern" name = "fern"
version = "0.6.0" version = "0.6.0"
@ -888,17 +799,6 @@ dependencies = [
"digest 0.8.1", "digest 0.8.1",
] ]
[[package]]
name = "hostname"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867"
dependencies = [
"libc",
"match_cfg",
"winapi 0.3.8",
]
[[package]] [[package]]
name = "html5ever" name = "html5ever"
version = "0.22.5" version = "0.22.5"
@ -1008,6 +908,24 @@ dependencies = [
"tokio-tls", "tokio-tls",
] ]
[[package]]
name = "hyperx"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81d7ed6ec7d25c4de28b999a5693f14609a8b756137b1b4cb4927d119f59ef25"
dependencies = [
"base64 0.11.0",
"bytes 0.5.4",
"http",
"httparse",
"language-tags",
"log 0.4.8",
"mime 0.3.16",
"percent-encoding 2.1.0",
"time 0.1.43",
"unicase 2.6.0",
]
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.1.5" version = "0.1.5"
@ -1128,20 +1046,21 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
[[package]] [[package]]
name = "lettre" name = "lettre"
version = "0.10.0-pre" version = "0.10.0-pre"
source = "git+https://github.com/lettre/lettre?rev=245c600c82ee18b766e8729f005ff453a55dce34#245c600c82ee18b766e8729f005ff453a55dce34" source = "git+https://github.com/lettre/lettre?rev=88df2a502d537ebfdd4218fb6b9f4168fb0f7943#88df2a502d537ebfdd4218fb6b9f4168fb0f7943"
dependencies = [ dependencies = [
"base64 0.11.0", "base64 0.12.0",
"bufstream", "bufstream",
"email", "hyperx",
"fast_chemail", "idna 0.2.0",
"hostname", "line-wrap",
"log 0.4.8",
"mime 0.3.16", "mime 0.3.16",
"native-tls", "native-tls",
"nom", "nom",
"once_cell",
"quoted_printable",
"regex",
"serde", "serde",
"serde_json", "textnonce",
"time 0.2.14",
"uuid", "uuid",
] ]
@ -1175,6 +1094,15 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "line-wrap"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
dependencies = [
"safemem",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.3.4" version = "0.3.4"
@ -1230,12 +1158,6 @@ dependencies = [
"tendril", "tendril",
] ]
[[package]]
name = "match_cfg"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]] [[package]]
name = "matches" name = "matches"
version = "0.1.8" version = "0.1.8"
@ -2725,6 +2647,19 @@ dependencies = [
"utf-8", "utf-8",
] ]
[[package]]
name = "textnonce"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acc659075a12c12c07bbb384862c352506707f6597f5b495f65427d08519b617"
dependencies = [
"base64 0.12.0",
"byteorder",
"chrono",
"rand 0.7.3",
"serde",
]
[[package]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.11.0" version = "0.11.0"

@ -92,9 +92,8 @@ num-traits = "0.2.11"
num-derive = "0.3.0" num-derive = "0.3.0"
# Email libraries # Email libraries
lettre = "0.10.0-pre" lettre = { version = "0.10.0-pre", features = ["smtp-transport", "builder", "serde", "native-tls"], default-features = false }
native-tls = "0.2.4" native-tls = "0.2.4"
quoted_printable = "0.4.2"
# Template library # Template library
handlebars = { version = "3.0.1", features = ["dir_source"] } handlebars = { version = "3.0.1", features = ["dir_source"] }
@ -124,7 +123,7 @@ rocket = { git = 'https://github.com/SergioBenitez/Rocket', rev = '1010f6a2a88fa
rocket_contrib = { git = 'https://github.com/SergioBenitez/Rocket', rev = '1010f6a2a88fac899dec0cd2f642156908038a53' } rocket_contrib = { git = 'https://github.com/SergioBenitez/Rocket', rev = '1010f6a2a88fac899dec0cd2f642156908038a53' }
# Use git version for timeout fix #706 # Use git version for timeout fix #706
lettre = { git = 'https://github.com/lettre/lettre', rev = '245c600c82ee18b766e8729f005ff453a55dce34' } lettre = { git = 'https://github.com/lettre/lettre', rev = '88df2a502d537ebfdd4218fb6b9f4168fb0f7943' }
# For favicon extraction from main website # For favicon extraction from main website
data-url = { git = 'https://github.com/servo/rust-url', package="data-url", rev = '7f1bd6ce1c2fde599a757302a843a60e714c5f72' } data-url = { git = 'https://github.com/servo/rust-url', package="data-url", rev = '7f1bd6ce1c2fde599a757302a843a60e714c5f72' }

@ -45,7 +45,9 @@ use std::option::NoneError as NoneErr;
use std::time::SystemTimeError as TimeErr; use std::time::SystemTimeError as TimeErr;
use u2f::u2ferror::U2fError as U2fErr; use u2f::u2ferror::U2fError as U2fErr;
use yubico::yubicoerror::YubicoError as YubiErr; use yubico::yubicoerror::YubicoError as YubiErr;
use lettre::smtp::error::Error as LettreErr; use lettre::error::Error as LettreErr;
use lettre::address::AddressError as AddrErr;
use lettre::transport::smtp::error::Error as SmtpErr;
#[derive(Serialize)] #[derive(Serialize)]
pub struct Empty {} pub struct Empty {}
@ -73,7 +75,9 @@ make_error! {
ReqError(ReqErr): _has_source, _api_error, ReqError(ReqErr): _has_source, _api_error,
RegexError(RegexErr): _has_source, _api_error, RegexError(RegexErr): _has_source, _api_error,
YubiError(YubiErr): _has_source, _api_error, YubiError(YubiErr): _has_source, _api_error,
LetreErr(LettreErr): _has_source, _api_error, LetreError(LettreErr):_has_source, _api_error,
AddressError(AddrErr):_has_source, _api_error,
SmtpError(SmtpErr): _has_source, _api_error,
} }
// This is implemented by hand because NoneError doesn't implement neither Display nor Error // This is implemented by hand because NoneError doesn't implement neither Display nor Error

@ -1,13 +1,11 @@
use lettre::smtp::authentication::Credentials; use std::str::FromStr;
use lettre::smtp::authentication::Mechanism as SmtpAuthMechanism;
use lettre::smtp::ConnectionReuseParameters; use lettre::message::{header, Mailbox, Message, MultiPart, SinglePart};
use lettre::{ use lettre::transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism};
builder::{EmailBuilder, MimeMultipartType, PartBuilder}, use lettre::{Address, SmtpTransport, Tls, TlsParameters, Transport};
ClientSecurity, ClientTlsParameters, SmtpClient, SmtpTransport, Transport,
};
use native_tls::{Protocol, TlsConnector}; use native_tls::{Protocol, TlsConnector};
use percent_encoding::{percent_encode, NON_ALPHANUMERIC}; use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
use quoted_printable::encode_to_str;
use crate::api::EmptyResult; use crate::api::EmptyResult;
use crate::auth::{encode_jwt, generate_delete_claims, generate_invite_claims, generate_verify_email_claims}; use crate::auth::{encode_jwt, generate_delete_claims, generate_invite_claims, generate_verify_email_claims};
@ -24,23 +22,23 @@ fn mailer() -> SmtpTransport {
.build() .build()
.unwrap(); .unwrap();
let params = ClientTlsParameters::new(host.clone(), tls); let params = TlsParameters::new(host.clone(), tls);
if CONFIG.smtp_explicit_tls() { if CONFIG.smtp_explicit_tls() {
ClientSecurity::Wrapper(params) Tls::Wrapper(params)
} else { } else {
ClientSecurity::Required(params) Tls::Required(params)
} }
} else { } else {
ClientSecurity::None Tls::None
}; };
use std::time::Duration; use std::time::Duration;
let smtp_client = SmtpClient::new((host.as_str(), CONFIG.smtp_port()), client_security).unwrap(); let smtp_client = SmtpTransport::new(host).port(CONFIG.smtp_port()).tls(client_security);
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.clone(), pass.clone())), (Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user, pass)),
_ => smtp_client, _ => smtp_client,
}; };
@ -48,19 +46,16 @@ fn mailer() -> SmtpTransport {
Some(mechanism) => { Some(mechanism) => {
let correct_mechanism = format!("\"{}\"", crate::util::upcase_first(mechanism.trim_matches('"'))); let correct_mechanism = format!("\"{}\"", crate::util::upcase_first(mechanism.trim_matches('"')));
// TODO: Allow more than one mechanism
match serde_json::from_str::<SmtpAuthMechanism>(&correct_mechanism) { match serde_json::from_str::<SmtpAuthMechanism>(&correct_mechanism) {
Ok(auth_mechanism) => smtp_client.authentication_mechanism(auth_mechanism), Ok(auth_mechanism) => smtp_client.authentication(vec![auth_mechanism]),
_ => panic!("Failure to parse mechanism. Is it proper Json? Eg. `\"Plain\"` not `Plain`"), _ => panic!("Failure to parse mechanism. Is it proper Json? Eg. `\"Plain\"` not `Plain`"),
} }
} }
_ => smtp_client, _ => smtp_client,
}; };
smtp_client smtp_client.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())))
.smtp_utf8(true)
.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())))
.connection_reuse(ConnectionReuseParameters::NoReuse)
.transport()
} }
fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> { fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String, String), Error> {
@ -283,38 +278,28 @@ fn send_email(address: &str, subject: &str, body_html: &str, body_text: &str) ->
let address = format!("{}@{}", address_split[1], domain_puny); let address = format!("{}@{}", address_split[1], domain_puny);
let html = PartBuilder::new() let html = SinglePart::builder()
.body(encode_to_str(body_html)) .header(header::ContentType("text/html; charset=utf-8".parse().unwrap()))
.header(("Content-Type", "text/html; charset=utf-8")) .header(header::ContentTransferEncoding::QuotedPrintable)
.header(("Content-Transfer-Encoding", "quoted-printable")) .body(body_html);
.build();
let text = PartBuilder::new()
.body(encode_to_str(body_text))
.header(("Content-Type", "text/plain; charset=utf-8"))
.header(("Content-Transfer-Encoding", "quoted-printable"))
.build();
let alternative = PartBuilder::new()
.message_type(MimeMultipartType::Alternative)
.child(text)
.child(html);
let email = EmailBuilder::new()
.to(address)
.from((CONFIG.smtp_from().as_str(), CONFIG.smtp_from_name().as_str()))
.subject(subject)
.child(alternative.build())
.build()
.map_err(|e| Error::new("Error building email", e.to_string()))?;
let mut transport = mailer(); let text = SinglePart::builder()
.header(header::ContentType("text/plain; charset=utf-8".parse().unwrap()))
.header(header::ContentTransferEncoding::QuotedPrintable)
.body(body_text);
let result = transport.send(email); let alternative = MultiPart::alternative().singlepart(text).singlepart(html);
let email = Message::builder()
.to(Mailbox::new(None, Address::from_str(&address)?))
.from(Mailbox::new(
Some(CONFIG.smtp_from_name()),
Address::from_str(&CONFIG.smtp_from())?,
))
.subject(subject)
.multipart(alternative)
.map_err(|e| Error::new("Error building email", e.to_string()))?;
// Explicitly close the connection, in case of error let _ = mailer().send(&email)?;
transport.close();
result?;
Ok(()) Ok(())
} }

Loading…
Cancel
Save