mirror of
https://gitlab.com/mailcat-devs/mailcat.git
synced 2025-12-20 09:53:26 +01:00
Extract attachments
This commit is contained in:
parent
b1e9a349c8
commit
424ce25b91
2 changed files with 59 additions and 24 deletions
10
src/main.rs
10
src/main.rs
|
|
@ -29,6 +29,14 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
println!("Date: {}", date);
|
||||
}
|
||||
println!("---");
|
||||
print!("{}", message.body()?.text.unwrap_or_default());
|
||||
let parts = message.parts()?;
|
||||
println!("{}", parts.text.unwrap_or_default());
|
||||
for (i, attachment) in parts.attachments.iter().enumerate() {
|
||||
println!(
|
||||
"[{}] {}",
|
||||
i,
|
||||
&attachment.filename.as_deref().unwrap_or("<unnamed>")
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,53 @@
|
|||
use mailparse::{DispositionType, MailHeaderMap, ParsedMail};
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Default)]
|
||||
pub struct Body {
|
||||
pub struct Parts {
|
||||
pub text: Option<String>,
|
||||
pub html: Option<String>,
|
||||
pub attachments: Vec<Attachment>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub struct Attachment {
|
||||
pub filename: Option<String>,
|
||||
pub ctype: mime::Mime,
|
||||
pub body: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Attachment {
|
||||
fn from_part(part: &ParsedMail) -> anyhow::Result<Self> {
|
||||
let content_disposition = dbg!(part.get_content_disposition());
|
||||
Ok(Self {
|
||||
filename: content_disposition.params.get("filename").cloned(),
|
||||
ctype: part.ctype.mimetype.parse()?,
|
||||
body: part.get_body_raw()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ParsedMailExt {
|
||||
fn is_attachment(&self) -> bool;
|
||||
fn subject(&self) -> Option<String>;
|
||||
fn date(&self) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, anyhow::Error>;
|
||||
fn body(&self) -> Result<Body, anyhow::Error>;
|
||||
fn parts(&self) -> Result<Parts, anyhow::Error>;
|
||||
}
|
||||
|
||||
fn find_body(message: &ParsedMail, body: &mut Body) -> Result<(), anyhow::Error> {
|
||||
if message.is_attachment() {
|
||||
return Ok(());
|
||||
}
|
||||
let mimetype: mime::Mime = message.ctype.mimetype.parse()?;
|
||||
if mimetype == mime::TEXT_PLAIN {
|
||||
body.text.get_or_insert(message.get_body()?);
|
||||
} else if mimetype == mime::TEXT_HTML {
|
||||
body.html.get_or_insert(message.get_body()?);
|
||||
}
|
||||
for subpart in &message.subparts {
|
||||
find_body(subpart, body)?;
|
||||
if body.text.is_some() && body.html.is_some() {
|
||||
fn find_body(message: &ParsedMail, parts: &mut Parts) -> Result<(), anyhow::Error> {
|
||||
if !message.subparts.is_empty() {
|
||||
for subpart in &message.subparts {
|
||||
find_body(subpart, parts)?;
|
||||
}
|
||||
} else {
|
||||
if message.is_attachment() {
|
||||
parts.attachments.push(Attachment::from_part(message)?);
|
||||
return Ok(());
|
||||
}
|
||||
let mimetype: mime::Mime = message.ctype.mimetype.parse()?;
|
||||
if mimetype == mime::TEXT_PLAIN {
|
||||
parts.text.get_or_insert(message.get_body()?);
|
||||
} else if mimetype == mime::TEXT_HTML {
|
||||
parts.html.get_or_insert(message.get_body()?);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -49,8 +69,8 @@ impl<'a> ParsedMailExt for ParsedMail<'a> {
|
|||
Ok(date)
|
||||
}
|
||||
|
||||
fn body(&self) -> Result<Body, anyhow::Error> {
|
||||
let mut body = Body::default();
|
||||
fn parts(&self) -> Result<Parts, anyhow::Error> {
|
||||
let mut body = Parts::default();
|
||||
find_body(self, &mut body)?;
|
||||
Ok(body)
|
||||
}
|
||||
|
|
@ -152,10 +172,11 @@ TsSbamFrw6EgcMWZw61sb2hhLgo=
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
message.body()?,
|
||||
Body {
|
||||
message.parts()?,
|
||||
Parts {
|
||||
text: Some("Prostý text.".to_string()),
|
||||
html: None,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
|
|
@ -174,10 +195,11 @@ TsSbamFrw6EgcMWZw61sb2hhLgo=
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
message.body()?,
|
||||
Body {
|
||||
message.parts()?,
|
||||
Parts {
|
||||
text: Some("Prostý text.".to_string()),
|
||||
html: Some("<strong>Tučný HTML text</strong>".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
|
|
@ -199,10 +221,15 @@ TsSbamFrw6EgcMWZw61sb2hhLgo=
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
message.body()?,
|
||||
Body {
|
||||
message.parts()?,
|
||||
Parts {
|
||||
text: Some("Prostý text.".to_string()),
|
||||
html: Some("<strong>Tučný HTML text</strong>".to_string()),
|
||||
attachments: vec![Attachment {
|
||||
filename: Some("test.txt".to_string()),
|
||||
ctype: mime::TEXT_PLAIN,
|
||||
body: "Nějaká příloha.\n".into(),
|
||||
}]
|
||||
},
|
||||
);
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue