Skip to main content

io_email/message/jmap/
delete.rs

1//! JMAP message-delete coroutine wrapping Email/set { destroy } (RFC
2//! 8621 ยง4.7); JMAP destroy is a global delete across all mailboxes.
3//!
4//! # Example
5//!
6//! ```rust,ignore
7//! use io_email::message::jmap::delete::JmapMessageDelete;
8//!
9//! client.run(JmapMessageDelete::new(&session, &auth, "_", "email-id")?)?;
10//! ```
11
12use alloc::{string::String, vec};
13
14use io_jmap::{
15    coroutine::{JmapCoroutine, JmapCoroutineState, JmapYield},
16    rfc8620::JmapSession,
17    rfc8621::email::set::{
18        JmapEmailSet as InnerSet, JmapEmailSetArgs, JmapEmailSetError as InnerErr,
19    },
20};
21use log::trace;
22use secrecy::SecretString;
23use thiserror::Error;
24
25/// Errors produced by [`JmapMessageDelete`].
26#[derive(Debug, Error)]
27pub enum JmapMessageDeleteError {
28    #[error(transparent)]
29    Set(#[from] InnerErr),
30    #[error("Email/set did not destroy `{0}`")]
31    NotDestroyed(String),
32}
33
34/// I/O-free coroutine destroying a single JMAP email by id.
35pub struct JmapMessageDelete {
36    inner: InnerSet,
37    id: String,
38}
39
40impl JmapMessageDelete {
41    /// `mailbox` is unused; kept for shared-API symmetry.
42    pub fn new(
43        session: &JmapSession,
44        http_auth: &SecretString,
45        _mailbox: &str,
46        id: &str,
47    ) -> Result<Self, JmapMessageDeleteError> {
48        trace!("prepare JMAP message delete");
49        let args = JmapEmailSetArgs {
50            destroy: Some(vec![id.into()]),
51            ..JmapEmailSetArgs::default()
52        };
53        Ok(Self {
54            inner: InnerSet::new(session, http_auth, args)?,
55            id: id.into(),
56        })
57    }
58}
59
60impl JmapCoroutine for JmapMessageDelete {
61    type Yield = JmapYield;
62    type Return = Result<(), JmapMessageDeleteError>;
63
64    fn resume(&mut self, bytes: Option<&[u8]>) -> JmapCoroutineState<Self::Yield, Self::Return> {
65        match self.inner.resume(bytes) {
66            JmapCoroutineState::Yielded(y) => JmapCoroutineState::Yielded(y),
67            JmapCoroutineState::Complete(Ok(ok)) => {
68                if ok.destroyed.iter().any(|d| d == &self.id) {
69                    JmapCoroutineState::Complete(Ok(()))
70                } else {
71                    JmapCoroutineState::Complete(Err(JmapMessageDeleteError::NotDestroyed(
72                        self.id.clone(),
73                    )))
74                }
75            }
76            JmapCoroutineState::Complete(Err(err)) => JmapCoroutineState::Complete(Err(err.into())),
77        }
78    }
79}