mailparse/
headers.rs

1use crate::{MailHeader, MailHeaderMap};
2use std::fmt;
3use std::slice;
4
5/// A struct that wrapps the header portion of a message and provides
6/// utility functions to look up specific headers.
7pub struct Headers<'a> {
8    raw_bytes: &'a [u8],
9    headers: &'a [MailHeader<'a>],
10}
11
12impl<'a> Headers<'a> {
13    pub(crate) fn new(raw_bytes: &'a [u8], headers: &'a [MailHeader<'a>]) -> Headers<'a> {
14        Headers { raw_bytes, headers }
15    }
16
17    /// Returns the raw, unparsed bytes that make up the header block of
18    /// the message. This includes everything up to and including the empty
19    /// line at the end of the header block.
20    ///
21    /// # Examples
22    /// ```
23    ///     use mailparse::{parse_mail, headers::Headers};
24    ///     let mail = parse_mail(concat!(
25    ///             "SubJECT : foo\n",
26    ///             "\n",
27    ///             "Body starts here").as_bytes())
28    ///         .unwrap();
29    ///     assert_eq!(mail.get_headers().get_raw_bytes(), b"SubJECT : foo\n\n");
30    pub fn get_raw_bytes(&self) -> &'a [u8] {
31        self.raw_bytes
32    }
33}
34
35/// Allows iterating over the individual `MailHeader` items in this block of
36/// headers.
37///
38/// # Examples
39/// ```
40///     use mailparse::{parse_mail, headers::Headers};
41///     let mail = parse_mail(concat!(
42///             "Subject: foo\n",
43///             "Another header: bar\n",
44///             "\n",
45///             "Body starts here").as_bytes())
46///         .unwrap();
47///     let mut iter = mail.get_headers().into_iter();
48///     assert_eq!(iter.next().unwrap().get_key(), "Subject");
49///     assert_eq!(iter.next().unwrap().get_key(), "Another header");
50/// ```
51impl<'a> IntoIterator for Headers<'a> {
52    type Item = &'a MailHeader<'a>;
53    type IntoIter = slice::Iter<'a, MailHeader<'a>>;
54
55    fn into_iter(self) -> Self::IntoIter {
56        self.headers.into_iter()
57    }
58}
59
60/// Allows formatting and printing the `Headers` struct items.
61///
62/// # Examples
63/// ```
64///     use mailparse::parse_mail;
65///     let mail = parse_mail(concat!(
66///             "Subject: foo\n",
67///             "Another header: bar\n",
68///             "\n",
69///             "Body starts here").as_bytes())
70///         .unwrap();
71///     let mut headers = mail.get_headers();
72///     assert_eq!(format!("{:?}", headers), "Headers { \
73///                headers: [MailHeader { key: \"Subject\", value: \"foo\" }, \
74///                MailHeader { key: \"Another header\", value: \"bar\" }] }");
75/// ```
76impl<'a> fmt::Debug for Headers<'a> {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        f.debug_struct("Headers")
79            .field("headers", &self.headers)
80            .finish()
81    }
82}
83
84impl<'a> MailHeaderMap for Headers<'a> {
85    /// # Examples
86    /// ```
87    ///     use mailparse::{parse_mail, MailHeaderMap, headers::Headers};
88    ///     let mail = parse_mail(concat!(
89    ///             "Subject: Test\n",
90    ///             "\n",
91    ///             "This is a test message").as_bytes())
92    ///         .unwrap();
93    ///     assert_eq!(mail.get_headers().get_first_value("Subject"), Some("Test".to_string()));
94    /// ```
95    fn get_first_value(&self, key: &str) -> Option<String> {
96        self.headers.get_first_value(key)
97    }
98
99    fn get_first_header(&self, key: &str) -> Option<&MailHeader> {
100        self.headers.get_first_header(key)
101    }
102
103    /// # Examples
104    /// ```
105    ///     use mailparse::{parse_mail, MailHeaderMap, headers::Headers};
106    ///     let mail = parse_mail(concat!(
107    ///             "Key: Value1\n",
108    ///             "Key: Value2").as_bytes())
109    ///         .unwrap();
110    ///     assert_eq!(mail.get_headers().get_all_values("Key"),
111    ///         vec!["Value1".to_string(), "Value2".to_string()]);
112    /// ```
113    fn get_all_values(&self, key: &str) -> Vec<String> {
114        self.headers.get_all_values(key)
115    }
116
117    fn get_all_headers(&self, key: &str) -> Vec<&MailHeader> {
118        self.headers.get_all_headers(key)
119    }
120}