diff --git a/src/builder/mod.rs b/src/builder/mod.rs index deef869..db688eb 100644 --- a/src/builder/mod.rs +++ b/src/builder/mod.rs @@ -1,11 +1,9 @@ use crate::{error::Error as LettreError, Email, EmailAddress, Envelope}; -pub use email::{Address, Header, Mailbox as OriginalMailbox, MimeMessage, MimeMultipartType}; +pub use email::{Address, Header, Mailbox, MimeMessage, MimeMultipartType}; use error::Error; pub use mime; use mime::Mime; -use std::borrow::Cow; use std::ffi::OsStr; -use std::fmt; use std::fs; use std::path::Path; use std::str::FromStr; @@ -14,84 +12,9 @@ use uuid::Uuid; pub mod error; -// From rust-email, allows adding rfc2047 encoding - -/// Represents an RFC 5322 mailbox -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct Mailbox { - inner: OriginalMailbox, -} - -impl Mailbox { - /// Create a new Mailbox without a display name - pub fn new(address: String) -> Mailbox { - Mailbox { - inner: OriginalMailbox::new(address), - } - } - - /// Create a new Mailbox with a display name - pub fn new_with_name(name: String, address: String) -> Mailbox { - Mailbox { - inner: OriginalMailbox::new_with_name(encode_rfc2047(&name).to_string(), address), - } - } - - fn original(self) -> OriginalMailbox { - self.inner - } -} - -impl fmt::Display for Mailbox { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{}", self.inner) - } -} - -impl<'a> From<&'a str> for Mailbox { - fn from(mailbox: &'a str) -> Mailbox { - Mailbox::new(mailbox.into()) - } -} - -impl From for Mailbox { - fn from(mailbox: String) -> Mailbox { - Mailbox::new(mailbox) - } -} - -impl, T: Into> From<(S, T)> for Mailbox { - fn from(header: (S, T)) -> Mailbox { - let (address, alias) = header; - Mailbox::new_with_name(alias.into(), address.into()) - } -} - -/// Encode a UTF-8 string according to RFC 2047, if need be. -/// -/// Currently, this only uses "B" encoding, when pure ASCII cannot represent the -/// string accurately. -/// -/// Can be used on header content. -pub fn encode_rfc2047(text: &str) -> Cow { - if text.is_ascii() { - Cow::Borrowed(text) - } else { - Cow::Owned( - base64::encode_config(text.as_bytes(), base64::STANDARD) - // base64 so ascii - .as_bytes() - .chunks(75 - 12) - .map(|d| format!("=?utf-8?B?{}?=", std::str::from_utf8(d).unwrap())) - .collect::>() - .join("\r\n"), - ) - } -} - -impl From for OriginalMailbox { +impl From for email::Mailbox { fn from(addr: EmailAddress) -> Self { - OriginalMailbox::new(addr.into_inner()) + Mailbox::new(addr.into_inner()) } } @@ -131,7 +54,7 @@ pub struct EmailBuilder { /// The References ids for the mail header references: Vec, /// The sender address for the mail header - sender: Option, + sender: Option, /// The envelope envelope: Option, /// Date issued @@ -218,35 +141,35 @@ impl EmailBuilder { /// Adds a `From` header and stores the sender address pub fn from>(mut self, address: A) -> EmailBuilder { let mailbox = address.into(); - self.from.push(Address::Mailbox(mailbox.original())); + self.from.push(Address::Mailbox(mailbox)); self } /// Adds a `To` header and stores the recipient address pub fn to>(mut self, address: A) -> EmailBuilder { let mailbox = address.into(); - self.to.push(Address::Mailbox(mailbox.original())); + self.to.push(Address::Mailbox(mailbox)); self } /// Adds a `Cc` header and stores the recipient address pub fn cc>(mut self, address: A) -> EmailBuilder { let mailbox = address.into(); - self.cc.push(Address::Mailbox(mailbox.original())); + self.cc.push(Address::Mailbox(mailbox)); self } /// Adds a `Bcc` header and stores the recipient address pub fn bcc>(mut self, address: A) -> EmailBuilder { let mailbox = address.into(); - self.bcc.push(Address::Mailbox(mailbox.original())); + self.bcc.push(Address::Mailbox(mailbox)); self } /// Adds a `Reply-To` header pub fn reply_to>(mut self, address: A) -> EmailBuilder { let mailbox = address.into(); - self.reply_to.push(Address::Mailbox(mailbox.original())); + self.reply_to.push(Address::Mailbox(mailbox)); self } @@ -265,16 +188,13 @@ impl EmailBuilder { /// Adds a `Sender` header pub fn sender>(mut self, address: A) -> EmailBuilder { let mailbox = address.into(); - self.sender = Some(mailbox.original()); + self.sender = Some(mailbox); self } /// Adds a `Subject` header pub fn subject>(mut self, subject: S) -> EmailBuilder { - self.message = self.message.header(( - "Subject".to_string(), - encode_rfc2047(subject.into().as_ref()), - )); + self.message = self.message.header(("Subject".to_string(), subject.into())); self } @@ -533,22 +453,10 @@ impl EmailBuilder { #[cfg(test)] mod test { - use super::*; + use super::{Email, EmailBuilder}; use crate::EmailAddress; use time::now; - #[test] - fn test_encode_rfc2047() { - assert_eq!(encode_rfc2047("test"), "test"); - assert_eq!(encode_rfc2047("testà"), "=?utf-8?B?dGVzdMOg?="); - assert_eq!( - encode_rfc2047( - "testàtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest" - ), - "=?utf-8?B?dGVzdMOgdGVzdHRlc3R0ZXN0dGVzdHRlc3R0ZXN0dGVzdHRlc3R0ZXN0dGVzdHR?=\r\n=?utf-8?B?lc3R0ZXN0dGVzdHRlc3R0ZXN0dGVzdHRlc3R0ZXN0?=" - ); - } - #[test] fn test_multiple_from() { let email_builder = EmailBuilder::new(); @@ -586,7 +494,6 @@ mod test { .to("user@localhost") .from("user@localhost") .cc(("cc@localhost", "Alias")) - .cc(("cc2@localhost", "Aliäs")) .bcc("bcc@localhost") .reply_to("reply@localhost") .in_reply_to("original".to_string()) @@ -604,7 +511,7 @@ mod test { format!( "Date: {}\r\nSubject: Hello\r\nX-test: value\r\nSender: \ \r\nTo: \r\nFrom: \ - \r\nCc: \"Alias\" , \"=?utf-8?B?QWxpw6Rz?=\" \r\n\ + \r\nCc: \"Alias\" \r\n\ Reply-To: \r\nIn-Reply-To: original\r\n\ MIME-Version: 1.0\r\nMessage-ID: \ <{}.lettre@localhost>\r\n\r\nHello World!\r\n", @@ -656,22 +563,13 @@ mod test { .subject("A Subject") .to("user@localhost") .date(&date_now); - let string_res = String::from_utf8(email_builder.build_body().unwrap()); - assert!(string_res.unwrap().starts_with("Subject: A Subject\r\n")); - } - #[test] - fn test_email_subject_encoding() { - let date_now = now(); - let email_builder = EmailBuilder::new() - .text("TestTest") - .subject("A ö Subject") - .to("user@localhost") - .date(&date_now); - let string_res = String::from_utf8(email_builder.build_body().unwrap()); - assert!(string_res - .unwrap() - .starts_with("Subject: =?utf-8?B?QSDDtiBTdWJqZWN0?=\r\n")); + let body_res = email_builder.build_body(); + assert_eq!(body_res.is_ok(), true); + + let string_res = std::string::String::from_utf8(body_res.unwrap()); + assert_eq!(string_res.is_ok(), true); + assert!(string_res.unwrap().starts_with("Subject: A Subject")); } #[test]