melib: add has_attachments property to Envelope
Check subattachments in has_attachments check. Instead of getting a flattened attachment view of multipart/mixed (eg [multipart/mixed, text/plain, text/plain]) get only the subattachments (eg [text/plain, text/plain]). Don't count text-only multipart/mixed as attachmentsembed
parent
03317d74ca
commit
d0039740b0
|
@ -326,6 +326,7 @@ pub struct Envelope {
|
|||
hash: EnvelopeHash,
|
||||
|
||||
flags: Flag,
|
||||
has_attachments: bool,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Envelope {
|
||||
|
@ -359,6 +360,7 @@ impl Envelope {
|
|||
thread: ThreadHash::null(),
|
||||
|
||||
hash,
|
||||
has_attachments: false,
|
||||
flags: Flag::default(),
|
||||
}
|
||||
}
|
||||
|
@ -392,7 +394,7 @@ impl Envelope {
|
|||
self.hash
|
||||
}
|
||||
pub fn populate_headers(&mut self, bytes: &[u8]) -> Result<()> {
|
||||
let (headers, _) = match parser::mail(bytes).to_full_result() {
|
||||
let (headers, body) = match parser::mail(bytes).to_full_result() {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
debug!("error in parsing mail\n{:?}\n", e);
|
||||
|
@ -459,6 +461,22 @@ impl Envelope {
|
|||
} else {
|
||||
self.set_date(value);
|
||||
}
|
||||
} else if name.eq_ignore_ascii_case(b"content-type") {
|
||||
match parser::content_type(value).to_full_result() {
|
||||
Ok((ct, cst, _))
|
||||
if ct.eq_ignore_ascii_case(b"multipart")
|
||||
&& cst.eq_ignore_ascii_case(b"mixed") =>
|
||||
{
|
||||
let mut builder = AttachmentBuilder::new(body);
|
||||
builder.set_content_type(value);
|
||||
let b = builder.build();
|
||||
let subs = b.attachments();
|
||||
|
||||
self.has_attachments =
|
||||
subs.iter().fold(false, |acc, sub| acc || !sub.is_text());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -560,9 +578,9 @@ impl Envelope {
|
|||
continue;
|
||||
}
|
||||
if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
|
||||
builder.content_transfer_encoding(value);
|
||||
builder.set_content_transfer_encoding(value);
|
||||
} else if name.eq_ignore_ascii_case(b"content-type") {
|
||||
builder.content_type(value);
|
||||
builder.set_content_type(value);
|
||||
}
|
||||
}
|
||||
builder.build()
|
||||
|
@ -755,6 +773,9 @@ impl Envelope {
|
|||
pub fn is_seen(&self) -> bool {
|
||||
self.flags.contains(Flag::SEEN)
|
||||
}
|
||||
pub fn has_attachments(&self) -> bool {
|
||||
self.has_attachments
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Envelope {}
|
||||
|
|
|
@ -69,7 +69,11 @@ impl AttachmentBuilder {
|
|||
raw: content.to_vec(),
|
||||
}
|
||||
}
|
||||
pub fn content_type(&mut self, value: &[u8]) -> &Self {
|
||||
pub fn content_type(&mut self) -> &ContentType {
|
||||
&self.content_type
|
||||
}
|
||||
|
||||
pub fn set_content_type(&mut self, value: &[u8]) -> &Self {
|
||||
match parser::content_type(value).to_full_result() {
|
||||
Ok((ct, cst, params)) => {
|
||||
if ct.eq_ignore_ascii_case(b"multipart") {
|
||||
|
@ -86,7 +90,8 @@ impl AttachmentBuilder {
|
|||
(_boundary.as_ptr() as usize).wrapping_sub(value.as_ptr() as usize);
|
||||
let boundary = SliceBuild::new(offset, _boundary.len());
|
||||
let subattachments = Self::subattachments(&self.raw, boundary.get(&value));
|
||||
assert!(!subattachments.is_empty());
|
||||
// Invalid mail or wrong assumption?
|
||||
// assert!(!subattachments.is_empty());
|
||||
self.content_type = ContentType::Multipart {
|
||||
boundary,
|
||||
kind: if cst.eq_ignore_ascii_case(b"mixed") {
|
||||
|
@ -154,7 +159,7 @@ impl AttachmentBuilder {
|
|||
}
|
||||
self
|
||||
}
|
||||
pub fn content_transfer_encoding(&mut self, value: &[u8]) -> &Self {
|
||||
pub fn set_content_transfer_encoding(&mut self, value: &[u8]) -> &Self {
|
||||
self.content_transfer_encoding = if value.eq_ignore_ascii_case(b"base64") {
|
||||
ContentTransferEncoding::Base64
|
||||
} else if value.eq_ignore_ascii_case(b"7bit") {
|
||||
|
@ -231,9 +236,9 @@ impl AttachmentBuilder {
|
|||
builder.raw = body_slice.get(a).ltrim().into();
|
||||
for (name, value) in headers {
|
||||
if name.eq_ignore_ascii_case(b"content-type") {
|
||||
builder.content_type(value);
|
||||
builder.set_content_type(value);
|
||||
} else if name.eq_ignore_ascii_case(b"content-transfer-encoding") {
|
||||
builder.content_transfer_encoding(value);
|
||||
builder.set_content_transfer_encoding(value);
|
||||
}
|
||||
}
|
||||
vec.push(builder.build());
|
||||
|
@ -371,6 +376,12 @@ impl Attachment {
|
|||
pub fn content_transfer_encoding(&self) -> &ContentTransferEncoding {
|
||||
&self.content_transfer_encoding
|
||||
}
|
||||
pub fn is_text(&self) -> bool {
|
||||
match self.content_type {
|
||||
ContentType::Text { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn is_html(&self) -> bool {
|
||||
match self.content_type {
|
||||
ContentType::Text {
|
||||
|
|
|
@ -112,9 +112,10 @@ impl MailboxView {
|
|||
FromString(address_list!((e.from()) as comma_sep_list)),
|
||||
DateString(MailboxView::format_date(e)),
|
||||
SubjectString(format!(
|
||||
"{} ({}){}",
|
||||
"{} ({}){}{}",
|
||||
e.subject(),
|
||||
len,
|
||||
if e.has_attachments() { " π" } else { "" },
|
||||
if is_snoozed { " π€" } else { "" }
|
||||
)),
|
||||
)
|
||||
|
@ -124,8 +125,9 @@ impl MailboxView {
|
|||
FromString(address_list!((e.from()) as comma_sep_list)),
|
||||
DateString(MailboxView::format_date(e)),
|
||||
SubjectString(format!(
|
||||
"{}{}",
|
||||
"{}{}{}",
|
||||
e.subject(),
|
||||
if e.has_attachments() { " π" } else { "" },
|
||||
if is_snoozed { " π€" } else { "" }
|
||||
)),
|
||||
)
|
||||
|
@ -343,8 +345,23 @@ impl MailboxView {
|
|||
((_x, idx), (widths.2 + _x, idx)),
|
||||
false,
|
||||
);
|
||||
if threads.is_snoozed(root_idx) {
|
||||
self.content[(x - 1, idx)].set_fg(Color::Red);
|
||||
match (
|
||||
threads.is_snoozed(root_idx),
|
||||
&context.accounts[self.cursor_pos.0]
|
||||
.get_env(&i)
|
||||
.has_attachments(),
|
||||
) {
|
||||
(true, true) => {
|
||||
self.content[(x - 1, idx)].set_fg(Color::Red);
|
||||
self.content[(x - 2, idx)].set_fg(Color::Byte(103));
|
||||
}
|
||||
(true, false) => {
|
||||
self.content[(x - 1, idx)].set_fg(Color::Red);
|
||||
}
|
||||
(false, true) => {
|
||||
self.content[(x - 1, idx)].set_fg(Color::Byte(103));
|
||||
}
|
||||
(false, false) => {}
|
||||
}
|
||||
|
||||
self.order.insert(i, idx);
|
||||
|
|
Loadingβ¦
Reference in New Issue