mirror of
https://gitlab.com/mailcat-devs/mailcat.git
synced 2025-12-20 13:23:26 +01:00
Use trait methods instead of MailMessage
This commit is contained in:
parent
bffb26c54a
commit
202736e0bd
2 changed files with 76 additions and 59 deletions
11
src/main.rs
11
src/main.rs
|
|
@ -23,12 +23,15 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let message = mailparse::parse_mail(&input)?.parse()?;
|
let message = mailparse::parse_mail(&input)?;
|
||||||
println!("Subject: {}", message.subject.unwrap_or_default());
|
println!("Subject: {}", message.subject().unwrap_or_default());
|
||||||
if let Some(date) = message.date {
|
if let Some(date) = message.date()? {
|
||||||
println!("Date: {}", date);
|
println!("Date: {}", date);
|
||||||
}
|
}
|
||||||
println!("---");
|
println!("---");
|
||||||
print!("{}", message.body.unwrap_or_default());
|
print!(
|
||||||
|
"{}",
|
||||||
|
message.body()?.unwrap_or_default().text.unwrap_or_default()
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
124
src/parsing.rs
124
src/parsing.rs
|
|
@ -1,16 +1,15 @@
|
||||||
use mailparse::{DispositionType, MailHeaderMap, ParsedMail};
|
use mailparse::{DispositionType, MailHeaderMap, ParsedMail};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug, Default)]
|
||||||
pub struct MailMessage {
|
pub struct Body {
|
||||||
pub subject: Option<String>,
|
pub text: Option<String>,
|
||||||
pub date: Option<chrono::DateTime<chrono::FixedOffset>>,
|
|
||||||
pub body: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ParsedMailExt {
|
pub trait ParsedMailExt {
|
||||||
fn is_attachment(&self) -> bool;
|
fn is_attachment(&self) -> bool;
|
||||||
fn get_body_text(&self) -> Result<Option<String>, anyhow::Error>;
|
fn subject(&self) -> Option<String>;
|
||||||
fn parse(&self) -> Result<MailMessage, anyhow::Error>;
|
fn date(&self) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, anyhow::Error>;
|
||||||
|
fn body(&self) -> Result<Option<Body>, anyhow::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParsedMailExt for ParsedMail<'a> {
|
impl<'a> ParsedMailExt for ParsedMail<'a> {
|
||||||
|
|
@ -18,37 +17,34 @@ impl<'a> ParsedMailExt for ParsedMail<'a> {
|
||||||
self.get_content_disposition().disposition == DispositionType::Attachment
|
self.get_content_disposition().disposition == DispositionType::Attachment
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_body_text(&self) -> Result<Option<String>, anyhow::Error> {
|
fn subject(&self) -> Option<String> {
|
||||||
let mimetype: mime::Mime = self.ctype.mimetype.parse()?;
|
self.headers.get_first_value("Subject")
|
||||||
if self.is_attachment() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
if mimetype == mime::TEXT_PLAIN {
|
|
||||||
return Ok(Some(self.get_body()?));
|
|
||||||
}
|
|
||||||
for subpart in &self.subparts {
|
|
||||||
if let Some(body) = subpart.get_body_text()? {
|
|
||||||
return Ok(Some(body));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(None)
|
|
||||||
}
|
}
|
||||||
|
fn date(&self) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, anyhow::Error> {
|
||||||
fn parse(&self) -> Result<MailMessage, anyhow::Error> {
|
|
||||||
let subject = self.headers.get_first_value("Subject");
|
|
||||||
let date = self
|
let date = self
|
||||||
.headers
|
.headers
|
||||||
.get_first_value("Date")
|
.get_first_value("Date")
|
||||||
.map(|s| chrono::DateTime::parse_from_rfc2822(&s))
|
.map(|s| chrono::DateTime::parse_from_rfc2822(&s))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
Ok(date)
|
||||||
|
}
|
||||||
|
|
||||||
let body = self.get_body_text()?;
|
fn body(&self) -> Result<Option<Body>, anyhow::Error> {
|
||||||
let message = MailMessage {
|
let mimetype: mime::Mime = self.ctype.mimetype.parse()?;
|
||||||
subject,
|
if self.is_attachment() {
|
||||||
date,
|
return Ok(None);
|
||||||
body,
|
}
|
||||||
};
|
if mimetype == mime::TEXT_PLAIN {
|
||||||
Ok(message)
|
return Ok(Some(Body {
|
||||||
|
text: Some(self.get_body()?),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
for subpart in &self.subparts {
|
||||||
|
if let Some(body) = subpart.body()? {
|
||||||
|
return Ok(Some(body));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,49 +147,67 @@ TsSbamFrw6EgcMWZw61sb2hhLgo=
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_plain_text_body() -> Result<(), anyhow::Error> {
|
fn test_plain_text_body() -> Result<(), anyhow::Error> {
|
||||||
let message = mailparse::parse_mail(TEXT_PLAIN.as_bytes())?.parse()?;
|
let message = mailparse::parse_mail(TEXT_PLAIN.as_bytes())?;
|
||||||
let expected_message = MailMessage {
|
assert_eq!(message.subject(), Some("Plain text body".to_string()));
|
||||||
subject: Some("Plain text body".to_string()),
|
assert_eq!(
|
||||||
date: Some(
|
message.date()?,
|
||||||
|
Some(
|
||||||
chrono::FixedOffset::east(3600 * 2)
|
chrono::FixedOffset::east(3600 * 2)
|
||||||
.ymd(2021, 7, 17)
|
.ymd(2021, 7, 17)
|
||||||
.and_hms(18, 4, 10),
|
.and_hms(18, 4, 10),
|
||||||
),
|
)
|
||||||
body: Some("Prostý text.".to_string()),
|
);
|
||||||
};
|
assert_eq!(
|
||||||
assert_eq!(message, expected_message);
|
message.body()?,
|
||||||
|
Some(Body {
|
||||||
|
text: Some("Prostý text.".to_string())
|
||||||
|
}),
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multipart_alternative_text_body() -> Result<(), anyhow::Error> {
|
fn test_multipart_alternative_text_body() -> Result<(), anyhow::Error> {
|
||||||
let message = mailparse::parse_mail(MULTIPART_ALTERNATIVE.as_bytes())?.parse()?;
|
let message = mailparse::parse_mail(MULTIPART_ALTERNATIVE.as_bytes())?;
|
||||||
let expected_message = MailMessage {
|
assert_eq!(message.subject(), Some("Plain text with HTML".to_string()));
|
||||||
subject: Some("Plain text with HTML".to_string()),
|
assert_eq!(
|
||||||
date: Some(
|
message.date()?,
|
||||||
|
Some(
|
||||||
chrono::FixedOffset::east(3600 * 2)
|
chrono::FixedOffset::east(3600 * 2)
|
||||||
.ymd(2021, 7, 17)
|
.ymd(2021, 7, 17)
|
||||||
.and_hms(18, 13, 26),
|
.and_hms(18, 13, 26),
|
||||||
),
|
)
|
||||||
body: Some("Prostý text.".to_string()),
|
);
|
||||||
};
|
assert_eq!(
|
||||||
assert_eq!(message, expected_message);
|
message.body()?,
|
||||||
|
Some(Body {
|
||||||
|
text: Some("Prostý text.".to_string())
|
||||||
|
}),
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multipart_mixed_alternative_text_body() -> Result<(), anyhow::Error> {
|
fn test_multipart_mixed_alternative_text_body() -> Result<(), anyhow::Error> {
|
||||||
let message = mailparse::parse_mail(MULTIPART_MIXED_ALTERNATIVE.as_bytes())?.parse()?;
|
let message = mailparse::parse_mail(MULTIPART_MIXED_ALTERNATIVE.as_bytes())?;
|
||||||
let expected_message = MailMessage {
|
assert_eq!(
|
||||||
subject: Some("Plain text with HTML and attachment".to_string()),
|
message.subject(),
|
||||||
date: Some(
|
Some("Plain text with HTML and attachment".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
message.date()?,
|
||||||
|
Some(
|
||||||
chrono::FixedOffset::east(3600 * 2)
|
chrono::FixedOffset::east(3600 * 2)
|
||||||
.ymd(2021, 7, 17)
|
.ymd(2021, 7, 17)
|
||||||
.and_hms(21, 39, 8),
|
.and_hms(21, 39, 8),
|
||||||
),
|
)
|
||||||
body: Some("Prostý text.".to_string()),
|
);
|
||||||
};
|
assert_eq!(
|
||||||
assert_eq!(message, expected_message);
|
message.body()?,
|
||||||
|
Some(Body {
|
||||||
|
text: Some("Prostý text.".to_string())
|
||||||
|
}),
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue