lettre/message/header/
textual.rs

1use super::{Header, HeaderName, HeaderValue};
2use crate::BoxError;
3
4macro_rules! text_header {
5    ($(#[$attr:meta])* Header($type_name: ident, $header_name: expr )) => {
6        $(#[$attr])*
7        #[derive(Debug, Clone, PartialEq, Eq)]
8        pub struct $type_name(String);
9
10        impl Header for $type_name {
11            fn name() -> HeaderName {
12                HeaderName::new_from_ascii_str($header_name)
13            }
14
15            fn parse(s: &str) -> Result<Self, BoxError> {
16                Ok(Self(s.into()))
17            }
18
19            fn display(&self) -> HeaderValue {
20             HeaderValue::new(Self::name(),   self.0.clone())
21            }
22        }
23
24        impl From<String> for $type_name {
25            #[inline]
26            fn from(text: String) -> Self {
27                Self(text)
28            }
29        }
30
31        impl AsRef<str> for $type_name {
32            #[inline]
33            fn as_ref(&self) -> &str {
34                &self.0
35            }
36        }
37    };
38}
39
40text_header!(
41    /// `Subject` of the message, defined in [RFC5322](https://tools.ietf.org/html/rfc5322#section-3.6.5)
42    Header(Subject, "Subject")
43);
44text_header!(
45    /// `Comments` of the message, defined in [RFC5322](https://tools.ietf.org/html/rfc5322#section-3.6.5)
46    Header(Comments, "Comments")
47);
48text_header!(
49    /// `Keywords` header. Should contain a comma-separated list of one or more
50    /// words or quoted-strings, defined in [RFC5322](https://tools.ietf.org/html/rfc5322#section-3.6.5)
51    Header(Keywords, "Keywords")
52);
53text_header!(
54    /// `In-Reply-To` header. Contains one or more
55    /// unique message identifiers,
56    /// defined in [RFC5322](https://tools.ietf.org/html/rfc5322#section-3.6.4)
57    Header(InReplyTo, "In-Reply-To")
58);
59text_header!(
60    /// `References` header. Contains one or more
61    /// unique message identifiers,
62    /// defined in [RFC5322](https://tools.ietf.org/html/rfc5322#section-3.6.4)
63    Header(References, "References")
64);
65text_header!(
66    /// `Message-Id` header. Contains a unique message identifier,
67    /// defined in [RFC5322](https://tools.ietf.org/html/rfc5322#section-3.6.4)
68    Header(MessageId, "Message-ID")
69);
70text_header!(
71    /// `User-Agent` header. Contains information about the client,
72    /// defined in [draft-melnikov-email-user-agent-00](https://tools.ietf.org/html/draft-melnikov-email-user-agent-00#section-3)
73    Header(UserAgent, "User-Agent")
74);
75text_header! {
76    /// `Content-Id` header,
77    /// defined in [RFC2045](https://tools.ietf.org/html/rfc2045#section-7)
78    Header(ContentId, "Content-ID")
79}
80text_header! {
81    /// `Content-Location` header,
82    /// defined in [RFC2110](https://tools.ietf.org/html/rfc2110#section-4.3)
83    Header(ContentLocation, "Content-Location")
84}
85
86#[cfg(test)]
87mod test {
88    use pretty_assertions::assert_eq;
89
90    use super::Subject;
91    use crate::message::header::{HeaderName, HeaderValue, Headers};
92
93    #[test]
94    fn format_ascii() {
95        let mut headers = Headers::new();
96        headers.set(Subject("Sample subject".into()));
97
98        assert_eq!(headers.to_string(), "Subject: Sample subject\r\n");
99    }
100
101    #[test]
102    fn format_utf8() {
103        let mut headers = Headers::new();
104        headers.set(Subject("Тема сообщения".into()));
105
106        assert_eq!(
107            headers.to_string(),
108            "Subject: =?utf-8?b?0KLQtdC80LAg0YHQvtC+0LHRidC10L3QuNGP?=\r\n"
109        );
110    }
111
112    #[test]
113    fn format_utf8_word() {
114        let mut headers = Headers::new();
115        headers.set(Subject("Administratör".into()));
116
117        assert_eq!(
118            headers.to_string(),
119            "Subject: =?utf-8?b?QWRtaW5pc3RyYXTDtnI=?=\r\n"
120        );
121    }
122
123    #[test]
124    fn parse_ascii() {
125        let mut headers = Headers::new();
126        headers.insert_raw(HeaderValue::new(
127            HeaderName::new_from_ascii_str("Subject"),
128            "Sample subject".to_owned(),
129        ));
130
131        assert_eq!(
132            headers.get::<Subject>(),
133            Some(Subject("Sample subject".into()))
134        );
135    }
136}