mail_parser/core/
builder.rs

1/*
2 * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
3 *
4 * SPDX-License-Identifier: Apache-2.0 OR MIT
5 */
6
7use crate::{HeaderName, HeaderValue, MessageParser};
8
9impl MessageParser {
10    /// Create a new builder for a message parser using the default settings.
11    ///
12    /// The default settings are:
13    ///
14    /// * IANA-registered headers defined in `HeaderName` are parsed with their corresponding parser.
15    /// * Other headers (`HeaderName::Other`) are parsed as raw.
16    ///
17    pub fn new() -> Self {
18        Self {
19            header_map: Default::default(),
20            def_hdr_parse_fnc: |s| s.parse_raw(),
21        }
22    }
23
24    /// Parse all MIME headers:
25    ///
26    /// * `Content-Type`
27    /// * `Content-Disposition`
28    /// * `Content-Id`
29    /// * `Content-Description`
30    /// * `Content-Location`
31    /// * `Content-Transfer-Encoding`
32    ///
33    /// Adding these MIME headers is required in order to parse message bodies.
34    ///
35    pub fn with_mime_headers(self) -> Self {
36        self.header_content_type(HeaderName::ContentType)
37            .header_content_type(HeaderName::ContentDisposition)
38            .header_id(HeaderName::ContentId)
39            .header_text(HeaderName::ContentDescription)
40            .header_text(HeaderName::ContentLocation)
41            .header_text(HeaderName::ContentTransferEncoding)
42    }
43
44    /// Parse all Date headers:
45    ///
46    /// * `Date`
47    /// * `Resent-Date`
48    ///
49    pub fn with_date_headers(self) -> Self {
50        self.header_date(HeaderName::Date)
51            .header_date(HeaderName::ResentDate)
52    }
53
54    /// Parse all address headers:
55    ///
56    /// * `From`
57    /// * `Sender`
58    /// * `Reply-To`
59    /// * `To`
60    /// * `Cc`
61    /// * `Bcc`
62    /// * `Resent-From`
63    /// * `Resent-Sender`
64    /// * `Resent-To`
65    /// * `Resent-Cc`
66    /// * `Resent-Bcc`
67    ///
68    pub fn with_address_headers(self) -> Self {
69        self.header_address(HeaderName::From)
70            .header_address(HeaderName::Sender)
71            .header_address(HeaderName::ReplyTo)
72            .header_address(HeaderName::To)
73            .header_address(HeaderName::Cc)
74            .header_address(HeaderName::Bcc)
75            .header_address(HeaderName::ResentFrom)
76            .header_address(HeaderName::ResentSender)
77            .header_address(HeaderName::ResentTo)
78            .header_address(HeaderName::ResentCc)
79            .header_address(HeaderName::ResentBcc)
80    }
81
82    /// Parse all ID headers:
83    ///
84    /// * `Message-Id`
85    /// * `In-Reply-To`
86    /// * `References`
87    /// * `Resent-Message-Id`
88    ///
89    pub fn with_message_ids(self) -> Self {
90        self.header_id(HeaderName::MessageId)
91            .header_id(HeaderName::InReplyTo)
92            .header_id(HeaderName::References)
93            .header_id(HeaderName::ResentMessageId)
94    }
95
96    /// Parse all MIME headers plus:
97    ///
98    /// * `Date`
99    /// * `From`
100    /// * `Reply-To`
101    /// * `To`
102    /// * `Cc`
103    /// * `Bcc`
104    ///
105    pub fn with_minimal_headers(self) -> Self {
106        self.with_mime_headers()
107            .header_date(HeaderName::Date)
108            .header_text(HeaderName::Subject)
109            .header_address(HeaderName::From)
110            .header_address(HeaderName::ReplyTo)
111            .header_address(HeaderName::To)
112            .header_address(HeaderName::Cc)
113            .header_address(HeaderName::Bcc)
114    }
115
116    /// Remove a custom header parser.
117    pub fn without_header(mut self, header: impl Into<HeaderName<'static>>) -> Self {
118        self.header_map.remove(&header.into());
119        self
120    }
121
122    /// Parse a header as text decoding RFC 2047 encoded words.
123    pub fn header_text(mut self, header: impl Into<HeaderName<'static>>) -> Self {
124        self.header_map
125            .insert(header.into(), |s| s.parse_unstructured());
126        self
127    }
128
129    /// Parse a header as a RFC 5322 date.
130    pub fn header_date(mut self, header: impl Into<HeaderName<'static>>) -> Self {
131        self.header_map.insert(header.into(), |s| s.parse_date());
132        self
133    }
134
135    /// Parse a header as an address.
136    pub fn header_address(mut self, header: impl Into<HeaderName<'static>>) -> Self {
137        self.header_map.insert(header.into(), |s| s.parse_address());
138        self
139    }
140
141    /// Parse a header as an ID.
142    pub fn header_id(mut self, header: impl Into<HeaderName<'static>>) -> Self {
143        self.header_map.insert(header.into(), |s| s.parse_id());
144        self
145    }
146
147    /// Parse a header as a MIME `Content-Type` or `Content-Disposition` type.
148    pub fn header_content_type(mut self, header: impl Into<HeaderName<'static>>) -> Self {
149        self.header_map
150            .insert(header.into(), |s| s.parse_content_type());
151        self
152    }
153
154    /// Parse a header as a comma-separated list of values.
155    pub fn header_comma_separated(mut self, header: impl Into<HeaderName<'static>>) -> Self {
156        self.header_map
157            .insert(header.into(), |s| s.parse_comma_separared());
158        self
159    }
160
161    /// Parse a header as a received header.
162    pub fn header_received(mut self, header: impl Into<HeaderName<'static>>) -> Self {
163        self.header_map
164            .insert(header.into(), |s| s.parse_received());
165        self
166    }
167
168    /// Parse a header as a raw string, no RFC 2047 decoding is done.
169    pub fn header_raw(mut self, header: impl Into<HeaderName<'static>>) -> Self {
170        self.header_map.insert(header.into(), |s| s.parse_raw());
171        self
172    }
173
174    /// Ignore and skip parsing a header.
175    pub fn ignore_header(mut self, header: impl Into<HeaderName<'static>>) -> Self {
176        self.header_map.insert(header.into(), |s| {
177            s.parse_and_ignore();
178            HeaderValue::Empty
179        });
180        self
181    }
182
183    /// Parse all other headers as text decoding RFC 2047 encoded words.
184    pub fn default_header_text(mut self) -> Self {
185        self.def_hdr_parse_fnc = |s| s.parse_unstructured();
186        self
187    }
188
189    /// Parse all other headers as raw strings, no RFC 2047 decoding is done.
190    pub fn default_header_raw(mut self) -> Self {
191        self.def_hdr_parse_fnc = |s| s.parse_raw();
192        self
193    }
194
195    /// Ignore and skip parsing all other headers.
196    pub fn default_header_ignore(mut self) -> Self {
197        self.def_hdr_parse_fnc = |s| {
198            s.parse_and_ignore();
199            HeaderValue::Empty
200        };
201        self
202    }
203}
204
205impl Default for MessageParser {
206    fn default() -> Self {
207        Self::new()
208    }
209}