lettre/address/
envelope.rs1use super::Address;
2#[cfg(feature = "builder")]
3use crate::message::header::{self, Headers};
4#[cfg(feature = "builder")]
5use crate::message::{Mailbox, Mailboxes};
6use crate::Error;
7
8#[derive(PartialEq, Eq, Clone, Debug)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Envelope {
14    #[cfg_attr(
18        feature = "serde",
19        serde(deserialize_with = "serde_forward_path::deserialize")
20    )]
21    forward_path: Vec<Address>,
22    reverse_path: Option<Address>,
24}
25
26#[cfg(feature = "serde")]
29mod serde_forward_path {
30    use super::Address;
31    struct CustomVisitor;
34    impl<'de> serde::de::Visitor<'de> for CustomVisitor {
35        type Value = Vec<Address>;
36
37        fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38            formatter.write_str("a non-empty list of recipient addresses")
39        }
40
41        fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
42        where
43            S: serde::de::SeqAccess<'de>,
44        {
45            let mut seq: Vec<Address> = Vec::with_capacity(access.size_hint().unwrap_or(0));
46            while let Some(key) = access.next_element()? {
47                seq.push(key);
48            }
49            if seq.is_empty() {
50                Err(serde::de::Error::invalid_length(seq.len(), &self))
51            } else {
52                Ok(seq)
53            }
54        }
55    }
56    pub(super) fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Address>, D::Error>
57    where
58        D: serde::Deserializer<'de>,
59    {
60        deserializer.deserialize_seq(CustomVisitor {})
61    }
62
63    #[cfg(test)]
64    mod tests {
65        #[test]
66        fn deserializing_empty_recipient_list_returns_error() {
67            assert!(
68                serde_json::from_str::<crate::address::Envelope>(r#"{"forward_path": []}"#)
69                    .is_err()
70            );
71        }
72        #[test]
73        fn deserializing_non_empty_recipient_list_is_ok() {
74            serde_json::from_str::<crate::address::Envelope>(
75                r#"{ "forward_path": [ {"user":"foo", "domain":"example.com"} ] }"#,
76            )
77            .unwrap();
78        }
79    }
80}
81
82impl Envelope {
83    pub fn new(from: Option<Address>, to: Vec<Address>) -> Result<Envelope, Error> {
103        if to.is_empty() {
104            return Err(Error::MissingTo);
105        }
106        Ok(Envelope {
107            forward_path: to,
108            reverse_path: from,
109        })
110    }
111
112    pub fn to(&self) -> &[Address] {
129        self.forward_path.as_slice()
130    }
131
132    pub fn from(&self) -> Option<&Address> {
152        self.reverse_path.as_ref()
153    }
154
155    #[cfg(feature = "smtp-transport")]
156    pub(crate) fn has_non_ascii_addresses(&self) -> bool {
158        self.reverse_path
159            .iter()
160            .chain(self.forward_path.iter())
161            .any(|a| !a.is_ascii())
162    }
163}
164
165#[cfg(feature = "builder")]
166#[cfg_attr(docsrs, doc(cfg(feature = "builder")))]
167impl TryFrom<&Headers> for Envelope {
168    type Error = Error;
169
170    fn try_from(headers: &Headers) -> Result<Self, Self::Error> {
171        let from = match headers.get::<header::Sender>() {
172            Some(sender) => Some(Mailbox::from(sender).email),
174            None => match headers.get::<header::From>() {
176                Some(header::From(a)) => {
177                    let mut from: Vec<Mailbox> = a.into();
178                    if from.len() > 1 {
179                        return Err(Error::TooManyFrom);
180                    }
181                    let from = from.pop().expect("From header has 1 Mailbox");
182                    Some(from.email)
183                }
184                None => None,
185            },
186        };
187
188        fn add_addresses_from_mailboxes(
189            addresses: &mut Vec<Address>,
190            mailboxes: Option<Mailboxes>,
191        ) {
192            if let Some(mailboxes) = mailboxes {
193                addresses.extend(mailboxes.into_iter().map(|mb| mb.email));
194            }
195        }
196        let mut to = vec![];
197        add_addresses_from_mailboxes(&mut to, headers.get::<header::To>().map(|h| h.0));
198        add_addresses_from_mailboxes(&mut to, headers.get::<header::Cc>().map(|h| h.0));
199        add_addresses_from_mailboxes(&mut to, headers.get::<header::Bcc>().map(|h| h.0));
200
201        Self::new(from, to)
202    }
203}