jmap_client/email/
helpers.rs

1/*
2 * Copyright Stalwart Labs LLC See the COPYING
3 * file at the top-level directory of this distribution.
4 *
5 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8 * option. This file may not be copied, modified, or distributed
9 * except according to those terms.
10 */
11
12use crate::{
13    client::Client,
14    core::{
15        changes::{ChangesRequest, ChangesResponse},
16        copy::CopyRequest,
17        get::GetRequest,
18        query::{Comparator, Filter, QueryRequest, QueryResponse},
19        query_changes::{QueryChangesRequest, QueryChangesResponse},
20        request::{Arguments, Request},
21        response::{EmailCopyResponse, EmailGetResponse, EmailSetResponse},
22        set::SetRequest,
23    },
24    Get, Method, Set,
25};
26
27use super::{
28    import::{EmailImportRequest, EmailImportResponse},
29    parse::{EmailParseRequest, EmailParseResponse},
30    search_snippet::{SearchSnippetGetRequest, SearchSnippetGetResponse},
31    BodyProperty, Email, Property,
32};
33
34impl Client {
35    #[maybe_async::maybe_async]
36    pub async fn email_import<T, U, V, W>(
37        &self,
38        raw_message: Vec<u8>,
39        mailbox_ids: T,
40        keywords: Option<V>,
41        received_at: Option<i64>,
42    ) -> crate::Result<Email>
43    where
44        T: IntoIterator<Item = U>,
45        U: Into<String>,
46        V: IntoIterator<Item = W>,
47        W: Into<String>,
48    {
49        self.email_import_account(
50            self.default_account_id(),
51            raw_message,
52            mailbox_ids,
53            keywords,
54            received_at,
55        )
56        .await
57    }
58
59    #[maybe_async::maybe_async]
60    pub async fn email_import_account<T, U, V, W>(
61        &self,
62        account_id: &str,
63        raw_message: Vec<u8>,
64        mailbox_ids: T,
65        keywords: Option<V>,
66        received_at: Option<i64>,
67    ) -> crate::Result<Email>
68    where
69        T: IntoIterator<Item = U>,
70        U: Into<String>,
71        V: IntoIterator<Item = W>,
72        W: Into<String>,
73    {
74        let blob_id = self
75            .upload(account_id.into(), raw_message, None)
76            .await?
77            .take_blob_id();
78        let mut request = self.build();
79        let import_request = request
80            .import_email()
81            .account_id(account_id)
82            .email(blob_id)
83            .mailbox_ids(mailbox_ids);
84
85        if let Some(keywords) = keywords {
86            import_request.keywords(keywords);
87        }
88
89        if let Some(received_at) = received_at {
90            import_request.received_at(received_at);
91        }
92
93        let id = import_request.create_id();
94        request
95            .send_single::<EmailImportResponse>()
96            .await?
97            .created(&id)
98    }
99
100    #[maybe_async::maybe_async]
101    pub async fn email_set_mailbox(
102        &self,
103        id: &str,
104        mailbox_id: &str,
105        set: bool,
106    ) -> crate::Result<Option<Email>> {
107        let mut request = self.build();
108        request.set_email().update(id).mailbox_id(mailbox_id, set);
109        request.send_single::<EmailSetResponse>().await?.updated(id)
110    }
111
112    #[maybe_async::maybe_async]
113    pub async fn email_set_mailboxes<T, U>(
114        &self,
115        id: &str,
116        mailbox_ids: T,
117    ) -> crate::Result<Option<Email>>
118    where
119        T: IntoIterator<Item = U>,
120        U: Into<String>,
121    {
122        let mut request = self.build();
123        request.set_email().update(id).mailbox_ids(mailbox_ids);
124        request.send_single::<EmailSetResponse>().await?.updated(id)
125    }
126
127    #[maybe_async::maybe_async]
128    pub async fn email_set_keyword(
129        &self,
130        id: &str,
131        keyword: &str,
132        set: bool,
133    ) -> crate::Result<Option<Email>> {
134        let mut request = self.build();
135        request.set_email().update(id).keyword(keyword, set);
136        request.send_single::<EmailSetResponse>().await?.updated(id)
137    }
138
139    #[maybe_async::maybe_async]
140    pub async fn email_set_keywords<T, U>(
141        &self,
142        id: &str,
143        keywords: T,
144    ) -> crate::Result<Option<Email>>
145    where
146        T: IntoIterator<Item = U>,
147        U: Into<String>,
148    {
149        let mut request = self.build();
150        request.set_email().update(id).keywords(keywords);
151        request.send_single::<EmailSetResponse>().await?.updated(id)
152    }
153
154    #[maybe_async::maybe_async]
155    pub async fn email_destroy(&self, id: &str) -> crate::Result<()> {
156        let mut request = self.build();
157        request.set_email().destroy([id]);
158        request
159            .send_single::<EmailSetResponse>()
160            .await?
161            .destroyed(id)
162    }
163
164    #[maybe_async::maybe_async]
165    pub async fn email_get(
166        &self,
167        id: &str,
168        properties: Option<impl IntoIterator<Item = Property>>,
169    ) -> crate::Result<Option<Email<Get>>> {
170        let mut request = self.build();
171        let get_request = request.get_email().ids([id]);
172        if let Some(properties) = properties {
173            get_request.properties(properties);
174        }
175        request
176            .send_single::<EmailGetResponse>()
177            .await
178            .map(|mut r| r.take_list().pop())
179    }
180
181    #[maybe_async::maybe_async]
182    pub async fn email_changes(
183        &self,
184        since_state: impl Into<String>,
185        max_changes: Option<usize>,
186    ) -> crate::Result<ChangesResponse<Email<Get>>> {
187        let mut request = self.build();
188        let changes_request = request.changes_email(since_state);
189        if let Some(max_changes) = max_changes {
190            changes_request.max_changes(max_changes);
191        }
192        request.send_single().await
193    }
194
195    #[maybe_async::maybe_async]
196    pub async fn email_query(
197        &self,
198        filter: Option<impl Into<Filter<super::query::Filter>>>,
199        sort: Option<impl IntoIterator<Item = Comparator<super::query::Comparator>>>,
200    ) -> crate::Result<QueryResponse> {
201        let mut request = self.build();
202        let query_request = request.query_email();
203        if let Some(filter) = filter {
204            query_request.filter(filter);
205        }
206        if let Some(sort) = sort {
207            query_request.sort(sort.into_iter());
208        }
209        request.send_single::<QueryResponse>().await
210    }
211
212    #[maybe_async::maybe_async]
213    pub async fn email_query_changes(
214        &self,
215        since_query_state: impl Into<String>,
216        filter: Option<impl Into<Filter<super::query::Filter>>>,
217    ) -> crate::Result<QueryChangesResponse> {
218        let mut request = self.build();
219        let query_request = request.query_email_changes(since_query_state);
220        if let Some(filter) = filter {
221            query_request.filter(filter);
222        }
223        request.send_single::<QueryChangesResponse>().await
224    }
225
226    #[maybe_async::maybe_async]
227    pub async fn email_parse(
228        &self,
229        blob_id: &str,
230        properties: Option<impl IntoIterator<Item = Property>>,
231        body_properties: Option<impl IntoIterator<Item = BodyProperty>>,
232        max_body_value_bytes: Option<usize>,
233    ) -> crate::Result<Email> {
234        let mut request = self.build();
235        let parse_request = request.parse_email().blob_ids([blob_id]);
236        if let Some(properties) = properties {
237            parse_request.properties(properties);
238        }
239
240        if let Some(body_properties) = body_properties {
241            parse_request.body_properties(body_properties);
242        }
243
244        if let Some(max_body_value_bytes) = max_body_value_bytes {
245            parse_request
246                .fetch_all_body_values(true)
247                .max_body_value_bytes(max_body_value_bytes);
248        }
249
250        request
251            .send_single::<EmailParseResponse>()
252            .await
253            .and_then(|mut r| r.parsed(blob_id))
254    }
255
256    #[maybe_async::maybe_async]
257    pub async fn email_copy<T, U, V, W>(
258        &self,
259        from_account_id: impl Into<String>,
260        id: impl Into<String>,
261        mailbox_ids: T,
262        keywords: Option<V>,
263        received_at: Option<i64>,
264    ) -> crate::Result<Email>
265    where
266        T: IntoIterator<Item = U>,
267        U: Into<String>,
268        V: IntoIterator<Item = W>,
269        W: Into<String>,
270    {
271        let id = id.into();
272        let mut request = self.build();
273        let email = request
274            .copy_email(from_account_id)
275            .create(id.clone())
276            .mailbox_ids(mailbox_ids);
277
278        if let Some(keywords) = keywords {
279            email.keywords(keywords);
280        }
281
282        if let Some(received_at) = received_at {
283            email.received_at(received_at);
284        }
285
286        request
287            .send_single::<EmailCopyResponse>()
288            .await?
289            .created(&id)
290    }
291
292    #[maybe_async::maybe_async]
293    pub async fn search_snippet_get(
294        &self,
295        filter: Option<impl Into<Filter<super::query::Filter>>>,
296        email_ids: impl IntoIterator<Item = impl Into<String>>,
297    ) -> crate::Result<SearchSnippetGetResponse> {
298        let mut request = self.build();
299        let snippet_request = request.get_search_snippet();
300        if let Some(filter) = filter {
301            snippet_request.filter(filter);
302        }
303        snippet_request.email_ids(email_ids);
304        request.send_single::<SearchSnippetGetResponse>().await
305    }
306}
307
308impl Request<'_> {
309    pub fn get_email(&mut self) -> &mut GetRequest<Email<Set>> {
310        self.add_method_call(
311            Method::GetEmail,
312            Arguments::email_get(self.params(Method::GetEmail)),
313        )
314        .email_get_mut()
315    }
316
317    #[maybe_async::maybe_async]
318    pub async fn send_get_email(self) -> crate::Result<EmailGetResponse> {
319        self.send_single().await
320    }
321
322    pub fn changes_email(&mut self, since_state: impl Into<String>) -> &mut ChangesRequest {
323        self.add_method_call(
324            Method::ChangesEmail,
325            Arguments::changes(self.params(Method::ChangesEmail), since_state.into()),
326        )
327        .changes_mut()
328    }
329
330    #[maybe_async::maybe_async]
331    pub async fn send_changes_email(self) -> crate::Result<ChangesResponse<Email<Get>>> {
332        self.send_single().await
333    }
334
335    pub fn query_email(&mut self) -> &mut QueryRequest<Email<Set>> {
336        self.add_method_call(
337            Method::QueryEmail,
338            Arguments::email_query(self.params(Method::QueryEmail)),
339        )
340        .email_query_mut()
341    }
342
343    #[maybe_async::maybe_async]
344    pub async fn send_query_email(self) -> crate::Result<QueryResponse> {
345        self.send_single().await
346    }
347
348    pub fn query_email_changes(
349        &mut self,
350        since_query_state: impl Into<String>,
351    ) -> &mut QueryChangesRequest<Email<Set>> {
352        self.add_method_call(
353            Method::QueryChangesEmail,
354            Arguments::email_query_changes(
355                self.params(Method::QueryChangesEmail),
356                since_query_state.into(),
357            ),
358        )
359        .email_query_changes_mut()
360    }
361
362    #[maybe_async::maybe_async]
363    pub async fn send_query_email_changes(self) -> crate::Result<QueryChangesResponse> {
364        self.send_single().await
365    }
366
367    pub fn set_email(&mut self) -> &mut SetRequest<Email<Set>> {
368        self.add_method_call(
369            Method::SetEmail,
370            Arguments::email_set(self.params(Method::SetEmail)),
371        )
372        .email_set_mut()
373    }
374
375    #[maybe_async::maybe_async]
376    pub async fn send_set_email(self) -> crate::Result<EmailSetResponse> {
377        self.send_single().await
378    }
379
380    pub fn copy_email(
381        &mut self,
382        from_account_id: impl Into<String>,
383    ) -> &mut CopyRequest<Email<Set>> {
384        self.add_method_call(
385            Method::CopyEmail,
386            Arguments::email_copy(self.params(Method::CopyEmail), from_account_id.into()),
387        )
388        .email_copy_mut()
389    }
390
391    #[maybe_async::maybe_async]
392    pub async fn send_copy_email(self) -> crate::Result<EmailCopyResponse> {
393        self.send_single().await
394    }
395
396    pub fn import_email(&mut self) -> &mut EmailImportRequest {
397        self.add_method_call(
398            Method::ImportEmail,
399            Arguments::email_import(self.params(Method::ImportEmail)),
400        )
401        .email_import_mut()
402    }
403
404    #[maybe_async::maybe_async]
405    pub async fn send_import_email(self) -> crate::Result<EmailImportResponse> {
406        self.send_single().await
407    }
408
409    pub fn parse_email(&mut self) -> &mut EmailParseRequest {
410        self.add_method_call(
411            Method::ParseEmail,
412            Arguments::email_parse(self.params(Method::ParseEmail)),
413        )
414        .email_parse_mut()
415    }
416
417    #[maybe_async::maybe_async]
418    pub async fn send_parse_email(self) -> crate::Result<EmailParseResponse> {
419        self.send_single().await
420    }
421
422    pub fn get_search_snippet(&mut self) -> &mut SearchSnippetGetRequest {
423        self.add_method_call(
424            Method::GetSearchSnippet,
425            Arguments::search_snippet_get(self.params(Method::GetSearchSnippet)),
426        )
427        .search_snippet_get_mut()
428    }
429
430    #[maybe_async::maybe_async]
431    pub async fn send_get_search_snippet(self) -> crate::Result<SearchSnippetGetResponse> {
432        self.send_single().await
433    }
434}