summaryrefslogtreecommitdiff
path: root/melib/src/email/attachments.rs
diff options
context:
space:
mode:
Diffstat (limited to 'melib/src/email/attachments.rs')
-rw-r--r--melib/src/email/attachments.rs103
1 files changed, 85 insertions, 18 deletions
diff --git a/melib/src/email/attachments.rs b/melib/src/email/attachments.rs
index 723d4ed3..c02d1a60 100644
--- a/melib/src/email/attachments.rs
+++ b/melib/src/email/attachments.rs
@@ -142,7 +142,7 @@ impl AttachmentBuilder {
Ok((_, (ct, cst, params))) => {
if ct.eq_ignore_ascii_case(b"multipart") {
let mut boundary = None;
- for (n, v) in params {
+ for (n, v) in &params {
if n.eq_ignore_ascii_case(b"boundary") {
boundary = Some(v);
break;
@@ -155,6 +155,10 @@ impl AttachmentBuilder {
self.content_type = ContentType::Multipart {
boundary,
kind: MultipartType::from(cst),
+ parameters: params
+ .into_iter()
+ .map(|(kb, vb)| (kb.to_vec(), vb.to_vec()))
+ .collect::<Vec<(Vec<u8>, Vec<u8>)>>(),
parts,
};
} else {
@@ -208,7 +212,7 @@ impl AttachmentBuilder {
self.content_type = ContentType::CMSSignature;
} else {
let mut name: Option<String> = None;
- for (n, v) in params {
+ for (n, v) in &params {
if n.eq_ignore_ascii_case(b"name") {
if let Ok(v) = crate::email::parser::encodings::phrase(v.trim(), false)
.as_ref()
@@ -225,7 +229,14 @@ impl AttachmentBuilder {
tag.extend(ct);
tag.push(b'/');
tag.extend(cst);
- self.content_type = ContentType::Other { tag, name };
+ self.content_type = ContentType::Other {
+ tag,
+ name,
+ parameters: params
+ .into_iter()
+ .map(|(kb, vb)| (kb.to_vec(), vb.to_vec()))
+ .collect::<Vec<(Vec<u8>, Vec<u8>)>>(),
+ };
}
}
Err(e) => {
@@ -556,11 +567,18 @@ impl Attachment {
text.extend(self.decode(Default::default()));
}
ContentType::Multipart {
- ref kind,
+ kind: MultipartType::Related,
ref parts,
+ ref parameters,
..
- } => match kind {
- MultipartType::Alternative => {
+ } => {
+ if let Some(main_attachment) = parameters
+ .iter()
+ .find_map(|(k, v)| if k == b"type" { Some(v) } else { None })
+ .and_then(|t| parts.iter().find(|a| a.content_type == t.as_slice()))
+ {
+ main_attachment.get_text_recursive(text);
+ } else {
for a in parts {
if a.content_disposition.kind.is_inline() {
if let ContentType::Text {
@@ -573,14 +591,33 @@ impl Attachment {
}
}
}
- _ => {
- for a in parts {
- if a.content_disposition.kind.is_inline() {
+ }
+ ContentType::Multipart {
+ kind: MultipartType::Alternative,
+ ref parts,
+ ..
+ } => {
+ for a in parts {
+ if a.content_disposition.kind.is_inline() {
+ if let ContentType::Text {
+ kind: Text::Plain, ..
+ } = a.content_type
+ {
a.get_text_recursive(text);
+ break;
}
}
}
- },
+ }
+ ContentType::Multipart {
+ kind: _, ref parts, ..
+ } => {
+ for a in parts {
+ if a.content_disposition.kind.is_inline() {
+ a.get_text_recursive(text);
+ }
+ }
+ }
_ => {}
}
}
@@ -646,7 +683,10 @@ impl Attachment {
ref parts,
..
} => parts.iter().all(Attachment::is_html),
-
+ ContentType::Multipart {
+ kind: MultipartType::Related,
+ ..
+ } => false,
ContentType::Multipart { ref parts, .. } => parts.iter().any(Attachment::is_html),
_ => false,
}
@@ -709,12 +749,25 @@ impl Attachment {
boundary,
kind,
parts,
+ parameters,
} => {
let boundary = String::from_utf8_lossy(boundary);
ret.push_str(&format!("Content-Type: {}; boundary={}", kind, boundary));
if *kind == MultipartType::Signed {
ret.push_str("; micalg=pgp-sha512; protocol=\"application/pgp-signature\"");
}
+ for (n, v) in parameters {
+ ret.push_str("; ");
+ ret.push_str(&String::from_utf8_lossy(n));
+ ret.push('=');
+ if v.contains(&b' ') {
+ ret.push('"');
+ }
+ ret.push_str(&String::from_utf8_lossy(v));
+ if v.contains(&b' ') {
+ ret.push('"');
+ }
+ }
ret.push_str("\r\n");
let boundary_start = format!("\r\n--{}\r\n", boundary);
@@ -732,15 +785,25 @@ impl Attachment {
ret.push_str(&format!("Content-Type: {}\r\n\r\n", a.content_type));
ret.push_str(&String::from_utf8_lossy(a.body()));
}
- ContentType::OctetStream { ref name } => {
+ ContentType::OctetStream { name, parameters } => {
if let Some(name) = name {
- ret.push_str(&format!(
- "Content-Type: {}; name={}\r\n\r\n",
- a.content_type, name
- ));
+ ret.push_str(&format!("Content-Type: {}; name={}", a.content_type, name));
} else {
- ret.push_str(&format!("Content-Type: {}\r\n\r\n", a.content_type));
+ ret.push_str(&format!("Content-Type: {}", a.content_type));
+ }
+ for (n, v) in parameters {
+ ret.push_str("; ");
+ ret.push_str(&String::from_utf8_lossy(n));
+ ret.push('=');
+ if v.contains(&b' ') {
+ ret.push('"');
+ }
+ ret.push_str(&String::from_utf8_lossy(v));
+ if v.contains(&b' ') {
+ ret.push('"');
+ }
}
+ ret.push_str("\r\n\r\n");
ret.push_str(BASE64_MIME.encode(a.body()).trim());
}
_ => {
@@ -803,7 +866,10 @@ impl Attachment {
match self.content_type {
ContentType::Other { .. } => Vec::new(),
ContentType::Text { .. } => self.decode_helper(options),
- ContentType::OctetStream { ref name } => name
+ ContentType::OctetStream {
+ ref name,
+ parameters: _,
+ } => name
.clone()
.unwrap_or_else(|| self.mime_type())
.into_bytes(),
@@ -820,6 +886,7 @@ impl Attachment {
ContentType::Multipart {
ref kind,
ref parts,
+ parameters: _,
..
} => match kind {
MultipartType::Alternative => {