Bump to mail-parser 0.9

This commit is contained in:
mdecimus
2023-09-05 18:23:52 +02:00
parent 6939603932
commit 833db92ded
34 changed files with 513 additions and 580 deletions

View File

@@ -29,7 +29,7 @@ use imap_proto::{
use jmap::email::ingest::IngestEmail;
use jmap_proto::types::{acl::Acl, keyword::Keyword, state::StateChange, type_state::TypeState};
use mail_parser::Message;
use mail_parser::MessageParser;
use tokio::io::AsyncRead;
use crate::core::{MailboxId, SelectedMailbox, Session, SessionData};
@@ -135,7 +135,7 @@ impl SessionData {
.jmap
.email_ingest(IngestEmail {
raw_message: &message.message,
message: Message::parse(&message.message),
message: MessageParser::new().parse(&message.message),
account_id,
account_quota,
mailbox_ids: vec![mailbox_id],

View File

@@ -45,7 +45,7 @@ use jmap_proto::{
property::Property, state::StateChange, type_state::TypeState, value::Value,
},
};
use mail_parser::{GetHeader, Message, PartType, RfcHeader};
use mail_parser::{Address, GetHeader, HeaderName, Message, MessageParser, PartType};
use store::{
query::log::{Change, Query},
write::{assert::HashedValue, BatchBuilder, F_BITMAP, F_VALUE},
@@ -319,7 +319,7 @@ impl SessionData {
};
let message = if let Some(raw_message) = &raw_message {
if let Some(message) = Message::parse(raw_message) {
if let Some(message) = MessageParser::new().parse(raw_message) {
message.into()
} else {
tracing::warn!(
@@ -671,8 +671,8 @@ impl<'x> AsImapDataItem<'x> for Message<'x> {
};
let content_type = part
.headers
.rfc(&RfcHeader::ContentType)
.and_then(|ct| ct.as_content_type_ref());
.header_value(&HeaderName::ContentType)
.and_then(|ct| ct.as_content_type());
let mut body_md5 = None;
let mut extension = BodyPartExtension::default();
@@ -695,18 +695,18 @@ impl<'x> AsImapDataItem<'x> for Message<'x> {
fields.body_id = part
.headers
.rfc(&RfcHeader::ContentId)
.and_then(|id| id.as_text_ref().map(|id| format!("<{}>", id).into()));
.header_value(&HeaderName::ContentId)
.and_then(|id| id.as_text().map(|id| format!("<{}>", id).into()));
fields.body_description = part
.headers
.rfc(&RfcHeader::ContentDescription)
.and_then(|ct| ct.as_text_ref().map(|ct| ct.into()));
.header_value(&HeaderName::ContentDescription)
.and_then(|ct| ct.as_text().map(|ct| ct.into()));
fields.body_encoding = part
.headers
.rfc(&RfcHeader::ContentTransferEncoding)
.and_then(|ct| ct.as_text_ref().map(|ct| ct.into()));
.header_value(&HeaderName::ContentTransferEncoding)
.and_then(|ct| ct.as_text().map(|ct| ct.into()));
fields.body_size_octets = body.as_ref().map(|b| b.len()).unwrap_or(0);
@@ -730,8 +730,10 @@ impl<'x> AsImapDataItem<'x> for Message<'x> {
.map(|b| format!("{:x}", md5::compute(b)).into());
}
extension.body_disposition =
part.headers.rfc(&RfcHeader::ContentDisposition).map(|cd| {
extension.body_disposition = part
.headers
.header_value(&HeaderName::ContentDisposition)
.map(|cd| {
let cd = cd.content_type();
(
@@ -747,18 +749,18 @@ impl<'x> AsImapDataItem<'x> for Message<'x> {
)
});
extension.body_language =
part.headers
.rfc(&RfcHeader::ContentLanguage)
.and_then(|hv| {
hv.as_text_list()
.map(|list| list.into_iter().map(|item| item.into()).collect())
});
extension.body_language = part
.headers
.header_value(&HeaderName::ContentLanguage)
.and_then(|hv| {
hv.as_text_list()
.map(|list| list.into_iter().map(|item| item.into()).collect())
});
extension.body_location = part
.headers
.rfc(&RfcHeader::ContentLocation)
.and_then(|ct| ct.as_text_ref().map(|ct| ct.into()));
.header_value(&HeaderName::ContentLocation)
.and_then(|ct| ct.as_text().map(|ct| ct.into()));
}
match &part.body {
@@ -1045,27 +1047,27 @@ impl<'x> AsImapDataItem<'x> for Message<'x> {
date: self.date().cloned(),
subject: self.subject().map(|s| s.into()),
from: self
.header_values(RfcHeader::From)
.header_values(HeaderName::From)
.flat_map(|a| a.as_imap_address())
.collect(),
sender: self
.header_values(RfcHeader::Sender)
.header_values(HeaderName::Sender)
.flat_map(|a| a.as_imap_address())
.collect(),
reply_to: self
.header_values(RfcHeader::ReplyTo)
.header_values(HeaderName::ReplyTo)
.flat_map(|a| a.as_imap_address())
.collect(),
to: self
.header_values(RfcHeader::To)
.header_values(HeaderName::To)
.flat_map(|a| a.as_imap_address())
.collect(),
cc: self
.header_values(RfcHeader::Cc)
.header_values(HeaderName::Cc)
.flat_map(|a| a.as_imap_address())
.collect(),
bcc: self
.header_values(RfcHeader::Bcc)
.header_values(HeaderName::Bcc)
.flat_map(|a| a.as_imap_address())
.collect(),
in_reply_to: self.in_reply_to().as_text_list().map(|list| {
@@ -1109,15 +1111,7 @@ impl AsImapAddress for mail_parser::HeaderValue<'_> {
let mut addresses = Vec::new();
match self {
mail_parser::HeaderValue::Address(addr) => {
if let Some(email) = &addr.address {
addresses.push(fetch::Address::Single(fetch::EmailAddress {
name: addr.name.as_ref().map(|n| n.as_ref().into()),
address: email.as_ref().into(),
}));
}
}
mail_parser::HeaderValue::AddressList(list) => {
mail_parser::HeaderValue::Address(Address::List(list)) => {
for addr in list {
if let Some(email) = &addr.address {
addresses.push(fetch::Address::Single(fetch::EmailAddress {
@@ -1127,23 +1121,7 @@ impl AsImapAddress for mail_parser::HeaderValue<'_> {
}
}
}
mail_parser::HeaderValue::Group(group) => {
addresses.push(fetch::Address::Group(fetch::AddressGroup {
name: group.name.as_ref().map(|n| n.as_ref().into()),
addresses: group
.addresses
.iter()
.filter_map(|addr| {
fetch::EmailAddress {
name: addr.name.as_ref().map(|n| n.as_ref().into()),
address: addr.address.as_ref()?.as_ref().into(),
}
.into()
})
.collect(),
}));
}
mail_parser::HeaderValue::GroupList(list) => {
mail_parser::HeaderValue::Address(Address::Group(list)) => {
for group in list {
addresses.push(fetch::Address::Group(fetch::AddressGroup {
name: group.name.as_ref().map(|n| n.as_ref().into()),

View File

@@ -33,7 +33,7 @@ use imap_proto::{
};
use jmap_proto::types::{collection::Collection, id::Id, keyword::Keyword, property::Property};
use mail_parser::{HeaderName, RfcHeader};
use mail_parser::HeaderName;
use store::{
fts::{builder::MAX_TOKEN_LENGTH, Language},
query::{self, log::Query, sort::Pagination, ResultSet},
@@ -353,17 +353,22 @@ impl SessionData {
Language::None,
));
}
search::Filter::Header(header, value) => {
if let Some(HeaderName::Rfc(header_name)) = HeaderName::parse(&header) {
search::Filter::Header(header, value) => match HeaderName::parse(&header) {
Some(HeaderName::Other(_)) | None => {
return Err(StatusResponse::no(format!(
"Querying non-RFC header '{header}' is not allowed.",
)));
}
Some(header_name) => {
let is_id = matches!(
header_name,
RfcHeader::MessageId
| RfcHeader::InReplyTo
| RfcHeader::References
| RfcHeader::ResentMessageId
HeaderName::MessageId
| HeaderName::InReplyTo
| HeaderName::References
| HeaderName::ResentMessageId
);
let tokens = if !value.is_empty() {
let header_num = u8::from(header_name).to_string();
let header_num = header_name.id().to_string();
value
.split_ascii_whitespace()
.filter_map(|token| {
@@ -386,7 +391,7 @@ impl SessionData {
0 => {
filters.push(query::Filter::has_raw_text(
Property::Headers,
u8::from(header_name).to_string(),
header_name.id().to_string(),
));
}
1 => {
@@ -406,12 +411,8 @@ impl SessionData {
filters.push(query::Filter::End);
}
}
} else {
return Err(StatusResponse::no(format!(
"Querying non-RFC header '{header}' is not allowed.",
)));
};
}
}
},
search::Filter::Keyword(keyword) => {
filters.push(query::Filter::is_in_bitmap(
Property::Keywords,