jmap_client/email/
import.rs1use crate::{
13 core::{
14 request::ResultReference,
15 set::{from_timestamp, SetError},
16 RequestParams,
17 },
18 Error,
19};
20use ahash::AHashMap;
21use chrono::{DateTime, Utc};
22use serde::{Deserialize, Serialize};
23
24use super::{Email, Property};
25
26#[derive(Debug, Clone, Serialize)]
27pub struct EmailImportRequest {
28 #[serde(rename = "accountId")]
29 account_id: String,
30
31 #[serde(rename = "ifInState")]
32 #[serde(skip_serializing_if = "Option::is_none")]
33 if_in_state: Option<String>,
34
35 emails: AHashMap<String, EmailImport>,
36}
37
38#[derive(Debug, Clone, Serialize)]
39pub struct EmailImport {
40 #[serde(skip)]
41 create_id: usize,
42
43 #[serde(rename = "blobId")]
44 blob_id: String,
45
46 #[serde(rename = "mailboxIds")]
47 #[serde(skip_serializing_if = "Option::is_none")]
48 mailbox_ids: Option<AHashMap<String, bool>>,
49
50 #[serde(rename = "#mailboxIds")]
51 #[serde(skip_deserializing)]
52 #[serde(skip_serializing_if = "Option::is_none")]
53 mailbox_ids_ref: Option<ResultReference>,
54
55 #[serde(rename = "keywords")]
56 keywords: AHashMap<String, bool>,
57
58 #[serde(rename = "receivedAt")]
59 #[serde(skip_serializing_if = "Option::is_none")]
60 received_at: Option<DateTime<Utc>>,
61}
62
63#[derive(Debug, Clone, Deserialize)]
64pub struct EmailImportResponse {
65 #[serde(rename = "accountId")]
66 account_id: String,
67
68 #[serde(rename = "oldState")]
69 old_state: Option<String>,
70
71 #[serde(rename = "newState")]
72 new_state: String,
73
74 #[serde(rename = "created")]
75 created: Option<AHashMap<String, Email>>,
76
77 #[serde(rename = "notCreated")]
78 not_created: Option<AHashMap<String, SetError<Property>>>,
79}
80
81impl EmailImportRequest {
82 pub fn new(params: RequestParams) -> Self {
83 EmailImportRequest {
84 account_id: params.account_id,
85 if_in_state: None,
86 emails: AHashMap::new(),
87 }
88 }
89
90 pub fn account_id(&mut self, account_id: impl Into<String>) -> &mut Self {
91 self.account_id = account_id.into();
92 self
93 }
94
95 pub fn if_in_state(&mut self, if_in_state: impl Into<String>) -> &mut Self {
96 self.if_in_state = Some(if_in_state.into());
97 self
98 }
99
100 pub fn email(&mut self, blob_id: impl Into<String>) -> &mut EmailImport {
101 let create_id = self.emails.len();
102 let create_id_str = format!("i{}", create_id);
103 self.emails.insert(
104 create_id_str.clone(),
105 EmailImport::new(blob_id.into(), create_id),
106 );
107 self.emails.get_mut(&create_id_str).unwrap()
108 }
109}
110
111impl EmailImport {
112 fn new(blob_id: String, create_id: usize) -> Self {
113 EmailImport {
114 create_id,
115 blob_id,
116 mailbox_ids: None,
117 mailbox_ids_ref: None,
118 keywords: AHashMap::new(),
119 received_at: None,
120 }
121 }
122
123 pub fn mailbox_ids<T, U>(&mut self, mailbox_ids: T) -> &mut Self
124 where
125 T: IntoIterator<Item = U>,
126 U: Into<String>,
127 {
128 self.mailbox_ids = Some(mailbox_ids.into_iter().map(|s| (s.into(), true)).collect());
129 self.mailbox_ids_ref = None;
130 self
131 }
132
133 pub fn mailbox_ids_ref(&mut self, reference: ResultReference) -> &mut Self {
134 self.mailbox_ids_ref = reference.into();
135 self.mailbox_ids = None;
136 self
137 }
138
139 pub fn keywords<T, U>(&mut self, keywords: T) -> &mut Self
140 where
141 T: IntoIterator<Item = U>,
142 U: Into<String>,
143 {
144 self.keywords = keywords.into_iter().map(|s| (s.into(), true)).collect();
145 self
146 }
147
148 pub fn received_at(&mut self, received_at: i64) -> &mut Self {
149 self.received_at = Some(from_timestamp(received_at));
150 self
151 }
152
153 pub fn create_id(&self) -> String {
154 format!("i{}", self.create_id)
155 }
156}
157
158impl EmailImportResponse {
159 pub fn account_id(&self) -> &str {
160 &self.account_id
161 }
162
163 pub fn old_state(&self) -> Option<&str> {
164 self.old_state.as_deref()
165 }
166
167 pub fn new_state(&self) -> &str {
168 &self.new_state
169 }
170
171 pub fn take_new_state(&mut self) -> String {
172 std::mem::take(&mut self.new_state)
173 }
174
175 pub fn created(&mut self, id: &str) -> crate::Result<Email> {
176 if let Some(result) = self.created.as_mut().and_then(|r| r.remove(id)) {
177 Ok(result)
178 } else if let Some(error) = self.not_created.as_mut().and_then(|r| r.remove(id)) {
179 Err(error.to_string_error().into())
180 } else {
181 Err(Error::Internal(format!("Id {} not found.", id)))
182 }
183 }
184
185 pub fn created_ids(&self) -> Option<impl Iterator<Item = &String>> {
186 self.created.as_ref().map(|map| map.keys())
187 }
188
189 pub fn not_created_ids(&self) -> Option<impl Iterator<Item = &String>> {
190 self.not_created.as_ref().map(|map| map.keys())
191 }
192}