server: handle application/* as an attachment
This commit is contained in:
parent
834e873862
commit
574de65c35
@ -119,9 +119,10 @@ async fn download_attachment(
|
||||
} else {
|
||||
format!("id:{}", id)
|
||||
};
|
||||
info!("download attachment {mid} {idx}");
|
||||
info!("download attachment message id '{mid}' idx '{idx}'");
|
||||
let idx: Vec<_> = idx
|
||||
.split('.')
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.parse().expect("not a usize"))
|
||||
.collect();
|
||||
let attachment = attachment_bytes(&nm, &mid, &idx)?;
|
||||
|
||||
@ -87,6 +87,7 @@ pub fn extract_body(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body,
|
||||
// APPLICATION_ZIP and APPLICATION_GZIP are handled in the thread function
|
||||
APPLICATION_ZIP => extract_unhandled(m),
|
||||
APPLICATION_GZIP => extract_unhandled(m),
|
||||
mt if mt.starts_with("application/") => Ok(Body::text("".to_string())),
|
||||
_ => extract_unhandled(m),
|
||||
};
|
||||
if let Err(err) = ret {
|
||||
@ -362,7 +363,7 @@ pub fn extract_mixed(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body
|
||||
.subparts
|
||||
.iter()
|
||||
.map(|sp| sp.ctype.mimetype.as_str())
|
||||
.filter(|mt| !handled_types.contains(mt))
|
||||
.filter(|mt| !handled_types.contains(mt) && !mt.starts_with("application/"))
|
||||
.collect();
|
||||
unhandled_types.sort();
|
||||
if !unhandled_types.is_empty() {
|
||||
@ -434,7 +435,11 @@ pub fn extract_mixed(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body
|
||||
)));
|
||||
}
|
||||
}
|
||||
mt => parts.push(unhandled_html(MULTIPART_MIXED, mt)),
|
||||
mt => {
|
||||
if !mt.starts_with("application/") {
|
||||
parts.push(unhandled_html(MULTIPART_MIXED, mt))
|
||||
}
|
||||
}
|
||||
}
|
||||
part_addr.pop();
|
||||
}
|
||||
@ -500,7 +505,7 @@ pub fn extract_related(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Bo
|
||||
.subparts
|
||||
.iter()
|
||||
.map(|sp| sp.ctype.mimetype.as_str())
|
||||
.filter(|mt| !handled_types.contains(mt))
|
||||
.filter(|mt| !handled_types.contains(mt) && !mt.starts_with("application/"))
|
||||
.collect();
|
||||
unhandled_types.sort();
|
||||
if !unhandled_types.is_empty() {
|
||||
@ -580,6 +585,13 @@ pub fn walk_attachments_inner<T, F: Fn(&ParsedMail, &[usize]) -> Option<T> + Cop
|
||||
// get the bytes for serving attachments of HTTP
|
||||
pub fn extract_attachments(m: &ParsedMail, id: &str) -> Result<Vec<Attachment>, ServerError> {
|
||||
let mut attachments = Vec::new();
|
||||
|
||||
if m.ctype.mimetype.starts_with("application/") {
|
||||
if let Some(attachment) = extract_attachment(m, id, &[]) {
|
||||
attachments.push(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, sp) in m.subparts.iter().enumerate() {
|
||||
if let Some(attachment) = extract_attachment(sp, id, &[idx]) {
|
||||
// Filter out inline attachements, they're flattened into the body of the message.
|
||||
@ -602,12 +614,30 @@ pub fn extract_attachment(m: &ParsedMail, id: &str, idx: &[usize]) -> Option<Att
|
||||
pct.map(|pct| pct.params.get("name").map(|f| f.clone())),
|
||||
) {
|
||||
// Use filename from Content-Disposition
|
||||
(Some(filename), _) => filename,
|
||||
(Some(filename), _) => Some(filename),
|
||||
// Use filename from Content-Type
|
||||
(_, Some(Some(name))) => name,
|
||||
// No known filename, assume it's not an attachment
|
||||
_ => return None,
|
||||
(_, Some(Some(name))) => Some(name),
|
||||
// No known filename
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let filename = if let Some(fname) = filename {
|
||||
fname
|
||||
} else {
|
||||
if m.ctype.mimetype.starts_with("application/") {
|
||||
// Generate a default filename
|
||||
format!(
|
||||
"attachment-{}",
|
||||
idx.iter()
|
||||
.map(|i| i.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(".")
|
||||
)
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
info!("filename {}", filename);
|
||||
|
||||
// TODO: grab this from somewhere
|
||||
|
||||
@ -479,6 +479,12 @@ pub fn attachment_bytes(nm: &Notmuch, id: &str, idx: &[usize]) -> Result<Attachm
|
||||
let file = File::open(&path)?;
|
||||
let mmap = unsafe { MmapOptions::new().map(&file)? };
|
||||
let m = parse_mail(&mmap)?;
|
||||
if idx.is_empty() {
|
||||
let Some(attachment) = extract_attachment(&m, id, &[]) else {
|
||||
return Err(ServerError::PartNotFound);
|
||||
};
|
||||
return Ok(attachment);
|
||||
}
|
||||
if let Some(attachment) = walk_attachments(&m, |sp, cur_idx| {
|
||||
if cur_idx == idx {
|
||||
let attachment = extract_attachment(&sp, id, idx).unwrap_or(Attachment {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user