eml_codec/imf/
field.rs

1use chrono::{DateTime, FixedOffset};
2use nom::combinator::map;
3
4use crate::header;
5use crate::imf::address::{address_list, mailbox_list, nullable_address_list, AddressList};
6use crate::imf::datetime::section as date;
7use crate::imf::identification::{msg_id, msg_list, MessageID, MessageIDList};
8use crate::imf::mailbox::{mailbox, AddrSpec, MailboxList, MailboxRef};
9use crate::imf::mime::{version, Version};
10use crate::imf::trace::{received_log, return_path, ReceivedLog};
11use crate::text::misc_token::{phrase_list, unstructured, PhraseList, Unstructured};
12
13#[derive(Debug, PartialEq)]
14pub enum Field<'a> {
15    // 3.6.1.  The Origination Date Field
16    Date(Option<DateTime<FixedOffset>>),
17
18    // 3.6.2.  Originator Fields
19    From(MailboxList<'a>),
20    Sender(MailboxRef<'a>),
21    ReplyTo(AddressList<'a>),
22
23    // 3.6.3.  Destination Address Fields
24    To(AddressList<'a>),
25    Cc(AddressList<'a>),
26    Bcc(AddressList<'a>),
27
28    // 3.6.4.  Identification Fields
29    MessageID(MessageID<'a>),
30    InReplyTo(MessageIDList<'a>),
31    References(MessageIDList<'a>),
32
33    // 3.6.5.  Informational Fields
34    Subject(Unstructured<'a>),
35    Comments(Unstructured<'a>),
36    Keywords(PhraseList<'a>),
37
38    // 3.6.6   Resent Fields (not implemented)
39    // 3.6.7   Trace Fields
40    Received(ReceivedLog<'a>),
41    ReturnPath(Option<AddrSpec<'a>>),
42
43    MIMEVersion(Version),
44}
45impl<'a> TryFrom<&header::Field<'a>> for Field<'a> {
46    type Error = ();
47    fn try_from(f: &header::Field<'a>) -> Result<Self, Self::Error> {
48        let content = match f {
49            header::Field::Good(header::Kv2(key, value)) => {
50                match key.to_ascii_lowercase().as_slice() {
51                    b"date" => map(date, Field::Date)(value),
52                    b"from" => map(mailbox_list, Field::From)(value),
53                    b"sender" => map(mailbox, Field::Sender)(value),
54                    b"reply-to" => map(address_list, Field::ReplyTo)(value),
55                    b"to" => map(address_list, Field::To)(value),
56                    b"cc" => map(address_list, Field::Cc)(value),
57                    b"bcc" => map(nullable_address_list, Field::Bcc)(value),
58                    b"message-id" => map(msg_id, Field::MessageID)(value),
59                    b"in-reply-to" => map(msg_list, Field::InReplyTo)(value),
60                    b"references" => map(msg_list, Field::References)(value),
61                    b"subject" => map(unstructured, Field::Subject)(value),
62                    b"comments" => map(unstructured, Field::Comments)(value),
63                    b"keywords" => map(phrase_list, Field::Keywords)(value),
64                    b"return-path" => map(return_path, Field::ReturnPath)(value),
65                    b"received" => map(received_log, Field::Received)(value),
66                    b"mime-version" => map(version, Field::MIMEVersion)(value),
67                    _ => return Err(()),
68                }
69            }
70            _ => return Err(()),
71        };
72
73        content.map(|(_, content)| content).or(Err(()))
74    }
75}