Skip to main content

io_email/message/maildir/
add.rs

1//! Maildir message-add coroutine wrapping
2//! [`io_maildir::entry::store::MaildirEntryStore`]: writes raw bytes
3//! to tmp/, then renames into cur/ with info-section letters.
4//!
5//! Returns the Maildir filename minus the `:2,FLAGS` suffix.
6//!
7//! # Example
8//!
9//! ```rust,ignore
10//! use io_email::message::maildir::add::MaildirMessageAdd;
11//!
12//! let id = client.run(MaildirMessageAdd::new(&client.store, "INBOX", &flags, raw)?)?;
13//! ```
14
15use alloc::{string::String, vec::Vec};
16
17use io_maildir::{
18    coroutine::*,
19    entry::store::{MaildirEntryStore as InnerStore, MaildirEntryStoreError as InnerErr},
20    maildir::types::{Maildir, MaildirSubdir},
21    store::MaildirStore,
22};
23use log::trace;
24use thiserror::Error;
25
26use crate::{
27    flag::types::Flag,
28    maildir::convert::{InvalidMailboxName, flags_to_maildir, mailbox_path},
29};
30
31/// Errors produced by [`MaildirMessageAdd`].
32#[derive(Debug, Error)]
33pub enum MaildirMessageAddError {
34    #[error(transparent)]
35    Store(#[from] InnerErr),
36    #[error(transparent)]
37    InvalidMailbox(#[from] InvalidMailboxName),
38}
39
40/// I/O-free coroutine appending a raw message to a Maildir cur/.
41pub struct MaildirMessageAdd {
42    inner: InnerStore,
43}
44
45impl MaildirMessageAdd {
46    pub fn new(
47        store: &MaildirStore,
48        mailbox: &str,
49        flags: &[Flag],
50        bytes: Vec<u8>,
51    ) -> Result<Self, MaildirMessageAddError> {
52        trace!("prepare Maildir message add");
53        let path = mailbox_path(mailbox)?;
54        let maildir = Maildir::from_path(store.resolve(&path));
55        let md_flags = flags_to_maildir(flags);
56        Ok(Self {
57            inner: InnerStore::new(maildir, MaildirSubdir::Cur, md_flags, bytes),
58        })
59    }
60}
61
62impl MaildirCoroutine for MaildirMessageAdd {
63    type Yield = MaildirYield;
64    type Return = Result<String, MaildirMessageAddError>;
65
66    fn resume(
67        &mut self,
68        arg: Option<MaildirReply>,
69    ) -> MaildirCoroutineState<Self::Yield, Self::Return> {
70        match self.inner.resume(arg) {
71            MaildirCoroutineState::Yielded(y) => MaildirCoroutineState::Yielded(y),
72            MaildirCoroutineState::Complete(Ok(ok)) => MaildirCoroutineState::Complete(Ok(ok.id)),
73            MaildirCoroutineState::Complete(Err(err)) => {
74                MaildirCoroutineState::Complete(Err(err.into()))
75            }
76        }
77    }
78}