message: replace mailparser dep with mailparsing

Use our own parser
This commit is contained in:
Wez Furlong
2023-08-25 08:55:28 -07:00
parent d133a1d98c
commit e03ee5badf
10 changed files with 65 additions and 76 deletions
Generated
+1 -1
View File
@@ -2875,8 +2875,8 @@ dependencies = [
"kumo-log-types",
"lazy_static",
"lruttl",
"mail-parser",
"mailparse",
"mailparsing",
"mlua",
"prometheus",
"rand",
+2
View File
@@ -12,4 +12,6 @@ pub enum MailParsingError {
InvalidContentTransferEncoding(String),
#[error("parsing body: {0}")]
BodyParse(String),
#[error("Data is not ASCII or UTF-8")]
NotAscii,
}
+5 -2
View File
@@ -3,6 +3,7 @@ use crate::rfc5322_parser::Parser;
use crate::{
AddressList, MailParsingError, Mailbox, MailboxList, MimeParameters, Result, SharedString,
};
use std::convert::TryInto;
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
@@ -188,10 +189,12 @@ impl<'a> Header<'a> {
Parser::parse_unstructured_header(self.get_raw_value())
}
pub fn parse_headers<S: Into<SharedString<'a>>>(
pub fn parse_headers<S: TryInto<SharedString<'a>>>(
header_block: S,
) -> Result<HeaderParseResult<'a>> {
let header_block = header_block.into();
let header_block = header_block
.try_into()
.map_err(|_| MailParsingError::NotAscii)?;
let mut headers = vec![];
let mut idx = 0;
let mut overall_conformance = HeaderConformance::default();
+1 -1
View File
@@ -10,7 +10,7 @@ pub use error::MailParsingError;
pub type Result<T> = std::result::Result<T, MailParsingError>;
pub use header::{Header, HeaderConformance, HeaderParseResult};
pub use headermap::HeaderMap;
pub use headermap::*;
pub use mimepart::MimePart;
pub use rfc5322_parser::*;
pub use strings::SharedString;
+3 -2
View File
@@ -2,6 +2,7 @@ use crate::header::{HeaderConformance, HeaderParseResult};
use crate::headermap::HeaderMap;
use crate::{Header, MailParsingError, MimeParameters, Result, SharedString};
use charset::Charset;
use std::convert::TryInto;
use std::str::FromStr;
/// Define our own because data_encoding::BASE64_MIME, despite its name,
@@ -80,8 +81,8 @@ impl Rfc2045Info {
impl<'a> MimePart<'a> {
/// Parse some data into a tree of MimeParts
pub fn parse<S: Into<SharedString<'a>>>(bytes: S) -> Result<Self> {
let bytes = bytes.into();
pub fn parse<S: TryInto<SharedString<'a>>>(bytes: S) -> Result<Self> {
let bytes = bytes.try_into().map_err(|_| MailParsingError::NotAscii)?;
Self::parse_impl(bytes, true)
}
+2 -2
View File
@@ -1225,10 +1225,10 @@ pub enum Address {
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddressList(Vec<Address>);
pub struct AddressList(pub Vec<Address>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MailboxList(Vec<Mailbox>);
pub struct MailboxList(pub Vec<Mailbox>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Mailbox {
+8
View File
@@ -120,3 +120,11 @@ impl<'a> From<&'a str> for SharedString<'a> {
Self::Borrowed(s)
}
}
impl<'a> TryFrom<&'a [u8]> for SharedString<'a> {
type Error = std::str::Utf8Error;
fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> {
let s = std::str::from_utf8(s)?;
Ok(Self::Borrowed(s))
}
}
+1 -1
View File
@@ -19,7 +19,7 @@ kumo-log-types = {path="../kumo-log-types"}
lazy_static = "1.4"
lruttl = {path="../lruttl"}
mailparse = "0.14"
mail-parser = "0.8"
mailparsing = {path="../mailparsing"}
mlua = {workspace=true, features=["vendored", "lua54", "async", "send", "serialize"]}
prometheus = "0.13"
rand = "0.8"
+33 -64
View File
@@ -1,5 +1,5 @@
use config::any_err;
use mail_parser::{Addr, Group, HeaderValue};
use mailparsing::{Address, AddressList, EncodeHeaderValue, Mailbox};
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
use rfc5321::{ForwardPath, ReversePath};
use serde::{Deserialize, Serialize};
@@ -146,6 +146,13 @@ impl HeaderAddressList {
}
}
impl From<AddressList> for HeaderAddressList {
fn from(input: AddressList) -> HeaderAddressList {
let addresses: Vec<HeaderAddressEntry> = input.0.iter().map(Into::into).collect();
HeaderAddressList(addresses)
}
}
impl UserData for HeaderAddressList {
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
fields.add_field_method_get("user", |_, this| {
@@ -183,18 +190,22 @@ pub enum HeaderAddressEntry {
Group(AddressGroup),
}
impl From<Addr<'_>> for HeaderAddressEntry {
fn from(addr: Addr) -> Self {
Self::Address(addr.into())
}
}
impl From<Group<'_>> for HeaderAddressEntry {
fn from(group: Group) -> Self {
Self::Group(AddressGroup {
name: group.name.map(|s| s.to_string()),
addresses: group.addresses.into_iter().map(|a| a.into()).collect(),
})
impl From<&Address> for HeaderAddressEntry {
fn from(addr: &Address) -> HeaderAddressEntry {
match addr {
Address::Mailbox(mbox) => HeaderAddressEntry::Address(mbox.into()),
Address::Group { name, entries } => {
let addresses = entries.0.iter().map(Into::into).collect();
HeaderAddressEntry::Group(AddressGroup {
name: if name.is_empty() {
None
} else {
Some(name.to_string())
},
addresses,
})
}
}
}
}
@@ -204,6 +215,15 @@ pub struct HeaderAddress {
pub address: Option<String>,
}
impl From<&Mailbox> for HeaderAddress {
fn from(mbox: &Mailbox) -> HeaderAddress {
Self {
name: mbox.name.clone(),
address: Some(mbox.address.encode_value().to_string()),
}
}
}
impl HeaderAddress {
fn user(&self) -> anyhow::Result<&str> {
let (user, _domain) = self.crack_address().map_err(any_err)?;
@@ -251,59 +271,8 @@ impl UserData for HeaderAddress {
}
}
impl From<Addr<'_>> for HeaderAddress {
fn from(addr: Addr) -> Self {
Self {
name: addr.name.map(|s| s.to_string()),
address: addr.address.map(|s| s.to_string()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AddressGroup {
pub name: Option<String>,
pub addresses: Vec<HeaderAddress>,
}
impl HeaderAddressList {
pub fn parse_header_value(data: &[u8]) -> Option<Self> {
// The parser needs a newline in the data otherwise it
// won't recognize the value
let mut fixed = data.to_vec();
fixed.push(b'\n');
let res = mail_parser::parsers::MessageStream::new(&fixed).parse_address();
let mut results = vec![];
match res {
HeaderValue::Address(addr) => {
results.push(addr.into());
}
HeaderValue::AddressList(list) => {
for addr in list {
results.push(addr.into());
}
}
HeaderValue::Group(group) => {
results.push(group.into());
}
HeaderValue::GroupList(list) => {
for group in list {
results.push(group.into());
}
}
HeaderValue::Text(_)
| HeaderValue::TextList(_)
| HeaderValue::DateTime(_)
| HeaderValue::ContentType(_)
| HeaderValue::Empty => {}
}
if results.is_empty() {
None
} else {
Some(Self(results))
}
}
}
+9 -3
View File
@@ -9,6 +9,7 @@ use futures::FutureExt;
use kumo_log_types::rfc3464::Report;
use kumo_log_types::rfc5965::ARFReport;
use mailparse::{MailHeader, MailHeaderMap};
use mailparsing::HeaderParseResult;
use mlua::{LuaSerdeExt, UserData, UserDataMethods};
use prometheus::IntGauge;
use serde::{Deserialize, Serialize};
@@ -593,10 +594,15 @@ impl Message {
header_name: &str,
) -> anyhow::Result<Option<HeaderAddressList>> {
let data = self.get_data();
let (headers, _body_offset) = mailparse::parse_headers(&data)?;
let HeaderParseResult { headers, .. } =
mailparsing::Header::parse_headers(data.as_ref().as_ref())?;
match headers.get_first_header(header_name) {
Some(hdr) => Ok(HeaderAddressList::parse_header_value(hdr.get_value_raw())),
match headers.get_first(header_name) {
Some(hdr) => {
let list = hdr.as_address_list()?;
let result: HeaderAddressList = list.into();
Ok(Some(result))
}
None => Ok(None),
}
}