Populate attribute list
This commit is contained in:
parent
f5385bba44
commit
aca37b64c8
1 changed files with 101 additions and 120 deletions
|
@ -1,4 +1,5 @@
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -278,64 +279,12 @@ impl MailboxView {
|
||||||
FetchAttribute::Envelope => {
|
FetchAttribute::Envelope => {
|
||||||
attributes.push(MessageAttribute::Envelope(message_envelope(&parsed)))
|
attributes.push(MessageAttribute::Envelope(message_envelope(&parsed)))
|
||||||
}
|
}
|
||||||
FetchAttribute::Body => {
|
FetchAttribute::Body => attributes.push(MessageAttribute::Body(
|
||||||
/*
|
build_imap_email_struct(&parsed, &parsed.structure)?,
|
||||||
* CAPTURE:
|
)),
|
||||||
b fetch 29878:29879 (BODY)
|
FetchAttribute::BodyStructure => attributes.push(MessageAttribute::Body(
|
||||||
* 29878 FETCH (BODY (("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 3264 82)("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 31834 643) "alternative"))
|
build_imap_email_struct(&parsed, &parsed.structure)?,
|
||||||
* 29879 FETCH (BODY ("text" "html" ("charset" "us-ascii") NIL NIL "7bit" 4107 131))
|
)),
|
||||||
^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^ ^^^^^^ ^^^^ ^^^
|
|
||||||
| | | | | | number of lines
|
|
||||||
| | | | | size
|
|
||||||
| | | | content transfer encoding
|
|
||||||
| | | description
|
|
||||||
| | id
|
|
||||||
| parameter list
|
|
||||||
b OK Fetch completed (0.001 + 0.000 secs).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*match parsed.structure {
|
|
||||||
Part(part_id) => {
|
|
||||||
match parsed.parts.get(part_id)? {
|
|
||||||
Text(
|
|
||||||
let fb = FetchBody {
|
|
||||||
parameter_list: vec![],
|
|
||||||
id: NString(None),
|
|
||||||
descritpion: NString(None),
|
|
||||||
// Default value is 7bit"
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc2045#section-6.1
|
|
||||||
content_transfer_encoding: IString::try_from("7bit").unwrap(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List(part_list) => todo!(),
|
|
||||||
MultiPart((first, rest)) => todo!(),
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// @TODO This is a stub
|
|
||||||
let is = IString::try_from("test").unwrap();
|
|
||||||
let b = BodyStructure::Single {
|
|
||||||
body: FetchBody {
|
|
||||||
basic: BasicFields {
|
|
||||||
parameter_list: vec![],
|
|
||||||
id: NString(Some(is.clone())),
|
|
||||||
description: NString(Some(is.clone())),
|
|
||||||
content_transfer_encoding: is.clone(),
|
|
||||||
size: 1,
|
|
||||||
},
|
|
||||||
specific: SpecificFields::Text {
|
|
||||||
// @FIXME I do not understand yet how this part works
|
|
||||||
subtype: is,
|
|
||||||
number_of_lines: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Always None for Body, can be populated for BodyStructure
|
|
||||||
extension: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
attributes.push(MessageAttribute::Body(b));
|
|
||||||
}
|
|
||||||
FetchAttribute::BodyExt {
|
FetchAttribute::BodyExt {
|
||||||
section,
|
section,
|
||||||
partial,
|
partial,
|
||||||
|
@ -350,30 +299,6 @@ impl MailboxView {
|
||||||
data: NString(Some(is)),
|
data: NString(Some(is)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
FetchAttribute::BodyStructure => {
|
|
||||||
// @TODO This is a stub
|
|
||||||
let is = IString::try_from("test").unwrap();
|
|
||||||
let b = BodyStructure::Single {
|
|
||||||
body: FetchBody {
|
|
||||||
basic: BasicFields {
|
|
||||||
parameter_list: vec![],
|
|
||||||
id: NString(Some(is.clone())),
|
|
||||||
description: NString(Some(is.clone())),
|
|
||||||
content_transfer_encoding: is.clone(),
|
|
||||||
size: 1,
|
|
||||||
},
|
|
||||||
specific: SpecificFields::Text {
|
|
||||||
// @FIXME I do not understand yet how this part works
|
|
||||||
subtype: is,
|
|
||||||
number_of_lines: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Always None for Body, can be populated for BodyStructure
|
|
||||||
extension: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
attributes.push(MessageAttribute::BodyStructure(b));
|
|
||||||
}
|
|
||||||
FetchAttribute::InternalDate => {
|
FetchAttribute::InternalDate => {
|
||||||
attributes.push(MessageAttribute::InternalDate(MyDateTime(
|
attributes.push(MessageAttribute::InternalDate(MyDateTime(
|
||||||
Utc.fix()
|
Utc.fix()
|
||||||
|
@ -564,6 +489,20 @@ fn convert_address(a: &mail_parser::Addr<'_>) -> Address {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
--CAPTURE--
|
||||||
|
b fetch 29878:29879 (BODY)
|
||||||
|
* 29878 FETCH (BODY (("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 3264 82)("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 31834 643) "alternative"))
|
||||||
|
* 29879 FETCH (BODY ("text" "html" ("charset" "us-ascii") NIL NIL "7bit" 4107 131))
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^ ^^^^^^ ^^^^ ^^^
|
||||||
|
| | | | | | number of lines
|
||||||
|
| | | | | size
|
||||||
|
| | | | content transfer encoding
|
||||||
|
| | | description
|
||||||
|
| | id
|
||||||
|
| parameter list
|
||||||
|
b OK Fetch completed (0.001 + 0.000 secs).
|
||||||
|
*/
|
||||||
fn build_imap_email_struct<'a>(
|
fn build_imap_email_struct<'a>(
|
||||||
msg: &Message<'a>,
|
msg: &Message<'a>,
|
||||||
node: &MessageStructure,
|
node: &MessageStructure,
|
||||||
|
@ -574,47 +513,89 @@ fn build_imap_email_struct<'a>(
|
||||||
"Email part referenced in email structure is missing"
|
"Email part referenced in email structure is missing"
|
||||||
))?;
|
))?;
|
||||||
match part {
|
match part {
|
||||||
MessagePart::Text(bp) => Ok(BodyStructure::Single {
|
|
||||||
body: FetchBody {
|
|
||||||
basic: BasicFields {
|
|
||||||
parameter_list: vec![], //@TODO
|
|
||||||
id: match bp.headers_rfc.get(&RfcHeader::ContentId) {
|
|
||||||
Some(HeaderValue::Text(v)) => {
|
|
||||||
NString(IString::try_from(v.clone().into_owned()).ok())
|
|
||||||
}
|
|
||||||
_ => NString(None),
|
|
||||||
},
|
|
||||||
description: NString(None), //@TODO
|
|
||||||
content_transfer_encoding: match bp
|
|
||||||
.headers_rfc
|
|
||||||
.get(&RfcHeader::ContentTransferEncoding)
|
|
||||||
{
|
|
||||||
Some(HeaderValue::Text(v)) => {
|
|
||||||
IString::try_from(v.clone().into_owned())
|
|
||||||
.unwrap_or(unchecked_istring("7bit"))
|
|
||||||
}
|
|
||||||
_ => unchecked_istring("7bit"),
|
|
||||||
},
|
|
||||||
size: u32::try_from(bp.len())?,
|
|
||||||
},
|
|
||||||
specific: SpecificFields::Text {
|
|
||||||
subtype: match bp.headers_rfc.get(&RfcHeader::ContentType) {
|
|
||||||
Some(HeaderValue::ContentType(ContentType {
|
|
||||||
c_subtype: Some(st),
|
|
||||||
..
|
|
||||||
})) => IString::try_from(st.clone().into_owned())
|
|
||||||
.unwrap_or(unchecked_istring("plain")),
|
|
||||||
_ => unchecked_istring("plain"),
|
|
||||||
},
|
|
||||||
number_of_lines: u32::try_from(bp.get_text_contents().lines().count())?,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extension: None,
|
|
||||||
}),
|
|
||||||
MessagePart::Multipart(_) => {
|
MessagePart::Multipart(_) => {
|
||||||
unreachable!("A multipart entry can not be found here.")
|
unreachable!("A multipart entry can not be found here.")
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
MessagePart::Text(bp) => {
|
||||||
|
// Extract subtype+attributes from Content-Type header
|
||||||
|
let (st, ct_attrs) = match bp.headers_rfc.get(&RfcHeader::ContentType) {
|
||||||
|
Some(HeaderValue::ContentType(c)) => {
|
||||||
|
(c.c_subtype.as_ref(), c.attributes.as_ref())
|
||||||
|
}
|
||||||
|
_ => (None, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transform the Content-Type attributes into IMAP's parameter list
|
||||||
|
// Also check if there is a charset defined.
|
||||||
|
let (charset_found, mut parameter_list) = ct_attrs
|
||||||
|
.map(|attr| {
|
||||||
|
attr.iter().fold(
|
||||||
|
(false, vec![]),
|
||||||
|
|(charset_found, mut param_list), (k, v)| {
|
||||||
|
let nk = k.to_lowercase();
|
||||||
|
match (
|
||||||
|
IString::try_from(k.as_ref()),
|
||||||
|
IString::try_from(v.as_ref()),
|
||||||
|
) {
|
||||||
|
(Ok(ik), Ok(iv)) => param_list.push((ik, iv)),
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
(charset_found || nk == "charset", param_list)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or((false, vec![]));
|
||||||
|
|
||||||
|
// If the charset is not defined, set it to "us-ascii"
|
||||||
|
if !charset_found {
|
||||||
|
parameter_list
|
||||||
|
.push((unchecked_istring("charset"), unchecked_istring("us-ascii")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the subtype is not defined, set it to "plain"
|
||||||
|
let subtype = st
|
||||||
|
.map(|st| IString::try_from(st.clone().into_owned()).ok())
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or(unchecked_istring("plain"));
|
||||||
|
|
||||||
|
Ok(BodyStructure::Single {
|
||||||
|
body: FetchBody {
|
||||||
|
basic: BasicFields {
|
||||||
|
parameter_list,
|
||||||
|
id: match bp.headers_rfc.get(&RfcHeader::ContentId) {
|
||||||
|
Some(HeaderValue::Text(v)) => {
|
||||||
|
NString(IString::try_from(v.clone().into_owned()).ok())
|
||||||
|
}
|
||||||
|
_ => NString(None),
|
||||||
|
},
|
||||||
|
description: NString(None), //@TODO
|
||||||
|
content_transfer_encoding: match bp
|
||||||
|
.headers_rfc
|
||||||
|
.get(&RfcHeader::ContentTransferEncoding)
|
||||||
|
{
|
||||||
|
Some(HeaderValue::Text(v)) => {
|
||||||
|
IString::try_from(v.clone().into_owned())
|
||||||
|
.unwrap_or(unchecked_istring("7bit"))
|
||||||
|
}
|
||||||
|
_ => unchecked_istring("7bit"),
|
||||||
|
},
|
||||||
|
size: u32::try_from(bp.len())?,
|
||||||
|
},
|
||||||
|
specific: SpecificFields::Text {
|
||||||
|
subtype,
|
||||||
|
number_of_lines: u32::try_from(
|
||||||
|
bp.get_text_contents().lines().count(),
|
||||||
|
)?,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extension: None,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
MessagePart::Html(_) => todo!(),
|
||||||
|
MessagePart::Binary(_) => todo!(),
|
||||||
|
MessagePart::InlineBinary(_) => todo!(),
|
||||||
|
MessagePart::Message(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageStructure::List(l) => todo!(),
|
MessageStructure::List(l) => todo!(),
|
||||||
|
|
Loading…
Reference in a new issue