mail_parser/core/builder.rs
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
use crate::{HeaderName, HeaderValue, MessageParser};
impl MessageParser {
/// Create a new builder for a message parser using the default settings.
///
/// The default settings are:
///
/// * IANA-registered headers defined in `HeaderName` are parsed with their corresponding parser.
/// * Other headers (`HeaderName::Other`) are parsed as raw.
///
pub fn new() -> Self {
Self {
header_map: Default::default(),
def_hdr_parse_fnc: |s| s.parse_raw(),
}
}
/// Parse all MIME headers:
///
/// * `Content-Type`
/// * `Content-Disposition`
/// * `Content-Id`
/// * `Content-Description`
/// * `Content-Location`
/// * `Content-Transfer-Encoding`
///
/// Adding these MIME headers is required in order to parse message bodies.
///
pub fn with_mime_headers(self) -> Self {
self.header_content_type(HeaderName::ContentType)
.header_content_type(HeaderName::ContentDisposition)
.header_id(HeaderName::ContentId)
.header_text(HeaderName::ContentDescription)
.header_text(HeaderName::ContentLocation)
.header_text(HeaderName::ContentTransferEncoding)
}
/// Parse all Date headers:
///
/// * `Date`
/// * `Resent-Date`
///
pub fn with_date_headers(self) -> Self {
self.header_date(HeaderName::Date)
.header_date(HeaderName::ResentDate)
}
/// Parse all address headers:
///
/// * `From`
/// * `Sender`
/// * `Reply-To`
/// * `To`
/// * `Cc`
/// * `Bcc`
/// * `Resent-From`
/// * `Resent-Sender`
/// * `Resent-To`
/// * `Resent-Cc`
/// * `Resent-Bcc`
///
pub fn with_address_headers(self) -> Self {
self.header_address(HeaderName::From)
.header_address(HeaderName::Sender)
.header_address(HeaderName::ReplyTo)
.header_address(HeaderName::To)
.header_address(HeaderName::Cc)
.header_address(HeaderName::Bcc)
.header_address(HeaderName::ResentFrom)
.header_address(HeaderName::ResentSender)
.header_address(HeaderName::ResentTo)
.header_address(HeaderName::ResentCc)
.header_address(HeaderName::ResentBcc)
}
/// Parse all ID headers:
///
/// * `Message-Id`
/// * `In-Reply-To`
/// * `References`
/// * `Resent-Message-Id`
///
pub fn with_message_ids(self) -> Self {
self.header_id(HeaderName::MessageId)
.header_id(HeaderName::InReplyTo)
.header_id(HeaderName::References)
.header_id(HeaderName::ResentMessageId)
}
/// Parse all MIME headers plus:
///
/// * `Date`
/// * `From`
/// * `Reply-To`
/// * `To`
/// * `Cc`
/// * `Bcc`
///
pub fn with_minimal_headers(self) -> Self {
self.with_mime_headers()
.header_date(HeaderName::Date)
.header_text(HeaderName::Subject)
.header_address(HeaderName::From)
.header_address(HeaderName::ReplyTo)
.header_address(HeaderName::To)
.header_address(HeaderName::Cc)
.header_address(HeaderName::Bcc)
}
/// Remove a custom header parser.
pub fn without_header(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map.remove(&header.into());
self
}
/// Parse a header as text decoding RFC 2047 encoded words.
pub fn header_text(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map
.insert(header.into(), |s| s.parse_unstructured());
self
}
/// Parse a header as a RFC 5322 date.
pub fn header_date(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map.insert(header.into(), |s| s.parse_date());
self
}
/// Parse a header as an address.
pub fn header_address(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map.insert(header.into(), |s| s.parse_address());
self
}
/// Parse a header as an ID.
pub fn header_id(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map.insert(header.into(), |s| s.parse_id());
self
}
/// Parse a header as a MIME `Content-Type` or `Content-Disposition` type.
pub fn header_content_type(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map
.insert(header.into(), |s| s.parse_content_type());
self
}
/// Parse a header as a comma-separated list of values.
pub fn header_comma_separated(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map
.insert(header.into(), |s| s.parse_comma_separared());
self
}
/// Parse a header as a received header.
pub fn header_received(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map
.insert(header.into(), |s| s.parse_received());
self
}
/// Parse a header as a raw string, no RFC 2047 decoding is done.
pub fn header_raw(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map.insert(header.into(), |s| s.parse_raw());
self
}
/// Ignore and skip parsing a header.
pub fn ignore_header(mut self, header: impl Into<HeaderName<'static>>) -> Self {
self.header_map.insert(header.into(), |s| {
s.parse_and_ignore();
HeaderValue::Empty
});
self
}
/// Parse all other headers as text decoding RFC 2047 encoded words.
pub fn default_header_text(mut self) -> Self {
self.def_hdr_parse_fnc = |s| s.parse_unstructured();
self
}
/// Parse all other headers as raw strings, no RFC 2047 decoding is done.
pub fn default_header_raw(mut self) -> Self {
self.def_hdr_parse_fnc = |s| s.parse_raw();
self
}
/// Ignore and skip parsing all other headers.
pub fn default_header_ignore(mut self) -> Self {
self.def_hdr_parse_fnc = |s| {
s.parse_and_ignore();
HeaderValue::Empty
};
self
}
}
impl Default for MessageParser {
fn default() -> Self {
Self::new()
}
}