use indexmap::IndexMap;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde_json::Value;
use crate::jmap::{
argument::Argument,
email::EmailObject,
identity::Identity,
methods::Set,
objects::{Account, BlobObject, Id, Object, PatchObject},
protocol::Method,
thread::ThreadObject,
};
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum UndoStatus {
Pending,
#[default]
Final,
Canceled,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeliveryStatusObject {
pub smtp_reply: String,
pub delivered: String,
pub displayed: Displayed,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum Displayed {
Yes,
#[default]
Unknown,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum Delivered {
#[default]
Queued,
Yes,
No,
Unknown,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EmailSubmissionObject {
#[serde(skip_serializing)]
pub account_id: Id<Account>,
pub identity_id: Id<Identity>,
pub email_id: Argument<Id<EmailObject>>,
#[serde(skip_serializing)]
pub thread_id: Id<ThreadObject>,
pub envelope: Option<EnvelopeObject>,
#[serde(skip_serializing)]
pub send_at: String,
pub undo_status: UndoStatus,
#[serde(skip_serializing)]
pub delivery_status: Option<IndexMap<String, DeliveryStatusObject>>,
#[serde(skip_serializing)]
pub dsn_blob_ids: Vec<Id<BlobObject>>,
#[serde(skip_serializing)]
pub mdn_blob_ids: Vec<Id<BlobObject>>,
}
impl Object for EmailSubmissionObject {
const NAME: &'static str = "EmailSubmission";
}
impl EmailSubmissionObject {
pub fn new(
account_id: Id<Account>,
identity_id: Id<Identity>,
email_id: impl Into<Argument<Id<EmailObject>>>,
envelope: Option<EnvelopeObject>,
undo_status: Option<UndoStatus>,
) -> Self {
Self {
account_id,
identity_id,
email_id: email_id.into(),
thread_id: "".into(),
envelope,
send_at: String::new(),
undo_status: undo_status.unwrap_or_default(),
delivery_status: None,
dsn_blob_ids: vec![],
mdn_blob_ids: vec![],
}
}
}
impl Serialize for EmailSubmissionObject {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct(crate::identify!(EmailSubmissionObject), 4)?;
state.serialize_field("identityId", &self.identity_id)?;
state.serialize_field(
if matches!(self.email_id, Argument::Value(_)) {
"emailId"
} else {
"#emailId"
},
&self.email_id,
)?;
state.serialize_field("envelope", &self.envelope)?;
state.serialize_field("undoStatus", &self.undo_status)?;
state.end()
}
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EmailSubmissionSet {
#[serde(flatten)]
pub set_call: Set<EmailSubmissionObject>,
#[serde(default)]
pub on_success_update_email: Option<IndexMap<Id<EmailSubmissionObject>, PatchObject>>,
#[serde(default)]
pub on_success_destroy_email: Option<Vec<Id<EmailSubmissionObject>>>,
}
impl Method<EmailSubmissionObject> for EmailSubmissionSet {
const NAME: &'static str = "EmailSubmission/set";
}
impl EmailSubmissionSet {
pub fn new(set_call: Set<EmailSubmissionObject>) -> Self {
Self {
set_call,
on_success_update_email: None,
on_success_destroy_email: None,
}
}
pub fn on_success_update_email(
self,
on_success_update_email: Option<IndexMap<Id<EmailSubmissionObject>, PatchObject>>,
) -> Self {
Self {
on_success_update_email,
..self
}
}
pub fn on_success_destroy_email(
self,
on_success_destroy_email: Option<Vec<Id<EmailSubmissionObject>>>,
) -> Self {
Self {
on_success_destroy_email,
..self
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EnvelopeObject {
pub mail_from: Address,
pub rcpt_to: Vec<Address>,
}
impl Object for EnvelopeObject {
const NAME: &'static str = "Envelope";
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Address {
pub email: String,
pub parameters: Option<Value>,
}