Files
himalaya/src/imap/message/move.rs
T
2026-05-20 00:53:23 +02:00

73 lines
2.4 KiB
Rust

use anyhow::{bail, Result};
use clap::Parser;
use io_imap::{
coroutines::{r#move::*, select::*},
types::mailbox::Mailbox,
};
use io_stream::runtimes::std::handle;
use pimalaya_toolbox::terminal::printer::{Message, Printer};
use crate::imap::{
account::ImapAccount,
mailbox::arg::{MailboxNameOptionalFlag, MailboxNoSelectFlag, TargetMailboxNameArg},
};
/// Move message(s) to the given mailbox.
///
/// This command moves messages identified by the given sequence set
/// from the source mailbox to the destination mailbox. Requires the
/// MOVE IMAP extension.
#[derive(Debug, Parser)]
pub struct MoveMessageCommand {
#[command(flatten)]
pub mailbox_name: MailboxNameOptionalFlag,
#[command(flatten)]
pub mailbox_no_select: MailboxNoSelectFlag,
/// The sequence set of messages (e.g., "1", "1,2,3", "1:*").
#[arg(name = "sequence_set", value_name = "SEQUENCE")]
pub sequence_set: String,
#[command(flatten)]
pub mailbox_dest_name: TargetMailboxNameArg,
/// Use sequence numbers instead of UIDs.
#[arg(long)]
pub seq: bool,
}
impl MoveMessageCommand {
pub fn execute(self, printer: &mut impl Printer, account: ImapAccount) -> Result<()> {
let mut imap = account.new_imap_session()?;
let mailbox = self.mailbox_name.inner.try_into()?;
if !self.mailbox_no_select.inner {
let mut arg = None;
let mut coroutine = ImapSelect::new(imap.context, mailbox);
imap.context = loop {
match coroutine.resume(arg.take()) {
ImapSelectResult::Io { io } => arg = Some(handle(&mut imap.stream, io)?),
ImapSelectResult::Ok { context, .. } => break context,
ImapSelectResult::Err { err, .. } => bail!(err),
}
};
}
let sequence_set = self.sequence_set.as_str().try_into()?;
let destination: Mailbox<'static> = self.mailbox_dest_name.inner.try_into()?;
let mut arg = None;
let mut coroutine = ImapMove::new(imap.context, sequence_set, destination, !self.seq);
loop {
match coroutine.resume(arg.take()) {
ImapMoveResult::Io { io } => arg = Some(handle(&mut imap.stream, io)?),
ImapMoveResult::Ok { .. } => break,
ImapMoveResult::Err { err, .. } => bail!(err),
}
}
printer.out(Message::new("Message(s) successfully moved"))
}
}