use serde::{Deserialize, Serialize};
use crate::{Attachment, DraftId, EmailAddress, FolderId, GrantId, ThreadId};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Draft {
pub id: DraftId,
pub grant_id: GrantId,
#[serde(skip_serializing_if = "Option::is_none")]
pub thread_id: Option<ThreadId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject: Option<String>,
#[serde(default)]
pub from: Vec<EmailAddress>,
#[serde(default)]
pub to: Vec<EmailAddress>,
#[serde(default)]
pub cc: Vec<EmailAddress>,
#[serde(default)]
pub bcc: Vec<EmailAddress>,
#[serde(default)]
pub reply_to: Vec<EmailAddress>,
#[serde(skip_serializing_if = "Option::is_none")]
pub body: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starred: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub snippet: Option<String>,
#[serde(default)]
pub attachments: Vec<Attachment>,
#[serde(default)]
pub folders: Vec<FolderId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<i64>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct CreateDraftRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub subject: Option<String>,
#[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 body: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub thread_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starred: Option<bool>,
}
impl CreateDraftRequest {
pub fn builder() -> CreateDraftRequestBuilder {
CreateDraftRequestBuilder::default()
}
}
#[derive(Debug, Clone, Default)]
pub struct CreateDraftRequestBuilder {
request: CreateDraftRequest,
}
impl CreateDraftRequestBuilder {
pub fn subject(mut self, subject: impl Into<String>) -> Self {
self.request.subject = Some(subject.into());
self
}
pub fn from(mut self, from: Vec<EmailAddress>) -> Self {
self.request.from = Some(from);
self
}
pub fn to(mut self, to: Vec<EmailAddress>) -> Self {
self.request.to = Some(to);
self
}
pub fn cc(mut self, cc: Vec<EmailAddress>) -> Self {
self.request.cc = Some(cc);
self
}
pub fn bcc(mut self, bcc: Vec<EmailAddress>) -> Self {
self.request.bcc = Some(bcc);
self
}
pub fn reply_to(mut self, reply_to: Vec<EmailAddress>) -> Self {
self.request.reply_to = Some(reply_to);
self
}
pub fn body(mut self, body: impl Into<String>) -> Self {
self.request.body = Some(body.into());
self
}
pub fn thread_id(mut self, thread_id: impl Into<String>) -> Self {
self.request.thread_id = Some(thread_id.into());
self
}
pub fn starred(mut self, starred: bool) -> Self {
self.request.starred = Some(starred);
self
}
pub fn build(self) -> CreateDraftRequest {
self.request
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpdateDraftRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub subject: Option<String>,
#[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 body: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starred: Option<bool>,
}
impl UpdateDraftRequest {
pub fn builder() -> UpdateDraftRequestBuilder {
UpdateDraftRequestBuilder::default()
}
}
#[derive(Debug, Clone, Default)]
pub struct UpdateDraftRequestBuilder {
request: UpdateDraftRequest,
}
impl UpdateDraftRequestBuilder {
pub fn subject(mut self, subject: impl Into<String>) -> Self {
self.request.subject = Some(subject.into());
self
}
pub fn from(mut self, from: Vec<EmailAddress>) -> Self {
self.request.from = Some(from);
self
}
pub fn to(mut self, to: Vec<EmailAddress>) -> Self {
self.request.to = Some(to);
self
}
pub fn cc(mut self, cc: Vec<EmailAddress>) -> Self {
self.request.cc = Some(cc);
self
}
pub fn bcc(mut self, bcc: Vec<EmailAddress>) -> Self {
self.request.bcc = Some(bcc);
self
}
pub fn reply_to(mut self, reply_to: Vec<EmailAddress>) -> Self {
self.request.reply_to = Some(reply_to);
self
}
pub fn body(mut self, body: impl Into<String>) -> Self {
self.request.body = Some(body.into());
self
}
pub fn starred(mut self, starred: bool) -> Self {
self.request.starred = Some(starred);
self
}
pub fn build(self) -> UpdateDraftRequest {
self.request
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_draft_creation() {
let draft = Draft {
id: DraftId::new("draft_123"),
grant_id: GrantId::new("grant_123"),
thread_id: Some(ThreadId::new("thread_123")),
subject: Some("Test Draft".to_string()),
from: vec![],
to: vec![],
cc: vec![],
bcc: vec![],
reply_to: vec![],
body: Some("Draft body".to_string()),
starred: Some(false),
snippet: Some("Draft snippet".to_string()),
attachments: vec![],
folders: vec![],
created_at: Some(1234567890),
};
assert_eq!(draft.id.as_str(), "draft_123");
assert_eq!(draft.grant_id.as_str(), "grant_123");
assert_eq!(draft.subject, Some("Test Draft".to_string()));
}
#[test]
fn test_draft_serialization() {
let draft = Draft {
id: DraftId::new("draft_123"),
grant_id: GrantId::new("grant_123"),
thread_id: None,
subject: Some("Test".to_string()),
from: vec![],
to: vec![],
cc: vec![],
bcc: vec![],
reply_to: vec![],
body: Some("Body".to_string()),
starred: Some(false),
snippet: Some("Snippet".to_string()),
attachments: vec![],
folders: vec![],
created_at: Some(1234567890),
};
let json = serde_json::to_string(&draft).unwrap();
assert!(json.contains("draft_123"));
assert!(json.contains("grant_123"));
assert!(json.contains("Test"));
let deserialized: Draft = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, draft);
}
#[test]
fn test_create_draft_request_builder() {
let to = vec![EmailAddress::new("recipient@example.com").unwrap()];
let draft = CreateDraftRequest::builder()
.subject("Test")
.to(to.clone())
.body("Test body")
.build();
assert_eq!(draft.subject, Some("Test".to_string()));
assert_eq!(draft.to, Some(to));
assert_eq!(draft.body, Some("Test body".to_string()));
}
#[test]
fn test_create_draft_request_all_fields() {
let from = vec![EmailAddress::new("sender@example.com").unwrap()];
let to = vec![EmailAddress::new("recipient@example.com").unwrap()];
let cc = vec![EmailAddress::new("cc@example.com").unwrap()];
let draft = CreateDraftRequest::builder()
.subject("Subject")
.from(from.clone())
.to(to.clone())
.cc(cc.clone())
.body("Body content")
.thread_id("thread_123")
.starred(true)
.build();
assert_eq!(draft.subject, Some("Subject".to_string()));
assert_eq!(draft.from, Some(from));
assert_eq!(draft.to, Some(to));
assert_eq!(draft.cc, Some(cc));
assert_eq!(draft.body, Some("Body content".to_string()));
assert_eq!(draft.thread_id, Some("thread_123".to_string()));
assert_eq!(draft.starred, Some(true));
}
#[test]
fn test_create_draft_request_serialization() {
let to = vec![EmailAddress::new("recipient@example.com").unwrap()];
let draft = CreateDraftRequest::builder()
.subject("Test")
.to(to)
.body("Body")
.build();
let json = serde_json::to_string(&draft).unwrap();
let deserialized: CreateDraftRequest = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, draft);
}
#[test]
fn test_update_draft_request_builder() {
let update = UpdateDraftRequest::builder()
.subject("Updated subject")
.body("Updated body")
.starred(true)
.build();
assert_eq!(update.subject, Some("Updated subject".to_string()));
assert_eq!(update.body, Some("Updated body".to_string()));
assert_eq!(update.starred, Some(true));
}
#[test]
fn test_update_draft_request_with_recipients() {
let to = vec![EmailAddress::new("new@example.com").unwrap()];
let update = UpdateDraftRequest::builder()
.to(to.clone())
.subject("New subject")
.build();
assert_eq!(update.to, Some(to));
assert_eq!(update.subject, Some("New subject".to_string()));
}
#[test]
fn test_update_draft_request_serialization() {
let update = UpdateDraftRequest::builder()
.subject("Test")
.body("Body")
.build();
let json = serde_json::to_string(&update).unwrap();
let deserialized: UpdateDraftRequest = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, update);
}
}