use std::collections::HashMap;
use jmap_types::{Date, Id, UTCDate};
use serde::{Deserialize, Serialize};
use crate::keyword::Keyword;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EmailAddress {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub email: String,
}
impl EmailAddress {
pub fn new(email: impl Into<String>) -> Self {
Self {
name: None,
email: email.into(),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EmailAddressGroup {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub addresses: Vec<EmailAddress>,
}
impl EmailAddressGroup {
pub fn new(addresses: Vec<EmailAddress>) -> Self {
Self {
name: None,
addresses,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EmailHeader {
pub name: String,
pub value: String,
}
impl EmailHeader {
pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
Self {
name: name.into(),
value: value.into(),
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EmailBodyValue {
pub value: String,
#[serde(default)]
pub is_encoding_problem: bool,
#[serde(default)]
pub is_truncated: bool,
}
impl EmailBodyValue {
pub fn new(value: impl Into<String>) -> Self {
Self {
value: value.into(),
is_encoding_problem: false,
is_truncated: false,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EmailBodyPart {
#[serde(skip_serializing_if = "Option::is_none")]
pub part_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub blob_id: Option<Id>,
#[serde(skip_serializing_if = "Option::is_none")]
pub size: Option<u64>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub headers: Vec<EmailHeader>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub type_: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub charset: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disposition: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub language: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub location: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sub_parts: Option<Vec<EmailBodyPart>>,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Email {
pub id: Id,
pub blob_id: Id,
pub thread_id: Id,
pub mailbox_ids: HashMap<Id, bool>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub keywords: HashMap<Keyword, bool>,
pub size: u64,
pub received_at: UTCDate,
#[serde(skip_serializing_if = "Option::is_none")]
pub message_id: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub in_reply_to: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub references: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sender: Option<Vec<EmailAddress>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub from: Option<Vec<EmailAddress>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub to: Option<Vec<EmailAddress>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cc: Option<Vec<EmailAddress>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bcc: Option<Vec<EmailAddress>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_to: Option<Vec<EmailAddress>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sent_at: Option<Date>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub headers: Vec<EmailHeader>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub body_values: HashMap<String, EmailBodyValue>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub text_body: Vec<EmailBodyPart>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub html_body: Vec<EmailBodyPart>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attachments: Vec<EmailBodyPart>,
#[serde(skip_serializing_if = "Option::is_none")]
pub body_structure: Option<EmailBodyPart>,
#[serde(default)]
pub has_attachment: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
}
impl Email {
pub fn new(
id: Id,
blob_id: Id,
thread_id: Id,
mailbox_ids: HashMap<Id, bool>,
size: u64,
received_at: UTCDate,
) -> Self {
Self {
id,
blob_id,
thread_id,
mailbox_ids,
keywords: HashMap::new(),
size,
received_at,
message_id: None,
in_reply_to: None,
references: None,
sender: None,
from: None,
to: None,
cc: None,
bcc: None,
reply_to: None,
subject: None,
sent_at: None,
headers: Vec::new(),
body_values: HashMap::new(),
text_body: Vec::new(),
html_body: Vec::new(),
attachments: Vec::new(),
body_structure: None,
has_attachment: false,
preview: None,
}
}
}