improve backend features management for every command

This commit is contained in:
Clément DOUIN 2024-01-03 12:58:44 +01:00
parent a8c6756f56
commit 0352e91e36
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
29 changed files with 1290 additions and 371 deletions

View file

@ -101,7 +101,7 @@ impl AccountSyncCommand {
let account_name = account_config.name.as_str();
let backend_builder =
BackendBuilder::new(toml_account_config, account_config.clone(), false).await?;
BackendBuilder::new(toml_account_config, account_config.clone()).await?;
let sync_builder = AccountSyncBuilder::new(backend_builder.into())
.await?
.with_some_folders_strategy(strategy)

View file

@ -111,6 +111,14 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref())
}
pub fn watch_envelopes_kind(&self) -> Option<&BackendKind> {
self.envelope
.as_ref()
.and_then(|envelope| envelope.watch.as_ref())
.and_then(|watch| watch.backend.as_ref())
.or_else(|| self.backend.as_ref())
}
pub fn add_flags_kind(&self) -> Option<&BackendKind> {
self.flag
.as_ref()

View file

@ -40,7 +40,6 @@ use email::{
get::imap::GetMessagesImap,
move_::{imap::MoveMessagesImap, maildir::MoveMessagesMaildir},
peek::{imap::PeekMessagesImap, maildir::PeekMessagesMaildir},
send_raw::{sendmail::SendRawMessageSendmail, smtp::SendRawMessageSmtp},
Messages,
},
sendmail::SendmailContext,
@ -93,6 +92,68 @@ pub struct BackendContextBuilder {
pub sendmail: Option<SendmailContext>,
}
impl BackendContextBuilder {
pub async fn new(
toml_account_config: &TomlAccountConfig,
account_config: &AccountConfig,
kinds: Vec<&BackendKind>,
) -> Result<Self> {
Ok(Self {
maildir: toml_account_config
.maildir
.as_ref()
.filter(|_| kinds.contains(&&BackendKind::Maildir))
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
.filter(|_| kinds.contains(&&BackendKind::MaildirForSync))
.map(|mdir_config| MaildirSessionBuilder::new(account_config.clone(), mdir_config)),
#[cfg(feature = "imap")]
imap: {
let ctx_builder = toml_account_config
.imap
.as_ref()
.filter(|_| kinds.contains(&&BackendKind::Imap))
.map(|imap_config| {
ImapSessionBuilder::new(account_config.clone(), imap_config.clone())
.with_prebuilt_credentials()
});
match ctx_builder {
Some(ctx_builder) => Some(ctx_builder.await?),
None => None,
}
},
#[cfg(feature = "notmuch")]
notmuch: toml_account_config
.notmuch
.as_ref()
.filter(|_| kinds.contains(&&BackendKind::Notmuch))
.map(|notmuch_config| {
NotmuchSessionBuilder::new(account_config.clone(), notmuch_config.clone())
}),
#[cfg(feature = "smtp")]
smtp: toml_account_config
.smtp
.as_ref()
.filter(|_| kinds.contains(&&BackendKind::Smtp))
.map(|smtp_config| {
SmtpClientBuilder::new(account_config.clone(), smtp_config.clone())
}),
#[cfg(feature = "sendmail")]
sendmail: toml_account_config
.sendmail
.as_ref()
.filter(|_| kinds.contains(&&BackendKind::Sendmail))
.map(|sendmail_config| {
SendmailContext::new(account_config.clone(), sendmail_config.clone())
}),
})
}
}
#[async_trait]
impl email::backend::BackendContextBuilder for BackendContextBuilder {
type Context = BackendContext;
@ -151,7 +212,6 @@ impl BackendBuilder {
pub async fn new(
toml_account_config: TomlAccountConfig,
account_config: AccountConfig,
with_sending: bool,
) -> Result<Self> {
let used_backends = toml_account_config.get_used_backends();
@ -159,11 +219,6 @@ impl BackendBuilder {
let is_maildir_for_sync_used = used_backends.contains(&BackendKind::MaildirForSync);
#[cfg(feature = "imap")]
let is_imap_used = used_backends.contains(&BackendKind::Imap);
#[cfg(feature = "notmuch")]
let is_notmuch_used = used_backends.contains(&BackendKind::Notmuch);
#[cfg(feature = "smtp")]
let is_smtp_used = used_backends.contains(&BackendKind::Smtp);
let is_sendmail_used = used_backends.contains(&BackendKind::Sendmail);
let backend_ctx_builder = BackendContextBuilder {
maildir: toml_account_config
@ -195,31 +250,7 @@ impl BackendBuilder {
None => None,
}
},
#[cfg(feature = "notmuch")]
notmuch: toml_account_config
.notmuch
.as_ref()
.filter(|_| is_notmuch_used)
.map(|notmuch_config| {
NotmuchSessionBuilder::new(account_config.clone(), notmuch_config.clone())
}),
#[cfg(feature = "smtp")]
smtp: toml_account_config
.smtp
.as_ref()
.filter(|_| with_sending)
.filter(|_| is_smtp_used)
.map(|smtp_config| {
SmtpClientBuilder::new(account_config.clone(), smtp_config.clone())
}),
sendmail: toml_account_config
.sendmail
.as_ref()
.filter(|_| with_sending)
.filter(|_| is_sendmail_used)
.map(|sendmail_config| {
SendmailContext::new(account_config.clone(), sendmail_config.clone())
}),
..Default::default()
};
let mut backend_builder =
@ -511,21 +542,6 @@ impl BackendBuilder {
_ => (),
}
match toml_account_config.send_raw_message_kind() {
#[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => {
backend_builder = backend_builder.with_send_raw_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
});
}
Some(BackendKind::Sendmail) => {
backend_builder = backend_builder.with_send_raw_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
});
}
_ => (),
}
match toml_account_config.add_raw_message_kind() {
Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| {
@ -689,23 +705,22 @@ pub struct Backend {
impl Backend {
pub async fn new(
toml_account_config: TomlAccountConfig,
account_config: AccountConfig,
with_sending: bool,
toml_account_config: &TomlAccountConfig,
account_config: &AccountConfig,
backend_kinds: impl IntoIterator<Item = &BackendKind>,
with_features: impl Fn(&mut email::backend::BackendBuilder<BackendContextBuilder>),
) -> Result<Self> {
BackendBuilder::new(toml_account_config, account_config, with_sending)
.await?
.build()
.await
}
let backend_kinds = backend_kinds.into_iter().collect();
let backend_ctx_builder =
BackendContextBuilder::new(toml_account_config, account_config, backend_kinds).await?;
let mut backend_builder =
email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder);
with_features(&mut backend_builder);
pub async fn new_v2(
toml_account_config: TomlAccountConfig,
builder: email::backend::BackendBuilder<BackendContextBuilder>,
) -> Result<Self> {
Ok(Self {
toml_account_config,
backend: builder.build().await?,
toml_account_config: toml_account_config.clone(),
backend: backend_builder.build().await?,
})
}

View file

@ -1,18 +1,16 @@
use anyhow::Result;
use clap::Parser;
use email::backend::BackendBuilder;
#[cfg(feature = "imap")]
use email::{envelope::list::imap::ListEnvelopesImap, imap::ImapSessionBuilder};
use email::envelope::list::imap::ListEnvelopesImap;
#[cfg(feature = "maildir")]
use email::{
envelope::list::maildir::ListEnvelopesMaildir,
maildir::{config::MaildirConfig, MaildirSessionBuilder},
};
use email::envelope::list::maildir::ListEnvelopesMaildir;
#[cfg(feature = "notmuch")]
use email::envelope::list::notmuch::ListEnvelopesNotmuch;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::{Backend, BackendContextBuilder, BackendKind},
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameOptionalArg,
@ -54,90 +52,48 @@ pub struct ListEnvelopesCommand {
impl ListEnvelopesCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing envelope list command");
info!("executing list envelopes command");
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let folder = &self.folder.name;
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend_kind = toml_account_config.list_envelopes_kind();
let backend_ctx_builder = BackendContextBuilder {
maildir: toml_account_config
.maildir
.as_ref()
.filter(|_| matches!(backend_kind, Some(BackendKind::Maildir)))
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
.filter(|_| matches!(backend_kind, Some(BackendKind::MaildirForSync)))
.map(|mdir_config| MaildirSessionBuilder::new(account_config.clone(), mdir_config)),
#[cfg(feature = "imap")]
imap: {
let ctx_builder = toml_account_config
.imap
.as_ref()
.filter(|_| matches!(backend_kind, Some(BackendKind::Imap)))
.map(|imap_config| {
ImapSessionBuilder::new(account_config.clone(), imap_config.clone())
.with_prebuilt_credentials()
});
match ctx_builder {
Some(ctx_builder) => Some(ctx_builder.await?),
None => None,
}
},
#[cfg(feature = "notmuch")]
notmuch: toml_account_config
.notmuch
.as_ref()
.filter(|_| matches!(backend_kind, Some(BackendKind::Notmuch)))
.map(|notmuch_config| {
NotmuchSessionBuilder::new(account_config.clone(), notmuch_config.clone())
}),
..Default::default()
};
let mut backend_builder = BackendBuilder::new(account_config.clone(), backend_ctx_builder);
match toml_account_config.list_envelopes_kind() {
Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(ListEnvelopesMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
backend_builder = backend_builder
.with_list_envelopes(|ctx| ctx.imap.as_ref().and_then(ListEnvelopesImap::new));
}
#[cfg(feature = "notmuch")]
Some(BackendKind::Notmuch) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.notmuch.as_ref().and_then(ListEnvelopesNotmuch::new)
});
}
_ => (),
}
let backend = Backend::new_v2(toml_account_config.clone(), backend_builder).await?;
let page = 1.max(self.page) - 1;
let page_size = self
.page_size
.unwrap_or(account_config.get_envelope_list_page_size());
let page = 1.max(self.page) - 1;
.unwrap_or_else(|| account_config.get_envelope_list_page_size());
let list_envelopes_kind = toml_account_config.list_envelopes_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
list_envelopes_kind,
|builder| match list_envelopes_kind {
Some(BackendKind::Maildir) => {
builder.set_list_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_list_envelopes(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(ListEnvelopesMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_list_envelopes(|ctx| {
ctx.imap.as_ref().and_then(ListEnvelopesImap::new)
});
}
_ => (),
},
)
.await?;
let envelopes = backend.list_envelopes(folder, page_size, page).await?;

View file

@ -1,10 +1,20 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::envelope::watch::imap::WatchImapEnvelopes;
#[cfg(feature = "maildir")]
use email::envelope::watch::maildir::WatchMaildirEnvelopes;
#[cfg(feature = "notmuch")]
use email::envelope::watch::notmuch::WatchNotmuchEnvelopes;
use log::info;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, folder::arg::name::FolderNameOptionalFlag, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameOptionalFlag,
printer::Printer,
};
/// Watch envelopes for changes.
@ -25,15 +35,43 @@ pub struct WatchEnvelopesCommand {
impl WatchEnvelopesCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing envelopes watch command");
info!("executing watch envelopes command");
let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let watch_envelopes_kind = toml_account_config.watch_envelopes_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
watch_envelopes_kind,
|builder| match watch_envelopes_kind {
Some(BackendKind::Maildir) => {
builder.set_watch_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(WatchMaildirEnvelopes::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_watch_envelopes(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(WatchMaildirEnvelopes::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_watch_envelopes(|ctx| {
ctx.imap.as_ref().and_then(WatchImapEnvelopes::new)
});
}
_ => (),
},
)
.await?;
printer.print_log(format!(
"Start watching folder {folder} for envelopes changes…"

View file

@ -1,10 +1,16 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::flag::add::imap::AddFlagsImap;
#[cfg(feature = "maildir")]
use email::flag::add::maildir::AddFlagsMaildir;
#[cfg(feature = "notmuch")]
use email::flag::add::notmuch::AddFlagsNotmuch;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
@ -33,17 +39,40 @@ pub struct FlagAddCommand {
impl FlagAddCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing flag add command");
info!("executing add flag(s) command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let add_flags_kind = toml_account_config.add_flags_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_flags_kind,
|builder| match add_flags_kind {
Some(BackendKind::Maildir) => {
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_flags(|ctx| ctx.imap.as_ref().and_then(AddFlagsImap::new));
}
_ => (),
},
)
.await?;
backend.add_flags(folder, &ids, &flags).await?;
printer.print(format!("Flag(s) {flags} successfully added!"))

View file

@ -1,10 +1,16 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::flag::remove::imap::RemoveFlagsImap;
#[cfg(feature = "maildir")]
use email::flag::remove::maildir::RemoveFlagsMaildir;
#[cfg(feature = "notmuch")]
use email::flag::remove::notmuch::RemoveFlagsNotmuch;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
@ -33,17 +39,44 @@ pub struct FlagRemoveCommand {
impl FlagRemoveCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing flag remove command");
info!("executing remove flag(s) command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let remove_flags_kind = toml_account_config.remove_flags_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
remove_flags_kind,
|builder| match remove_flags_kind {
Some(BackendKind::Maildir) => {
builder.set_remove_flags(|ctx| {
ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_remove_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(RemoveFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_remove_flags(|ctx| ctx.imap.as_ref().and_then(RemoveFlagsImap::new));
}
_ => (),
},
)
.await?;
backend.remove_flags(folder, &ids, &flags).await?;
printer.print(format!("Flag(s) {flags} successfully removed!"))

View file

@ -1,10 +1,16 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::flag::set::imap::SetFlagsImap;
#[cfg(feature = "maildir")]
use email::flag::set::maildir::SetFlagsMaildir;
#[cfg(feature = "notmuch")]
use email::flag::set::notmuch::SetFlagsNotmuch;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
@ -33,19 +39,42 @@ pub struct FlagSetCommand {
impl FlagSetCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing flag set command");
info!("executing set flag(s) command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let set_flags_kind = toml_account_config.set_flags_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
set_flags_kind,
|builder| match set_flags_kind {
Some(BackendKind::Maildir) => {
builder
.set_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_set_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_set_flags(|ctx| ctx.imap.as_ref().and_then(SetFlagsImap::new));
}
_ => (),
},
)
.await?;
backend.set_flags(folder, &ids, &flags).await?;
printer.print(format!("Flag(s) {flags} successfully set!"))
printer.print(format!("Flag(s) {flags} successfully replaced!"))
}
}

View file

@ -1,13 +1,21 @@
use anyhow::{Context, Result};
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::{get::imap::GetMessagesImap, peek::imap::PeekMessagesImap};
#[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info;
use std::{fs, path::PathBuf};
use uuid::Uuid;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag,
printer::Printer,
};
/// Download all attachments for the given message.
@ -31,17 +39,52 @@ pub struct AttachmentDownloadCommand {
impl AttachmentDownloadCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing attachment download command");
info!("executing download attachment(s) command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let ids = &self.envelopes.ids;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let get_messages_kind = toml_account_config.get_messages_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
get_messages_kind,
|builder| match get_messages_kind {
Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
});
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(PeekMessagesMaildir::new)
});
builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (),
},
)
.await?;
let emails = backend.get_messages(&folder, ids).await?;
let mut emails_count = 0;

View file

@ -1,10 +1,14 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::copy::imap::CopyMessagesImap;
#[cfg(feature = "maildir")]
use email::message::copy::maildir::CopyMessagesMaildir;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs,
@ -33,22 +37,50 @@ pub struct MessageCopyCommand {
impl MessageCopyCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message copy command");
let from_folder = &self.source_folder.name;
let to_folder = &self.target_folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
info!("executing copy message(s) command");
let source = &self.source_folder.name;
let target = &self.target_folder.name;
let ids = &self.envelopes.ids;
backend.copy_messages(from_folder, to_folder, ids).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let copy_messages_kind = toml_account_config.copy_messages_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
copy_messages_kind,
|builder| match copy_messages_kind {
Some(BackendKind::Maildir) => {
builder.set_copy_messages(|ctx| {
ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_copy_messages(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(CopyMessagesMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_copy_messages(|ctx| ctx.imap.as_ref().and_then(CopyMessagesImap::new));
}
_ => (),
},
)
.await?;
backend.copy_messages(source, target, ids).await?;
printer.print(format!(
"Message(s) successfully copied from {from_folder} to {to_folder}!"
"Message(s) successfully copied from {source} to {target}!"
))
}
}

View file

@ -1,11 +1,19 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::{flag::add::imap::AddFlagsImap, message::move_::imap::MoveMessagesImap};
#[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::move_::maildir::MoveMessagesMaildir};
use log::info;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag,
printer::Printer,
};
/// Mark as deleted a message from a folder.
@ -31,17 +39,51 @@ pub struct MessageDeleteCommand {
impl MessageDeleteCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message delete command");
info!("executing delete message(s) command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let ids = &self.envelopes.ids;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let delete_messages_kind = toml_account_config.delete_messages_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
delete_messages_kind,
|builder| match delete_messages_kind {
Some(BackendKind::Maildir) => {
builder.set_move_messages(|ctx| {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
});
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_move_messages(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(MoveMessagesMaildir::new)
});
builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_move_messages(|ctx| ctx.imap.as_ref().and_then(MoveMessagesImap::new));
builder.set_add_flags(|ctx| ctx.imap.as_ref().and_then(AddFlagsImap::new));
}
_ => (),
},
)
.await?;
backend.delete_messages(folder, ids).await?;
printer.print(format!("Message(s) successfully removed from {folder}!"))

View file

@ -1,10 +1,18 @@
use anyhow::{anyhow, Result};
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap;
#[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail;
#[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg,
@ -43,15 +51,65 @@ pub struct MessageForwardCommand {
impl MessageForwardCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message forward command");
info!("executing forward message command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let add_message_kind = toml_account_config.add_raw_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_message_kind.into_iter().chain(send_message_kind),
|builder| {
match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| {
ctx.imap.as_ref().and_then(AddRawMessageImap::new)
});
}
_ => (),
};
match send_message_kind {
#[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
});
}
#[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
});
}
_ => (),
};
},
)
.await?;
let id = self.envelope.id;
let tpl = backend

View file

@ -1,12 +1,24 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap;
#[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail;
#[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp;
use log::{debug, info};
use mail_builder::MessageBuilder;
use url::Url;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, printer::Printer, ui::editor,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
printer::Printer,
ui::editor,
};
/// Parse and edit a message from a mailto URL string.
@ -38,14 +50,63 @@ impl MessageMailtoCommand {
}
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message mailto command");
info!("executing mailto message command");
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
let add_message_kind = toml_account_config.add_raw_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_message_kind.into_iter().chain(send_message_kind),
|builder| {
match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| {
ctx.imap.as_ref().and_then(AddRawMessageImap::new)
});
}
_ => (),
};
match send_message_kind {
#[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
});
}
#[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
});
}
_ => (),
};
},
)
.await?;
let mut builder = MessageBuilder::new().to(self.url.path());
let mut body = String::new();

View file

@ -1,10 +1,14 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::move_::imap::MoveMessagesImap;
#[cfg(feature = "maildir")]
use email::message::move_::maildir::MoveMessagesMaildir;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs,
@ -33,22 +37,50 @@ pub struct MessageMoveCommand {
impl MessageMoveCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message move command");
let from_folder = &self.source_folder.name;
let to_folder = &self.target_folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
info!("executing move message(s) command");
let source = &self.source_folder.name;
let target = &self.target_folder.name;
let ids = &self.envelopes.ids;
backend.move_messages(from_folder, to_folder, ids).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let move_messages_kind = toml_account_config.move_messages_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
move_messages_kind,
|builder| match move_messages_kind {
Some(BackendKind::Maildir) => {
builder.set_move_messages(|ctx| {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_move_messages(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(MoveMessagesMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_move_messages(|ctx| ctx.imap.as_ref().and_then(MoveMessagesImap::new));
}
_ => (),
},
)
.await?;
backend.move_messages(source, target, ids).await?;
printer.print(format!(
"Message(s) successfully moved from {from_folder} to {to_folder}!"
"Message(s) successfully moved from {source} to {target}!"
))
}
}

View file

@ -1,12 +1,20 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::{get::imap::GetMessagesImap, peek::imap::PeekMessagesImap};
#[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info;
use mml::message::FilterParts;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag,
printer::Printer,
};
/// Read a message.
@ -75,17 +83,52 @@ pub struct MessageReadCommand {
impl MessageReadCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message read command");
info!("executing read message(s) command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let ids = &self.envelopes.ids;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let get_messages_kind = toml_account_config.get_messages_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
get_messages_kind,
|builder| match get_messages_kind {
Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
});
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(PeekMessagesMaildir::new)
});
builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (),
},
)
.await?;
let emails = if self.preview {
backend.peek_messages(&folder, &ids).await
} else {

View file

@ -1,11 +1,19 @@
use anyhow::{anyhow, Result};
use clap::Parser;
use email::flag::Flag;
#[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap;
#[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail;
#[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg,
@ -47,15 +55,64 @@ pub struct MessageReplyCommand {
impl MessageReplyCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message reply command");
info!("executing reply message command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
let add_message_kind = toml_account_config.add_raw_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_message_kind.into_iter().chain(send_message_kind),
|builder| {
match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| {
ctx.imap.as_ref().and_then(AddRawMessageImap::new)
});
}
_ => (),
};
match send_message_kind {
#[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
});
}
#[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
});
}
_ => (),
};
},
)
.await?;
let id = self.envelope.id;
let tpl = backend

View file

@ -1,11 +1,19 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap;
#[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir;
use log::info;
use std::io::{self, BufRead, IsTerminal};
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, folder::arg::name::FolderNameOptionalFlag, message::arg::MessageRawArg,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameOptionalFlag,
message::arg::MessageRawArg,
printer::Printer,
};
@ -29,15 +37,46 @@ pub struct MessageSaveCommand {
impl MessageSaveCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message save command");
info!("executing save message command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let add_message_kind = toml_account_config.add_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_message_kind,
|builder| match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| {
ctx.imap.as_ref().and_then(AddRawMessageImap::new)
});
}
_ => (),
},
)
.await?;
let is_tty = io::stdin().is_terminal();
let is_json = printer.is_json();

View file

@ -1,11 +1,19 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail;
#[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp;
use log::info;
use std::io::{self, BufRead, IsTerminal};
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, message::arg::MessageRawArg, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
message::arg::MessageRawArg,
printer::Printer,
};
/// Send a message.
@ -26,14 +34,38 @@ pub struct MessageSendCommand {
impl MessageSendCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message send command");
info!("executing send message command");
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
let send_message_kind = toml_account_config.send_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
send_message_kind,
|builder| {
match send_message_kind {
#[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
});
}
#[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
});
}
_ => (),
};
},
)
.await?;
let msg = if io::stdin().is_terminal() {
self.message.raw()

View file

@ -1,11 +1,19 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap;
#[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail;
#[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp;
use email::message::Message;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
@ -36,14 +44,63 @@ pub struct MessageWriteCommand {
impl MessageWriteCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing message write command");
info!("executing write message command");
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
let add_message_kind = toml_account_config.add_raw_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_message_kind.into_iter().chain(send_message_kind),
|builder| {
match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| {
ctx.imap.as_ref().and_then(AddRawMessageImap::new)
});
}
_ => (),
};
match send_message_kind {
#[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
});
}
#[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
});
}
_ => (),
};
},
)
.await?;
let tpl = Message::new_tpl_builder(&account_config)
.with_headers(self.headers.raw)

View file

@ -1,10 +1,14 @@
use anyhow::{anyhow, Result};
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::{get::imap::GetMessagesImap, peek::imap::PeekMessagesImap};
#[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg,
@ -44,12 +48,47 @@ impl TemplateForwardCommand {
info!("executing template forward command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let get_messages_kind = toml_account_config.get_messages_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
get_messages_kind,
|builder| match get_messages_kind {
Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
});
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(PeekMessagesMaildir::new)
});
builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (),
},
)
.await?;
let id = self.envelope.id;
let tpl: String = backend

View file

@ -1,10 +1,14 @@
use anyhow::{anyhow, Result};
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::{get::imap::GetMessagesImap, peek::imap::PeekMessagesImap};
#[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg,
@ -45,16 +49,51 @@ pub struct TemplateReplyCommand {
impl TemplateReplyCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template reply command");
info!("executing reply template command");
let folder = &self.folder.name;
let id = self.envelope.id;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let get_messages_kind = toml_account_config.get_messages_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
get_messages_kind,
|builder| match get_messages_kind {
Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
});
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(PeekMessagesMaildir::new)
});
builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (),
},
)
.await?;
let tpl: String = backend
.get_messages(folder, &[id])

View file

@ -1,13 +1,21 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap;
#[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir;
use log::info;
use mml::MmlCompilerBuilder;
use std::io::{self, BufRead, IsTerminal};
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, email::template::arg::TemplateRawArg,
folder::arg::name::FolderNameOptionalFlag, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
email::template::arg::TemplateRawArg,
folder::arg::name::FolderNameOptionalFlag,
printer::Printer,
};
/// Save a template to a folder.
@ -36,12 +44,43 @@ impl TemplateSaveCommand {
info!("executing template save command");
let folder = &self.folder.name;
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let add_message_kind = toml_account_config.add_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_message_kind,
|builder| match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| {
ctx.imap.as_ref().and_then(AddRawMessageImap::new)
});
}
_ => (),
},
)
.await?;
let is_tty = io::stdin().is_terminal();
let is_json = printer.is_json();

View file

@ -1,12 +1,20 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail;
#[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp;
use log::info;
use mml::MmlCompilerBuilder;
use std::io::{self, BufRead, IsTerminal};
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, email::template::arg::TemplateRawArg, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
email::template::arg::TemplateRawArg,
printer::Printer,
};
/// Send a template.
@ -31,12 +39,36 @@ impl TemplateSendCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template send command");
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let (toml_account_config, account_config) =
config.clone().into_account_configs(account, cache)?;
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
let send_message_kind = toml_account_config.send_raw_message_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
send_message_kind,
|builder| {
match send_message_kind {
#[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new)
});
}
#[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new)
});
}
_ => (),
};
},
)
.await?;
let tpl = if io::stdin().is_terminal() {
self.template.raw()

View file

@ -30,12 +30,12 @@ pub struct TemplateWriteCommand {
impl TemplateWriteCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template write command");
info!("executing write template command");
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (_, account_config) = config.clone().into_account_configs(account, cache)?;
let (_, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let tpl: String = Message::new_tpl_builder(&account_config)
.with_headers(self.headers.raw)

View file

@ -1,10 +1,18 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::folder::add::imap::AddFolderImap;
#[cfg(feature = "maildir")]
use email::folder::add::maildir::AddFolderMaildir;
use log::info;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
};
/// Create a new folder.
@ -25,19 +33,43 @@ pub struct FolderCreateCommand {
impl FolderCreateCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing folder create command");
info!("executing create folder command");
let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let add_folder_kind = toml_account_config.add_folder_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
add_folder_kind,
|builder| match add_folder_kind {
Some(BackendKind::Maildir) => {
builder
.set_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new));
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_folder(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddFolderMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_folder(|ctx| ctx.imap.as_ref().and_then(AddFolderImap::new));
}
_ => (),
},
)
.await?;
backend.add_folder(&folder).await?;
printer.print(format!("Folder {folder} successfully created!"))?;
Ok(())
printer.print(format!("Folder {folder} successfully created!"))
}
}

View file

@ -1,12 +1,20 @@
use anyhow::Result;
use clap::Parser;
use dialoguer::Confirm;
#[cfg(feature = "imap")]
use email::folder::delete::imap::DeleteFolderImap;
#[cfg(feature = "maildir")]
use email::folder::delete::maildir::DeleteFolderMaildir;
use log::info;
use std::process;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
};
/// Delete a folder.
@ -41,15 +49,42 @@ impl FolderDeleteCommand {
process::exit(0);
};
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let delete_folder_kind = toml_account_config.delete_folder_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
delete_folder_kind,
|builder| match delete_folder_kind {
Some(BackendKind::Maildir) => {
builder.set_delete_folder(|ctx| {
ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_delete_folder(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(DeleteFolderMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_delete_folder(|ctx| ctx.imap.as_ref().and_then(DeleteFolderImap::new));
}
_ => (),
},
)
.await?;
backend.delete_folder(&folder).await?;
printer.print(format!("Folder {folder} successfully deleted!"))?;
Ok(())
printer.print(format!("Folder {folder} successfully deleted!"))
}
}

View file

@ -1,10 +1,18 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::folder::expunge::imap::ExpungeFolderImap;
#[cfg(feature = "maildir")]
use email::folder::expunge::maildir::ExpungeFolderMaildir;
use log::info;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
};
/// Expunge a folder.
@ -26,19 +34,46 @@ pub struct FolderExpungeCommand {
impl FolderExpungeCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing folder expunge command");
info!("executing expunge folder command");
let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let expunge_folder_kind = toml_account_config.expunge_folder_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
expunge_folder_kind,
|builder| match expunge_folder_kind {
Some(BackendKind::Maildir) => {
builder.set_expunge_folder(|ctx| {
ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_expunge_folder(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(ExpungeFolderMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_expunge_folder(|ctx| {
ctx.imap.as_ref().and_then(ExpungeFolderImap::new)
});
}
_ => (),
},
)
.await?;
backend.expunge_folder(&folder).await?;
printer.print(format!("Folder {folder} successfully expunged!"))?;
Ok(())
printer.print(format!("Folder {folder} successfully expunged!"))
}
}

View file

@ -1,10 +1,14 @@
use anyhow::Result;
use clap::Parser;
#[cfg(feature = "imap")]
use email::folder::list::imap::ListFoldersImap;
#[cfg(feature = "maildir")]
use email::folder::list::maildir::ListFoldersMaildir;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::Folders,
@ -29,13 +33,41 @@ pub struct FolderListCommand {
impl FolderListCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing folder list command");
info!("executing list folders command");
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let list_folders_kind = toml_account_config.list_folders_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
list_folders_kind,
|builder| match list_folders_kind {
Some(BackendKind::Maildir) => {
builder.set_list_folders(|ctx| {
ctx.maildir.as_ref().and_then(ListFoldersMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_list_folders(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(ListFoldersMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_list_folders(|ctx| ctx.imap.as_ref().and_then(ListFoldersImap::new));
}
_ => (),
},
)
.await?;
let folders: Folders = backend.list_folders().await?.into();
@ -45,8 +77,6 @@ impl FolderListCommand {
format: &account_config.get_message_read_format(),
max_width: self.table.max_width,
},
)?;
Ok(())
)
}
}

View file

@ -1,12 +1,18 @@
use anyhow::Result;
use clap::Parser;
use dialoguer::Confirm;
#[cfg(feature = "imap")]
use email::folder::purge::imap::PurgeFolderImap;
use log::info;
use std::process;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
};
/// Purge a folder.
@ -27,7 +33,7 @@ pub struct FolderPurgeCommand {
impl FolderPurgeCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing folder purge command");
info!("executing purge folder command");
let folder = &self.folder.name;
@ -41,15 +47,43 @@ impl FolderPurgeCommand {
process::exit(0);
};
let some_account_name = self.account.name.as_ref().map(String::as_str);
let (toml_account_config, account_config) = config
.clone()
.into_account_configs(some_account_name, self.cache.disable)?;
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
self.cache.disable,
)?;
let purge_folder_kind = toml_account_config.purge_folder_kind();
let backend = Backend::new(
&toml_account_config,
&account_config,
purge_folder_kind,
|builder| match purge_folder_kind {
// TODO
// Some(BackendKind::Maildir) => {
// builder.set_purge_folder(|ctx| {
// ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new)
// });
// }
// Some(BackendKind::MaildirForSync) => {
// builder.set_purge_folder(|ctx| {
// ctx.maildir_for_sync
// .as_ref()
// .and_then(PurgeFolderMaildir::new)
// });
// }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_purge_folder(|ctx| ctx.imap.as_ref().and_then(PurgeFolderImap::new));
}
_ => (),
},
)
.await?;
backend.purge_folder(&folder).await?;
printer.print(format!("Folder {folder} successfully purged!"))?;
Ok(())
printer.print(format!("Folder {folder} successfully purged!"))
}
}