Browse Source

Update lettre to latest master

Daniel García 5 years ago
parent
commit
63cbd9ef9c
4 changed files with 99 additions and 176 deletions
  1. 55 120
      Cargo.lock
  2. 2 3
      Cargo.toml
  3. 6 2
      src/error.rs
  4. 36 51
      src/mail.rs

+ 55 - 120
Cargo.lock

@@ -27,12 +27,6 @@ dependencies = [
  "nodrop",
 ]
 
-[[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"
@@ -109,6 +103,12 @@ version = "0.11.0"
 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"
@@ -148,7 +148,6 @@ dependencies = [
  "once_cell",
  "openssl",
  "percent-encoding 2.1.0",
- "quoted_printable",
  "regex",
  "reqwest",
  "ring",
@@ -482,85 +481,6 @@ version = "0.4.5"
 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"
@@ -585,15 +505,6 @@ version = "0.1.2"
 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"
@@ -888,17 +799,6 @@ dependencies = [
  "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]]
 name = "html5ever"
 version = "0.22.5"
@@ -1008,6 +908,24 @@ dependencies = [
  "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]]
 name = "idna"
 version = "0.1.5"
@@ -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",
 ]
 
@@ -1175,6 +1094,15 @@ dependencies = [
  "vcpkg",
 ]
 
+[[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"
@@ -1230,12 +1158,6 @@ dependencies = [
  "tendril",
 ]
 
-[[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"
@@ -2725,6 +2647,19 @@ dependencies = [
  "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]]
 name = "textwrap"
 version = "0.11.0"

+ 2 - 3
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' }

+ 6 - 2
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

+ 36 - 51
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(())
 }