summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--src/lib.rs40
2 files changed, 39 insertions, 3 deletions
diff --git a/Cargo.toml b/Cargo.toml
index ba7c4b7..c031570 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mailparse"
-version = "0.1.1"
+version = "0.2.0"
authors = ["Kartikaya Gupta <kats@seldon.staktrace.com>"]
description = "A simple parser for MIME e-mail messages"
documentation = "https://staktrace.github.io/mailparse/target/doc/mailparse/"
diff --git a/src/lib.rs b/src/lib.rs
index 091f34d..00e6176 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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");
}
}