diff --git a/src/email/mod.rs b/src/email/mod.rs
index 0c73216..b35847e 100644
--- a/src/email/mod.rs
+++ b/src/email/mod.rs
@@ -247,10 +247,8 @@ pub struct EmailBuilder {
reply_to_header: Vec
,
/// The sender address for the mail header
sender_header: Option,
- /// The envelope recipients' addresses
- to: Vec,
- /// The envelope sender address
- from: Option,
+ /// The envelope
+ envelope: Option,
/// Date issued
date_issued: bool,
}
@@ -264,6 +262,34 @@ pub struct Envelope {
from: String,
}
+impl Envelope {
+ /// Constructs an envelope with no receivers and an empty sender
+ pub fn new() -> Self {
+ Envelope {
+ to: vec![],
+ from: String::new(),
+ }
+ }
+ /// Adds a receiver
+ pub fn to>(mut self, address: S) -> Self {
+ self.add_to(address);
+ self
+ }
+ /// Adds a receiver
+ pub fn add_to>(&mut self, address: S) {
+ self.to.push(address.into());
+ }
+ /// Sets the sender
+ pub fn from>(mut self, address: S) -> Self {
+ self.set_from(address);
+ self
+ }
+ /// Sets the sender
+ pub fn set_from>(&mut self, address: S) {
+ self.from = address.into();
+ }
+}
+
/// Simple email representation
#[derive(PartialEq,Eq,Clone,Debug)]
pub struct Email {
@@ -360,8 +386,7 @@ impl EmailBuilder {
cc_header: vec![],
reply_to_header: vec![],
sender_header: None,
- to: vec![],
- from: None,
+ envelope: None,
date_issued: false,
}
}
@@ -397,7 +422,6 @@ impl EmailBuilder {
/// Adds a `From` header and stores the sender address
pub fn add_from(&mut self, address: A) {
let mailbox = address.to_mailbox();
- self.from = Some(mailbox.address.clone());
self.from_header.push(Address::Mailbox(mailbox));
}
@@ -410,7 +434,6 @@ impl EmailBuilder {
/// Adds a `To` header and stores the recipient address
pub fn add_to(&mut self, address: A) {
let mailbox = address.to_mailbox();
- self.to.push(mailbox.address.clone());
self.to_header.push(Address::Mailbox(mailbox));
}
@@ -423,7 +446,6 @@ impl EmailBuilder {
/// Adds a `Cc` header and stores the recipient address
pub fn add_cc(&mut self, address: A) {
let mailbox = address.to_mailbox();
- self.to.push(mailbox.address.clone());
self.cc_header.push(Address::Mailbox(mailbox));
}
@@ -448,7 +470,6 @@ impl EmailBuilder {
/// Adds a `Sender` header
pub fn set_sender(&mut self, address: A) {
let mailbox = address.to_mailbox();
- self.from = Some(mailbox.address.clone());
self.sender_header = Some(mailbox);
}
@@ -551,14 +572,23 @@ impl EmailBuilder {
self.add_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);
+ }
+
/// Builds the Email
pub fn build(mut self) -> Result {
- if self.from.is_none() {
- return Err(Error::MissingFrom);
- }
- if self.to.is_empty() {
- return Err(Error::MissingTo);
- }
// If there are multiple addresses in "From", the "Sender" is required.
if self.from_header.len() >= 2 && self.sender_header.is_none() {
// So, we must find something to put as Sender.
@@ -575,13 +605,64 @@ impl EmailBuilder {
assert!(self.sender_header.is_some());
}
// Add the sender header, if any.
- if let Some(v) = self.sender_header {
+ if let Some(ref v) = self.sender_header {
self.message.add_header(("Sender", v.to_string().as_ref()));
}
+ // Calculate the envelope
+ let envelope = match self.envelope {
+ Some(e) => e,
+ None => {
+ // we need to generate the envelope
+ let mut e = Envelope::new();
+ // add all receivers in to_header and cc_header
+ for receiver in self.to_header.iter().chain(self.cc_header.iter()) {
+ match *receiver {
+ Address::Mailbox(ref m) => e.add_to(m.address.clone()),
+ Address::Group(_, ref ms) => {
+ for m in ms.iter() {
+ e.add_to(m.address.clone());
+ }
+ }
+ }
+ }
+ if e.to.is_empty() {
+ return Err(Error::MissingTo);
+ }
+ e.set_from(match self.sender_header {
+ Some(x) => x.address.clone(), // if we have a sender_header, use it
+ None => {
+ // use a from header
+ debug_assert!(self.from_header.len()<=1); // else we'd have sender_header
+ match self.from_header.first() {
+ Some(a) => match *a {
+ // if we have a from header
+ Address::Mailbox(ref mailbox) => mailbox.address.clone(), // use it
+ Address::Group(_,ref mailbox_list) => match mailbox_list.first() {
+ // if it's an author group, use the first author
+ Some(mailbox) => mailbox.address.clone(),
+ // for an empty author group (the rarest of the rare cases)
+ None => return Err(Error::MissingFrom), // empty envelope sender
+ },
+ },
+ // if we don't have a from header
+ None => return Err(Error::MissingFrom), // empty envelope sender
+ }
+ }
+ });
+ e
+ }
+ };
// Add the collected addresses as mailbox-list all at once.
// The unwraps are fine because the conversions for Vec never errs.
- self.message.add_header(Header::new_with_value("To".into(), self.to_header).unwrap());
- self.message.add_header(Header::new_with_value("From".into(), self.from_header).unwrap());
+ if !self.to_header.is_empty() {
+ 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());
+ } 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());
}
@@ -607,10 +688,7 @@ impl EmailBuilder {
Ok(Email {
message: self.message.build(),
- envelope: Envelope {
- to: self.to,
- from: self.from.unwrap(),
- },
+ envelope: envelope,
message_id: message_id,
})
}