diff --git a/Cargo.lock b/Cargo.lock index 5966de52..c98db5bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1217,7 +1217,7 @@ dependencies = [ [[package]] name = "email-lib" version = "0.21.0" -source = "git+https://git.sr.ht/~soywod/pimalaya#ca42096c5537cf15becbb12bf0935381a1ea2908" +source = "git+https://git.sr.ht/~soywod/pimalaya#358717d3579ffacad2bbabd9d116a292473e38ae" dependencies = [ "advisory-lock", "anyhow", @@ -1239,6 +1239,7 @@ dependencies = [ "mail-parser", "mail-send", "maildirpp", + "md5", "mml-lib", "notify", "notify-rust", @@ -1246,11 +1247,11 @@ dependencies = [ "oauth-lib", "once_cell", "ouroboros 0.15.6", + "paste", "pgp-lib", "process-lib", "rayon", "regex", - "rusqlite", "secret-lib", "serde", "serde-xml-rs", @@ -1265,9 +1266,9 @@ dependencies = [ [[package]] name = "email-macros" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6354267c9a1db068b10ad982db9b8a82445f73f9bc9a57ed4924ddb913a065" +checksum = "0f24a09fd651027f8764f8a12c12358715cb9bab622ab3125ede3dd6ae047c95" dependencies = [ "quote", "syn 2.0.41", @@ -2962,6 +2963,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + [[package]] name = "pbkdf2" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 571350f2..e079a006 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,21 +19,14 @@ rustdoc-args = ["--cfg", "docsrs"] # features documentation: # https://pimalaya.org/himalaya/cli/latest/installation.html#cargo default = [ - "wizard", - "imap", "maildir", # "notmuch", "smtp", "sendmail", - "account", - "folder", - "envelope", - "flag", - "message", - "attachment", - "template", + "account-discovery", + "account-sync", # "pgp-commands", # "pgp-gpg", @@ -46,60 +39,8 @@ notmuch = ["email-lib/notmuch"] smtp = ["email-lib/smtp"] sendmail = ["email-lib/sendmail"] -wizard = ["email-lib/account-discovery"] -account = ["account-configure", "account-list", "account-sync"] -account-subcmd = [] -account-configure = ["account-subcmd"] -account-list = ["account-subcmd"] -account-sync = ["account-subcmd", "email-lib/account-sync"] - -folder = ["folder-add", "folder-list", "folder-expunge", "folder-purge", "folder-delete"] -folder-subcmd = [] -folder-add = ["folder-subcmd", "email-lib/folder-add"] -folder-list = ["folder-subcmd", "email-lib/folder-list"] -folder-expunge = ["folder-subcmd", "email-lib/folder-expunge"] -folder-purge = ["folder-subcmd", "email-lib/folder-purge"] -folder-delete = ["folder-subcmd", "email-lib/folder-delete"] - -envelope = ["envelope-list", "envelope-watch", "envelope-get"] -envelope-subcmd = [] -envelope-list = ["envelope-subcmd", "email-lib/envelope-list"] -envelope-watch = ["envelope-subcmd", "email-lib/envelope-watch"] -envelope-get = ["envelope-subcmd", "email-lib/envelope-get"] - -flag = ["flag-add", "flag-set", "flag-remove"] -flag-subcmd = [] -flag-add = ["flag-subcmd", "email-lib/flag-add"] -flag-set = ["flag-subcmd", "email-lib/flag-set"] -flag-remove = ["flag-subcmd", "email-lib/flag-remove"] - -message = ["message-read", "message-write", "message-mailto", "message-reply", "message-forward", "message-save", "message-send", "message-copy", "message-move", "message-delete"] -message-subcmd = [] -message-add = ["email-lib/message-add"] -message-peek = ["email-lib/message-peek"] -message-get = ["email-lib/message-get"] -message-copy = ["message-subcmd", "email-lib/message-copy"] -message-move = ["message-subcmd", "email-lib/message-move"] -message-delete = ["message-subcmd", "email-lib/message-delete"] -message-read = ["message-add", "message-peek", "message-get"] -message-write = ["message-add", "message-send"] -message-mailto = ["message-add", "message-send"] -message-reply = ["message-get", "message-add", "message-send"] -message-forward = ["message-get", "message-add", "message-send"] -message-save = ["message-add"] -message-send = ["message-subcmd", "email-lib/message-send"] - -attachment = ["attachment-download"] -attachment-subcmd = [] -attachment-download = ["attachment-subcmd", "message-read"] - -template = ["template-write", "template-reply", "template-forward", "template-save", "template-send"] -template-subcmd = [] -template-write = ["template-subcmd"] -template-reply = ["template-subcmd", "email-lib/message-get"] -template-forward = ["template-subcmd", "email-lib/message-get"] -template-save = ["template-subcmd", "email-lib/message-add"] -template-send = ["template-subcmd", "email-lib/message-send"] +account-discovery = ["email-lib/account-discovery"] +account-sync = ["email-lib/account-sync"] pgp = [] pgp-commands = ["email-lib/pgp-commands", "mml-lib/pgp-commands", "pgp"] @@ -120,8 +61,7 @@ clap_mangen = "0.2" console = "0.15.2" dialoguer = "0.10.2" dirs = "4.0" -# email-lib = { version = "=0.21.0", default-features = false } -email-lib = { git = "https://git.sr.ht/~soywod/pimalaya", default-features = false } +email-lib = { version = "=0.21.0", default-features = false } email_address = "0.2.4" env_logger = "0.8" erased-serde = "0.3" @@ -156,4 +96,7 @@ version = "0.29" features = ["bundled"] [target.'cfg(not(windows))'.dependencies.coredump] -version = "0.1" \ No newline at end of file +version = "0.1" + +[patch.crates-io] +email-lib = { git = "https://git.sr.ht/~soywod/pimalaya" } diff --git a/src/account/command/mod.rs b/src/account/command/mod.rs index cdac4f84..549068ec 100644 --- a/src/account/command/mod.rs +++ b/src/account/command/mod.rs @@ -1,6 +1,4 @@ -#[cfg(feature = "account-configure")] mod configure; -#[cfg(feature = "account-list")] mod list; #[cfg(feature = "account-sync")] mod sync; @@ -10,12 +8,9 @@ use clap::Subcommand; use crate::{config::TomlConfig, printer::Printer}; -#[cfg(feature = "account-configure")] -use self::configure::AccountConfigureCommand; -#[cfg(feature = "account-list")] -use self::list::AccountListCommand; #[cfg(feature = "account-sync")] use self::sync::AccountSyncCommand; +use self::{configure::AccountConfigureCommand, list::AccountListCommand}; /// Manage accounts. /// @@ -24,11 +19,9 @@ use self::sync::AccountSyncCommand; /// file. This subcommand allows you to manage them. #[derive(Debug, Subcommand)] pub enum AccountSubcommand { - #[cfg(feature = "account-configure")] #[command(alias = "cfg")] Configure(AccountConfigureCommand), - #[cfg(feature = "account-list")] #[command(alias = "lst")] List(AccountListCommand), @@ -41,9 +34,7 @@ impl AccountSubcommand { #[allow(unused)] pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { match self { - #[cfg(feature = "account-configure")] Self::Configure(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "account-list")] Self::List(cmd) => cmd.execute(printer, config).await, #[cfg(feature = "account-sync")] Self::Sync(cmd) => cmd.execute(printer, config).await, diff --git a/src/account/command/sync.rs b/src/account/command/sync.rs index 5f6024e5..b955cf47 100644 --- a/src/account/command/sync.rs +++ b/src/account/command/sync.rs @@ -8,25 +8,22 @@ use anyhow::Result; use clap::{ArgAction, Parser}; #[cfg(feature = "imap")] use email::imap::ImapContextBuilder; -#[cfg(feature = "account-sync")] use email::maildir::config::MaildirConfig; #[cfg(feature = "maildir")] use email::maildir::MaildirContextBuilder; #[cfg(feature = "notmuch")] use email::notmuch::NotmuchContextBuilder; use email::{ - account::{ - config::AccountConfig, - sync::{AccountSyncBuilder, AccountSyncProgressEvent}, - }, + account::{config::AccountConfig, sync::AccountSyncBuilder}, backend::BackendBuilder, - folder::sync::FolderSyncStrategy, + folder::sync::config::FolderSyncStrategy, + sync::SyncEvent, }; use indicatif::{MultiProgress, ProgressBar, ProgressFinish, ProgressStyle}; use log::info; use once_cell::sync::Lazy; use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeSet, HashMap}, ops::Deref, sync::{Arc, Mutex}, }; @@ -96,8 +93,8 @@ impl AccountSyncCommand { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { info!("executing sync account command"); - let included_folders = HashSet::from_iter(self.include_folder); - let excluded_folders = HashSet::from_iter(self.exclude_folder); + let included_folders = BTreeSet::from_iter(self.include_folder); + let excluded_folders = BTreeSet::from_iter(self.exclude_folder); let strategy = if !included_folders.is_empty() { Some(FolderSyncStrategy::Include(included_folders)) @@ -116,26 +113,25 @@ impl AccountSyncCommand { let backend_builder = AccountSyncBackendBuilder::new(toml_account_config, account_config.clone()).await?; - let sync_builder = AccountSyncBuilder::new(account_config.clone(), backend_builder.into()) - .await? - .with_some_folders_strategy(strategy) - .with_dry_run(self.dry_run); + let sync_builder = AccountSyncBuilder::new(backend_builder.into())? + .with_dry_run(self.dry_run) + .with_some_folders_filter(strategy); if self.dry_run { let report = sync_builder.sync().await?; - let mut hunks_count = report.folders_patch.len(); + let mut hunks_count = report.folder.patch.len(); - if !report.folders_patch.is_empty() { + if !report.folder.patch.is_empty() { printer.print_log("Folders patch:")?; - for (hunk, _) in report.folders_patch { + for (hunk, _) in report.folder.patch { printer.print_log(format!(" - {hunk}"))?; } printer.print_log("")?; } - if !report.emails_patch.is_empty() { + if !report.email.patch.is_empty() { printer.print_log("Envelopes patch:")?; - for (hunk, _) in report.emails_patch { + for (hunk, _) in report.email.patch { hunks_count += 1; printer.print_log(format!(" - {hunk}"))?; } @@ -154,27 +150,27 @@ impl AccountSyncCommand { let main_progress = multi.add( ProgressBar::new(100) .with_style(MAIN_PROGRESS_STYLE.clone()) - .with_message("Synchronizing folders…"), + .with_message("Listing folders…"), ); - // Force the progress bar to show - main_progress.set_position(0); + main_progress.tick(); let report = sync_builder - .with_on_progress(move |evt| { - use AccountSyncProgressEvent::*; + .with_handler(move |evt| { match evt { - ApplyFolderPatches(..) => { - main_progress.inc(3); + SyncEvent::ListedAllFolders => { + main_progress.set_message("Synchronizing folders…"); } - ApplyEnvelopePatches(patches) => { - let mut envelopes_progresses = sub_progresses.lock().unwrap(); - let patches_len = - patches.values().fold(0, |sum, patch| sum + patch.len()); - main_progress.set_length((110 * patches_len / 100) as u64); - main_progress.set_position((5 * patches_len / 100) as u64); - main_progress.set_message("Synchronizing envelopes…"); + SyncEvent::ProcessedAllFolderHunks => { + main_progress.set_message("Listing envelopes…"); + } + SyncEvent::GeneratedEmailPatch(patches) => { + let patches_len = patches.values().flatten().count(); + main_progress.set_length(patches_len as u64); + main_progress.set_position(0); + main_progress.set_message("Synchronizing emails…"); + let mut envelopes_progresses = sub_progresses.lock().unwrap(); for (folder, patch) in patches { let progress = ProgressBar::new(patch.len() as u64) .with_style(SUB_PROGRESS_STYLE.clone()) @@ -184,7 +180,7 @@ impl AccountSyncCommand { envelopes_progresses.insert(folder, progress.clone()); } } - ApplyEnvelopeHunk(hunk) => { + SyncEvent::ProcessedEmailHunk(hunk) => { main_progress.inc(1); let mut progresses = sub_progresses.lock().unwrap(); if let Some(progress) = progresses.get_mut(hunk.folder()) { @@ -196,31 +192,33 @@ impl AccountSyncCommand { } } } - ApplyEnvelopeCachePatch(_patch) => { - main_progress.set_length(100); - main_progress.set_position(95); - main_progress.set_message("Saving cache database…"); - } - ExpungeFolders(folders) => { + SyncEvent::ProcessedAllEmailHunks => { let mut progresses = sub_progresses.lock().unwrap(); for progress in progresses.values() { progress.finish_and_clear() } progresses.clear(); + main_progress.set_length(100); main_progress.set_position(100); - main_progress - .set_message(format!("Expunging {} folders…", folders.len())); + main_progress.set_message("Expunging folders…"); + } + SyncEvent::ExpungedAllFolders => { + main_progress.finish_and_clear(); + } + _ => { + main_progress.tick(); } - _ => (), }; - Ok(()) + + async { Ok(()) } }) .sync() .await?; let folders_patch_err = report - .folders_patch + .folder + .patch .iter() .filter_map(|(hunk, err)| err.as_ref().map(|err| (hunk, err))) .collect::>(); @@ -232,15 +230,9 @@ impl AccountSyncCommand { .try_for_each(|(hunk, err)| printer.print_log(format!(" - {hunk}: {err}")))?; } - if let Some(err) = report.folders_cache_patch.1 { - printer.print_log("")?; - printer.print_log(format!( - "Error occurred while applying the folder cache patch: {err}" - ))?; - } - let envelopes_patch_err = report - .emails_patch + .email + .patch .iter() .filter_map(|(hunk, err)| err.as_ref().map(|err| (hunk, err))) .collect::>(); @@ -252,13 +244,6 @@ impl AccountSyncCommand { } } - if let Some(err) = report.emails_cache_patch.1 { - printer.print_log("")?; - printer.print_log(format!( - "Error occurred while applying the envelopes cache patch: {err}" - ))?; - } - printer.print(format!("Account {account_name} successfully synchronized!"))?; } @@ -283,7 +268,6 @@ impl AccountSyncBackendBuilder { let is_imap_used = used_backends.contains(&BackendKind::Imap); #[cfg(feature = "maildir")] let is_maildir_used = used_backends.contains(&BackendKind::Maildir); - #[cfg(feature = "account-sync")] let is_maildir_for_sync_used = used_backends.contains(&BackendKind::MaildirForSync); #[cfg(feature = "notmuch")] let is_notmuch_used = used_backends.contains(&BackendKind::Notmuch); @@ -300,7 +284,10 @@ impl AccountSyncBackendBuilder { .filter(|_| is_imap_used) .map(Clone::clone) .map(Arc::new) - .map(|config| ImapContextBuilder::new(config).with_prebuilt_credentials()); + .map(|config| { + ImapContextBuilder::new(account_config.clone(), config) + .with_prebuilt_credentials() + }); match builder { Some(builder) => Some(builder.await?), None => None, @@ -314,15 +301,14 @@ impl AccountSyncBackendBuilder { .filter(|_| is_maildir_used) .map(Clone::clone) .map(Arc::new) - .map(MaildirContextBuilder::new), + .map(|mdir_config| MaildirContextBuilder::new(account_config.clone(), mdir_config)), - #[cfg(feature = "account-sync")] maildir_for_sync: Some(MaildirConfig { root_dir: account_config.get_sync_dir()?, }) .filter(|_| is_maildir_for_sync_used) .map(Arc::new) - .map(MaildirContextBuilder::new), + .map(|mdir_config| MaildirContextBuilder::new(account_config.clone(), mdir_config)), #[cfg(feature = "notmuch")] notmuch: toml_account_config @@ -331,7 +317,9 @@ impl AccountSyncBackendBuilder { .filter(|_| is_notmuch_used) .map(Clone::clone) .map(Arc::new) - .map(NotmuchContextBuilder::new), + .map(|notmuch_config| { + NotmuchContextBuilder::new(account_config.clone(), notmuch_config) + }), #[cfg(feature = "smtp")] smtp: None, diff --git a/src/account/config.rs b/src/account/config.rs index 375b0cd5..32b802f6 100644 --- a/src/account/config.rs +++ b/src/account/config.rs @@ -60,7 +60,6 @@ pub struct TomlAccountConfig { } impl TomlAccountConfig { - #[cfg(any(feature = "account-sync", feature = "folder-add"))] pub fn add_folder_kind(&self) -> Option<&BackendKind> { self.folder .as_ref() @@ -69,7 +68,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "folder-list"))] pub fn list_folders_kind(&self) -> Option<&BackendKind> { self.folder .as_ref() @@ -78,7 +76,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "folder-expunge"))] pub fn expunge_folder_kind(&self) -> Option<&BackendKind> { self.folder .as_ref() @@ -87,7 +84,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(feature = "folder-purge")] pub fn purge_folder_kind(&self) -> Option<&BackendKind> { self.folder .as_ref() @@ -96,7 +92,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "folder-delete"))] pub fn delete_folder_kind(&self) -> Option<&BackendKind> { self.folder .as_ref() @@ -105,7 +100,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "envelope-get"))] pub fn get_envelope_kind(&self) -> Option<&BackendKind> { self.envelope .as_ref() @@ -114,7 +108,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "envelope-list"))] pub fn list_envelopes_kind(&self) -> Option<&BackendKind> { self.envelope .as_ref() @@ -123,7 +116,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(feature = "envelope-watch")] pub fn watch_envelopes_kind(&self) -> Option<&BackendKind> { self.envelope .as_ref() @@ -132,7 +124,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "flag-add"))] pub fn add_flags_kind(&self) -> Option<&BackendKind> { self.flag .as_ref() @@ -141,7 +132,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "flag-set"))] pub fn set_flags_kind(&self) -> Option<&BackendKind> { self.flag .as_ref() @@ -150,7 +140,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(feature = "flag-remove")] pub fn remove_flags_kind(&self) -> Option<&BackendKind> { self.flag .as_ref() @@ -159,7 +148,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "message-add"))] pub fn add_message_kind(&self) -> Option<&BackendKind> { self.message .as_ref() @@ -168,7 +156,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "message-peek"))] pub fn peek_messages_kind(&self) -> Option<&BackendKind> { self.message .as_ref() @@ -177,7 +164,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "message-get"))] pub fn get_messages_kind(&self) -> Option<&BackendKind> { self.message .as_ref() @@ -186,7 +172,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(feature = "message-copy")] pub fn copy_messages_kind(&self) -> Option<&BackendKind> { self.message .as_ref() @@ -195,7 +180,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "account-sync", feature = "message-move"))] pub fn move_messages_kind(&self) -> Option<&BackendKind> { self.message .as_ref() @@ -204,7 +188,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(feature = "message-delete")] pub fn delete_messages_kind(&self) -> Option<&BackendKind> { self.message .as_ref() @@ -213,7 +196,6 @@ impl TomlAccountConfig { .or(self.backend.as_ref()) } - #[cfg(any(feature = "message-send", feature = "template-send"))] pub fn send_message_kind(&self) -> Option<&BackendKind> { self.message .as_ref() @@ -233,17 +215,14 @@ impl TomlAccountConfig { used_backends.extend(folder.get_used_backends()); } - #[cfg(feature = "envelope-subcmd")] if let Some(ref envelope) = self.envelope { used_backends.extend(envelope.get_used_backends()); } - #[cfg(feature = "flag-subcmd")] if let Some(ref flag) = self.flag { used_backends.extend(flag.get_used_backends()); } - #[cfg(feature = "message-subcmd")] if let Some(ref msg) = self.message { used_backends.extend(msg.get_used_backends()); } diff --git a/src/account/mod.rs b/src/account/mod.rs index 41e1d89a..62bed180 100644 --- a/src/account/mod.rs +++ b/src/account/mod.rs @@ -1,7 +1,6 @@ pub mod arg; pub mod command; pub mod config; -#[cfg(feature = "wizard")] pub(crate) mod wizard; use anyhow::Result; diff --git a/src/account/wizard.rs b/src/account/wizard.rs index bace12d4..a032e4c0 100644 --- a/src/account/wizard.rs +++ b/src/account/wizard.rs @@ -1,21 +1,20 @@ -use std::str::FromStr; - use anyhow::{bail, Result}; #[cfg(feature = "account-sync")] -use dialoguer::Confirm; -use dialoguer::Input; +use dialoguer::{Confirm, Input}; use email::account; #[cfg(feature = "account-sync")] use email::account::sync::config::SyncConfig; use email_address::EmailAddress; +use std::str::FromStr; -#[allow(unused)] -use crate::backend::{self, config::BackendConfig, BackendKind}; -#[cfg(feature = "message-send")] -use crate::message::config::{MessageConfig, MessageSendConfig}; #[cfg(feature = "account-sync")] use crate::wizard_prompt; -use crate::{ui::THEME, wizard_warn}; +use crate::{ + backend::{self, config::BackendConfig, BackendKind}, + message::config::{MessageConfig, MessageSendConfig}, + ui::THEME, + wizard_warn, +}; use super::TomlAccountConfig; @@ -95,32 +94,24 @@ pub(crate) async fn configure() -> Result> { #[cfg(feature = "smtp")] Some(BackendConfig::Smtp(smtp_config)) => { config.smtp = Some(smtp_config); - - #[cfg(feature = "message-send")] - { - config.message = Some(MessageConfig { - send: Some(MessageSendConfig { - backend: Some(BackendKind::Smtp), - ..Default::default() - }), + config.message = Some(MessageConfig { + send: Some(MessageSendConfig { + backend: Some(BackendKind::Smtp), ..Default::default() - }); - } + }), + ..Default::default() + }); } #[cfg(feature = "sendmail")] Some(BackendConfig::Sendmail(sendmail_config)) => { config.sendmail = Some(sendmail_config); - - #[cfg(feature = "message-send")] - { - config.message = Some(MessageConfig { - send: Some(MessageSendConfig { - backend: Some(BackendKind::Sendmail), - ..Default::default() - }), + config.message = Some(MessageConfig { + send: Some(MessageSendConfig { + backend: Some(BackendKind::Sendmail), ..Default::default() - }); - } + }), + ..Default::default() + }); } _ => (), }; diff --git a/src/backend/mod.rs b/src/backend/mod.rs index d9a2475e..de8b772e 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,53 +1,16 @@ pub mod config; -#[cfg(feature = "wizard")] pub(crate) mod wizard; use anyhow::Result; use async_trait::async_trait; use std::{ops::Deref, sync::Arc}; -#[cfg(any(feature = "account-sync", feature = "envelope-get"))] -use email::envelope::get::GetEnvelope; -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] -use email::envelope::list::ListEnvelopes; -#[cfg(feature = "envelope-watch")] -use email::envelope::watch::WatchEnvelopes; -#[cfg(any(feature = "account-sync", feature = "flag-add"))] -use email::flag::add::AddFlags; -#[cfg(feature = "flag-remove")] -use email::flag::remove::RemoveFlags; -#[cfg(any(feature = "account-sync", feature = "flag-set"))] -use email::flag::set::SetFlags; -#[cfg(any(feature = "account-sync", feature = "folder-add"))] -use email::folder::add::AddFolder; -#[cfg(any(feature = "account-sync", feature = "folder-delete"))] -use email::folder::delete::DeleteFolder; -#[cfg(any(feature = "account-sync", feature = "folder-expunge"))] -use email::folder::expunge::ExpungeFolder; -#[cfg(any(feature = "account-sync", feature = "folder-list"))] -use email::folder::list::ListFolders; -#[cfg(feature = "folder-purge")] -use email::folder::purge::PurgeFolder; #[cfg(feature = "imap")] use email::imap::{ImapContextBuilder, ImapContextSync}; #[cfg(feature = "account-sync")] use email::maildir::config::MaildirConfig; #[cfg(any(feature = "account-sync", feature = "maildir"))] use email::maildir::{MaildirContextBuilder, MaildirContextSync}; -#[cfg(any(feature = "account-sync", feature = "message-add"))] -use email::message::add::AddMessage; -#[cfg(feature = "message-copy")] -use email::message::copy::CopyMessages; -#[cfg(feature = "message-delete")] -use email::message::delete::DeleteMessages; -#[cfg(any(feature = "account-sync", feature = "message-get"))] -use email::message::get::GetMessages; -#[cfg(any(feature = "account-sync", feature = "message-peek"))] -use email::message::peek::PeekMessages; -#[cfg(any(feature = "account-sync", feature = "message-move"))] -use email::message::r#move::MoveMessages; -#[cfg(feature = "message-send")] -use email::message::send::SendMessage; #[cfg(feature = "notmuch")] use email::notmuch::{NotmuchContextBuilder, NotmuchContextSync}; #[cfg(feature = "sendmail")] @@ -57,17 +20,22 @@ use email::smtp::{SmtpContextBuilder, SmtpContextSync}; use email::{ account::config::AccountConfig, backend::{ - macros::BackendContext, BackendFeatureBuilder, FindBackendSubcontext, MapBackendFeature, + feature::BackendFeature, macros::BackendContext, mapper::SomeBackendContextBuilderMapper, + }, + envelope::{get::GetEnvelope, list::ListEnvelopes, watch::WatchEnvelopes, Id, SingleId}, + flag::{add::AddFlags, remove::RemoveFlags, set::SetFlags, Flag, Flags}, + folder::{ + add::AddFolder, delete::DeleteFolder, expunge::ExpungeFolder, list::ListFolders, + purge::PurgeFolder, + }, + message::{ + add::AddMessage, copy::CopyMessages, delete::DeleteMessages, get::GetMessages, + peek::PeekMessages, r#move::MoveMessages, send::SendMessage, Messages, }, - envelope::{Id, SingleId}, - flag::{Flag, Flags}, - message::Messages, }; use serde::{Deserialize, Serialize}; -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] -use crate::envelope::Envelopes; -use crate::{account::config::TomlAccountConfig, cache::IdMapper}; +use crate::{account::config::TomlAccountConfig, cache::IdMapper, envelope::Envelopes}; #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] @@ -152,7 +120,10 @@ impl BackendContextBuilder { .filter(|_| kinds.contains(&&BackendKind::Imap)) .map(Clone::clone) .map(Arc::new) - .map(|config| ImapContextBuilder::new(config).with_prebuilt_credentials()); + .map(|imap_config| { + ImapContextBuilder::new(account_config.clone(), imap_config) + .with_prebuilt_credentials() + }); match builder { Some(builder) => Some(builder.await?), None => None, @@ -166,7 +137,7 @@ impl BackendContextBuilder { .filter(|_| kinds.contains(&&BackendKind::Maildir)) .map(Clone::clone) .map(Arc::new) - .map(MaildirContextBuilder::new), + .map(|mdir_config| MaildirContextBuilder::new(account_config.clone(), mdir_config)), #[cfg(feature = "account-sync")] maildir_for_sync: Some(MaildirConfig { @@ -174,7 +145,7 @@ impl BackendContextBuilder { }) .filter(|_| kinds.contains(&&BackendKind::MaildirForSync)) .map(Arc::new) - .map(MaildirContextBuilder::new), + .map(|mdir_config| MaildirContextBuilder::new(account_config.clone(), mdir_config)), #[cfg(feature = "notmuch")] notmuch: toml_account_config @@ -183,7 +154,9 @@ impl BackendContextBuilder { .filter(|_| kinds.contains(&&BackendKind::Notmuch)) .map(Clone::clone) .map(Arc::new) - .map(NotmuchContextBuilder::new), + .map(|notmuch_config| { + NotmuchContextBuilder::new(account_config.clone(), notmuch_config) + }), #[cfg(feature = "smtp")] smtp: toml_account_config @@ -192,7 +165,7 @@ impl BackendContextBuilder { .filter(|_| kinds.contains(&&BackendKind::Smtp)) .map(Clone::clone) .map(Arc::new) - .map(SmtpContextBuilder::new), + .map(|smtp_config| SmtpContextBuilder::new(account_config.clone(), smtp_config)), #[cfg(feature = "sendmail")] sendmail: toml_account_config @@ -201,363 +174,347 @@ impl BackendContextBuilder { .filter(|_| kinds.contains(&&BackendKind::Sendmail)) .map(Clone::clone) .map(Arc::new) - .map(SendmailContextBuilder::new), + .map(|sendmail_config| { + SendmailContextBuilder::new(account_config.clone(), sendmail_config) + }), }) } } #[async_trait] -impl email::backend::BackendContextBuilder for BackendContextBuilder { +impl email::backend::context::BackendContextBuilder for BackendContextBuilder { type Context = BackendContext; - #[cfg(any(feature = "account-sync", feature = "folder-add"))] - fn add_folder(&self) -> BackendFeatureBuilder { + fn add_folder(&self) -> Option> { match self.toml_account_config.add_folder_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.add_folder_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.add_folder_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.add_folder_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.add_folder_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.add_folder()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.add_folder_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.add_folder_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "folder-list"))] - fn list_folders(&self) -> BackendFeatureBuilder { + fn list_folders(&self) -> Option> { match self.toml_account_config.list_folders_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.list_folders_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.list_folders_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.list_folders_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.list_folders_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.list_folders()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.list_folders_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.list_folders_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "folder-expunge"))] - fn expunge_folder(&self) -> BackendFeatureBuilder { + fn expunge_folder(&self) -> Option> { match self.toml_account_config.expunge_folder_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.expunge_folder_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.expunge_folder_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.expunge_folder_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.expunge_folder_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.expunge_folder()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.expunge_folder_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.expunge_folder_with_some(&self.notmuch), _ => None, } } - #[cfg(feature = "folder-purge")] - fn purge_folder(&self) -> BackendFeatureBuilder { + fn purge_folder(&self) -> Option> { match self.toml_account_config.purge_folder_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.purge_folder_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.purge_folder_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.purge_folder_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.purge_folder_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.purge_folder()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.purge_folder_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.purge_folder_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "folder-delete"))] - fn delete_folder(&self) -> BackendFeatureBuilder { + fn delete_folder(&self) -> Option> { match self.toml_account_config.delete_folder_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.delete_folder_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.delete_folder_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.delete_folder_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.delete_folder_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.delete_folder()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.delete_folder_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.delete_folder_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "envelope-list"))] - fn list_envelopes(&self) -> BackendFeatureBuilder { - match self.toml_account_config.list_envelopes_kind() { + fn get_envelope(&self) -> Option> { + match self.toml_account_config.get_envelope_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.list_envelopes_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.get_envelope_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.list_envelopes_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.get_envelope_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { - let f = self.maildir_for_sync.as_ref()?.list_envelopes()?; + let f = self.maildir_for_sync.as_ref()?.get_envelope()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.list_envelopes_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.get_envelope_with_some(&self.notmuch), _ => None, } } - #[cfg(feature = "envelope-watch")] - fn watch_envelopes(&self) -> BackendFeatureBuilder { - match self.toml_account_config.watch_envelopes_kind() { + fn list_envelopes(&self) -> Option> { + match self.toml_account_config.list_envelopes_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.watch_envelopes_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.list_envelopes_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.watch_envelopes_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.list_envelopes_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { - let f = self.maildir_for_sync.as_ref()?.watch_envelopes()?; + let f = self.maildir_for_sync.as_ref()?.list_envelopes()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.watch_envelopes_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.list_envelopes_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "envelope-get"))] - fn get_envelope(&self) -> BackendFeatureBuilder { - match self.toml_account_config.get_envelope_kind() { + fn watch_envelopes(&self) -> Option> { + match self.toml_account_config.watch_envelopes_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.get_envelope_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.watch_envelopes_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.get_envelope_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.watch_envelopes_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { - let f = self.maildir_for_sync.as_ref()?.get_envelope()?; + let f = self.maildir_for_sync.as_ref()?.watch_envelopes()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.get_envelope_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.watch_envelopes_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "flag-add"))] - fn add_flags(&self) -> BackendFeatureBuilder { + fn add_flags(&self) -> Option> { match self.toml_account_config.add_flags_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.add_flags_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.add_flags_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.add_flags_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.add_flags_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.add_flags()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.add_flags_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.add_flags_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "flag-set"))] - fn set_flags(&self) -> BackendFeatureBuilder { + fn set_flags(&self) -> Option> { match self.toml_account_config.set_flags_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.set_flags_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.set_flags_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.set_flags_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.set_flags_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.set_flags()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.set_flags_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.set_flags_with_some(&self.notmuch), _ => None, } } - #[cfg(feature = "flag-remove")] - fn remove_flags(&self) -> BackendFeatureBuilder { + fn remove_flags(&self) -> Option> { match self.toml_account_config.remove_flags_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.remove_flags_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.remove_flags_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.remove_flags_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.remove_flags_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.remove_flags()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.remove_flags_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.remove_flags_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "message-add"))] - fn add_message(&self) -> BackendFeatureBuilder { + fn add_message(&self) -> Option> { match self.toml_account_config.add_message_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.add_message_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.add_message_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.add_message_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.add_message_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.add_message()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.add_message_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.add_message_with_some(&self.notmuch), _ => None, } } - #[cfg(feature = "message-send")] - fn send_message(&self) -> BackendFeatureBuilder { + fn send_message(&self) -> Option> { match self.toml_account_config.send_message_kind() { #[cfg(feature = "smtp")] - Some(BackendKind::Smtp) => self.send_message_from(self.smtp.as_ref()), + Some(BackendKind::Smtp) => self.send_message_with_some(&self.smtp), #[cfg(feature = "sendmail")] - Some(BackendKind::Sendmail) => self.send_message_from(self.sendmail.as_ref()), + Some(BackendKind::Sendmail) => self.send_message_with_some(&self.sendmail), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "message-peek"))] - fn peek_messages(&self) -> BackendFeatureBuilder { + fn peek_messages(&self) -> Option> { match self.toml_account_config.peek_messages_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.peek_messages_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.peek_messages_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.peek_messages_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.peek_messages_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.peek_messages()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.peek_messages_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.peek_messages_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "message-get"))] - fn get_messages(&self) -> BackendFeatureBuilder { + fn get_messages(&self) -> Option> { match self.toml_account_config.get_messages_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.get_messages_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.get_messages_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.get_messages_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.get_messages_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.get_messages()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.get_messages_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.get_messages_with_some(&self.notmuch), _ => None, } } - #[cfg(feature = "message-copy")] - fn copy_messages(&self) -> BackendFeatureBuilder { + fn copy_messages(&self) -> Option> { match self.toml_account_config.copy_messages_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.copy_messages_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.copy_messages_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.copy_messages_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.copy_messages_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.copy_messages()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.copy_messages_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.copy_messages_with_some(&self.notmuch), _ => None, } } - #[cfg(any(feature = "account-sync", feature = "message-move"))] - fn move_messages(&self) -> BackendFeatureBuilder { + fn move_messages(&self) -> Option> { match self.toml_account_config.move_messages_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.move_messages_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.move_messages_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.move_messages_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.move_messages_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.move_messages()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.move_messages_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.move_messages_with_some(&self.notmuch), _ => None, } } - #[cfg(feature = "message-delete")] - fn delete_messages(&self) -> BackendFeatureBuilder { + fn delete_messages(&self) -> Option> { match self.toml_account_config.delete_messages_kind() { #[cfg(feature = "imap")] - Some(BackendKind::Imap) => self.delete_messages_from(self.imap.as_ref()), + Some(BackendKind::Imap) => self.delete_messages_with_some(&self.imap), #[cfg(feature = "maildir")] - Some(BackendKind::Maildir) => self.delete_messages_from(self.maildir.as_ref()), + Some(BackendKind::Maildir) => self.delete_messages_with_some(&self.maildir), #[cfg(feature = "account-sync")] Some(BackendKind::MaildirForSync) => { let f = self.maildir_for_sync.as_ref()?.delete_messages()?; Some(Arc::new(move |ctx| f(ctx.maildir_for_sync.as_ref()?))) } #[cfg(feature = "notmuch")] - Some(BackendKind::Notmuch) => self.delete_messages_from(self.notmuch.as_ref()), + Some(BackendKind::Notmuch) => self.delete_messages_with_some(&self.notmuch), _ => None, } } - async fn build(self, config: Arc) -> Result { + async fn build(self) -> Result { let mut ctx = BackendContext::default(); #[cfg(feature = "imap")] if let Some(imap) = self.imap { - ctx.imap = Some(imap.build(config.clone()).await?); + ctx.imap = Some(imap.build().await?); } #[cfg(feature = "maildir")] if let Some(maildir) = self.maildir { - ctx.maildir = Some(maildir.build(config.clone()).await?); + ctx.maildir = Some(maildir.build().await?); } #[cfg(feature = "account-sync")] if let Some(maildir) = self.maildir_for_sync { - ctx.maildir_for_sync = Some(maildir.build(config.clone()).await?); + ctx.maildir_for_sync = Some(maildir.build().await?); } #[cfg(feature = "notmuch")] if let Some(notmuch) = self.notmuch { - ctx.notmuch = Some(notmuch.build(config.clone()).await?); + ctx.notmuch = Some(notmuch.build().await?); } #[cfg(feature = "smtp")] if let Some(smtp) = self.smtp { - ctx.smtp = Some(smtp.build(config.clone()).await?); + ctx.smtp = Some(smtp.build().await?); } #[cfg(feature = "sendmail")] if let Some(sendmail) = self.sendmail { - ctx.sendmail = Some(sendmail.build(config.clone()).await?); + ctx.sendmail = Some(sendmail.build().await?); } Ok(ctx) @@ -586,37 +543,37 @@ pub struct BackendContext { } #[cfg(feature = "imap")] -impl FindBackendSubcontext for BackendContext { - fn find_subcontext(&self) -> Option<&ImapContextSync> { - self.imap.as_ref() +impl AsRef> for BackendContext { + fn as_ref(&self) -> &Option { + &self.imap } } #[cfg(feature = "maildir")] -impl FindBackendSubcontext for BackendContext { - fn find_subcontext(&self) -> Option<&MaildirContextSync> { - self.maildir.as_ref() +impl AsRef> for BackendContext { + fn as_ref(&self) -> &Option { + &self.maildir } } #[cfg(feature = "notmuch")] -impl FindBackendSubcontext for BackendContext { - fn find_subcontext(&self) -> Option<&NotmuchContextSync> { - self.notmuch.as_ref() +impl AsRef> for BackendContext { + fn as_ref(&self) -> &Option { + &self.notmuch } } #[cfg(feature = "smtp")] -impl FindBackendSubcontext for BackendContext { - fn find_subcontext(&self) -> Option<&SmtpContextSync> { - self.smtp.as_ref() +impl AsRef> for BackendContext { + fn as_ref(&self) -> &Option { + &self.smtp } } #[cfg(feature = "sendmail")] -impl FindBackendSubcontext for BackendContext { - fn find_subcontext(&self) -> Option<&SendmailContextSync> { - self.sendmail.as_ref() +impl AsRef> for BackendContext { + fn as_ref(&self) -> &Option { + &self.sendmail } } @@ -641,7 +598,7 @@ impl Backend { .await?; let mut backend_builder = email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder) - .with_default_features_disabled(); + .without_features(); with_features(&mut backend_builder); @@ -651,7 +608,6 @@ impl Backend { }) } - #[allow(unused)] fn build_id_mapper( &self, folder: &str, @@ -697,7 +653,6 @@ impl Backend { Ok(id_mapper) } - #[cfg(any(feature = "account-sync", feature = "envelope-list"))] pub async fn list_envelopes( &self, folder: &str, @@ -711,7 +666,6 @@ impl Backend { Ok(envelopes) } - #[cfg(any(feature = "account-sync", feature = "flag-add"))] pub async fn add_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> { let backend_kind = self.toml_account_config.add_flags_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -719,7 +673,6 @@ impl Backend { self.backend.add_flags(folder, &ids, flags).await } - #[cfg(any(feature = "account-sync", feature = "flag-add"))] pub async fn add_flag(&self, folder: &str, ids: &[usize], flag: Flag) -> Result<()> { let backend_kind = self.toml_account_config.add_flags_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -727,7 +680,6 @@ impl Backend { self.backend.add_flag(folder, &ids, flag).await } - #[cfg(any(feature = "account-sync", feature = "flag-set"))] pub async fn set_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> { let backend_kind = self.toml_account_config.set_flags_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -735,7 +687,6 @@ impl Backend { self.backend.set_flags(folder, &ids, flags).await } - #[cfg(any(feature = "account-sync", feature = "flag-set"))] pub async fn set_flag(&self, folder: &str, ids: &[usize], flag: Flag) -> Result<()> { let backend_kind = self.toml_account_config.set_flags_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -743,7 +694,6 @@ impl Backend { self.backend.set_flag(folder, &ids, flag).await } - #[cfg(feature = "flag-remove")] pub async fn remove_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> { let backend_kind = self.toml_account_config.remove_flags_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -751,7 +701,6 @@ impl Backend { self.backend.remove_flags(folder, &ids, flags).await } - #[cfg(feature = "flag-remove")] pub async fn remove_flag(&self, folder: &str, ids: &[usize], flag: Flag) -> Result<()> { let backend_kind = self.toml_account_config.remove_flags_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -759,7 +708,6 @@ impl Backend { self.backend.remove_flag(folder, &ids, flag).await } - #[cfg(any(feature = "account-sync", feature = "message-add"))] pub async fn add_message(&self, folder: &str, email: &[u8]) -> Result { let backend_kind = self.toml_account_config.add_message_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -768,7 +716,6 @@ impl Backend { Ok(id) } - #[cfg(any(feature = "account-sync", feature = "message-peek"))] pub async fn peek_messages(&self, folder: &str, ids: &[usize]) -> Result { let backend_kind = self.toml_account_config.get_messages_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -776,7 +723,6 @@ impl Backend { self.backend.peek_messages(folder, &ids).await } - #[cfg(any(feature = "account-sync", feature = "message-get"))] pub async fn get_messages(&self, folder: &str, ids: &[usize]) -> Result { let backend_kind = self.toml_account_config.get_messages_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; @@ -784,7 +730,6 @@ impl Backend { self.backend.get_messages(folder, &ids).await } - #[cfg(feature = "message-copy")] pub async fn copy_messages( &self, from_folder: &str, @@ -799,7 +744,6 @@ impl Backend { .await } - #[cfg(any(feature = "account-sync", feature = "message-move"))] pub async fn move_messages( &self, from_folder: &str, @@ -814,7 +758,6 @@ impl Backend { .await } - #[cfg(feature = "message-delete")] pub async fn delete_messages(&self, folder: &str, ids: &[usize]) -> Result<()> { let backend_kind = self.toml_account_config.delete_messages_kind(); let id_mapper = self.build_id_mapper(folder, backend_kind)?; diff --git a/src/backend/wizard.rs b/src/backend/wizard.rs index 5cc2018d..e2252f15 100644 --- a/src/backend/wizard.rs +++ b/src/backend/wizard.rs @@ -33,8 +33,8 @@ const SEND_MESSAGE_BACKEND_KINDS: &[BackendKind] = &[ ]; pub(crate) async fn configure( - #[allow(unused)] account_name: &str, - #[allow(unused)] email: &str, + account_name: &str, + email: &str, autoconfig: Option<&AutoConfig>, ) -> Result> { let kind = Select::with_theme(&*THEME) @@ -60,8 +60,8 @@ pub(crate) async fn configure( } pub(crate) async fn configure_sender( - #[allow(unused)] account_name: &str, - #[allow(unused)] email: &str, + account_name: &str, + email: &str, autoconfig: Option<&AutoConfig>, ) -> Result> { let kind = Select::with_theme(&*THEME) diff --git a/src/cli.rs b/src/cli.rs index 266785f0..6dfc914f 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2,25 +2,18 @@ use anyhow::Result; use clap::{Parser, Subcommand}; use std::path::PathBuf; -#[cfg(feature = "account-subcmd")] -use crate::account::command::AccountSubcommand; -#[cfg(feature = "envelope-subcmd")] -use crate::envelope::command::EnvelopeSubcommand; -#[cfg(feature = "flag-subcmd")] -use crate::flag::command::FlagSubcommand; -#[cfg(feature = "folder-subcmd")] -use crate::folder::command::FolderSubcommand; -#[cfg(feature = "attachment-subcmd")] -use crate::message::attachment::command::AttachmentSubcommand; -#[cfg(feature = "message-subcmd")] -use crate::message::command::MessageSubcommand; -#[cfg(feature = "template-subcmd")] -use crate::message::template::command::TemplateSubcommand; -#[allow(unused)] use crate::{ + account::command::AccountSubcommand, completion::command::CompletionGenerateCommand, config::{self, TomlConfig}, + envelope::command::EnvelopeSubcommand, + flag::command::FlagSubcommand, + folder::command::FolderSubcommand, manual::command::ManualGenerateCommand, + message::{ + attachment::command::AttachmentSubcommand, command::MessageSubcommand, + template::command::TemplateSubcommand, + }, output::{ColorFmt, OutputFmt}, printer::Printer, }; @@ -29,12 +22,8 @@ use crate::{ #[command(name = "himalaya", author, version, about)] #[command(propagate_version = true, infer_subcommands = true)] pub struct Cli { - #[cfg(feature = "envelope-list")] #[command(subcommand)] pub command: Option, - #[cfg(not(feature = "envelope-list"))] - #[command(subcommand)] - pub command: HimalayaCommand, /// Override the default configuration file path /// @@ -88,38 +77,31 @@ pub struct Cli { #[derive(Subcommand, Debug)] pub enum HimalayaCommand { - #[cfg(feature = "account-subcmd")] #[command(subcommand)] #[command(alias = "accounts")] Account(AccountSubcommand), - #[cfg(feature = "folder-subcmd")] #[command(subcommand)] #[command(visible_alias = "mailbox", aliases = ["mailboxes", "mboxes", "mbox"])] #[command(alias = "folders")] Folder(FolderSubcommand), - #[cfg(feature = "envelope-subcmd")] #[command(subcommand)] #[command(alias = "envelopes")] Envelope(EnvelopeSubcommand), - #[cfg(feature = "flag-subcmd")] #[command(subcommand)] #[command(alias = "flags")] Flag(FlagSubcommand), - #[cfg(feature = "message-subcmd")] #[command(subcommand)] #[command(alias = "messages", alias = "msgs", alias = "msg")] Message(MessageSubcommand), - #[cfg(feature = "attachment-subcmd")] #[command(subcommand)] #[command(alias = "attachments")] Attachment(AttachmentSubcommand), - #[cfg(feature = "template-subcmd")] #[command(subcommand)] #[command(alias = "templates", alias = "tpls", alias = "tpl")] Template(TemplateSubcommand), @@ -141,37 +123,30 @@ impl HimalayaCommand { config_path: Option<&PathBuf>, ) -> Result<()> { match self { - #[cfg(feature = "account-subcmd")] Self::Account(cmd) => { let config = TomlConfig::from_some_path_or_default(config_path).await?; cmd.execute(printer, &config).await } - #[cfg(feature = "folder-subcmd")] Self::Folder(cmd) => { let config = TomlConfig::from_some_path_or_default(config_path).await?; cmd.execute(printer, &config).await } - #[cfg(feature = "envelope-subcmd")] Self::Envelope(cmd) => { let config = TomlConfig::from_some_path_or_default(config_path).await?; cmd.execute(printer, &config).await } - #[cfg(feature = "flag-subcmd")] Self::Flag(cmd) => { let config = TomlConfig::from_some_path_or_default(config_path).await?; cmd.execute(printer, &config).await } - #[cfg(feature = "message-subcmd")] Self::Message(cmd) => { let config = TomlConfig::from_some_path_or_default(config_path).await?; cmd.execute(printer, &config).await } - #[cfg(feature = "attachment-subcmd")] Self::Attachment(cmd) => { let config = TomlConfig::from_some_path_or_default(config_path).await?; cmd.execute(printer, &config).await } - #[cfg(feature = "template-subcmd")] Self::Template(cmd) => { let config = TomlConfig::from_some_path_or_default(config_path).await?; cmd.execute(printer, &config).await diff --git a/src/config/args.rs b/src/config/args.rs deleted file mode 100644 index 655ba7c3..00000000 --- a/src/config/args.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! This module provides arguments related to the user config. - -use clap::{Arg, ArgMatches}; - -const ARG_CONFIG: &str = "config"; - -/// Represents the config file path argument. This argument allows the -/// user to customize the config file path. -pub fn global_args() -> impl IntoIterator { - [Arg::new(ARG_CONFIG) - .help("Override the configuration file path") - .long_help( - "Override the configuration file path - -If the file under the given path does not exist, the wizard will propose to create it.", - ) - .long("config") - .short('c') - .global(true) - .value_name("path")] -} - -/// Represents the config file path argument parser. -pub fn parse_global_arg(matches: &ArgMatches) -> Option<&str> { - matches.get_one::(ARG_CONFIG).map(String::as_str) -} diff --git a/src/config/mod.rs b/src/config/mod.rs index dff26c29..82b3217f 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,12 +1,10 @@ -pub mod args; -#[cfg(feature = "wizard")] pub mod wizard; use anyhow::{anyhow, Context, Result}; use dirs::{config_dir, home_dir}; use email::{ account::config::AccountConfig, config::Config, envelope::config::EnvelopeConfig, - folder::config::FolderConfig, message::config::MessageConfig, + flag::config::FlagConfig, folder::config::FolderConfig, message::config::MessageConfig, }; use serde::{Deserialize, Serialize}; @@ -19,11 +17,9 @@ use std::{ }; use toml; -use crate::account::config::TomlAccountConfig; #[cfg(feature = "account-sync")] use crate::backend::BackendKind; -#[cfg(feature = "wizard")] -use crate::{wizard_prompt, wizard_warn}; +use crate::{account::config::TomlAccountConfig, wizard_prompt, wizard_warn}; /// Represents the user config file. #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] @@ -34,8 +30,6 @@ pub struct TomlConfig { pub signature: Option, pub signature_delim: Option, pub downloads_dir: Option, - - #[serde(flatten)] pub accounts: HashMap, } @@ -50,7 +44,6 @@ impl TomlConfig { toml::from_str(&content).context(format!("cannot parse config file at {path:?}")) } - #[cfg(feature = "wizard")] /// Create and save a TOML configuration using the wizard. /// /// If the user accepts the confirmation, the wizard starts and @@ -83,10 +76,7 @@ impl TomlConfig { pub async fn from_default_paths() -> Result { match Self::first_valid_default_path() { Some(path) => Self::from_path(&path), - #[cfg(feature = "wizard")] None => Self::from_wizard(Self::default_path()?).await, - #[cfg(not(feature = "wizard"))] - None => anyhow::bail!("cannot find configuration file from default locations"), } } @@ -105,7 +95,6 @@ impl TomlConfig { pub async fn from_some_path_or_default(path: Option>) -> Result { match path.map(Into::into) { Some(ref path) if path.exists() => Self::from_path(path), - #[cfg(feature = "wizard")] Some(path) => Self::from_wizard(path).await, _ => Self::from_default_paths().await, } @@ -215,25 +204,28 @@ impl TomlConfig { signature: config.signature, signature_delim: config.signature_delim, downloads_dir: config.downloads_dir, - - folder: config.folder.map(|#[allow(unused)] c| FolderConfig { + folder: config.folder.map(|c| FolderConfig { aliases: c.alias, - #[cfg(any(feature = "account-sync", feature = "folder-list"))] list: c.list.map(|c| c.remote), + #[cfg(feature = "account-sync")] + sync: c.sync, }), - envelope: config.envelope.map(|#[allow(unused)] c| EnvelopeConfig { - #[cfg(any(feature = "account-sync", feature = "envelope-list"))] + envelope: config.envelope.map(|c| EnvelopeConfig { list: c.list.map(|c| c.remote), - #[cfg(feature = "envelope-watch")] watch: c.watch.map(|c| c.remote), + #[cfg(feature = "account-sync")] + sync: c.sync, + }), + flag: config.flag.map(|c| FlagConfig { + #[cfg(feature = "account-sync")] + sync: c.sync, }), - message: config.message.map(|#[allow(unused)] c| MessageConfig { - #[cfg(any(feature = "account-sync", feature = "message-read"))] + message: config.message.map(|c| MessageConfig { read: c.read.map(|c| c.remote), - #[cfg(any(feature = "account-sync", feature = "message-write"))] write: c.write.map(|c| c.remote), - #[cfg(feature = "message-send")] send: c.send.map(|c| c.remote), + #[cfg(feature = "account-sync")] + sync: c.sync, }), #[cfg(feature = "account-sync")] sync: config.sync, diff --git a/src/config/prelude.rs b/src/config/prelude.rs deleted file mode 100644 index 4728a0fd..00000000 --- a/src/config/prelude.rs +++ /dev/null @@ -1,791 +0,0 @@ -#[cfg(feature = "pgp-commands")] -use email::account::CmdsPgpConfig; -#[cfg(feature = "pgp-gpg")] -use email::account::GpgConfig; -#[cfg(feature = "pgp")] -use email::account::PgpConfig; -#[cfg(feature = "pgp-native")] -use email::account::{NativePgpConfig, NativePgpSecretKey, SignedSecretKey}; -#[cfg(feature = "notmuch")] -use email::backend::NotmuchConfig; -#[cfg(feature = "imap")] -use email::imap::config::{ImapAuthConfig, ImapConfig}; -#[cfg(feature = "smtp")] -use email::smtp::config::{SmtpAuthConfig, SmtpConfig}; -use email::{ - account::config::{ - oauth2::{OAuth2Config, OAuth2Method, OAuth2Scopes}, - passwd::PasswdConfig, - }, - email::config::{EmailHooks, EmailTextPlainFormat}, - folder::sync::FolderSyncStrategy, - maildir::config::MaildirConfig, - sendmail::config::SendmailConfig, -}; -use keyring::Entry; -use process::{Cmd, Pipeline, SingleCmd}; -use secret::Secret; -use serde::{ser::SerializeSeq, Deserialize, Serialize, Serializer}; -use std::{collections::HashSet, ops::Deref, path::PathBuf}; - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "Entry", from = "String")] -pub struct EntryDef(#[serde(getter = "Deref::deref")] String); - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "SingleCmd", from = "String")] -pub struct SingleCmdDef(#[serde(getter = "Deref::deref")] String); - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "Pipeline", from = "Vec")] -pub struct PipelineDef( - #[serde(getter = "Deref::deref", serialize_with = "pipeline")] Vec, -); - -// NOTE: did not find the way to do it with macros… -pub fn pipeline(cmds: &Vec, s: S) -> Result -where - S: Serializer, -{ - let mut seq = s.serialize_seq(Some(cmds.len()))?; - for cmd in cmds { - seq.serialize_element(&cmd.to_string())?; - } - seq.end() -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "Cmd", untagged)] -pub enum CmdDef { - #[serde(with = "SingleCmdDef")] - SingleCmd(SingleCmd), - #[serde(with = "PipelineDef")] - Pipeline(Pipeline), -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "Option", from = "OptionCmd", into = "OptionCmd")] -pub struct OptionCmdDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionCmd { - #[serde(default, skip)] - is_some: bool, - #[serde(flatten, with = "CmdDef")] - inner: Cmd, -} - -impl From for Option { - fn from(cmd: OptionCmd) -> Option { - if cmd.is_some { - Some(cmd.inner) - } else { - None - } - } -} - -impl Into for Option { - fn into(self) -> OptionCmd { - match self { - Some(cmd) => OptionCmd { - is_some: true, - inner: cmd, - }, - None => OptionCmd { - is_some: false, - inner: Default::default(), - }, - } - } -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "Secret", rename_all = "kebab-case")] -pub enum SecretDef { - Raw(String), - #[serde(with = "CmdDef")] - Cmd(Cmd), - #[serde(with = "EntryDef", rename = "keyring")] - KeyringEntry(Entry), - #[default] - Undefined, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "OAuth2Method")] -pub enum OAuth2MethodDef { - #[serde(rename = "xoauth2", alias = "XOAUTH2")] - XOAuth2, - #[serde(rename = "oauthbearer", alias = "OAUTHBEARER")] - OAuthBearer, -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionImapConfig", - into = "OptionImapConfig" -)] -pub struct OptionImapConfigDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionImapConfig { - #[serde(default, skip)] - is_none: bool, - #[serde(flatten, with = "ImapConfigDef")] - inner: ImapConfig, -} - -impl From for Option { - fn from(config: OptionImapConfig) -> Option { - if config.is_none { - None - } else { - Some(config.inner) - } - } -} - -impl Into for Option { - fn into(self) -> OptionImapConfig { - match self { - Some(config) => OptionImapConfig { - is_none: false, - inner: config, - }, - None => OptionImapConfig { - is_none: true, - inner: Default::default(), - }, - } - } -} - -#[cfg(feature = "imap")] -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "ImapConfig", rename_all = "kebab-case")] -pub struct ImapConfigDef { - pub host: String, - pub port: u16, - pub ssl: Option, - pub starttls: Option, - pub insecure: Option, - pub login: String, - #[serde(flatten, with = "ImapAuthConfigDef")] - pub auth: ImapAuthConfig, - pub notify_cmd: Option, - pub notify_query: Option, - pub watch_cmds: Option>, -} - -#[cfg(feature = "imap")] -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "ImapAuthConfig", tag = "auth")] -pub enum ImapAuthConfigDef { - #[serde(rename = "passwd", alias = "password", with = "ImapPasswdConfigDef")] - Passwd(#[serde(default)] PasswdConfig), - #[serde(rename = "oauth2", with = "ImapOAuth2ConfigDef")] - OAuth2(OAuth2Config), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "PasswdConfig")] -pub struct ImapPasswdConfigDef { - #[serde( - rename = "passwd", - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub passwd: Secret, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "OAuth2Config")] -pub struct ImapOAuth2ConfigDef { - #[serde(rename = "imap-oauth2-method", with = "OAuth2MethodDef", default)] - pub method: OAuth2Method, - #[serde(rename = "imap-oauth2-client-id")] - pub client_id: String, - #[serde( - rename = "imap-oauth2-client-secret", - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub client_secret: Secret, - #[serde(rename = "imap-oauth2-auth-url")] - pub auth_url: String, - #[serde(rename = "imap-oauth2-token-url")] - pub token_url: String, - #[serde( - rename = "imap-oauth2-access-token", - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub access_token: Secret, - #[serde( - rename = "imap-oauth2-refresh-token", - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub refresh_token: Secret, - #[serde(flatten, with = "ImapOAuth2ScopesDef")] - pub scopes: OAuth2Scopes, - #[serde(rename = "imap-oauth2-pkce", default)] - pub pkce: bool, - #[serde( - rename = "imap-oauth2-redirect-host", - default = "OAuth2Config::default_redirect_host" - )] - pub redirect_host: String, - #[serde( - rename = "imap-oauth2-redirect-port", - default = "OAuth2Config::default_redirect_port" - )] - pub redirect_port: u16, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "OAuth2Scopes")] -pub enum ImapOAuth2ScopesDef { - #[serde(rename = "imap-oauth2-scope")] - Scope(String), - #[serde(rename = "imap-oauth2-scopes")] - Scopes(Vec), -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionMaildirConfig", - into = "OptionMaildirConfig" -)] -pub struct OptionMaildirConfigDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionMaildirConfig { - #[serde(default, skip)] - is_none: bool, - #[serde(flatten, with = "MaildirConfigDef")] - inner: MaildirConfig, -} - -impl From for Option { - fn from(config: OptionMaildirConfig) -> Option { - if config.is_none { - None - } else { - Some(config.inner) - } - } -} - -impl Into for Option { - fn into(self) -> OptionMaildirConfig { - match self { - Some(config) => OptionMaildirConfig { - is_none: false, - inner: config, - }, - None => OptionMaildirConfig { - is_none: true, - inner: Default::default(), - }, - } - } -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "MaildirConfig", rename_all = "kebab-case")] -pub struct MaildirConfigDef { - #[serde(rename = "maildir-root-dir")] - pub root_dir: PathBuf, -} - -#[cfg(feature = "notmuch")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionNotmuchConfig", - into = "OptionNotmuchConfig" -)] -pub struct OptionNotmuchConfigDef; - -#[cfg(feature = "notmuch")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionNotmuchConfig { - #[serde(default, skip)] - is_none: bool, - #[serde(flatten, with = "NotmuchConfigDef")] - inner: NotmuchConfig, -} - -#[cfg(feature = "notmuch")] -impl From for Option { - fn from(config: OptionNotmuchConfig) -> Option { - if config.is_none { - None - } else { - Some(config.inner) - } - } -} - -#[cfg(feature = "notmuch")] -impl Into for Option { - fn into(self) -> OptionNotmuchConfig { - match self { - Some(config) => OptionNotmuchConfig { - is_none: false, - inner: config, - }, - None => OptionNotmuchConfig { - is_none: true, - inner: Default::default(), - }, - } - } -} - -#[cfg(feature = "notmuch")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "NotmuchConfig", rename_all = "kebab-case")] -pub struct NotmuchConfigDef { - #[serde(rename = "notmuch-db-path")] - pub db_path: PathBuf, -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionEmailTextPlainFormat", - into = "OptionEmailTextPlainFormat" -)] -pub struct OptionEmailTextPlainFormatDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionEmailTextPlainFormat { - #[serde(default, skip)] - is_none: bool, - #[serde(flatten, with = "EmailTextPlainFormatDef")] - inner: EmailTextPlainFormat, -} - -impl From for Option { - fn from(fmt: OptionEmailTextPlainFormat) -> Option { - if fmt.is_none { - None - } else { - Some(fmt.inner) - } - } -} - -impl Into for Option { - fn into(self) -> OptionEmailTextPlainFormat { - match self { - Some(config) => OptionEmailTextPlainFormat { - is_none: false, - inner: config, - }, - None => OptionEmailTextPlainFormat { - is_none: true, - inner: Default::default(), - }, - } - } -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "EmailTextPlainFormat", - tag = "type", - content = "width", - rename_all = "kebab-case" -)] -pub enum EmailTextPlainFormatDef { - #[default] - Auto, - Flowed, - Fixed(usize), -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionSmtpConfig", - into = "OptionSmtpConfig" -)] -pub struct OptionSmtpConfigDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionSmtpConfig { - #[serde(default, skip)] - is_none: bool, - #[serde(flatten, with = "SmtpConfigDef")] - inner: SmtpConfig, -} - -impl From for Option { - fn from(config: OptionSmtpConfig) -> Option { - if config.is_none { - None - } else { - Some(config.inner) - } - } -} - -impl Into for Option { - fn into(self) -> OptionSmtpConfig { - match self { - Some(config) => OptionSmtpConfig { - is_none: false, - inner: config, - }, - None => OptionSmtpConfig { - is_none: true, - inner: Default::default(), - }, - } - } -} - -#[cfg(feature = "smtp")] -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "SmtpConfig")] -struct SmtpConfigDef { - pub host: String, - pub port: u16, - pub ssl: Option, - pub starttls: Option, - pub insecure: Option, - pub login: String, - #[serde(flatten, with = "SmtpAuthConfigDef")] - pub auth: SmtpAuthConfig, -} - -#[cfg(feature = "smtp")] -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "SmtpAuthConfig", tag = "auth")] -pub enum SmtpAuthConfigDef { - #[serde(rename = "passwd", alias = "password", with = "SmtpPasswdConfigDef")] - Passwd(#[serde(default)] PasswdConfig), - #[serde(rename = "oauth2", with = "SmtpOAuth2ConfigDef")] - OAuth2(OAuth2Config), -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "PasswdConfig", default)] -pub struct SmtpPasswdConfigDef { - #[serde( - rename = "passwd", - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub passwd: Secret, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "OAuth2Config", rename_all = "kebab-case")] -pub struct SmtpOAuth2ConfigDef { - #[serde(with = "OAuth2MethodDef", default)] - pub method: OAuth2Method, - pub client_id: String, - #[serde( - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub client_secret: Secret, - pub auth_url: String, - pub token_url: String, - #[serde( - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub access_token: Secret, - #[serde( - with = "SecretDef", - default, - skip_serializing_if = "Secret::is_undefined" - )] - pub refresh_token: Secret, - #[serde(flatten, with = "SmtpOAuth2ScopesDef")] - pub scopes: OAuth2Scopes, - #[serde(default)] - pub pkce: bool, - #[serde(default = "OAuth2Config::default_redirect_host")] - pub redirect_host: String, - #[serde(default = "OAuth2Config::default_redirect_port")] - pub redirect_port: u16, -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "OAuth2Scopes")] -pub enum SmtpOAuth2ScopesDef { - #[serde(rename = "smtp-oauth2-scope")] - Scope(String), - #[serde(rename = "smtp-oauth2-scopes")] - Scopes(Vec), -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionSendmailConfig", - into = "OptionSendmailConfig" -)] -pub struct OptionSendmailConfigDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionSendmailConfig { - #[serde(default, skip)] - is_none: bool, - #[serde(flatten, with = "SendmailConfigDef")] - inner: SendmailConfig, -} - -impl From for Option { - fn from(config: OptionSendmailConfig) -> Option { - if config.is_none { - None - } else { - Some(config.inner) - } - } -} - -impl Into for Option { - fn into(self) -> OptionSendmailConfig { - match self { - Some(config) => OptionSendmailConfig { - is_none: false, - inner: config, - }, - None => OptionSendmailConfig { - is_none: true, - inner: Default::default(), - }, - } - } -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "SendmailConfig", rename_all = "kebab-case")] -pub struct SendmailConfigDef { - #[serde(with = "CmdDef", default = "sendmail_default_cmd")] - cmd: Cmd, -} - -fn sendmail_default_cmd() -> Cmd { - Cmd::from("/usr/sbin/sendmail") -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionEmailHooks", - into = "OptionEmailHooks" -)] -pub struct OptionEmailHooksDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionEmailHooks { - #[serde(default, skip)] - is_none: bool, - #[serde( - flatten, - skip_serializing_if = "EmailHooks::is_empty", - with = "EmailHooksDef" - )] - inner: EmailHooks, -} - -impl From for Option { - fn from(hooks: OptionEmailHooks) -> Option { - if hooks.is_none { - None - } else { - Some(hooks.inner) - } - } -} - -impl Into for Option { - fn into(self) -> OptionEmailHooks { - match self { - Some(hooks) => OptionEmailHooks { - is_none: false, - inner: hooks, - }, - None => OptionEmailHooks { - is_none: true, - inner: Default::default(), - }, - } - } -} - -/// Represents the email hooks. Useful for doing extra email -/// processing before or after sending it. -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "EmailHooks", rename_all = "kebab-case")] -pub struct EmailHooksDef { - /// Represents the hook called just before sending an email. - #[serde(default, with = "OptionCmdDef")] - pub pre_send: Option, -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde( - remote = "Option", - from = "OptionFolderSyncStrategy", - into = "OptionFolderSyncStrategy" -)] -pub struct OptionFolderSyncStrategyDef; - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionFolderSyncStrategy { - #[serde(default, skip)] - is_some: bool, - #[serde( - flatten, - skip_serializing_if = "FolderSyncStrategy::is_default", - with = "FolderSyncStrategyDef" - )] - inner: FolderSyncStrategy, -} - -impl From for Option { - fn from(option: OptionFolderSyncStrategy) -> Option { - if option.is_some { - Some(option.inner) - } else { - None - } - } -} - -impl Into for Option { - fn into(self) -> OptionFolderSyncStrategy { - match self { - Some(strategy) => OptionFolderSyncStrategy { - is_some: true, - inner: strategy, - }, - None => OptionFolderSyncStrategy { - is_some: false, - inner: Default::default(), - }, - } - } -} - -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "FolderSyncStrategy", rename_all = "kebab-case")] -pub enum FolderSyncStrategyDef { - #[default] - All, - #[serde(alias = "only")] - Include(HashSet), - #[serde(alias = "except")] - #[serde(alias = "ignore")] - Exclude(HashSet), -} - -#[cfg(feature = "pgp")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "Option", from = "OptionPgpConfig")] -pub struct OptionPgpConfigDef; - -#[cfg(feature = "pgp")] -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -pub struct OptionPgpConfig { - #[serde(default, skip)] - is_none: bool, - #[serde(flatten, with = "PgpConfigDef")] - inner: PgpConfig, -} - -#[cfg(feature = "pgp")] -impl From for Option { - fn from(config: OptionPgpConfig) -> Option { - if config.is_none { - None - } else { - Some(config.inner) - } - } -} - -#[cfg(feature = "pgp")] -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "PgpConfig", tag = "backend", rename_all = "kebab-case")] -pub enum PgpConfigDef { - #[cfg(feature = "pgp-commands")] - #[serde(with = "CmdsPgpConfigDef", alias = "commands")] - Cmds(CmdsPgpConfig), - #[cfg(feature = "pgp-gpg")] - #[serde(with = "GpgConfigDef")] - Gpg(GpgConfig), - #[cfg(feature = "pgp-native")] - #[serde(with = "NativePgpConfigDef")] - Native(NativePgpConfig), -} - -#[cfg(feature = "pgp-gpg")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "GpgConfig", rename_all = "kebab-case")] -pub struct GpgConfigDef; - -#[cfg(feature = "pgp-commands")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "CmdsPgpConfig", rename_all = "kebab-case")] -pub struct CmdsPgpConfigDef { - #[serde(default, with = "OptionCmdDef")] - encrypt_cmd: Option, - #[serde(default)] - encrypt_recipient_fmt: Option, - #[serde(default)] - encrypt_recipients_sep: Option, - #[serde(default, with = "OptionCmdDef")] - decrypt_cmd: Option, - #[serde(default, with = "OptionCmdDef")] - sign_cmd: Option, - #[serde(default, with = "OptionCmdDef")] - verify_cmd: Option, -} - -#[cfg(feature = "pgp-native")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "NativePgpConfig", rename_all = "kebab-case")] -pub struct NativePgpConfigDef { - #[serde(default, with = "NativePgpSecretKeyDef")] - secret_key: NativePgpSecretKey, - #[serde(default, with = "SecretDef")] - secret_key_passphrase: Secret, - #[serde(default = "NativePgpConfig::default_wkd")] - wkd: bool, - #[serde(default = "NativePgpConfig::default_key_servers")] - key_servers: Vec, -} - -#[cfg(feature = "pgp-native")] -#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] -#[serde(remote = "NativePgpSecretKey", rename_all = "kebab-case")] -pub enum NativePgpSecretKeyDef { - #[default] - None, - #[serde(skip)] - Raw(SignedSecretKey), - Path(PathBuf), - #[serde(with = "EntryDef")] - Keyring(Entry), -} diff --git a/src/email/envelope/command/list.rs b/src/email/envelope/command/list.rs index 968f039a..6b88c898 100644 --- a/src/email/envelope/command/list.rs +++ b/src/email/envelope/command/list.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -82,7 +83,7 @@ impl ListEnvelopesCommand { toml_account_config.clone(), account_config.clone(), list_envelopes_kind, - |builder| builder.set_list_envelopes(Some(None)), + |builder| builder.set_list_envelopes(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/envelope/command/mod.rs b/src/email/envelope/command/mod.rs index e334eab7..4b05c6cd 100644 --- a/src/email/envelope/command/mod.rs +++ b/src/email/envelope/command/mod.rs @@ -1,6 +1,4 @@ -#[cfg(feature = "envelope-list")] pub mod list; -#[cfg(feature = "envelope-watch")] pub mod watch; use anyhow::Result; @@ -8,10 +6,7 @@ use clap::Subcommand; use crate::{config::TomlConfig, printer::Printer}; -#[cfg(feature = "envelope-list")] -use self::list::ListEnvelopesCommand; -#[cfg(feature = "envelope-watch")] -use self::watch::WatchEnvelopesCommand; +use self::{list::ListEnvelopesCommand, watch::WatchEnvelopesCommand}; /// Manage envelopes. /// @@ -21,11 +16,9 @@ use self::watch::WatchEnvelopesCommand; /// manage them. #[derive(Debug, Subcommand)] pub enum EnvelopeSubcommand { - #[cfg(feature = "envelope-list")] #[command(alias = "lst")] List(ListEnvelopesCommand), - #[cfg(feature = "envelope-watch")] #[command()] Watch(WatchEnvelopesCommand), } @@ -34,9 +27,7 @@ impl EnvelopeSubcommand { #[allow(unused)] pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { match self { - #[cfg(feature = "envelope-list")] Self::List(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "envelope-watch")] Self::Watch(cmd) => cmd.execute(printer, config).await, } } diff --git a/src/email/envelope/command/watch.rs b/src/email/envelope/command/watch.rs index 18008b6b..a7c0ceb6 100644 --- a/src/email/envelope/command/watch.rs +++ b/src/email/envelope/command/watch.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::{backend::feature::BackendFeatureSource, envelope::watch::WatchEnvelopes}; use log::info; #[cfg(feature = "account-sync")] @@ -43,7 +44,7 @@ impl WatchEnvelopesCommand { toml_account_config.clone(), account_config, watch_envelopes_kind, - |builder| builder.set_watch_envelopes(Some(None)), + |builder| builder.set_watch_envelopes(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/envelope/config.rs b/src/email/envelope/config.rs index 63d38f62..6575f400 100644 --- a/src/email/envelope/config.rs +++ b/src/email/envelope/config.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "account-sync")] +use email::envelope::sync::config::EnvelopeSyncConfig; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -5,30 +7,25 @@ use crate::backend::BackendKind; #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct EnvelopeConfig { - #[cfg(any(feature = "account-sync", feature = "envelope-list"))] pub list: Option, - #[cfg(feature = "envelope-watch")] pub watch: Option, - #[cfg(any(feature = "account-sync", feature = "envelope-get"))] pub get: Option, + #[cfg(feature = "account-sync")] + pub sync: Option, } impl EnvelopeConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { - #[allow(unused_mut)] let mut kinds = HashSet::default(); - #[cfg(any(feature = "account-sync", feature = "envelope-list"))] if let Some(list) = &self.list { kinds.extend(list.get_used_backends()); } - #[cfg(feature = "envelope-watch")] if let Some(watch) = &self.watch { kinds.extend(watch.get_used_backends()); } - #[cfg(any(feature = "account-sync", feature = "envelope-get"))] if let Some(get) = &self.get { kinds.extend(get.get_used_backends()); } @@ -37,7 +34,6 @@ impl EnvelopeConfig { } } -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct ListEnvelopesConfig { pub backend: Option, @@ -46,7 +42,6 @@ pub struct ListEnvelopesConfig { pub remote: email::envelope::list::config::EnvelopeListConfig, } -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] impl ListEnvelopesConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -59,7 +54,6 @@ impl ListEnvelopesConfig { } } -#[cfg(feature = "envelope-watch")] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct WatchEnvelopesConfig { pub backend: Option, @@ -68,7 +62,6 @@ pub struct WatchEnvelopesConfig { pub remote: email::envelope::watch::config::WatchEnvelopeConfig, } -#[cfg(feature = "envelope-watch")] impl WatchEnvelopesConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -81,13 +74,11 @@ impl WatchEnvelopesConfig { } } -#[cfg(any(feature = "account-sync", feature = "envelope-get"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct GetEnvelopeConfig { pub backend: Option, } -#[cfg(any(feature = "account-sync", feature = "envelope-get"))] impl GetEnvelopeConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); diff --git a/src/email/envelope/flag/command/add.rs b/src/email/envelope/flag/command/add.rs index 61cbe8d6..a0520e5b 100644 --- a/src/email/envelope/flag/command/add.rs +++ b/src/email/envelope/flag/command/add.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -51,7 +52,7 @@ impl FlagAddCommand { toml_account_config.clone(), account_config, add_flags_kind, - |builder| builder.set_add_flags(Some(None)), + |builder| builder.set_add_flags(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/envelope/flag/command/mod.rs b/src/email/envelope/flag/command/mod.rs index ceb111e8..8e87783d 100644 --- a/src/email/envelope/flag/command/mod.rs +++ b/src/email/envelope/flag/command/mod.rs @@ -1,8 +1,5 @@ -#[cfg(feature = "flag-add")] mod add; -#[cfg(feature = "flag-remove")] mod remove; -#[cfg(feature = "flag-set")] mod set; use anyhow::Result; @@ -10,12 +7,7 @@ use clap::Subcommand; use crate::{config::TomlConfig, printer::Printer}; -#[cfg(feature = "flag-add")] -use self::add::FlagAddCommand; -#[cfg(feature = "flag-remove")] -use self::remove::FlagRemoveCommand; -#[cfg(feature = "flag-set")] -use self::set::FlagSetCommand; +use self::{add::FlagAddCommand, remove::FlagRemoveCommand, set::FlagSetCommand}; /// Manage flags. /// @@ -25,17 +17,14 @@ use self::set::FlagSetCommand; /// synchronization does not take care of them yet). #[derive(Debug, Subcommand)] pub enum FlagSubcommand { - #[cfg(feature = "flag-add")] #[command(arg_required_else_help = true)] #[command(alias = "create")] Add(FlagAddCommand), - #[cfg(feature = "flag-set")] #[command(arg_required_else_help = true)] #[command(aliases = ["update", "change", "replace"])] Set(FlagSetCommand), - #[cfg(feature = "flag-remove")] #[command(arg_required_else_help = true)] #[command(aliases = ["rm", "delete", "del"])] Remove(FlagRemoveCommand), @@ -45,11 +34,8 @@ impl FlagSubcommand { #[allow(unused)] pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { match self { - #[cfg(feature = "flag-add")] Self::Add(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "flag-set")] Self::Set(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "flag-remove")] Self::Remove(cmd) => cmd.execute(printer, config).await, } } diff --git a/src/email/envelope/flag/command/remove.rs b/src/email/envelope/flag/command/remove.rs index 596370dc..74fba55b 100644 --- a/src/email/envelope/flag/command/remove.rs +++ b/src/email/envelope/flag/command/remove.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -51,7 +52,7 @@ impl FlagRemoveCommand { toml_account_config.clone(), account_config, remove_flags_kind, - |builder| builder.set_remove_flags(Some(None)), + |builder| builder.set_remove_flags(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/envelope/flag/command/set.rs b/src/email/envelope/flag/command/set.rs index f8baae74..f98852b4 100644 --- a/src/email/envelope/flag/command/set.rs +++ b/src/email/envelope/flag/command/set.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -51,7 +52,7 @@ impl FlagSetCommand { toml_account_config.clone(), account_config, set_flags_kind, - |builder| builder.set_set_flags(Some(None)), + |builder| builder.set_set_flags(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/envelope/flag/config.rs b/src/email/envelope/flag/config.rs index 637e8b8b..f7e1a7c6 100644 --- a/src/email/envelope/flag/config.rs +++ b/src/email/envelope/flag/config.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "account-sync")] +use email::flag::sync::config::FlagSyncConfig; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -5,30 +7,25 @@ use crate::backend::BackendKind; #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FlagConfig { - #[cfg(feature = "flag-add")] pub add: Option, - #[cfg(feature = "flag-set")] pub set: Option, - #[cfg(feature = "flag-remove")] pub remove: Option, + #[cfg(feature = "account-sync")] + pub sync: Option, } impl FlagConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { - #[allow(unused_mut)] let mut kinds = HashSet::default(); - #[cfg(feature = "flag-add")] if let Some(add) = &self.add { kinds.extend(add.get_used_backends()); } - #[cfg(feature = "flag-set")] if let Some(set) = &self.set { kinds.extend(set.get_used_backends()); } - #[cfg(feature = "flag-remove")] if let Some(remove) = &self.remove { kinds.extend(remove.get_used_backends()); } @@ -37,13 +34,11 @@ impl FlagConfig { } } -#[cfg(feature = "flag-add")] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FlagAddConfig { pub backend: Option, } -#[cfg(feature = "flag-add")] impl FlagAddConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -56,13 +51,11 @@ impl FlagAddConfig { } } -#[cfg(feature = "flag-set")] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FlagSetConfig { pub backend: Option, } -#[cfg(feature = "flag-set")] impl FlagSetConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -75,13 +68,11 @@ impl FlagSetConfig { } } -#[cfg(feature = "flag-remove")] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FlagRemoveConfig { pub backend: Option, } -#[cfg(feature = "flag-remove")] impl FlagRemoveConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); diff --git a/src/email/envelope/mod.rs b/src/email/envelope/mod.rs index 88336909..adde73b7 100644 --- a/src/email/envelope/mod.rs +++ b/src/email/envelope/mod.rs @@ -30,7 +30,6 @@ pub struct Envelope { pub date: String, } -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] impl Table for Envelope { fn head() -> Row { Row::new() @@ -76,12 +75,10 @@ impl Table for Envelope { } } -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] /// Represents the list of envelopes. #[derive(Clone, Debug, Default, Serialize)] pub struct Envelopes(Vec); -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] impl Envelopes { pub fn from_backend( config: &AccountConfig, @@ -108,7 +105,6 @@ impl Envelopes { } } -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] impl ops::Deref for Envelopes { type Target = Vec; @@ -117,7 +113,6 @@ impl ops::Deref for Envelopes { } } -#[cfg(any(feature = "account-sync", feature = "envelope-list"))] impl PrintTable for Envelopes { fn print_table(&self, writer: &mut dyn WriteColor, opts: PrintTableOpts) -> Result<()> { writeln!(writer)?; diff --git a/src/email/message/attachment/command/download.rs b/src/email/message/attachment/command/download.rs index 34621358..8b4d7987 100644 --- a/src/email/message/attachment/command/download.rs +++ b/src/email/message/attachment/command/download.rs @@ -1,5 +1,6 @@ use anyhow::{Context, Result}; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; use std::{fs, path::PathBuf}; use uuid::Uuid; @@ -51,7 +52,7 @@ impl AttachmentDownloadCommand { toml_account_config.clone(), account_config.clone(), get_messages_kind, - |builder| builder.set_get_messages(Some(None)), + |builder| builder.set_get_messages(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/attachment/command/mod.rs b/src/email/message/attachment/command/mod.rs index 25c5c27f..f7b6970e 100644 --- a/src/email/message/attachment/command/mod.rs +++ b/src/email/message/attachment/command/mod.rs @@ -1,12 +1,10 @@ -#[cfg(feature = "attachment-download")] -pub mod download; +mod download; use anyhow::Result; use clap::Subcommand; use crate::{config::TomlConfig, printer::Printer}; -#[cfg(feature = "attachment-download")] use self::download::AttachmentDownloadCommand; /// Manage attachments. @@ -16,16 +14,13 @@ use self::download::AttachmentDownloadCommand; /// body. #[derive(Debug, Subcommand)] pub enum AttachmentSubcommand { - #[cfg(feature = "attachment-download")] #[command(arg_required_else_help = true)] Download(AttachmentDownloadCommand), } impl AttachmentSubcommand { - #[allow(unused)] pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { match self { - #[cfg(feature = "attachment-download")] Self::Download(cmd) => cmd.execute(printer, config).await, } } diff --git a/src/email/message/command/copy.rs b/src/email/message/command/copy.rs index 0b55dc1c..70329d07 100644 --- a/src/email/message/command/copy.rs +++ b/src/email/message/command/copy.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -53,7 +54,7 @@ impl MessageCopyCommand { toml_account_config.clone(), account_config, copy_messages_kind, - |builder| builder.set_copy_messages(Some(None)), + |builder| builder.set_copy_messages(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/command/delete.rs b/src/email/message/command/delete.rs index a6c0e97d..de6189e6 100644 --- a/src/email/message/command/delete.rs +++ b/src/email/message/command/delete.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -51,7 +52,7 @@ impl MessageDeleteCommand { toml_account_config.clone(), account_config, delete_messages_kind, - |builder| builder.set_delete_messages(Some(None)), + |builder| builder.set_delete_messages(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/command/forward.rs b/src/email/message/command/forward.rs index 71fe74a7..1a85aca6 100644 --- a/src/email/message/command/forward.rs +++ b/src/email/message/command/forward.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -63,8 +64,8 @@ impl MessageForwardCommand { account_config.clone(), add_message_kind.into_iter().chain(send_message_kind), |builder| { - builder.set_add_message(Some(None)); - builder.set_send_message(Some(None)); + builder.set_add_message(BackendFeatureSource::Context); + builder.set_send_message(BackendFeatureSource::Context); }, ) .await?; diff --git a/src/email/message/command/mailto.rs b/src/email/message/command/mailto.rs index f3011f30..da4c4957 100644 --- a/src/email/message/command/mailto.rs +++ b/src/email/message/command/mailto.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::{debug, info}; use mail_builder::MessageBuilder; use url::Url; @@ -58,8 +59,8 @@ impl MessageMailtoCommand { account_config.clone(), add_message_kind.into_iter().chain(send_message_kind), |builder| { - builder.set_add_message(Some(None)); - builder.set_send_message(Some(None)); + builder.set_add_message(BackendFeatureSource::Context); + builder.set_send_message(BackendFeatureSource::Context); }, ) .await?; diff --git a/src/email/message/command/mod.rs b/src/email/message/command/mod.rs index 6c68577e..b5065c92 100644 --- a/src/email/message/command/mod.rs +++ b/src/email/message/command/mod.rs @@ -1,22 +1,12 @@ -#[cfg(feature = "message-copy")] pub mod copy; -#[cfg(feature = "message-delete")] pub mod delete; -#[cfg(feature = "message-forward")] pub mod forward; -#[cfg(feature = "message-mailto")] pub mod mailto; -#[cfg(feature = "message-move")] pub mod r#move; -#[cfg(feature = "message-read")] pub mod read; -#[cfg(feature = "message-reply")] pub mod reply; -#[cfg(feature = "message-save")] pub mod save; -#[cfg(feature = "message-send")] pub mod send; -#[cfg(feature = "message-write")] pub mod write; use anyhow::Result; @@ -24,26 +14,12 @@ use clap::Subcommand; use crate::{config::TomlConfig, printer::Printer}; -#[cfg(feature = "message-copy")] -use self::copy::MessageCopyCommand; -#[cfg(feature = "message-delete")] -use self::delete::MessageDeleteCommand; -#[cfg(feature = "message-forward")] -use self::forward::MessageForwardCommand; -#[cfg(feature = "message-mailto")] -use self::mailto::MessageMailtoCommand; -#[cfg(feature = "message-move")] -use self::r#move::MessageMoveCommand; -#[cfg(feature = "message-read")] -use self::read::MessageReadCommand; -#[cfg(feature = "message-reply")] -use self::reply::MessageReplyCommand; -#[cfg(feature = "message-save")] -use self::save::MessageSaveCommand; -#[cfg(feature = "message-send")] -use self::send::MessageSendCommand; -#[cfg(feature = "message-write")] -use self::write::MessageWriteCommand; +use self::{ + copy::MessageCopyCommand, delete::MessageDeleteCommand, forward::MessageForwardCommand, + mailto::MessageMailtoCommand, r#move::MessageMoveCommand, read::MessageReadCommand, + reply::MessageReplyCommand, save::MessageSaveCommand, send::MessageSendCommand, + write::MessageWriteCommand, +}; /// Manage messages. /// @@ -53,43 +29,33 @@ use self::write::MessageWriteCommand; /// subcommand allows you to manage them. #[derive(Debug, Subcommand)] pub enum MessageSubcommand { - #[cfg(feature = "message-read")] #[command(arg_required_else_help = true)] Read(MessageReadCommand), - #[cfg(feature = "message-write")] #[command(aliases = ["add", "create", "new", "compose"])] Write(MessageWriteCommand), - #[cfg(feature = "message-reply")] #[command()] Reply(MessageReplyCommand), - #[cfg(feature = "message-forward")] #[command(aliases = ["fwd", "fd"])] Forward(MessageForwardCommand), - #[cfg(feature = "message-mailto")] #[command()] Mailto(MessageMailtoCommand), - #[cfg(feature = "message-save")] Save(MessageSaveCommand), - #[cfg(feature = "message-send")] Send(MessageSendCommand), - #[cfg(feature = "message-copy")] #[command(arg_required_else_help = true)] #[command(aliases = ["cpy", "cp"])] Copy(MessageCopyCommand), - #[cfg(feature = "message-move")] #[command(arg_required_else_help = true)] #[command(alias = "mv")] Move(MessageMoveCommand), - #[cfg(feature = "message-delete")] #[command(arg_required_else_help = true)] #[command(aliases = ["remove", "rm"])] Delete(MessageDeleteCommand), @@ -99,25 +65,15 @@ impl MessageSubcommand { #[allow(unused)] pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { match self { - #[cfg(feature = "message-read")] Self::Read(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-write")] Self::Write(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-reply")] Self::Reply(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-forward")] Self::Forward(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-mailto")] Self::Mailto(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-save")] Self::Save(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-send")] Self::Send(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-copy")] Self::Copy(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-move")] Self::Move(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "message-delete")] Self::Delete(cmd) => cmd.execute(printer, config).await, } } diff --git a/src/email/message/command/move.rs b/src/email/message/command/move.rs index 6ffb994e..39ed2081 100644 --- a/src/email/message/command/move.rs +++ b/src/email/message/command/move.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -54,7 +55,7 @@ impl MessageMoveCommand { toml_account_config.clone(), account_config, move_messages_kind, - |builder| builder.set_move_messages(Some(None)), + |builder| builder.set_move_messages(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/command/read.rs b/src/email/message/command/read.rs index 26fbafd2..7ef27beb 100644 --- a/src/email/message/command/read.rs +++ b/src/email/message/command/read.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; use mml::message::FilterParts; @@ -96,7 +97,7 @@ impl MessageReadCommand { toml_account_config.clone(), account_config.clone(), get_messages_kind, - |builder| builder.set_get_messages(Some(None)), + |builder| builder.set_get_messages(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/command/reply.rs b/src/email/message/command/reply.rs index 4fb1f629..04e15390 100644 --- a/src/email/message/command/reply.rs +++ b/src/email/message/command/reply.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -65,8 +66,8 @@ impl MessageReplyCommand { account_config.clone(), add_message_kind.into_iter().chain(send_message_kind), |builder| { - builder.set_add_message(Some(None)); - builder.set_send_message(Some(None)); + builder.set_add_message(BackendFeatureSource::Context); + builder.set_send_message(BackendFeatureSource::Context); }, ) .await?; diff --git a/src/email/message/command/save.rs b/src/email/message/command/save.rs index 43fe40e9..3efc76bb 100644 --- a/src/email/message/command/save.rs +++ b/src/email/message/command/save.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; use std::io::{self, BufRead, IsTerminal}; @@ -48,7 +49,7 @@ impl MessageSaveCommand { toml_account_config.clone(), account_config, add_message_kind, - |builder| builder.set_add_message(Some(None)), + |builder| builder.set_add_message(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/command/send.rs b/src/email/message/command/send.rs index dcb1f74f..6d844778 100644 --- a/src/email/message/command/send.rs +++ b/src/email/message/command/send.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::{backend::feature::BackendFeatureSource, message::send::SendMessageThenSaveCopy}; use log::info; use std::io::{self, BufRead, IsTerminal}; @@ -37,10 +38,7 @@ impl MessageSendCommand { self.cache.disable, )?; - let send_message_kind = toml_account_config.send_message_kind(); - - #[cfg(feature = "message-add")] - let send_message_kind = send_message_kind.into_iter().chain( + let send_message_kind = toml_account_config.send_message_kind().into_iter().chain( toml_account_config .add_message_kind() .filter(|_| account_config.should_save_copy_sent_message()), @@ -51,9 +49,8 @@ impl MessageSendCommand { account_config, send_message_kind, |builder| { - builder.set_send_message(Some(None)); - #[cfg(feature = "message-add")] - builder.set_add_message(Some(None)); + builder.set_send_message(BackendFeatureSource::Context); + builder.set_add_message(BackendFeatureSource::Context); }, ) .await?; @@ -69,7 +66,7 @@ impl MessageSendCommand { .join("\r\n") }; - backend.send_message(msg.as_bytes()).await?; + backend.send_message_then_save_copy(msg.as_bytes()).await?; printer.print("Message successfully sent!") } diff --git a/src/email/message/command/write.rs b/src/email/message/command/write.rs index 79036f1d..1a532554 100644 --- a/src/email/message/command/write.rs +++ b/src/email/message/command/write.rs @@ -1,6 +1,6 @@ use anyhow::Result; use clap::Parser; -use email::message::Message; +use email::{backend::feature::BackendFeatureSource, message::Message}; use log::info; #[cfg(feature = "account-sync")] @@ -54,8 +54,8 @@ impl MessageWriteCommand { account_config.clone(), add_message_kind.into_iter().chain(send_message_kind), |builder| { - builder.set_add_message(Some(None)); - builder.set_send_message(Some(None)); + builder.set_add_message(BackendFeatureSource::Context); + builder.set_send_message(BackendFeatureSource::Context); }, ) .await?; diff --git a/src/email/message/config.rs b/src/email/message/config.rs index 1c725627..62843451 100644 --- a/src/email/message/config.rs +++ b/src/email/message/config.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "account-sync")] +use email::message::sync::config::MessageSyncConfig; use serde::{Deserialize, Serialize}; use std::collections::HashSet; @@ -5,53 +7,41 @@ use crate::backend::BackendKind; #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessageConfig { - #[cfg(any(feature = "account-sync", feature = "message-add"))] pub write: Option, - #[cfg(any(feature = "message-send", feature = "template-send"))] pub send: Option, - #[cfg(feature = "account-sync")] pub peek: Option, - #[cfg(any(feature = "account-sync", feature = "message-get"))] pub read: Option, - #[cfg(feature = "message-copy")] pub copy: Option, - #[cfg(any(feature = "account-sync", feature = "message-move"))] pub r#move: Option, - #[cfg(feature = "message-delete")] pub delete: Option, + #[cfg(feature = "account-sync")] + pub sync: Option, } impl MessageConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { - #[allow(unused_mut)] let mut kinds = HashSet::default(); - #[cfg(any(feature = "account-sync", feature = "message-add"))] if let Some(add) = &self.write { kinds.extend(add.get_used_backends()); } - #[cfg(any(feature = "message-send", feature = "template-send"))] if let Some(send) = &self.send { kinds.extend(send.get_used_backends()); } - #[cfg(feature = "account-sync")] if let Some(peek) = &self.peek { kinds.extend(peek.get_used_backends()); } - #[cfg(any(feature = "account-sync", feature = "message-get"))] if let Some(get) = &self.read { kinds.extend(get.get_used_backends()); } - #[cfg(feature = "message-copy")] if let Some(copy) = &self.copy { kinds.extend(copy.get_used_backends()); } - #[cfg(any(feature = "account-sync", feature = "message-move"))] if let Some(move_) = &self.r#move { kinds.extend(move_.get_used_backends()); } @@ -60,7 +50,6 @@ impl MessageConfig { } } -#[cfg(any(feature = "account-sync", feature = "message-add"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessageAddConfig { pub backend: Option, @@ -69,7 +58,6 @@ pub struct MessageAddConfig { pub remote: email::message::add::config::MessageWriteConfig, } -#[cfg(any(feature = "account-sync", feature = "message-add"))] impl MessageAddConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -82,7 +70,6 @@ impl MessageAddConfig { } } -#[cfg(any(feature = "message-send", feature = "template-send"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessageSendConfig { pub backend: Option, @@ -91,7 +78,6 @@ pub struct MessageSendConfig { pub remote: email::message::send::config::MessageSendConfig, } -#[cfg(any(feature = "message-send", feature = "template-send"))] impl MessageSendConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -104,13 +90,11 @@ impl MessageSendConfig { } } -#[cfg(any(feature = "account-sync", feature = "message-peek"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessagePeekConfig { pub backend: Option, } -#[cfg(any(feature = "account-sync", feature = "message-peek"))] impl MessagePeekConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -123,7 +107,6 @@ impl MessagePeekConfig { } } -#[cfg(any(feature = "account-sync", feature = "message-get"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessageGetConfig { pub backend: Option, @@ -132,7 +115,6 @@ pub struct MessageGetConfig { pub remote: email::message::get::config::MessageReadConfig, } -#[cfg(any(feature = "account-sync", feature = "message-get"))] impl MessageGetConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -145,13 +127,11 @@ impl MessageGetConfig { } } -#[cfg(feature = "message-copy")] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessageCopyConfig { pub backend: Option, } -#[cfg(feature = "message-copy")] impl MessageCopyConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -164,13 +144,11 @@ impl MessageCopyConfig { } } -#[cfg(any(feature = "account-sync", feature = "message-move"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessageMoveConfig { pub backend: Option, } -#[cfg(any(feature = "account-sync", feature = "message-move"))] impl MessageMoveConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -183,13 +161,11 @@ impl MessageMoveConfig { } } -#[cfg(feature = "message-delete")] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct MessageDeleteConfig { pub backend: Option, } -#[cfg(feature = "message-delete")] impl MessageDeleteConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); diff --git a/src/email/message/template/command/forward.rs b/src/email/message/template/command/forward.rs index 3d3ac584..472ff724 100644 --- a/src/email/message/template/command/forward.rs +++ b/src/email/message/template/command/forward.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -59,7 +60,7 @@ impl TemplateForwardCommand { toml_account_config.clone(), account_config.clone(), get_messages_kind, - |builder| builder.set_get_messages(Some(None)), + |builder| builder.set_get_messages(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/template/command/mod.rs b/src/email/message/template/command/mod.rs index c1631b2b..6e1162e6 100644 --- a/src/email/message/template/command/mod.rs +++ b/src/email/message/template/command/mod.rs @@ -1,29 +1,18 @@ -#[cfg(feature = "template-forward")] -pub mod forward; -#[cfg(feature = "template-reply")] -pub mod reply; -#[cfg(feature = "template-save")] -pub mod save; -#[cfg(feature = "template-send")] -pub mod send; -#[cfg(feature = "template-write")] -pub mod write; +mod forward; +mod reply; +mod save; +mod send; +mod write; use anyhow::Result; use clap::Subcommand; use crate::{config::TomlConfig, printer::Printer}; -#[cfg(feature = "template-forward")] -use self::forward::TemplateForwardCommand; -#[cfg(feature = "template-reply")] -use self::reply::TemplateReplyCommand; -#[cfg(feature = "template-save")] -use self::save::TemplateSaveCommand; -#[cfg(feature = "template-send")] -use self::send::TemplateSendCommand; -#[cfg(feature = "template-write")] -use self::write::TemplateWriteCommand; +use self::{ + forward::TemplateForwardCommand, reply::TemplateReplyCommand, save::TemplateSaveCommand, + send::TemplateSendCommand, write::TemplateWriteCommand, +}; /// Manage templates. /// @@ -36,41 +25,30 @@ use self::write::TemplateWriteCommand; /// . #[derive(Debug, Subcommand)] pub enum TemplateSubcommand { - #[cfg(feature = "template-write")] #[command(aliases = ["add", "create", "new", "compose"])] Write(TemplateWriteCommand), - #[cfg(feature = "template-reply")] #[command(arg_required_else_help = true)] Reply(TemplateReplyCommand), - #[cfg(feature = "template-forward")] #[command(arg_required_else_help = true)] #[command(alias = "fwd")] Forward(TemplateForwardCommand), - #[cfg(feature = "template-save")] #[command()] Save(TemplateSaveCommand), - #[cfg(feature = "template-send")] #[command()] Send(TemplateSendCommand), } impl TemplateSubcommand { - #[allow(unused)] pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { match self { - #[cfg(feature = "template-write")] Self::Write(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "template-reply")] Self::Reply(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "template-forward")] Self::Forward(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "template-save")] Self::Save(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "template-send")] Self::Send(cmd) => cmd.execute(printer, config).await, } } diff --git a/src/email/message/template/command/reply.rs b/src/email/message/template/command/reply.rs index 4857a7d1..9502b197 100644 --- a/src/email/message/template/command/reply.rs +++ b/src/email/message/template/command/reply.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; #[cfg(feature = "account-sync")] @@ -64,7 +65,7 @@ impl TemplateReplyCommand { toml_account_config.clone(), account_config.clone(), get_messages_kind, - |builder| builder.set_get_messages(Some(None)), + |builder| builder.set_get_messages(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/template/command/save.rs b/src/email/message/template/command/save.rs index 65abb30d..c9a89459 100644 --- a/src/email/message/template/command/save.rs +++ b/src/email/message/template/command/save.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::backend::feature::BackendFeatureSource; use log::info; use mml::MmlCompilerBuilder; use std::io::{self, BufRead, IsTerminal}; @@ -52,7 +53,7 @@ impl TemplateSaveCommand { toml_account_config.clone(), account_config.clone(), add_message_kind, - |builder| builder.set_add_message(Some(None)), + |builder| builder.set_add_message(BackendFeatureSource::Context), ) .await?; diff --git a/src/email/message/template/command/send.rs b/src/email/message/template/command/send.rs index c323f4fa..bbd24abf 100644 --- a/src/email/message/template/command/send.rs +++ b/src/email/message/template/command/send.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::{backend::feature::BackendFeatureSource, message::send::SendMessageThenSaveCopy}; use log::info; use mml::MmlCompilerBuilder; use std::io::{self, BufRead, IsTerminal}; @@ -40,10 +41,7 @@ impl TemplateSendCommand { self.cache.disable, )?; - let send_message_kind = toml_account_config.send_message_kind(); - - #[cfg(feature = "message-add")] - let send_message_kind = send_message_kind.into_iter().chain( + let send_message_kind = toml_account_config.send_message_kind().into_iter().chain( toml_account_config .add_message_kind() .filter(|_| account_config.should_save_copy_sent_message()), @@ -54,9 +52,8 @@ impl TemplateSendCommand { account_config.clone(), send_message_kind, |builder| { - builder.set_send_message(Some(None)); - #[cfg(feature = "message-add")] - builder.set_add_message(Some(None)); + builder.set_send_message(BackendFeatureSource::Context); + builder.set_add_message(BackendFeatureSource::Context); }, ) .await?; @@ -80,7 +77,7 @@ impl TemplateSendCommand { let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; - backend.send_message(&msg).await?; + backend.send_message_then_save_copy(&msg).await?; printer.print("Message successfully sent!") } diff --git a/src/folder/command/add.rs b/src/folder/command/add.rs index 8f1493f5..be3f26e6 100644 --- a/src/folder/command/add.rs +++ b/src/folder/command/add.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::{backend::feature::BackendFeatureSource, folder::add::AddFolder}; use log::info; #[cfg(feature = "account-sync")] @@ -43,7 +44,7 @@ impl AddFolderCommand { toml_account_config.clone(), account_config, add_folder_kind, - |builder| builder.set_add_folder(Some(None)), + |builder| builder.set_add_folder(BackendFeatureSource::Context), ) .await?; diff --git a/src/folder/command/delete.rs b/src/folder/command/delete.rs index 85d18e4c..552d8157 100644 --- a/src/folder/command/delete.rs +++ b/src/folder/command/delete.rs @@ -1,6 +1,7 @@ use anyhow::Result; use clap::Parser; use dialoguer::Confirm; +use email::{backend::feature::BackendFeatureSource, folder::delete::DeleteFolder}; use log::info; use std::process; @@ -56,7 +57,7 @@ impl FolderDeleteCommand { toml_account_config.clone(), account_config, delete_folder_kind, - |builder| builder.set_delete_folder(Some(None)), + |builder| builder.set_delete_folder(BackendFeatureSource::Context), ) .await?; diff --git a/src/folder/command/expunge.rs b/src/folder/command/expunge.rs index 0b7841d8..ba10a0f2 100644 --- a/src/folder/command/expunge.rs +++ b/src/folder/command/expunge.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::{backend::feature::BackendFeatureSource, folder::expunge::ExpungeFolder}; use log::info; #[cfg(feature = "account-sync")] @@ -44,7 +45,7 @@ impl FolderExpungeCommand { toml_account_config.clone(), account_config, expunge_folder_kind, - |builder| builder.set_expunge_folder(Some(None)), + |builder| builder.set_expunge_folder(BackendFeatureSource::Context), ) .await?; diff --git a/src/folder/command/list.rs b/src/folder/command/list.rs index 8d712475..3cf28601 100644 --- a/src/folder/command/list.rs +++ b/src/folder/command/list.rs @@ -1,5 +1,6 @@ use anyhow::Result; use clap::Parser; +use email::{backend::feature::BackendFeatureSource, folder::list::ListFolders}; use log::info; #[cfg(feature = "account-sync")] @@ -45,7 +46,7 @@ impl FolderListCommand { toml_account_config.clone(), account_config.clone(), list_folders_kind, - |builder| builder.set_list_folders(Some(None)), + |builder| builder.set_list_folders(BackendFeatureSource::Context), ) .await?; diff --git a/src/folder/command/mod.rs b/src/folder/command/mod.rs index 91ae20be..81315747 100644 --- a/src/folder/command/mod.rs +++ b/src/folder/command/mod.rs @@ -1,12 +1,7 @@ -#[cfg(feature = "folder-add")] mod add; -#[cfg(feature = "folder-delete")] mod delete; -#[cfg(feature = "folder-expunge")] mod expunge; -#[cfg(feature = "folder-list")] mod list; -#[cfg(feature = "folder-purge")] mod purge; use anyhow::Result; @@ -14,16 +9,10 @@ use clap::Subcommand; use crate::{config::TomlConfig, printer::Printer}; -#[cfg(feature = "folder-add")] -use self::add::AddFolderCommand; -#[cfg(feature = "folder-delete")] -use self::delete::FolderDeleteCommand; -#[cfg(feature = "folder-expunge")] -use self::expunge::FolderExpungeCommand; -#[cfg(feature = "folder-list")] -use self::list::FolderListCommand; -#[cfg(feature = "folder-purge")] -use self::purge::FolderPurgeCommand; +use self::{ + add::AddFolderCommand, delete::FolderDeleteCommand, expunge::FolderExpungeCommand, + list::FolderListCommand, purge::FolderPurgeCommand, +}; /// Manage folders. /// @@ -31,23 +20,18 @@ use self::purge::FolderPurgeCommand; /// emails. This subcommand allows you to manage them. #[derive(Debug, Subcommand)] pub enum FolderSubcommand { - #[cfg(feature = "folder-add")] #[command(visible_alias = "create", alias = "new")] Add(AddFolderCommand), - #[cfg(feature = "folder-list")] #[command(alias = "lst")] List(FolderListCommand), - #[cfg(feature = "folder-expunge")] #[command()] Expunge(FolderExpungeCommand), - #[cfg(feature = "folder-purge")] #[command()] Purge(FolderPurgeCommand), - #[cfg(feature = "folder-delete")] #[command(alias = "remove", alias = "rm")] Delete(FolderDeleteCommand), } @@ -56,15 +40,10 @@ impl FolderSubcommand { #[allow(unused)] pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { match self { - #[cfg(feature = "folder-add")] Self::Add(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "folder-list")] Self::List(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "folder-expunge")] Self::Expunge(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "folder-purge")] Self::Purge(cmd) => cmd.execute(printer, config).await, - #[cfg(feature = "folder-delete")] Self::Delete(cmd) => cmd.execute(printer, config).await, } } diff --git a/src/folder/command/purge.rs b/src/folder/command/purge.rs index aab6c470..ec40bec9 100644 --- a/src/folder/command/purge.rs +++ b/src/folder/command/purge.rs @@ -1,6 +1,7 @@ use anyhow::Result; use clap::Parser; use dialoguer::Confirm; +use email::{backend::feature::BackendFeatureSource, folder::purge::PurgeFolder}; use log::info; use std::process; @@ -56,7 +57,7 @@ impl FolderPurgeCommand { toml_account_config.clone(), account_config, purge_folder_kind, - |builder| builder.set_purge_folder(Some(None)), + |builder| builder.set_purge_folder(BackendFeatureSource::Context), ) .await?; diff --git a/src/folder/config.rs b/src/folder/config.rs index e1ebd904..69a3bb4a 100644 --- a/src/folder/config.rs +++ b/src/folder/config.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "account-sync")] +use email::folder::sync::config::FolderSyncConfig; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; @@ -7,45 +9,35 @@ use crate::backend::BackendKind; pub struct FolderConfig { #[serde(alias = "aliases")] pub alias: Option>, - - #[cfg(any(feature = "account-sync", feature = "folder-add"))] pub add: Option, - #[cfg(any(feature = "account-sync", feature = "folder-list"))] pub list: Option, - #[cfg(any(feature = "account-sync", feature = "folder-expunge"))] pub expunge: Option, - #[cfg(feature = "folder-purge")] pub purge: Option, - #[cfg(any(feature = "account-sync", feature = "folder-delete"))] pub delete: Option, + #[cfg(feature = "account-sync")] + pub sync: Option, } impl FolderConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { - #[allow(unused_mut)] let mut kinds = HashSet::default(); - #[cfg(any(feature = "account-sync", feature = "folder-add"))] if let Some(add) = &self.add { kinds.extend(add.get_used_backends()); } - #[cfg(any(feature = "account-sync", feature = "folder-list"))] if let Some(list) = &self.list { kinds.extend(list.get_used_backends()); } - #[cfg(any(feature = "account-sync", feature = "folder-expunge"))] if let Some(expunge) = &self.expunge { kinds.extend(expunge.get_used_backends()); } - #[cfg(feature = "folder-purge")] if let Some(purge) = &self.purge { kinds.extend(purge.get_used_backends()); } - #[cfg(any(feature = "account-sync", feature = "folder-delete"))] if let Some(delete) = &self.delete { kinds.extend(delete.get_used_backends()); } @@ -54,13 +46,11 @@ impl FolderConfig { } } -#[cfg(any(feature = "account-sync", feature = "folder-add"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FolderAddConfig { pub backend: Option, } -#[cfg(any(feature = "account-sync", feature = "folder-add"))] impl FolderAddConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -73,7 +63,6 @@ impl FolderAddConfig { } } -#[cfg(any(feature = "account-sync", feature = "folder-list"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FolderListConfig { pub backend: Option, @@ -82,7 +71,6 @@ pub struct FolderListConfig { pub remote: email::folder::list::config::FolderListConfig, } -#[cfg(any(feature = "account-sync", feature = "folder-list"))] impl FolderListConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -95,13 +83,11 @@ impl FolderListConfig { } } -#[cfg(any(feature = "account-sync", feature = "folder-expunge"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FolderExpungeConfig { pub backend: Option, } -#[cfg(any(feature = "account-sync", feature = "folder-expunge"))] impl FolderExpungeConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -114,13 +100,11 @@ impl FolderExpungeConfig { } } -#[cfg(feature = "folder-purge")] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FolderPurgeConfig { pub backend: Option, } -#[cfg(feature = "folder-purge")] impl FolderPurgeConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); @@ -133,13 +117,11 @@ impl FolderPurgeConfig { } } -#[cfg(any(feature = "account-sync", feature = "folder-delete"))] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] pub struct FolderDeleteConfig { pub backend: Option, } -#[cfg(any(feature = "account-sync", feature = "folder-delete"))] impl FolderDeleteConfig { pub fn get_used_backends(&self) -> HashSet<&BackendKind> { let mut kinds = HashSet::default(); diff --git a/src/folder/mod.rs b/src/folder/mod.rs index 3f66e9b9..577abab1 100644 --- a/src/folder/mod.rs +++ b/src/folder/mod.rs @@ -1,29 +1,22 @@ pub mod arg; -#[cfg(feature = "folder-subcmd")] pub mod command; pub mod config; -#[cfg(feature = "folder-subcmd")] use anyhow::Result; -#[cfg(feature = "folder-subcmd")] use serde::Serialize; -#[cfg(feature = "folder-subcmd")] use std::ops; -#[cfg(feature = "folder-subcmd")] use crate::{ printer::{PrintTable, PrintTableOpts, WriteColor}, ui::{Cell, Row, Table}, }; -#[cfg(feature = "folder-subcmd")] #[derive(Clone, Debug, Default, Serialize)] pub struct Folder { pub name: String, pub desc: String, } -#[cfg(feature = "folder-subcmd")] impl From<&email::folder::Folder> for Folder { fn from(folder: &email::folder::Folder) -> Self { Folder { @@ -33,7 +26,6 @@ impl From<&email::folder::Folder> for Folder { } } -#[cfg(feature = "folder-subcmd")] impl Table for Folder { fn head() -> Row { Row::new() @@ -48,11 +40,9 @@ impl Table for Folder { } } -#[cfg(feature = "folder-subcmd")] #[derive(Clone, Debug, Default, Serialize)] pub struct Folders(Vec); -#[cfg(feature = "folder-subcmd")] impl ops::Deref for Folders { type Target = Vec; @@ -61,14 +51,12 @@ impl ops::Deref for Folders { } } -#[cfg(feature = "folder-subcmd")] impl From for Folders { fn from(folders: email::folder::Folders) -> Self { Folders(folders.iter().map(Folder::from).collect()) } } -#[cfg(feature = "folder-subcmd")] impl PrintTable for Folders { fn print_table(&self, writer: &mut dyn WriteColor, opts: PrintTableOpts) -> Result<()> { writeln!(writer)?; diff --git a/src/imap/mod.rs b/src/imap/mod.rs index 7df01042..73818b4c 100644 --- a/src/imap/mod.rs +++ b/src/imap/mod.rs @@ -1,2 +1 @@ -#[cfg(feature = "wizard")] pub(crate) mod wizard; diff --git a/src/maildir/mod.rs b/src/maildir/mod.rs index 7df01042..73818b4c 100644 --- a/src/maildir/mod.rs +++ b/src/maildir/mod.rs @@ -1,2 +1 @@ -#[cfg(feature = "wizard")] pub(crate) mod wizard; diff --git a/src/main.rs b/src/main.rs index 881e2e92..740882d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,18 @@ use anyhow::Result; use clap::Parser; use env_logger::{Builder as LoggerBuilder, Env, DEFAULT_FILTER_ENV}; -#[cfg(any(feature = "envelope-list", feature = "message-mailto"))] -use himalaya::config::TomlConfig; -#[cfg(feature = "envelope-list")] -use himalaya::envelope::command::list::ListEnvelopesCommand; -#[cfg(feature = "message-mailto")] -use himalaya::message::command::mailto::MessageMailtoCommand; -use himalaya::{cli::Cli, printer::StdoutPrinter}; -use log::{debug, warn}; +use himalaya::{ + cli::Cli, config::TomlConfig, envelope::command::list::ListEnvelopesCommand, + message::command::mailto::MessageMailtoCommand, printer::StdoutPrinter, +}; +use log::{debug, trace}; #[tokio::main] async fn main() -> Result<()> { #[cfg(not(target_os = "windows"))] if let Err((_, err)) = coredump::register_panic_handler() { - warn!("cannot register coredump panic handler: {err}"); - debug!("{err:?}"); + debug!("cannot register coredump panic handler: {err}"); + trace!("{err:?}"); } LoggerBuilder::new() @@ -23,7 +20,6 @@ async fn main() -> Result<()> { .format_timestamp(None) .init(); - #[cfg(feature = "message-mailto")] // if the first argument starts by "mailto:", execute straight the // mailto message command if let Some(ref url) = std::env::args() @@ -41,20 +37,13 @@ async fn main() -> Result<()> { let cli = Cli::parse(); let mut printer = StdoutPrinter::new(cli.output, cli.color); - #[cfg(feature = "envelope-list")] match cli.command { - Some(cmd) => return cmd.execute(&mut printer, cli.config_path.as_ref()).await, + Some(cmd) => cmd.execute(&mut printer, cli.config_path.as_ref()).await, None => { let config = TomlConfig::from_some_path_or_default(cli.config_path.as_ref()).await?; - return ListEnvelopesCommand::default() + ListEnvelopesCommand::default() .execute(&mut printer, &config) - .await; + .await } } - - #[cfg(not(feature = "envelope-list"))] - return cli - .command - .execute(&mut printer, cli.config_path.as_ref()) - .await; } diff --git a/src/notmuch/mod.rs b/src/notmuch/mod.rs index 7df01042..73818b4c 100644 --- a/src/notmuch/mod.rs +++ b/src/notmuch/mod.rs @@ -1,2 +1 @@ -#[cfg(feature = "wizard")] pub(crate) mod wizard; diff --git a/src/sendmail/mod.rs b/src/sendmail/mod.rs index 7df01042..73818b4c 100644 --- a/src/sendmail/mod.rs +++ b/src/sendmail/mod.rs @@ -1,2 +1 @@ -#[cfg(feature = "wizard")] pub(crate) mod wizard; diff --git a/src/smtp/mod.rs b/src/smtp/mod.rs index 7df01042..73818b4c 100644 --- a/src/smtp/mod.rs +++ b/src/smtp/mod.rs @@ -1,2 +1 @@ -#[cfg(feature = "wizard")] pub(crate) mod wizard; diff --git a/src/ui/choice.rs b/src/ui/choice.rs index 6ea62be0..99d97283 100644 --- a/src/ui/choice.rs +++ b/src/ui/choice.rs @@ -38,11 +38,9 @@ pub fn pre_edit() -> Result { #[derive(Clone, Debug, Eq, PartialEq)] pub enum PostEditChoice { - #[cfg(feature = "message-send")] Send, Edit, LocalDraft, - #[cfg(feature = "message-add")] RemoteDraft, Discard, } @@ -50,11 +48,9 @@ pub enum PostEditChoice { impl ToString for PostEditChoice { fn to_string(&self) -> String { match self { - #[cfg(feature = "message-send")] Self::Send => "Send it".into(), Self::Edit => "Edit it again".into(), Self::LocalDraft => "Save it as local draft".into(), - #[cfg(feature = "message-add")] Self::RemoteDraft => "Save it as remote draft".into(), Self::Discard => "Discard it".into(), } @@ -63,11 +59,9 @@ impl ToString for PostEditChoice { pub fn post_edit() -> Result { let choices = [ - #[cfg(feature = "message-send")] PostEditChoice::Send, PostEditChoice::Edit, PostEditChoice::LocalDraft, - #[cfg(feature = "message-add")] PostEditChoice::RemoteDraft, PostEditChoice::Discard, ]; diff --git a/src/ui/editor.rs b/src/ui/editor.rs index 4033bad4..85d6fead 100644 --- a/src/ui/editor.rs +++ b/src/ui/editor.rs @@ -2,14 +2,11 @@ use anyhow::{Context, Result}; use email::{ account::config::AccountConfig, email::utils::{local_draft_path, remove_local_draft}, -}; -#[cfg(feature = "message-add")] -use email::{ flag::{Flag, Flags}, folder::DRAFTS, + message::{add::AddMessage, send::SendMessageThenSaveCopy}, }; use log::debug; -#[cfg(any(feature = "message-send", feature = "template-send"))] use mml::MmlCompilerBuilder; use process::SingleCmd; use std::{env, fs, sync::Arc}; @@ -82,7 +79,6 @@ pub async fn edit_tpl_with_editor( loop { match choice::post_edit() { - #[cfg(feature = "message-send")] Ok(PostEditChoice::Send) => { printer.print_log("Sending email…")?; @@ -94,7 +90,7 @@ pub async fn edit_tpl_with_editor( let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; - backend.send_message(&email).await?; + backend.send_message_then_save_copy(&email).await?; remove_local_draft()?; printer.print("Done!")?; @@ -108,7 +104,6 @@ pub async fn edit_tpl_with_editor( printer.print("Email successfully saved locally")?; break; } - #[cfg(feature = "message-add")] Ok(PostEditChoice::RemoteDraft) => { #[allow(unused_mut)] let mut compiler = MmlCompilerBuilder::new(); diff --git a/src/ui/prompt.rs b/src/ui/prompt.rs index 4a1b449f..8f5a66bc 100644 --- a/src/ui/prompt.rs +++ b/src/ui/prompt.rs @@ -3,7 +3,6 @@ use std::io; use super::THEME; -#[allow(unused)] pub(crate) fn passwd(prompt: &str) -> io::Result { Password::with_theme(&*THEME) .with_prompt(prompt) @@ -14,7 +13,6 @@ pub(crate) fn passwd(prompt: &str) -> io::Result { .interact() } -#[allow(unused)] pub(crate) fn secret(prompt: &str) -> io::Result { Password::with_theme(&*THEME) .with_prompt(prompt)