use crate::email::EmailAddress;
use jmap_types::Id;
use serde::{Deserialize, Serialize};
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Identity {
pub id: Id,
pub name: String,
pub email: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_to: Option<Vec<EmailAddress>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bcc: Option<Vec<EmailAddress>>,
pub text_signature: String,
pub html_signature: String,
pub may_delete: bool,
#[serde(flatten, default, skip_serializing_if = "serde_json::Map::is_empty")]
pub extra: serde_json::Map<String, serde_json::Value>,
}
impl Identity {
pub fn new(id: Id, email: impl Into<String>, may_delete: bool) -> Self {
Self {
id,
email: email.into(),
may_delete,
name: String::new(),
reply_to: None,
bcc: None,
text_signature: String::new(),
html_signature: String::new(),
extra: serde_json::Map::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn identity_preserves_vendor_extras() {
let raw = json!({
"id": "i1",
"name": "Alice",
"email": "alice@example.com",
"textSignature": "-- Alice",
"htmlSignature": "<p>-- Alice</p>",
"mayDelete": true,
"acmeCorpDepartment": "engineering"
});
let id: Identity = serde_json::from_value(raw).unwrap();
assert_eq!(
id.extra.get("acmeCorpDepartment").and_then(|v| v.as_str()),
Some("engineering")
);
let back = serde_json::to_value(&id).unwrap();
assert_eq!(back["acmeCorpDepartment"], "engineering");
}
}