diff options
author | Bruce Guenter <bruce@untroubled.org> | 2016-11-11 08:12:42 -0600 |
---|---|---|
committer | staktrace <accounts.github@staktrace.com> | 2016-11-11 11:32:53 -0500 |
commit | e4f54f9af1685095a42d00a66f7a09db2f9eef37 (patch) | |
tree | 17e56cead98909ef003686ee05103535d40e6e31 /src/lib.rs | |
parent | ef6816e494c581ff670d30ab1dba2163c26ebf0b (diff) |
Make MailHeaderMap perform case-insensitive searches
The trait MailHeaderMap has two methods for searching headers, normal
and case-insensitive. This documentation says:
> According to the spec the mail headers are supposed to be
> case-sensitive, but in real-world scenarios that's not always the
> case.
Actually, the spec says nothing that headers supposed to case-sensitive,
and historical precedent is to be case-insensitive. Certainly, all the
mail processing software I am familiar with (Thunderbird, qmail, ezmlm,
and mutt) treat headers as case insensitive. RFC 822 section 3.4.7 says:
> When matching any other syntactic unit, case is to be ignored. For
> example, the field-names "From", "FROM", "from", and even "FroM" are
> semantically equal and should all be treated identically.
While RFC 2822 did drop that section (and RFC 5322 didn't restore it),
others interpret other parts to indicate case insensitivity.
https://stackoverflow.com/a/6143644
> RFC 5322 does actually specify this, but it is very indirect.
https://www.gnu.org/software/emacs/manual/html_node/emacs/Mail-Headers.html
> Upper and lower case are equivalent in field names.
https://nifi.apache.org/docs/nifi-docs/components/org.apache.nifi.processors.email.ExtractEmailHeaders/index.html
> NOTE the header key is case insensitive
This change makes all header searches case insensitive.
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 30 |
1 files changed, 8 insertions, 22 deletions
@@ -144,7 +144,7 @@ fn test_find_from_u8() { } impl<'a> MailHeader<'a> { - /// Get the name of the header. Note that header names are case-sensitive. + /// Get the name of the header. Note that header names are case-insensitive. pub fn get_key(&self) -> Result<String, MailParseError> { Ok(try!(encoding::all::ISO_8859_1.decode(self.key, encoding::DecoderTrap::Strict)) .trim() @@ -364,7 +364,7 @@ pub fn parse_header(raw_data: &[u8]) -> Result<(MailHeader, usize), MailParseErr pub trait MailHeaderMap { /// Look through the list of headers and return the value of the first one /// that matches the provided key. It returns Ok(None) if the no matching - /// header was found. + /// header was found. Header names are matched case-insensitively. /// /// # Examples /// ``` @@ -378,15 +378,14 @@ pub trait MailHeaderMap { /// ``` fn get_first_value(&self, key: &str) -> Result<Option<String>, MailParseError>; - /// Same as get_first_value, but does a case-insensitive search for the header. - /// According to the spec the mail headers are supposed to be case-sensitive, - /// but in real-world scenarios that's not always the case. + /// Same as get_first_value. fn get_first_value_ci(&self, key: &str) -> Result<Option<String>, MailParseError>; /// Look through the list of headers and return the values of all headers /// matching the provided key. Returns an empty vector if no matching headers /// were found. The order of the returned values is the same as the order - /// of the matching headers in the message. + /// of the matching headers in the message. Header names are matched + /// case-insensitively. /// /// # Examples /// ``` @@ -400,20 +399,13 @@ pub trait MailHeaderMap { /// ``` fn get_all_values(&self, key: &str) -> Result<Vec<String>, MailParseError>; - /// Same as get_all_values, but does a case-insensitive search for the header. - /// According to the spec the mail headers are supposed to be case-sensitive, - /// but in real-world scenarios that's not always the case. + /// Same as get_all_values. fn get_all_values_ci(&self, key: &str) -> Result<Vec<String>, MailParseError>; } impl<'a> MailHeaderMap for Vec<MailHeader<'a>> { fn get_first_value(&self, key: &str) -> Result<Option<String>, MailParseError> { - for x in self { - if try!(x.get_key()) == key { - return x.get_value().map(|v| Some(v)); - } - } - Ok(None) + self.get_first_value_ci(key) } fn get_first_value_ci(&self, key: &str) -> Result<Option<String>, MailParseError> { @@ -427,13 +419,7 @@ impl<'a> MailHeaderMap for Vec<MailHeader<'a>> { } fn get_all_values(&self, key: &str) -> Result<Vec<String>, MailParseError> { - let mut values: Vec<String> = Vec::new(); - for x in self { - if try!(x.get_key()) == key { - values.push(try!(x.get_value())); - } - } - Ok(values) + self.get_all_values_ci(key) } fn get_all_values_ci(&self, key: &str) -> Result<Vec<String>, MailParseError> { |