1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::{MailHeader, MailHeaderMap};
use std::slice;

/// A struct that wrapps the header portion of a message and provides
/// utility functions to look up specific headers.
pub struct Headers<'a> {
    raw_bytes: &'a [u8],
    headers: &'a [MailHeader<'a>],
}

impl<'a> Headers<'a> {
    pub(crate) fn new(raw_bytes: &'a [u8], headers: &'a [MailHeader<'a>]) -> Headers<'a> {
        Headers { raw_bytes, headers }
    }

    /// Returns the raw, unparsed bytes that make up the header block of
    /// the message. This includes everything up to and including the empty
    /// line at the end of the header block.
    ///
    /// # Examples
    /// ```
    ///     use mailparse::{parse_mail, headers::Headers};
    ///     let mail = parse_mail(concat!(
    ///             "SubJECT : foo\n",
    ///             "\n",
    ///             "Body starts here").as_bytes())
    ///         .unwrap();
    ///     assert_eq!(mail.get_headers().get_raw_bytes(), b"SubJECT : foo\n\n");
    pub fn get_raw_bytes(&self) -> &'a [u8] {
        self.raw_bytes
    }
}

/// Allows iterating over the individual `MailHeader` items in this block of
/// headers.
///
/// # Examples
/// ```
///     use mailparse::{parse_mail, headers::Headers};
///     let mail = parse_mail(concat!(
///             "Subject: foo\n",
///             "Another header: bar\n",
///             "\n",
///             "Body starts here").as_bytes())
///         .unwrap();
///     let mut iter = mail.get_headers().into_iter();
///     assert_eq!(iter.next().unwrap().get_key(), "Subject");
///     assert_eq!(iter.next().unwrap().get_key(), "Another header");
/// ```
impl<'a> IntoIterator for Headers<'a> {
    type Item = &'a MailHeader<'a>;
    type IntoIter = slice::Iter<'a, MailHeader<'a>>;

    fn into_iter(self) -> Self::IntoIter {
        self.headers.into_iter()
    }
}

impl<'a> MailHeaderMap for Headers<'a> {
    /// # Examples
    /// ```
    ///     use mailparse::{parse_mail, MailHeaderMap, headers::Headers};
    ///     let mail = parse_mail(concat!(
    ///             "Subject: Test\n",
    ///             "\n",
    ///             "This is a test message").as_bytes())
    ///         .unwrap();
    ///     assert_eq!(mail.get_headers().get_first_value("Subject"), Some("Test".to_string()));
    /// ```
    fn get_first_value(&self, key: &str) -> Option<String> {
        self.headers.get_first_value(key)
    }

    fn get_first_header(&self, key: &str) -> Option<&MailHeader> {
        self.headers.get_first_header(key)
    }

    /// # Examples
    /// ```
    ///     use mailparse::{parse_mail, MailHeaderMap, headers::Headers};
    ///     let mail = parse_mail(concat!(
    ///             "Key: Value1\n",
    ///             "Key: Value2").as_bytes())
    ///         .unwrap();
    ///     assert_eq!(mail.get_headers().get_all_values("Key"),
    ///         vec!["Value1".to_string(), "Value2".to_string()]);
    /// ```
    fn get_all_values(&self, key: &str) -> Vec<String> {
        self.headers.get_all_values(key)
    }

    fn get_all_headers(&self, key: &str) -> Vec<&MailHeader> {
        self.headers.get_all_headers(key)
    }
}