From 0352e91e368bbca635ebc3e294a45338e3aa3f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Wed, 3 Jan 2024 12:58:44 +0100 Subject: [PATCH] improve backend features management for every command --- src/account/command/sync.rs | 2 +- src/account/config.rs | 8 + src/backend/mod.rs | 137 ++++++++++-------- src/email/envelope/command/list.rs | 130 ++++++----------- src/email/envelope/command/watch.rs | 54 ++++++- src/email/envelope/flag/command/add.rs | 47 ++++-- src/email/envelope/flag/command/remove.rs | 51 +++++-- src/email/envelope/flag/command/set.rs | 49 +++++-- .../message/attachment/command/download.rs | 65 +++++++-- src/email/message/command/copy.rs | 58 ++++++-- src/email/message/command/delete.rs | 64 ++++++-- src/email/message/command/forward.rs | 72 ++++++++- src/email/message/command/mailto.rs | 77 +++++++++- src/email/message/command/move_.rs | 58 ++++++-- src/email/message/command/read.rs | 65 +++++++-- src/email/message/command/reply.rs | 71 ++++++++- src/email/message/command/save.rs | 55 ++++++- src/email/message/command/send.rs | 48 +++++- src/email/message/command/write.rs | 71 ++++++++- src/email/message/template/command/forward.rs | 51 ++++++- src/email/message/template/command/reply.rs | 53 ++++++- src/email/message/template/command/save.rs | 55 ++++++- src/email/message/template/command/send.rs | 46 +++++- src/email/message/template/command/write.rs | 10 +- src/folder/command/create.rs | 52 +++++-- src/folder/command/delete.rs | 53 +++++-- src/folder/command/expunge.rs | 55 +++++-- src/folder/command/list.rs | 50 +++++-- src/folder/command/purge.rs | 54 +++++-- 29 files changed, 1290 insertions(+), 371 deletions(-) diff --git a/src/account/command/sync.rs b/src/account/command/sync.rs index 5888263..1b94b30 100644 --- a/src/account/command/sync.rs +++ b/src/account/command/sync.rs @@ -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) diff --git a/src/account/config.rs b/src/account/config.rs index 33a665a..5d0295c 100644 --- a/src/account/config.rs +++ b/src/account/config.rs @@ -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() diff --git a/src/backend/mod.rs b/src/backend/mod.rs index a25c865..60f1254 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -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, } +impl BackendContextBuilder { + pub async fn new( + toml_account_config: &TomlAccountConfig, + account_config: &AccountConfig, + kinds: Vec<&BackendKind>, + ) -> Result { + 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 { 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, + with_features: impl Fn(&mut email::backend::BackendBuilder), ) -> Result { - 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, - ) -> Result { Ok(Self { - toml_account_config, - backend: builder.build().await?, + toml_account_config: toml_account_config.clone(), + backend: backend_builder.build().await?, }) } diff --git a/src/email/envelope/command/list.rs b/src/email/envelope/command/list.rs index a45e7b3..68d19da 100644 --- a/src/email/envelope/command/list.rs +++ b/src/email/envelope/command/list.rs @@ -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?; diff --git a/src/email/envelope/command/watch.rs b/src/email/envelope/command/watch.rs index d7f8397..62bbba0 100644 --- a/src/email/envelope/command/watch.rs +++ b/src/email/envelope/command/watch.rs @@ -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…" diff --git a/src/email/envelope/flag/command/add.rs b/src/email/envelope/flag/command/add.rs index 5150516..55fc697 100644 --- a/src/email/envelope/flag/command/add.rs +++ b/src/email/envelope/flag/command/add.rs @@ -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!")) diff --git a/src/email/envelope/flag/command/remove.rs b/src/email/envelope/flag/command/remove.rs index e2d3a14..4c0f1c1 100644 --- a/src/email/envelope/flag/command/remove.rs +++ b/src/email/envelope/flag/command/remove.rs @@ -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!")) diff --git a/src/email/envelope/flag/command/set.rs b/src/email/envelope/flag/command/set.rs index 5cbe7f1..5326445 100644 --- a/src/email/envelope/flag/command/set.rs +++ b/src/email/envelope/flag/command/set.rs @@ -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!")) } } diff --git a/src/email/message/attachment/command/download.rs b/src/email/message/attachment/command/download.rs index c1d3b5c..d9cab87 100644 --- a/src/email/message/attachment/command/download.rs +++ b/src/email/message/attachment/command/download.rs @@ -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; diff --git a/src/email/message/command/copy.rs b/src/email/message/command/copy.rs index 6e74e26..f77078b 100644 --- a/src/email/message/command/copy.rs +++ b/src/email/message/command/copy.rs @@ -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}!" )) } } diff --git a/src/email/message/command/delete.rs b/src/email/message/command/delete.rs index 21797fb..5bfbd95 100644 --- a/src/email/message/command/delete.rs +++ b/src/email/message/command/delete.rs @@ -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}!")) diff --git a/src/email/message/command/forward.rs b/src/email/message/command/forward.rs index 506e396..276d645 100644 --- a/src/email/message/command/forward.rs +++ b/src/email/message/command/forward.rs @@ -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 diff --git a/src/email/message/command/mailto.rs b/src/email/message/command/mailto.rs index 7a100fa..a2b0470 100644 --- a/src/email/message/command/mailto.rs +++ b/src/email/message/command/mailto.rs @@ -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(); diff --git a/src/email/message/command/move_.rs b/src/email/message/command/move_.rs index dc72a71..9995e46 100644 --- a/src/email/message/command/move_.rs +++ b/src/email/message/command/move_.rs @@ -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}!" )) } } diff --git a/src/email/message/command/read.rs b/src/email/message/command/read.rs index 49cab78..60e71c1 100644 --- a/src/email/message/command/read.rs +++ b/src/email/message/command/read.rs @@ -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 { diff --git a/src/email/message/command/reply.rs b/src/email/message/command/reply.rs index d7aa73e..db14c2c 100644 --- a/src/email/message/command/reply.rs +++ b/src/email/message/command/reply.rs @@ -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 diff --git a/src/email/message/command/save.rs b/src/email/message/command/save.rs index e0e018e..cf2ec59 100644 --- a/src/email/message/command/save.rs +++ b/src/email/message/command/save.rs @@ -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(); diff --git a/src/email/message/command/send.rs b/src/email/message/command/send.rs index 9041854..ad1fded 100644 --- a/src/email/message/command/send.rs +++ b/src/email/message/command/send.rs @@ -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() diff --git a/src/email/message/command/write.rs b/src/email/message/command/write.rs index 16eb455..ce326cc 100644 --- a/src/email/message/command/write.rs +++ b/src/email/message/command/write.rs @@ -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) diff --git a/src/email/message/template/command/forward.rs b/src/email/message/template/command/forward.rs index f1b510c..0e3c59d 100644 --- a/src/email/message/template/command/forward.rs +++ b/src/email/message/template/command/forward.rs @@ -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 diff --git a/src/email/message/template/command/reply.rs b/src/email/message/template/command/reply.rs index 4d5cd6a..57342db 100644 --- a/src/email/message/template/command/reply.rs +++ b/src/email/message/template/command/reply.rs @@ -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]) diff --git a/src/email/message/template/command/save.rs b/src/email/message/template/command/save.rs index b893c12..675429b 100644 --- a/src/email/message/template/command/save.rs +++ b/src/email/message/template/command/save.rs @@ -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(); diff --git a/src/email/message/template/command/send.rs b/src/email/message/template/command/send.rs index 0ae4ba5..bf874fa 100644 --- a/src/email/message/template/command/send.rs +++ b/src/email/message/template/command/send.rs @@ -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() diff --git a/src/email/message/template/command/write.rs b/src/email/message/template/command/write.rs index cf22bd4..7034555 100644 --- a/src/email/message/template/command/write.rs +++ b/src/email/message/template/command/write.rs @@ -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) diff --git a/src/folder/command/create.rs b/src/folder/command/create.rs index 3e27138..7125154 100644 --- a/src/folder/command/create.rs +++ b/src/folder/command/create.rs @@ -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!")) } } diff --git a/src/folder/command/delete.rs b/src/folder/command/delete.rs index 14a500a..43f64fb 100644 --- a/src/folder/command/delete.rs +++ b/src/folder/command/delete.rs @@ -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!")) } } diff --git a/src/folder/command/expunge.rs b/src/folder/command/expunge.rs index a6df0ca..5ad20a9 100644 --- a/src/folder/command/expunge.rs +++ b/src/folder/command/expunge.rs @@ -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!")) } } diff --git a/src/folder/command/list.rs b/src/folder/command/list.rs index accf287..f14e2d0 100644 --- a/src/folder/command/list.rs +++ b/src/folder/command/list.rs @@ -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(()) + ) } } diff --git a/src/folder/command/purge.rs b/src/folder/command/purge.rs index 9f97648..a867c1b 100644 --- a/src/folder/command/purge.rs +++ b/src/folder/command/purge.rs @@ -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!")) } }