diff options
author | Kartikaya Gupta <kats@seldon.staktrace.com> | 2016-06-22 10:09:42 -0400 |
---|---|---|
committer | Kartikaya Gupta <kats@seldon.staktrace.com> | 2016-06-22 10:10:55 -0400 |
commit | accf7a59489a4cd6107708d41900142d06544be9 (patch) | |
tree | 6414652f9c951ed913c56540794756732b353bc5 /src/lib.rs | |
parent | 47524a5b3da08a81a545e997c31b24c9cbe3707d (diff) |
Add case-insensitive accessors for headers
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 40 |
1 files changed, 38 insertions, 2 deletions
@@ -375,6 +375,11 @@ 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. + 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 @@ -391,6 +396,11 @@ pub trait MailHeaderMap { /// vec!["Value1".to_string(), "Value2".to_string()]); /// ``` 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. + fn get_all_values_ci(&self, key: &str) -> Result<Vec<String>, MailParseError>; } impl<'a> MailHeaderMap for Vec<MailHeader<'a>> { @@ -403,6 +413,16 @@ impl<'a> MailHeaderMap for Vec<MailHeader<'a>> { Ok(None) } + fn get_first_value_ci(&self, key: &str) -> Result<Option<String>, MailParseError> { + let lower_key = key.to_lowercase(); + for x in self { + if try!(x.get_key()).to_lowercase() == lower_key { + return x.get_value().map(|v| Some(v)); + } + } + Ok(None) + } + fn get_all_values(&self, key: &str) -> Result<Vec<String>, MailParseError> { let mut values: Vec<String> = Vec::new(); for x in self { @@ -412,6 +432,17 @@ impl<'a> MailHeaderMap for Vec<MailHeader<'a>> { } Ok(values) } + + fn get_all_values_ci(&self, key: &str) -> Result<Vec<String>, MailParseError> { + let lower_key = key.to_lowercase(); + let mut values: Vec<String> = Vec::new(); + for x in self { + if try!(x.get_key()).to_lowercase() == lower_key { + values.push(try!(x.get_value())); + } + } + Ok(values) + } } /// Parses all the headers from the raw data given. @@ -563,7 +594,7 @@ impl<'a> ParsedMail<'a> { /// assert_eq!(p.get_body().unwrap(), "This is the body"); /// ``` pub fn get_body(&self) -> Result<String, MailParseError> { - let transfer_coding = try!(self.headers.get_first_value("Content-Transfer-Encoding")) + let transfer_coding = try!(self.headers.get_first_value_ci("Content-Transfer-Encoding")) .map(|s| s.to_lowercase()); let decoded = match transfer_coding.unwrap_or(String::new()).as_ref() { "base64" => { @@ -625,7 +656,7 @@ impl<'a> ParsedMail<'a> { /// ``` pub fn parse_mail(raw_data: &[u8]) -> Result<ParsedMail, MailParseError> { let (headers, ix_body) = try!(parse_headers(raw_data)); - let ctype = match try!(headers.get_first_value("Content-Type")) { + let ctype = match try!(headers.get_first_value_ci("Content-Type")) { Some(s) => try!(parse_content_type(&s)), None => { ParsedContentType { @@ -928,5 +959,10 @@ mod tests { let mail = parse_mail(b"Content-Type: text/plain; charset=x-unknown\r\n\r\nhello world") .unwrap(); assert_eq!(mail.get_body().unwrap(), "hello world"); + + let mail = parse_mail(b"ConTENT-tyPE: text/html\r\n\r\nhello world") + .unwrap(); + assert_eq!(mail.ctype.mimetype, "text/html"); + assert_eq!(mail.get_body().unwrap(), "hello world"); } } |