melib/jmap: allow empty to,from etc fields in EmailObject

jmap-eventsource
Manos Pitsidianakis 2020-09-19 14:59:23 +03:00
parent fba69d1e5d
commit cfc380b47d
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
1 changed files with 74 additions and 77 deletions

View File

@ -134,54 +134,54 @@ pub struct EmailObject {
#[serde(default)] #[serde(default)]
pub blob_id: String, pub blob_id: String,
#[serde(default)] #[serde(default)]
mailbox_ids: HashMap<Id, bool>, pub mailbox_ids: HashMap<Id, bool>,
#[serde(default)] #[serde(default)]
size: u64, pub size: u64,
#[serde(default)] #[serde(default)]
received_at: String, pub received_at: String,
#[serde(default)] #[serde(default)]
message_id: Vec<String>, pub message_id: Vec<String>,
#[serde(default)] #[serde(default)]
to: SmallVec<[EmailAddress; 1]>, pub to: Option<SmallVec<[EmailAddress; 1]>>,
#[serde(default)] #[serde(default)]
bcc: Option<Vec<EmailAddress>>, pub bcc: Option<Vec<EmailAddress>>,
#[serde(default)] #[serde(default)]
reply_to: Option<Vec<EmailAddress>>, pub reply_to: Option<Vec<EmailAddress>>,
#[serde(default)] #[serde(default)]
cc: Option<SmallVec<[EmailAddress; 1]>>, pub cc: Option<SmallVec<[EmailAddress; 1]>>,
#[serde(default)] #[serde(default)]
sender: Option<Vec<EmailAddress>>, pub sender: Option<Vec<EmailAddress>>,
#[serde(default)] #[serde(default)]
from: SmallVec<[EmailAddress; 1]>, pub from: Option<SmallVec<[EmailAddress; 1]>>,
#[serde(default)] #[serde(default)]
in_reply_to: Option<Vec<String>>, pub in_reply_to: Option<Vec<String>>,
#[serde(default)] #[serde(default)]
references: Option<Vec<String>>, pub references: Option<Vec<String>>,
#[serde(default)] #[serde(default)]
keywords: HashMap<String, bool>, pub keywords: HashMap<String, bool>,
#[serde(default)] #[serde(default)]
attached_emails: Option<Id>, pub attached_emails: Option<Id>,
#[serde(default)] #[serde(default)]
attachments: Vec<Value>, pub attachments: Vec<Value>,
#[serde(default)] #[serde(default)]
has_attachment: bool, pub has_attachment: bool,
#[serde(default)] #[serde(default)]
#[serde(deserialize_with = "deserialize_header")] #[serde(deserialize_with = "deserialize_header")]
headers: HashMap<String, String>, pub headers: HashMap<String, String>,
#[serde(default)] #[serde(default)]
html_body: Vec<HtmlBody>, pub html_body: Vec<HtmlBody>,
#[serde(default)] #[serde(default)]
preview: Option<String>, pub preview: Option<String>,
#[serde(default)] #[serde(default)]
sent_at: Option<String>, pub sent_at: Option<String>,
#[serde(default)] #[serde(default)]
subject: Option<String>, pub subject: Option<String>,
#[serde(default)] #[serde(default)]
text_body: Vec<TextBody>, pub text_body: Vec<TextBody>,
#[serde(default)] #[serde(default)]
thread_id: Id, pub thread_id: Id,
#[serde(flatten)] #[serde(flatten)]
extra: HashMap<String, Value>, pub extra: HashMap<String, Value>,
} }
impl EmailObject { impl EmailObject {
@ -190,9 +190,9 @@ impl EmailObject {
#[derive(Deserialize, Serialize, Debug, Default)] #[derive(Deserialize, Serialize, Debug, Default)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct Header { pub struct Header {
name: String, pub name: String,
value: String, pub value: String,
} }
fn deserialize_header<'de, D>( fn deserialize_header<'de, D>(
@ -207,9 +207,9 @@ where
#[derive(Deserialize, Serialize, Debug, Default)] #[derive(Deserialize, Serialize, Debug, Default)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct EmailAddress { pub struct EmailAddress {
email: String, pub email: String,
name: Option<String>, pub name: Option<String>,
} }
impl Into<crate::email::Address> for EmailAddress { impl Into<crate::email::Address> for EmailAddress {
@ -269,18 +269,22 @@ impl std::convert::From<EmailObject> for crate::Envelope {
env.set_subject(std::mem::replace(subject, String::new()).into_bytes()); env.set_subject(std::mem::replace(subject, String::new()).into_bytes());
} }
env.set_from( if let Some(ref mut from) = t.from {
std::mem::replace(&mut t.from, SmallVec::new()) env.set_from(
.into_iter() std::mem::replace(from, SmallVec::new())
.map(|addr| addr.into()) .into_iter()
.collect::<SmallVec<[crate::email::Address; 1]>>(), .map(|addr| addr.into())
); .collect::<SmallVec<[crate::email::Address; 1]>>(),
env.set_to( );
std::mem::replace(&mut t.to, SmallVec::new()) }
.into_iter() if let Some(ref mut to) = t.to {
.map(|addr| addr.into()) env.set_to(
.collect::<SmallVec<[crate::email::Address; 1]>>(), std::mem::replace(to, SmallVec::new())
); .into_iter()
.map(|addr| addr.into())
.collect::<SmallVec<[crate::email::Address; 1]>>(),
);
}
if let Some(ref mut cc) = t.cc { if let Some(ref mut cc) = t.cc {
env.set_cc( env.set_cc(
@ -300,15 +304,8 @@ impl std::convert::From<EmailObject> for crate::Envelope {
); );
} }
if env.references.is_some() { if let Some(ref r) = env.references {
if let Some(pos) = env if let Some(pos) = r.refs.iter().position(|r| r == env.message_id()) {
.references
.as_ref()
.map(|r| &r.refs)
.unwrap()
.iter()
.position(|r| r == env.message_id())
{
env.references.as_mut().unwrap().refs.remove(pos); env.references.as_mut().unwrap().refs.remove(pos);
} }
} }
@ -322,56 +319,56 @@ impl std::convert::From<EmailObject> for crate::Envelope {
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct HtmlBody { pub struct HtmlBody {
blob_id: Id, pub blob_id: Id,
#[serde(default)] #[serde(default)]
charset: String, pub charset: String,
#[serde(default)] #[serde(default)]
cid: Option<String>, pub cid: Option<String>,
#[serde(default)] #[serde(default)]
disposition: Option<String>, pub disposition: Option<String>,
#[serde(default)] #[serde(default)]
headers: Value, pub headers: Value,
#[serde(default)] #[serde(default)]
language: Option<Vec<String>>, pub language: Option<Vec<String>>,
#[serde(default)] #[serde(default)]
location: Option<String>, pub location: Option<String>,
#[serde(default)] #[serde(default)]
name: Option<String>, pub name: Option<String>,
#[serde(default)] #[serde(default)]
part_id: Option<String>, pub part_id: Option<String>,
size: u64, pub size: u64,
#[serde(alias = "type")] #[serde(alias = "type")]
content_type: String, pub content_type: String,
#[serde(default)] #[serde(default)]
sub_parts: Vec<Value>, pub sub_parts: Vec<Value>,
} }
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct TextBody { pub struct TextBody {
blob_id: Id, pub blob_id: Id,
#[serde(default)] #[serde(default)]
charset: String, pub charset: String,
#[serde(default)] #[serde(default)]
cid: Option<String>, pub cid: Option<String>,
#[serde(default)] #[serde(default)]
disposition: Option<String>, pub disposition: Option<String>,
#[serde(default)] #[serde(default)]
headers: Value, pub headers: Value,
#[serde(default)] #[serde(default)]
language: Option<Vec<String>>, pub language: Option<Vec<String>>,
#[serde(default)] #[serde(default)]
location: Option<String>, pub location: Option<String>,
#[serde(default)] #[serde(default)]
name: Option<String>, pub name: Option<String>,
#[serde(default)] #[serde(default)]
part_id: Option<String>, pub part_id: Option<String>,
size: u64, pub size: u64,
#[serde(alias = "type")] #[serde(alias = "type")]
content_type: String, pub content_type: String,
#[serde(default)] #[serde(default)]
sub_parts: Vec<Value>, pub sub_parts: Vec<Value>,
} }
impl Object for EmailObject { impl Object for EmailObject {