use crate::{
message::mime_type::MimeHeader,
{ParserError, ParserResult},
};
#[inline]
pub fn start_with_fws(input: &str) -> bool {
input.starts_with(|c| c == ' ' || c == '\t')
}
pub fn get_mime_type<'a>(
headers: &'a [MimeHeader],
parent: Option<&'a [MimeHeader]>,
) -> ParserResult<(&'a str, &'a str)> {
match headers.iter().find(|h| h.name == "content-type") {
Some(content_type) => {
let mut value = content_type.value.splitn(2, '/');
match (value.next(), value.next()) {
(Some(t), Some(subtype)) => Ok((t, subtype)),
_ => Err(ParserError::InvalidMail(format!(
"Invalid content-type value: {}",
content_type.value
))),
}
}
None if parent.is_some() => {
#[allow(clippy::option_if_let_else)]
match parent.unwrap().iter().find(|h| h.name == "content-type") {
Some(content_type) if content_type.value == "multipart/digest" => {
Ok(("message", "rfc822"))
}
_ => Ok(("text", "plain")),
}
}
_ => Ok(("text", "plain")),
}
}
pub fn read_header(content: &mut &[&str]) -> Option<(String, String)> {
let mut split = content[0].splitn(2, ':');
match (split.next(), split.next()) {
(Some(header), Some(mut field)) => {
let folded_header = content[1..]
.iter()
.take_while(|s| start_with_fws(s))
.map(|s| {
*content = &content[1..];
*s
})
.collect::<Vec<&str>>()
.join("\r\n");
if field.starts_with(' ') {
field = &field[1..];
}
Some((
header.trim().to_ascii_lowercase(),
if folded_header.is_empty() {
field.to_string()
} else {
format!("{field}\r\n{folded_header}")
},
))
}
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_header() {
let input = vec![
"User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101",
" Thunderbird/78.8.1",
];
assert_eq!(
read_header(&mut (&input[..])),
Some((
"user-agent".to_string(),
"Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101\r\n Thunderbird/78.8.1"
.to_string()
))
);
}
}