diff --git a/.travis.yml b/.travis.yml index 30a30d3..561c46a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ matrix: allow_failures: - rust: nightly -sudo: false +sudo: required cache: apt: true @@ -34,6 +34,7 @@ addons: before_script: - smtp-sink 2525 1000& +- sudo chgrp -R postdrop /var/spool/postfix/maildrop script: - travis-cargo build diff --git a/Cargo.toml b/Cargo.toml index 329f2ae..5b9f22f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ openssl = "^0.9" rustc-serialize = "^0.3" rust-crypto = "^0.2" time = "^0.1" -uuid = { version = "^0.4", features = ["v4"] } +uuid = { version = "^0.5", features = ["v4"] } [dev-dependencies] env_logger = "^0.4" diff --git a/src/email/mod.rs b/src/email/mod.rs index 5e94119..dca15ea 100644 --- a/src/email/mod.rs +++ b/src/email/mod.rs @@ -506,7 +506,8 @@ impl EmailBuilder { /// Adds a `Subject` header pub fn set_subject>(&mut self, subject: S) { - self.message.add_header(("Subject".to_string(), subject.into())); + self.message + .add_header(("Subject".to_string(), subject.into())); } /// Adds a `Date` header with the given date @@ -517,7 +518,8 @@ impl EmailBuilder { /// Adds a `Date` header with the given date pub fn set_date(&mut self, date: &Tm) { - self.message.add_header(("Date", Tm::rfc822z(date).to_string())); + self.message + .add_header(("Date", Tm::rfc822z(date).to_string())); self.date_issued = true; } @@ -552,8 +554,8 @@ impl EmailBuilder { /// Sets the email body to plain text content pub fn set_text>(&mut self, body: S) { self.message.set_body(body); - self.message.add_header(("Content-Type", - format!("{}", mime!(Text/Plain; Charset=Utf8)).as_ref())); + self.message + .add_header(("Content-Type", format!("{}", mime!(Text/Plain; Charset=Utf8)).as_ref())); } /// Sets the email body to HTML content @@ -565,8 +567,8 @@ impl EmailBuilder { /// Sets the email body to HTML content pub fn set_html>(&mut self, body: S) { self.message.set_body(body); - self.message.add_header(("Content-Type", - format!("{}", mime!(Text/Html; Charset=Utf8)).as_ref())); + self.message + .add_header(("Content-Type", format!("{}", mime!(Text/Html; Charset=Utf8)).as_ref())); } /// Sets the email content @@ -636,7 +638,8 @@ impl EmailBuilder { } // Add the sender header, if any. if let Some(ref v) = self.sender_header { - self.message.add_header(("Sender", v.to_string().as_ref())); + self.message + .add_header(("Sender", v.to_string().as_ref())); } // Calculate the envelope let envelope = match self.envelope { @@ -688,25 +691,28 @@ impl EmailBuilder { // Add the collected addresses as mailbox-list all at once. // The unwraps are fine because the conversions for Vec
never errs. if !self.to_header.is_empty() { - self.message.add_header(Header::new_with_value("To".into(), self.to_header).unwrap()); + self.message + .add_header(Header::new_with_value("To".into(), self.to_header).unwrap()); } if !self.from_header.is_empty() { - self.message.add_header(Header::new_with_value("From".into(), self.from_header) - .unwrap()); + self.message + .add_header(Header::new_with_value("From".into(), self.from_header).unwrap()); } else { return Err(Error::MissingFrom); } if !self.cc_header.is_empty() { - self.message.add_header(Header::new_with_value("Cc".into(), self.cc_header).unwrap()); + self.message + .add_header(Header::new_with_value("Cc".into(), self.cc_header).unwrap()); } if !self.reply_to_header.is_empty() { - self.message.add_header(Header::new_with_value("Reply-To".into(), - self.reply_to_header) - .unwrap()); + self.message + .add_header(Header::new_with_value("Reply-To".into(), self.reply_to_header) + .unwrap()); } if !self.date_issued { - self.message.add_header(("Date", Tm::rfc822z(&now()).to_string().as_ref())); + self.message + .add_header(("Date", Tm::rfc822z(&now()).to_string().as_ref())); } self.message.add_header(("MIME-Version", "1.0")); @@ -828,7 +834,8 @@ mod test { let email_builder = SimpleEmail::default(); let date_now = now(); - let email = email_builder.to("user@localhost") + let email = email_builder + .to("user@localhost") .from("user@localhost") .cc(("cc@localhost", "Alias")) .reply_to("reply@localhost") @@ -862,14 +869,18 @@ mod test { message_id: current_message, }; - email.message.headers.insert(Header::new_with_value("Message-ID".to_string(), - format!("<{}@rust-smtp>", - current_message)) - .unwrap()); + email + .message + .headers + .insert(Header::new_with_value("Message-ID".to_string(), + format!("<{}@rust-smtp>", current_message)) + .unwrap()); - email.message.headers.insert(Header::new_with_value("To".to_string(), - "to@example.com".to_string()) - .unwrap()); + email + .message + .headers + .insert(Header::new_with_value("To".to_string(), "to@example.com".to_string()) + .unwrap()); email.message.body = "body".to_string(); @@ -883,7 +894,8 @@ mod test { fn test_multiple_from() { let email_builder = EmailBuilder::new(); let date_now = now(); - let email = email_builder.to("anna@example.com") + let email = email_builder + .to("anna@example.com") .from("dieter@example.com") .from("joachim@example.com") .date(&date_now) @@ -905,7 +917,8 @@ mod test { let email_builder = EmailBuilder::new(); let date_now = now(); - let email = email_builder.to("user@localhost") + let email = email_builder + .to("user@localhost") .from("user@localhost") .cc(("cc@localhost", "Alias")) .reply_to("reply@localhost") @@ -932,7 +945,8 @@ mod test { let email_builder = EmailBuilder::new(); let date_now = now(); - let email = email_builder.to("user@localhost") + let email = email_builder + .to("user@localhost") .from("user@localhost") .cc(("cc@localhost", "Alias")) .bcc("bcc@localhost") diff --git a/src/lib.rs b/src/lib.rs index f9524b0..f6babc4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,10 +92,11 @@ //! //! This is the most basic example of usage: //! -//! ```rust -//! use lettre::transport::smtp::{SmtpTransport, SmtpTransportBuilder}; +//! ```rust,no_run +//! use lettre::transport::smtp::SmtpTransportBuilder; //! use lettre::email::EmailBuilder; //! use lettre::transport::EmailTransport; +//! use lettre::transport::smtp::SecurityLevel; //! //! let email = EmailBuilder::new() //! .to("root@localhost") @@ -107,7 +108,7 @@ //! //! // Open a local connection on port 25 //! let mut mailer = -//! SmtpTransportBuilder::localhost().unwrap().build(); +//! SmtpTransportBuilder::localhost().unwrap().security_level(SecurityLevel::Opportunistic).build(); //! // Send the email //! let result = mailer.send(email); //! diff --git a/src/transport/sendmail/mod.rs b/src/transport/sendmail/mod.rs index 309a7e6..c013c9f 100644 --- a/src/transport/sendmail/mod.rs +++ b/src/transport/sendmail/mod.rs @@ -39,7 +39,8 @@ impl EmailTransport for SendmailTransport { .stdout(Stdio::piped()) .spawn()); - match process.stdin + match process + .stdin .as_mut() .unwrap() .write_all(email.message().as_bytes()) { diff --git a/src/transport/smtp/authentication.rs b/src/transport/smtp/authentication.rs index e7ac401..c9d521f 100644 --- a/src/transport/smtp/authentication.rs +++ b/src/transport/smtp/authentication.rs @@ -101,16 +101,22 @@ mod test { assert_eq!(mechanism.response("username", "password", None).unwrap(), "\u{0}username\u{0}password"); - assert!(mechanism.response("username", "password", Some("test")).is_err()); + assert!(mechanism + .response("username", "password", Some("test")) + .is_err()); } #[test] fn test_login() { let mechanism = Mechanism::Login; - assert_eq!(mechanism.response("alice", "wonderland", Some("Username")).unwrap(), + assert_eq!(mechanism + .response("alice", "wonderland", Some("Username")) + .unwrap(), "alice"); - assert_eq!(mechanism.response("alice", "wonderland", Some("Password")).unwrap(), + assert_eq!(mechanism + .response("alice", "wonderland", Some("Password")) + .unwrap(), "wonderland"); assert!(mechanism.response("username", "password", None).is_err()); } @@ -119,9 +125,10 @@ mod test { fn test_cram_md5() { let mechanism = Mechanism::CramMd5; - assert_eq!(mechanism.response("alice", - "wonderland", - Some("PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==")) + assert_eq!(mechanism + .response("alice", + "wonderland", + Some("PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==")) .unwrap(), "alice a540ebe4ef2304070bbc3c456c1f64c0"); assert!(mechanism.response("alice", "wonderland", None).is_err()); diff --git a/src/transport/smtp/client/mod.rs b/src/transport/smtp/client/mod.rs index 69c98a2..62faee9 100644 --- a/src/transport/smtp/client/mod.rs +++ b/src/transport/smtp/client/mod.rs @@ -265,10 +265,7 @@ impl Client { } try!(write!(self.stream.as_mut().unwrap(), "{}{}", string, end)); - try!(self.stream - .as_mut() - .unwrap() - .flush()); + try!(self.stream.as_mut().unwrap().flush()); debug!("Wrote: {}", escape_crlf(string)); @@ -281,19 +278,13 @@ impl Client { let mut parser = ResponseParser::default(); let mut line = String::new(); - try!(self.stream - .as_mut() - .unwrap() - .read_line(&mut line)); + try!(self.stream.as_mut().unwrap().read_line(&mut line)); debug!("Read: {}", escape_crlf(line.as_ref())); while try!(parser.read_line(remove_crlf(line.as_ref()).as_ref())) { line.clear(); - try!(self.stream - .as_mut() - .unwrap() - .read_line(&mut line)); + try!(self.stream.as_mut().unwrap().read_line(&mut line)); } let response = try!(parser.response()); diff --git a/src/transport/smtp/extension.rs b/src/transport/smtp/extension.rs index 2954e77..113dbdd 100644 --- a/src/transport/smtp/extension.rs +++ b/src/transport/smtp/extension.rs @@ -116,7 +116,8 @@ impl ServerInfo { /// Checks if the server supports an ESMTP feature pub fn supports_auth_mechanism(&self, mechanism: Mechanism) -> bool { - self.features.contains(&Extension::Authentication(mechanism)) + self.features + .contains(&Extension::Authentication(mechanism)) } } @@ -172,7 +173,9 @@ mod test { fn test_serverinfo() { let response = Response::new(Code::new(Severity::PositiveCompletion, Category::Unspecified4, 1), - vec!["me".to_string(), "8BITMIME".to_string(), "SIZE 42".to_string()]); + vec!["me".to_string(), + "8BITMIME".to_string(), + "SIZE 42".to_string()]); let mut features = HashSet::new(); assert!(features.insert(Extension::EightBitMime)); diff --git a/src/transport/smtp/mod.rs b/src/transport/smtp/mod.rs index 62737e2..a4504d6 100644 --- a/src/transport/smtp/mod.rs +++ b/src/transport/smtp/mod.rs @@ -297,13 +297,14 @@ impl EmailTransport for SmtpTransport { } if self.state.connection_reuse_count == 0 { - try!(self.client.connect(&self.client_info.server_addr, - match &self.client_info.security_level { - &SecurityLevel::EncryptedWrapper => { - Some(&self.client_info.ssl_context) - } - _ => None, - })); + try!(self.client + .connect(&self.client_info.server_addr, + match &self.client_info.security_level { + &SecurityLevel::EncryptedWrapper => { + Some(&self.client_info.ssl_context) + } + _ => None, + })); try!(self.client.set_timeout(self.client_info.timeout)); @@ -323,7 +324,8 @@ impl EmailTransport for SmtpTransport { (&SecurityLevel::EncryptedWrapper, _) => (), (_, true) => { try_smtp!(self.client.starttls(), self); - try_smtp!(self.client.upgrade_tls_stream(&self.client_info.ssl_context), + try_smtp!(self.client + .upgrade_tls_stream(&self.client_info.ssl_context), self); debug!("connection encrypted"); @@ -334,10 +336,7 @@ impl EmailTransport for SmtpTransport { } if self.client_info.credentials.is_some() { - let (username, password) = self.client_info - .credentials - .clone() - .unwrap(); + let (username, password) = self.client_info.credentials.clone().unwrap(); let mut found = false; @@ -376,13 +375,13 @@ impl EmailTransport for SmtpTransport { // Mail let mail_options = match (self.server_info - .as_ref() - .unwrap() - .supports_feature(&Extension::EightBitMime), - self.server_info - .as_ref() - .unwrap() - .supports_feature(&Extension::SmtpUtfEight)) { + .as_ref() + .unwrap() + .supports_feature(&Extension::EightBitMime), + self.server_info + .as_ref() + .unwrap() + .supports_feature(&Extension::SmtpUtfEight)) { (true, true) => Some("BODY=8BITMIME SMTPUTF8"), (true, false) => Some("BODY=8BITMIME"), (false, _) => None, @@ -416,7 +415,8 @@ impl EmailTransport for SmtpTransport { message_id, self.state.connection_reuse_count, message.len(), - result.as_ref() + result + .as_ref() .ok() .unwrap() .message() diff --git a/src/transport/smtp/response.rs b/src/transport/smtp/response.rs index d1421b6..28471b5 100644 --- a/src/transport/smtp/response.rs +++ b/src/transport/smtp/response.rs @@ -423,7 +423,9 @@ mod test { "8BITMIME".to_string(), "SIZE 42".to_string()]) .message(), - vec!["me".to_string(), "8BITMIME".to_string(), "SIZE 42".to_string()]); + vec!["me".to_string(), + "8BITMIME".to_string(), + "SIZE 42".to_string()]); let empty_message: Vec = vec![]; assert_eq!(Response::new(Code { severity: "2".parse::().unwrap(), diff --git a/tests/transport_smtp.rs b/tests/transport_smtp.rs index 44f3d48..56ae8dd 100644 --- a/tests/transport_smtp.rs +++ b/tests/transport_smtp.rs @@ -2,11 +2,15 @@ extern crate lettre; use lettre::email::EmailBuilder; use lettre::transport::EmailTransport; +use lettre::transport::smtp::SecurityLevel; use lettre::transport::smtp::SmtpTransportBuilder; #[test] fn smtp_transport_simple() { - let mut sender = SmtpTransportBuilder::localhost().unwrap().build(); + let mut sender = SmtpTransportBuilder::new("127.0.0.1:2525") + .unwrap() + .security_level(SecurityLevel::Opportunistic) + .build(); let email = EmailBuilder::new() .to("root@localhost") .from("user@localhost")