commit 63cbd9ef9c23ff7a13dfbbb7723fbb6ed4c5dc13
parent 9cca64003aa7fd8e3532d20c18bba6fd9de11eb3
Author: Daniel GarcĂa <dani-garcia@users.noreply.github.com>
Date: Sun, 3 May 2020 17:41:53 +0200
Update lettre to latest master
Diffstat:
M | Cargo.lock | | | 175 | +++++++++++++++++++++++++------------------------------------------------------ |
M | Cargo.toml | | | 5 | ++--- |
M | src/error.rs | | | 8 | ++++++-- |
M | src/mail.rs | | | 87 | +++++++++++++++++++++++++++++++++---------------------------------------------- |
4 files changed, 99 insertions(+), 176 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -28,12 +28,6 @@ dependencies = [
]
[[package]]
-name = "ascii_utils"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a"
-
-[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -110,6 +104,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
[[package]]
+name = "base64"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
+
+[[package]]
name = "binascii"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -148,7 +148,6 @@ dependencies = [
"once_cell",
"openssl",
"percent-encoding 2.1.0",
- "quoted_printable",
"regex",
"reqwest",
"ring",
@@ -483,85 +482,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "encoding_rs"
version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -586,15 +506,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "fern"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -889,17 +800,6 @@ dependencies = [
]
[[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]]
name = "html5ever"
version = "0.22.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1009,6 +909,24 @@ dependencies = [
]
[[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]]
name = "idna"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1128,20 +1046,21 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
[[package]]
name = "lettre"
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 = [
- "base64 0.11.0",
+ "base64 0.12.0",
"bufstream",
- "email",
- "fast_chemail",
- "hostname",
- "log 0.4.8",
+ "hyperx",
+ "idna 0.2.0",
+ "line-wrap",
"mime 0.3.16",
"native-tls",
"nom",
+ "once_cell",
+ "quoted_printable",
+ "regex",
"serde",
- "serde_json",
- "time 0.2.14",
+ "textnonce",
"uuid",
]
@@ -1176,6 +1095,15 @@ dependencies = [
]
[[package]]
+name = "line-wrap"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
+dependencies = [
+ "safemem",
+]
+
+[[package]]
name = "lock_api"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1231,12 +1159,6 @@ dependencies = [
]
[[package]]
-name = "match_cfg"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
-
-[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2726,6 +2648,19 @@ dependencies = [
]
[[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]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
@@ -92,9 +92,8 @@ num-traits = "0.2.11"
num-derive = "0.3.0"
# 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"
-quoted_printable = "0.4.2"
# Template library
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' }
# 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
data-url = { git = 'https://github.com/servo/rust-url', package="data-url", rev = '7f1bd6ce1c2fde599a757302a843a60e714c5f72' }
diff --git a/src/error.rs b/src/error.rs
@@ -45,7 +45,9 @@ use std::option::NoneError as NoneErr;
use std::time::SystemTimeError as TimeErr;
use u2f::u2ferror::U2fError as U2fErr;
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)]
pub struct Empty {}
@@ -73,7 +75,9 @@ make_error! {
ReqError(ReqErr): _has_source, _api_error,
RegexError(RegexErr): _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
diff --git a/src/mail.rs b/src/mail.rs
@@ -1,13 +1,11 @@
-use lettre::smtp::authentication::Credentials;
-use lettre::smtp::authentication::Mechanism as SmtpAuthMechanism;
-use lettre::smtp::ConnectionReuseParameters;
-use lettre::{
- builder::{EmailBuilder, MimeMultipartType, PartBuilder},
- ClientSecurity, ClientTlsParameters, SmtpClient, SmtpTransport, Transport,
-};
+use std::str::FromStr;
+
+use lettre::message::{header, Mailbox, Message, MultiPart, SinglePart};
+use lettre::transport::smtp::authentication::{Credentials, Mechanism as SmtpAuthMechanism};
+use lettre::{Address, SmtpTransport, Tls, TlsParameters, Transport};
+
use native_tls::{Protocol, TlsConnector};
use percent_encoding::{percent_encode, NON_ALPHANUMERIC};
-use quoted_printable::encode_to_str;
use crate::api::EmptyResult;
use crate::auth::{encode_jwt, generate_delete_claims, generate_invite_claims, generate_verify_email_claims};
@@ -24,23 +22,23 @@ fn mailer() -> SmtpTransport {
.build()
.unwrap();
- let params = ClientTlsParameters::new(host.clone(), tls);
+ let params = TlsParameters::new(host.clone(), tls);
if CONFIG.smtp_explicit_tls() {
- ClientSecurity::Wrapper(params)
+ Tls::Wrapper(params)
} else {
- ClientSecurity::Required(params)
+ Tls::Required(params)
}
} else {
- ClientSecurity::None
+ Tls::None
};
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()) {
- (Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user.clone(), pass.clone())),
+ let smtp_client = match (CONFIG.smtp_username(), CONFIG.smtp_password()) {
+ (Some(user), Some(pass)) => smtp_client.credentials(Credentials::new(user, pass)),
_ => smtp_client,
};
@@ -48,19 +46,16 @@ fn mailer() -> SmtpTransport {
Some(mechanism) => {
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) {
- 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`"),
}
}
_ => smtp_client,
};
- smtp_client
- .smtp_utf8(true)
- .timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())))
- .connection_reuse(ConnectionReuseParameters::NoReuse)
- .transport()
+ smtp_client.timeout(Some(Duration::from_secs(CONFIG.smtp_timeout())))
}
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 html = PartBuilder::new()
- .body(encode_to_str(body_html))
- .header(("Content-Type", "text/html; charset=utf-8"))
- .header(("Content-Transfer-Encoding", "quoted-printable"))
- .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 html = SinglePart::builder()
+ .header(header::ContentType("text/html; charset=utf-8".parse().unwrap()))
+ .header(header::ContentTransferEncoding::QuotedPrintable)
+ .body(body_html);
- 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
- transport.close();
-
- result?;
+ let _ = mailer().send(&email)?;
Ok(())
}