diff --git a/lettre_email/src/lib.rs b/lettre_email/src/lib.rs index 38f01ad..a47e090 100644 --- a/lettre_email/src/lib.rs +++ b/lettre_email/src/lib.rs @@ -87,36 +87,36 @@ impl IntoEmail for SimpleEmail { let mut builder = EmailBuilder::new(); if self.from.is_some() { - builder.add_from(self.from.unwrap()); + builder = builder.from(self.from.unwrap()); } for to_address in self.to { - builder.add_to(to_address.into_mailbox()); + builder = builder.to(to_address.into_mailbox()); } for cc_address in self.cc { - builder.add_cc(cc_address.into_mailbox()); + builder = builder.cc(cc_address.into_mailbox()); } if self.reply_to.is_some() { - builder.add_reply_to(self.reply_to.unwrap().into_mailbox()); + builder = builder.reply_to(self.reply_to.unwrap().into_mailbox()); } if self.subject.is_some() { - builder.set_subject(self.subject.unwrap()); + builder = builder.subject(self.subject.unwrap()); } // No date for now - match (self.text, self.html) { - (Some(text), Some(html)) => builder.set_alternative(html, text), - (Some(text), None) => builder.set_text(text), - (None, Some(html)) => builder.set_html(html), - (None, None) => (), - } + builder = match (self.text, self.html) { + (Some(text), Some(html)) => builder.alternative(html, text), + (Some(text), None) => builder.text(text), + (None, Some(html)) => builder.html(html), + (None, None) => builder, + }; for header in self.headers { - builder.add_header(header.into_header()); + builder = builder.header(header.into_header()); } builder.build() @@ -142,123 +142,68 @@ pub struct SimpleEmail { impl SimpleEmail { /// Adds a generic header pub fn header(mut self, header: A) -> SimpleEmail { - self.add_header(header); - self - } - - /// Adds a generic header - pub fn add_header(&mut self, header: A) { self.headers.push(header.into_header()); + self } /// Adds a `From` header and stores the sender address pub fn from(mut self, address: A) -> SimpleEmail { - self.add_from(address); - self - } - - /// Adds a `From` header and stores the sender address - pub fn add_from(&mut self, address: A) { self.from = Some(address.into_mailbox()); + self } /// Adds a `To` header and stores the recipient address pub fn to(mut self, address: A) -> SimpleEmail { - self.add_to(address); - self - } - - /// Adds a `To` header and stores the recipient address - pub fn add_to(&mut self, address: A) { self.to.push(address.into_mailbox()); + self } /// Adds a `Cc` header and stores the recipient address pub fn cc(mut self, address: A) -> SimpleEmail { - self.add_cc(address); - self - } - - /// Adds a `Cc` header and stores the recipient address - pub fn add_cc(&mut self, address: A) { self.cc.push(address.into_mailbox()); + self } /// Adds a `Bcc` header and stores the recipient address pub fn bcc(mut self, address: A) -> SimpleEmail { - self.add_bcc(address); - self - } - - /// Adds a `Bcc` header and stores the recipient address - pub fn add_bcc(&mut self, address: A) { self.bcc.push(address.into_mailbox()); + self } /// Adds a `Reply-To` header pub fn reply_to(mut self, address: A) -> SimpleEmail { - self.add_reply_to(address); - self - } - - /// Adds a `Reply-To` header - pub fn add_reply_to(&mut self, address: A) { self.reply_to = Some(address.into_mailbox()); + self } /// Adds a `Subject` header pub fn subject>(mut self, subject: S) -> SimpleEmail { - self.set_subject(subject); - self - } - - /// Adds a `Subject` header - pub fn set_subject>(&mut self, subject: S) { self.subject = Some(subject.into()); + self } /// Adds a `Date` header with the given date pub fn date(mut self, date: Tm) -> SimpleEmail { - self.set_date(date); - self - } - - /// Adds a `Date` header with the given date - pub fn set_date(&mut self, date: Tm) { self.date = Some(date); + self } /// Adds an attachment to the message pub fn attachment>(mut self, path: S) -> SimpleEmail { - self.add_attachment(path); - self - } - - /// Adds an attachment to the message - pub fn add_attachment>(&mut self, path: S) { self.attachments.push(path.into()); + self } /// Sets the email body to plain text content pub fn text>(mut self, body: S) -> SimpleEmail { - self.set_text(body); - self - } - - /// Sets the email body to plain text content - pub fn set_text>(&mut self, body: S) { self.text = Some(body.into()); + self } /// Sets the email body to HTML content pub fn html>(mut self, body: S) -> SimpleEmail { - self.set_html(body); - self - } - - /// Sets the email body to HTML content - pub fn set_html>(&mut self, body: S) { self.html = Some(body.into()); + self } } @@ -319,57 +264,31 @@ impl PartBuilder { /// Adds a generic header pub fn header(mut self, header: A) -> PartBuilder { - self.add_header(header); - self - } - - /// Adds a generic header - pub fn add_header(&mut self, header: A) { self.message.headers.insert(header.into_header()); + self } /// Sets the body pub fn body>(mut self, body: S) -> PartBuilder { - self.set_body(body); - self - } - - /// Sets the body - pub fn set_body>(&mut self, body: S) { self.message.body = body.into(); + self } /// Defines a `MimeMultipartType` value pub fn message_type(mut self, mime_type: MimeMultipartType) -> PartBuilder { - self.set_message_type(mime_type); - self - } - - /// Defines a `MimeMultipartType` value - pub fn set_message_type(&mut self, mime_type: MimeMultipartType) { self.message.message_type = Some(mime_type); - } - - /// Adds a `ContentType` header with the given MIME type - pub fn content_type(mut self, content_type: &Mime) -> PartBuilder { - self.set_content_type(content_type); self } /// Adds a `ContentType` header with the given MIME type - pub fn set_content_type(&mut self, content_type: &Mime) { - self.add_header(("Content-Type", format!("{}", content_type).as_ref())); + pub fn content_type(self, content_type: &Mime) -> PartBuilder { + self.header(("Content-Type", format!("{}", content_type).as_ref())) } /// Adds a child part pub fn child(mut self, child: MimeMessage) -> PartBuilder { - self.add_child(child); - self - } - - /// Adds a child part - pub fn add_child(&mut self, child: MimeMessage) { self.message.children.push(child); + self } /// Gets built `MimeMessage` @@ -397,142 +316,78 @@ impl EmailBuilder { /// Sets the email body pub fn body>(mut self, body: S) -> EmailBuilder { - self.message.set_body(body); + self.message = self.message.body(body); self } - /// Sets the email body - pub fn set_body>(&mut self, body: S) { - self.message.set_body(body); - } - /// Add a generic header pub fn header(mut self, header: A) -> EmailBuilder { - self.message.add_header(header); + self.message = self.message.header(header); self } - /// Add a generic header - pub fn add_header(&mut self, header: A) { - self.message.add_header(header); - } - /// Adds a `From` header and stores the sender address pub fn from(mut self, address: A) -> EmailBuilder { - self.add_from(address); - self - } - - /// Adds a `From` header and stores the sender address - pub fn add_from(&mut self, address: A) { let mailbox = address.into_mailbox(); self.from_header.push(Address::Mailbox(mailbox)); + self } /// Adds a `To` header and stores the recipient address pub fn to(mut self, address: A) -> EmailBuilder { - self.add_to(address); - self - } - - /// Adds a `To` header and stores the recipient address - pub fn add_to(&mut self, address: A) { let mailbox = address.into_mailbox(); self.to_header.push(Address::Mailbox(mailbox)); + self } /// Adds a `Cc` header and stores the recipient address pub fn cc(mut self, address: A) -> EmailBuilder { - self.add_cc(address); - self - } - - /// Adds a `Cc` header and stores the recipient address - pub fn add_cc(&mut self, address: A) { let mailbox = address.into_mailbox(); self.cc_header.push(Address::Mailbox(mailbox)); + self } /// Adds a `Bcc` header and stores the recipient address pub fn bcc(mut self, address: A) -> EmailBuilder { - self.add_bcc(address); - self - } - - /// Adds a `Bcc` header and stores the recipient address - pub fn add_bcc(&mut self, address: A) { let mailbox = address.into_mailbox(); self.bcc_header.push(Address::Mailbox(mailbox)); + self } /// Adds a `Reply-To` header pub fn reply_to(mut self, address: A) -> EmailBuilder { - self.add_reply_to(address); - self - } - - /// Adds a `Reply-To` header - pub fn add_reply_to(&mut self, address: A) { let mailbox = address.into_mailbox(); self.reply_to_header.push(Address::Mailbox(mailbox)); + self } /// Adds a `Sender` header pub fn sender(mut self, address: A) -> EmailBuilder { - self.set_sender(address); - self - } - - /// Adds a `Sender` header - pub fn set_sender(&mut self, address: A) { let mailbox = address.into_mailbox(); self.sender_header = Some(mailbox); + self } /// Adds a `Subject` header pub fn subject>(mut self, subject: S) -> EmailBuilder { - self.set_subject(subject); + self.message = self.message.header(("Subject".to_string(), subject.into())); self } - /// Adds a `Subject` header - pub fn set_subject>(&mut self, subject: S) { - self.message - .add_header(("Subject".to_string(), subject.into())); - } - /// Adds a `Date` header with the given date pub fn date(mut self, date: &Tm) -> EmailBuilder { - self.set_date(date); - self - } - - /// 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 = self.message.header(("Date", Tm::rfc822z(date).to_string())); self.date_issued = true; + self } /// Adds an attachment to the email pub fn attachment( - mut self, + self, path: &Path, filename: Option<&str>, content_type: &Mime, ) -> Result { - self.set_attachment(path, filename, content_type)?; - Ok(self) - } - - /// Adds an attachment to the email - /// If filename is not provided, the name of the file will be used. - pub fn set_attachment( - &mut self, - path: &Path, - filename: Option<&str>, - content_type: &Mime, - ) -> Result<(), Error> { let file = File::open(path); let body = match file { Ok(mut f) => { @@ -572,42 +427,23 @@ impl EmailBuilder { .header(("Content-Transfer-Encoding", "base64")) .build(); - self.set_message_type(MimeMultipartType::Mixed); - self.add_child(content); - - Ok(()) + Ok(self.message_type(MimeMultipartType::Mixed).child(content)) } /// Set the message type pub fn message_type(mut self, message_type: MimeMultipartType) -> EmailBuilder { - self.set_message_type(message_type); + self.message = self.message.message_type(message_type); self } - /// Set the message type - pub fn set_message_type(&mut self, message_type: MimeMultipartType) { - self.message.set_message_type(message_type); - } - /// Adds a child pub fn child(mut self, child: MimeMessage) -> EmailBuilder { - self.add_child(child); - self - } - - /// Adds a child - pub fn add_child(&mut self, child: MimeMessage) { - self.message.add_child(child); - } - - /// Sets the email body to plain text content - pub fn text>(mut self, body: S) -> EmailBuilder { - self.set_text(body); + self.message = self.message.child(child); self } /// Sets the email body to plain text content - pub fn set_text>(&mut self, body: S) { + pub fn text>(self, body: S) -> EmailBuilder { let text = PartBuilder::new() .body(body) .header(( @@ -615,17 +451,12 @@ impl EmailBuilder { format!("{}", mime::TEXT_PLAIN_UTF_8).as_ref(), )) .build(); - self.add_child(text); + self.child(text) } - /// Sets the email body to HTML content - pub fn html>(mut self, body: S) -> EmailBuilder { - self.set_html(body); - self - } /// Sets the email body to HTML content - pub fn set_html>(&mut self, body: S) { + pub fn html>(self, body: S) -> EmailBuilder { let html = PartBuilder::new() .body(body) .header(( @@ -633,28 +464,15 @@ impl EmailBuilder { format!("{}", mime::TEXT_HTML_UTF_8).as_ref(), )) .build(); - self.add_child(html); + self.child(html) } /// Sets the email content pub fn alternative, T: Into>( - mut self, + self, body_html: S, body_text: T, ) -> EmailBuilder { - self.set_alternative(body_html, body_text); - self - } - - /// Sets the email content - pub fn set_alternative, T: Into>( - &mut self, - body_html: S, - body_text: T, - ) { - let mut alternate = PartBuilder::new(); - alternate.set_message_type(MimeMultipartType::Alternative); - let text = PartBuilder::new() .body(body_text) .header(( @@ -671,26 +489,18 @@ impl EmailBuilder { )) .build(); - alternate.add_child(text); - alternate.add_child(html); + let alternate = PartBuilder::new().message_type(MimeMultipartType::Alternative) + .child(text).child(html); - self.set_message_type(MimeMultipartType::Mixed); - self.add_child(alternate.build()); + self.message_type(MimeMultipartType::Mixed).child(alternate.build()) } /// Sets the envelope for manual destination control /// If this function is not called, the envelope will be calculated /// from the "to" and "cc" addresses you set. pub fn envelope(mut self, envelope: Envelope) -> EmailBuilder { - self.set_envelope(envelope); - self - } - - /// Sets the envelope for manual destination control - /// If this function is not called, the envelope will be calculated - /// from the "to" and "cc" addresses you set. - pub fn set_envelope(&mut self, envelope: Envelope) { self.envelope = Some(envelope); + self } /// Builds the Email @@ -712,7 +522,7 @@ 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 = self.message.header(("Sender", v.to_string().as_ref())); } // Calculate the envelope let envelope = match self.envelope { @@ -760,35 +570,35 @@ 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 = self.message + .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 = self.message + .header(Header::new_with_value("From".into(), self.from_header).unwrap()); } else { return Err(Error::Email(EmailError::MissingFrom)); } if !self.cc_header.is_empty() { - self.message - .add_header(Header::new_with_value("Cc".into(), self.cc_header).unwrap()); + self.message = self.message + .header(Header::new_with_value("Cc".into(), self.cc_header).unwrap()); } if !self.bcc_header.is_empty() { - self.message - .add_header(Header::new_with_value("Bcc".into(), self.bcc_header).unwrap()); + self.message = self.message + .header(Header::new_with_value("Bcc".into(), self.bcc_header).unwrap()); } if !self.reply_to_header.is_empty() { - self.message.add_header( + self.message = self.message.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 = self.message + .header(("Date", Tm::rfc822z(&now()).to_string().as_ref())); } - self.message.add_header(("MIME-Version", "1.0")); + self.message = self.message.header(("MIME-Version", "1.0")); let message_id = Uuid::new_v4(); @@ -796,7 +606,7 @@ impl EmailBuilder { "Message-ID".to_string(), format!("<{}.lettre@localhost>", message_id), ) { - self.message.add_header(header) + self.message = self.message.header(header) } Ok(Email { @@ -821,30 +631,6 @@ impl<'a> SendableEmail<'a, &'a [u8]> for Email { } } -/// Email sendable by any type of client, giving access to all fields -pub trait ExtractableEmail { - /// From address - fn from_address(&self) -> Option; - /// To addresses - fn to_addresses(&self) -> Vec; - /// Cc addresses - fn cc_addresses(&self) -> Vec; - /// Bcc addresses - fn bcc_addresses(&self) -> Vec; - /// Replay-To addresses - fn reply_to_address(&self) -> String; - /// Subject - fn subject(&self) -> String; - /// Message ID - fn message_id(&self) -> String; - /// Other Headers - fn headers(&self) -> Vec; - /// html content - fn html(self) -> String; - /// text content - fn text(self) -> String; -} - #[cfg(test)] mod test { use super::EmailBuilder; diff --git a/website/content/creating-messages/email.md b/website/content/creating-messages/email.md index fcc3d48..77fae7e 100644 --- a/website/content/creating-messages/email.md +++ b/website/content/creating-messages/email.md @@ -20,7 +20,7 @@ fn main() { // ... or by an address only .from("user@example.com") .subject("Hi, Hello world") - .text("Hello world.") + .alternative("

Hi, Hello world.

", "Hi, Hello world.") .build(); assert!(email.is_ok()); @@ -34,32 +34,3 @@ then generate an `Email` that can be sent. The `text()` method will create a plain text email, while the `html()` method will create an HTML email. You can use the `alternative()` method to provide both versions, using plain text as fallback for the HTML version. - -#### Complete example - -Below is a more complete example, not using method chaining: - -```rust -extern crate lettre_email; - -use lettre_email::EmailBuilder; - -fn main() { - let mut builder = EmailBuilder::new(); - builder.add_to(("user@example.org", "Alias name")); - builder.add_cc(("user@example.net", "Alias name")); - builder.add_from("no-reply@example.com"); - builder.add_from("no-reply@example.eu"); - builder.set_sender("no-reply@example.com"); - builder.set_subject("Hello world"); - builder.set_alternative("

Hi, Hello world.

", "Hi, Hello world."); - builder.add_reply_to("contact@example.com"); - builder.add_header(("X-Custom-Header", "my header")); - - let email = builder.build(); - assert!(email.is_ok()); -} -``` - -See the `EmailBuilder` documentation for a complete list of methods. -