renamed sync feature to account-sync, put wizard stuff under feature

This commit is contained in:
Clément DOUIN 2024-01-09 09:28:45 +01:00
parent 921194da5c
commit b0d7e773dc
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
52 changed files with 1160 additions and 358 deletions

View file

@ -9,9 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added cargo feature `sync`.
- Added cargo feature `wizard`, enabled by default.
- Added one cargo feature per backend feature:
- `account` including `account-configure`, `account-list`, `sync` and the `account` subcommand
- `account` including `account-configure`, `account-list`, `account-sync` and the `account` subcommand
- `folder` including `folder-add`, `folder-list`, `folder-expunge`, `folder-purge`, `folder-delete` and the `folder` subcommand
- `envelope` including `envelope-list`, `envelope-watch`, `envelope-get` and the `envelope` subcommand
- `flag` including `flag-add`, `flag-set`, `flag-remove` and the `flag` subcommand

990
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -6,8 +6,8 @@ authors = ["soywod <clement.douin@posteo.net>"]
edition = "2021"
license = "MIT"
categories = ["command-line-interface", "command-line-utilities", "email"]
keywords = ["cli", "mail", "email", "client", "imap"]
homepage = "https://pimalaya.org/himalaya/cli/latest/"
keywords = ["cli", "email", "imap", "smtp", "sync"]
homepage = "https://pimalaya.org/"
documentation = "https://pimalaya.org/himalaya/cli/latest/"
repository = "https://github.com/soywod/himalaya/"
@ -16,12 +16,17 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[features]
# features documentation:
# https://pimalaya.org/himalaya/cli/latest/installation.html#cargo
default = [
"wizard",
"imap",
"maildir",
# "notmuch",
"smtp",
"sendmail",
"account",
"folder",
"envelope",
@ -29,21 +34,25 @@ default = [
"message",
"attachment",
"template",
"sync",
# "pgp-commands",
# "pgp-gpg",
# "pgp-commands", # enable PGP based on shell commands
# "pgp-gpg", # enable
# "pgp-native",
]
wizard = ["autoconfig"]
imap = ["email-lib/imap"]
maildir = ["email-lib/maildir"]
notmuch = ["email-lib/notmuch"]
smtp = ["email-lib/smtp"]
sendmail = ["email-lib/sendmail"]
account = ["account-configure", "account-list", "sync"]
account = ["account-configure", "account-list", "account-sync"]
account-subcmd = []
account-configure = ["account-subcmd"]
account-list = ["account-subcmd"]
sync = ["account-subcmd", "email-lib/sync"]
account-sync = ["account-subcmd", "email-lib/sync"]
folder = ["folder-add", "folder-list", "folder-expunge", "folder-purge", "folder-delete"]
folder-subcmd = []
folder-add = ["folder-subcmd", "email-lib/folder-add"]
@ -86,6 +95,7 @@ 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"]
pgp = []
pgp-commands = ["email-lib/pgp-commands", "mml-lib/pgp-commands", "pgp"]
pgp-gpg = ["email-lib/pgp-gpg", "mml-lib/pgp-gpg", "pgp"]
@ -98,6 +108,7 @@ tempfile = "3.3"
[dependencies]
anyhow = "1"
async-trait = "0.1"
autoconfig = { version = "0.4", optional = true }
chrono = "0.4.24"
clap = { version = "4.4", features = ["derive"] }
clap_complete = "4.4"

View file

@ -46,6 +46,9 @@
# Rust
rust-toolchain
# OpenSSL
openssl.dev
# Notmuch
notmuch

View file

@ -9,7 +9,7 @@ use log::info;
use log::{debug, warn};
#[cfg(any(feature = "imap", feature = "smtp"))]
use crate::config::wizard::{prompt_passwd, prompt_secret};
use crate::ui::prompt;
use crate::{account::arg::name::AccountNameArg, config::TomlConfig, printer::Printer};
/// Configure an account.
@ -72,11 +72,11 @@ impl AccountConfigureCommand {
if let Some(ref config) = account_config.imap {
match &config.auth {
ImapAuthConfig::Passwd(config) => {
config.configure(|| prompt_passwd("IMAP password")).await
config.configure(|| prompt::passwd("IMAP password")).await
}
ImapAuthConfig::OAuth2(config) => {
config
.configure(|| prompt_secret("IMAP OAuth 2.0 client secret"))
.configure(|| prompt::secret("IMAP OAuth 2.0 client secret"))
.await
}
}?;
@ -86,11 +86,11 @@ impl AccountConfigureCommand {
if let Some(ref config) = account_config.smtp {
match &config.auth {
SmtpAuthConfig::Passwd(config) => {
config.configure(|| prompt_passwd("SMTP password")).await
config.configure(|| prompt::passwd("SMTP password")).await
}
SmtpAuthConfig::OAuth2(config) => {
config
.configure(|| prompt_secret("SMTP OAuth 2.0 client secret"))
.configure(|| prompt::secret("SMTP OAuth 2.0 client secret"))
.await
}
}?;

View file

@ -2,7 +2,7 @@
mod configure;
#[cfg(feature = "account-list")]
mod list;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
mod sync;
use anyhow::Result;
@ -14,7 +14,7 @@ use crate::{config::TomlConfig, printer::Printer};
use self::configure::AccountConfigureCommand;
#[cfg(feature = "account-list")]
use self::list::AccountListCommand;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use self::sync::AccountSyncCommand;
/// Manage accounts.
@ -32,7 +32,7 @@ pub enum AccountSubcommand {
#[command(alias = "lst")]
List(AccountListCommand),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(alias = "synchronize", alias = "synchronise")]
Sync(AccountSyncCommand),
}
@ -45,7 +45,7 @@ impl AccountSubcommand {
Self::Configure(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "account-list")]
Self::List(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Self::Sync(cmd) => cmd.execute(printer, config).await,
}
}

View file

@ -5,7 +5,7 @@
#[cfg(feature = "pgp")]
use email::account::config::pgp::PgpConfig;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use email::account::sync::config::SyncConfig;
#[cfg(feature = "imap")]
use email::imap::config::ImapConfig;
@ -35,7 +35,7 @@ pub struct TomlAccountConfig {
pub downloads_dir: Option<PathBuf>,
pub backend: Option<BackendKind>,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
pub sync: Option<SyncConfig>,
#[cfg(feature = "pgp")]
pub pgp: Option<PgpConfig>,

View file

@ -1,6 +1,7 @@
pub mod arg;
pub mod command;
pub mod config;
#[cfg(feature = "wizard")]
pub(crate) mod wizard;
use anyhow::Result;

View file

@ -1,20 +1,18 @@
use anyhow::{bail, Result};
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use dialoguer::Confirm;
use dialoguer::Input;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use email::account::sync::config::SyncConfig;
use email_address::EmailAddress;
#[allow(unused)]
use crate::backend::{self, config::BackendConfig, BackendKind};
#[cfg(feature = "message-send")]
use crate::message::config::{MessageConfig, MessageSendConfig};
#[cfg(feature = "sync")]
use crate::ui::THEME;
#[cfg(feature = "account-sync")]
use crate::wizard_prompt;
#[allow(unused)]
use crate::{
backend::{self, config::BackendConfig, BackendKind},
config::wizard::THEME,
};
use super::TomlAccountConfig;
@ -104,7 +102,7 @@ pub(crate) async fn configure() -> Result<Option<(String, TomlAccountConfig)>> {
_ => (),
};
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
{
let should_configure_sync = Confirm::new()
.with_prompt(wizard_prompt!(

View file

@ -1,4 +1,5 @@
pub mod config;
#[cfg(feature = "wizard")]
pub(crate) mod wizard;
use anyhow::Result;
@ -52,7 +53,7 @@ use email::folder::list::maildir::ListFoldersMaildir;
use email::folder::purge::imap::PurgeFolderImap;
#[cfg(feature = "imap")]
use email::imap::{ImapSessionBuilder, ImapSessionSync};
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use email::maildir::config::MaildirConfig;
#[cfg(feature = "maildir")]
use email::maildir::{MaildirSessionBuilder, MaildirSessionSync};
@ -99,7 +100,7 @@ pub enum BackendKind {
Imap,
#[cfg(feature = "maildir")]
Maildir,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[serde(skip_deserializing)]
MaildirForSync,
#[cfg(feature = "notmuch")]
@ -118,7 +119,7 @@ impl ToString for BackendKind {
Self::Imap => "IMAP",
#[cfg(feature = "maildir")]
Self::Maildir => "Maildir",
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Self::MaildirForSync => "Maildir",
#[cfg(feature = "notmuch")]
Self::Notmuch => "Notmuch",
@ -139,7 +140,7 @@ pub struct BackendContextBuilder {
pub imap: Option<ImapSessionBuilder>,
#[cfg(feature = "maildir")]
pub maildir: Option<MaildirSessionBuilder>,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
pub maildir_for_sync: Option<MaildirSessionBuilder>,
#[cfg(feature = "smtp")]
pub smtp: Option<SmtpClientBuilder>,
@ -178,7 +179,7 @@ impl BackendContextBuilder {
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
@ -230,7 +231,7 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder {
ctx.maildir = Some(maildir.build().await?);
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
if let Some(maildir) = self.maildir_for_sync {
ctx.maildir_for_sync = Some(maildir.build().await?);
}
@ -260,7 +261,7 @@ pub struct BackendContext {
pub imap: Option<ImapSessionSync>,
#[cfg(feature = "maildir")]
pub maildir: Option<MaildirSessionSync>,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
pub maildir_for_sync: Option<MaildirSessionSync>,
#[cfg(feature = "smtp")]
pub smtp: Option<SmtpClientSync>,
@ -285,7 +286,7 @@ impl BackendBuilder {
let is_imap_used = used_backends.contains(&BackendKind::Imap);
#[cfg(feature = "maildir")]
let is_maildir_used = used_backends.contains(&BackendKind::Maildir);
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
let is_maildir_for_sync_used = used_backends.contains(&BackendKind::MaildirForSync);
let backend_ctx_builder = BackendContextBuilder {
@ -313,7 +314,7 @@ impl BackendBuilder {
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
@ -333,7 +334,7 @@ impl BackendBuilder {
backend_builder = backend_builder
.with_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_folder(|ctx| {
ctx.maildir_for_sync
@ -362,7 +363,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(ListFoldersMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_list_folders(|ctx| {
ctx.maildir_for_sync
@ -392,7 +393,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_expunge_folder(|ctx| {
ctx.maildir_for_sync
@ -423,7 +424,7 @@ impl BackendBuilder {
// .with_purge_folder(|ctx| ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new));
// }
// TODO
// #[cfg(feature = "sync")]
// #[cfg(feature = "account-sync")]
// Some(BackendKind::MaildirForSync) => {
// backend_builder = backend_builder
// .with_purge_folder(|ctx| ctx.maildir_for_sync.as_ref().and_then(PurgeFolderMaildir::new));
@ -450,7 +451,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_delete_folder(|ctx| {
ctx.maildir_for_sync
@ -480,7 +481,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir_for_sync
@ -510,7 +511,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(WatchMaildirEnvelopes::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_watch_envelopes(|ctx| {
ctx.maildir_for_sync
@ -541,7 +542,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(GetEnvelopeMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_get_envelope(|ctx| {
ctx.maildir_for_sync
@ -570,7 +571,7 @@ impl BackendBuilder {
backend_builder = backend_builder
.with_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
@ -596,7 +597,7 @@ impl BackendBuilder {
backend_builder = backend_builder
.with_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_set_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new)
@ -623,7 +624,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_remove_flags(|ctx| {
ctx.maildir_for_sync
@ -658,7 +659,7 @@ impl BackendBuilder {
backend_builder = backend_builder
.with_add_message(|ctx| ctx.maildir.as_ref().and_then(AddMaildirMessage::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_message(|ctx| {
ctx.maildir_for_sync
@ -683,7 +684,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_peek_messages(|ctx| {
ctx.maildir_for_sync
@ -729,7 +730,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_copy_messages(|ctx| {
ctx.maildir_for_sync
@ -759,7 +760,7 @@ impl BackendBuilder {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_move_messages(|ctx| {
ctx.maildir_for_sync
@ -856,7 +857,7 @@ impl Backend {
)?;
}
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
id_mapper = IdMapper::new(
&self.backend.account_config,

View file

@ -1,7 +1,6 @@
use anyhow::Result;
use dialoguer::Select;
use crate::config::wizard::THEME;
#[cfg(feature = "imap")]
use crate::imap;
#[cfg(feature = "maildir")]
@ -12,6 +11,7 @@ use crate::notmuch;
use crate::sendmail;
#[cfg(feature = "smtp")]
use crate::smtp;
use crate::ui::THEME;
use super::{config::BackendConfig, BackendKind};

View file

@ -1,8 +1,8 @@
pub mod args;
#[cfg(feature = "wizard")]
pub mod wizard;
use anyhow::{anyhow, Context, Result};
use dialoguer::Confirm;
use dirs::{config_dir, home_dir};
use email::{
account::config::AccountConfig, config::Config, envelope::config::EnvelopeConfig,
@ -15,13 +15,14 @@ use std::{
collections::HashMap,
fs,
path::{Path, PathBuf},
process,
};
use toml;
#[cfg(feature = "sync")]
use crate::account::config::TomlAccountConfig;
#[cfg(feature = "account-sync")]
use crate::backend::BackendKind;
use crate::{account::config::TomlAccountConfig, wizard_prompt, wizard_warn};
#[cfg(feature = "wizard")]
use crate::{wizard_prompt, wizard_warn};
/// Represents the user config file.
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
@ -48,6 +49,7 @@ 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
@ -56,6 +58,9 @@ impl TomlConfig {
///
/// NOTE: the wizard can only be used with interactive shells.
async fn from_wizard(path: PathBuf) -> Result<Self> {
use dialoguer::Confirm;
use std::process;
wizard_warn!("Cannot find existing configuration at {path:?}.");
let confirm = Confirm::new()
@ -77,7 +82,10 @@ impl TomlConfig {
pub async fn from_default_paths() -> Result<Self> {
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"),
}
}
@ -96,8 +104,9 @@ impl TomlConfig {
pub async fn from_some_path_or_default(path: Option<impl Into<PathBuf>>) -> Result<Self> {
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,
None => Self::from_default_paths().await,
_ => Self::from_default_paths().await,
}
}
@ -175,13 +184,13 @@ impl TomlConfig {
pub fn into_account_configs(
self,
account_name: Option<&str>,
#[cfg(feature = "sync")] disable_cache: bool,
#[cfg(feature = "account-sync")] disable_cache: bool,
) -> Result<(TomlAccountConfig, AccountConfig)> {
#[cfg_attr(not(feature = "sync"), allow(unused_mut))]
#[cfg_attr(not(feature = "account-sync"), allow(unused_mut))]
let (account_name, mut toml_account_config) =
self.into_toml_account_config(account_name)?;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
if let Some(true) = toml_account_config.sync.as_ref().and_then(|c| c.enable) {
if !disable_cache {
toml_account_config.backend = Some(BackendKind::MaildirForSync);
@ -228,7 +237,7 @@ impl TomlConfig {
send: c.send.map(|c| c.remote),
..Default::default()
}),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
sync: config.sync,
#[cfg(feature = "pgp")]
pgp: config.pgp,

View file

@ -1,11 +1,10 @@
use anyhow::Result;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Password, Select};
use once_cell::sync::Lazy;
use dialoguer::{Confirm, Input, Select};
use shellexpand_utils::expand;
use std::{fs, io, path::PathBuf, process};
use std::{fs, path::PathBuf, process};
use toml_edit::{Document, Item};
use crate::account;
use crate::{account, ui::THEME};
use super::TomlConfig;
@ -32,8 +31,6 @@ macro_rules! wizard_log {
};
}
pub(crate) static THEME: Lazy<ColorfulTheme> = Lazy::new(ColorfulTheme::default);
pub(crate) async fn configure(path: PathBuf) -> Result<TomlConfig> {
wizard_log!("Configuring your first account:");
@ -171,22 +168,3 @@ fn set_tables_dotted<'a>(item: &'a mut Item, keys: impl IntoIterator<Item = &'a
set_table_dotted(item, key)
}
}
#[allow(unused)]
pub(crate) fn prompt_passwd(prompt: &str) -> io::Result<String> {
Password::with_theme(&*THEME)
.with_prompt(prompt)
.with_confirmation(
"Confirm password",
"Passwords do not match, please try again.",
)
.interact()
}
#[allow(unused)]
pub(crate) fn prompt_secret(prompt: &str) -> io::Result<String> {
Password::with_theme(&*THEME)
.with_prompt(prompt)
.report(false)
.interact()
}

View file

@ -8,7 +8,7 @@ use email::envelope::list::maildir::ListEnvelopesMaildir;
use email::envelope::list::notmuch::ListEnvelopesNotmuch;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -44,7 +44,7 @@ pub struct ListEnvelopesCommand {
#[command(flatten)]
pub table: TableMaxWidthFlag,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -59,7 +59,7 @@ impl Default for ListEnvelopesCommand {
page: 1,
page_size: Default::default(),
table: Default::default(),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
cache: Default::default(),
account: Default::default(),
}
@ -72,7 +72,7 @@ impl ListEnvelopesCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -101,7 +101,7 @@ impl ListEnvelopesCommand {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_list_envelopes(|ctx| {
ctx.maildir_for_sync

View file

@ -8,7 +8,7 @@ use email::envelope::watch::maildir::WatchMaildirEnvelopes;
use email::envelope::watch::notmuch::WatchNotmuchEnvelopes;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -27,7 +27,7 @@ pub struct WatchEnvelopesCommand {
#[command(flatten)]
pub folder: FolderNameOptionalFlag,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -42,7 +42,7 @@ impl WatchEnvelopesCommand {
let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -65,7 +65,7 @@ impl WatchEnvelopesCommand {
ctx.maildir.as_ref().and_then(WatchMaildirEnvelopes::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_watch_envelopes(|ctx| {
ctx.maildir_for_sync

View file

@ -8,7 +8,7 @@ use email::flag::add::maildir::AddFlagsMaildir;
use email::flag::add::notmuch::AddFlagsNotmuch;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -31,7 +31,7 @@ pub struct FlagAddCommand {
#[command(flatten)]
pub args: IdsAndFlagsArgs,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -47,7 +47,7 @@ impl FlagAddCommand {
let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -67,7 +67,7 @@ impl FlagAddCommand {
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)

View file

@ -8,7 +8,7 @@ use email::flag::remove::maildir::RemoveFlagsMaildir;
use email::flag::remove::notmuch::RemoveFlagsNotmuch;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -31,7 +31,7 @@ pub struct FlagRemoveCommand {
#[command(flatten)]
pub args: IdsAndFlagsArgs,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -47,7 +47,7 @@ impl FlagRemoveCommand {
let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -69,7 +69,7 @@ impl FlagRemoveCommand {
ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_remove_flags(|ctx| {
ctx.maildir_for_sync

View file

@ -8,7 +8,7 @@ use email::flag::set::maildir::SetFlagsMaildir;
use email::flag::set::notmuch::SetFlagsNotmuch;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -31,7 +31,7 @@ pub struct FlagSetCommand {
#[command(flatten)]
pub args: IdsAndFlagsArgs,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -47,7 +47,7 @@ impl FlagSetCommand {
let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -67,7 +67,7 @@ impl FlagSetCommand {
builder
.set_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_set_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new)

View file

@ -8,7 +8,7 @@ use log::info;
use std::{fs, path::PathBuf};
use uuid::Uuid;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -31,7 +31,7 @@ pub struct AttachmentDownloadCommand {
#[command(flatten)]
pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -48,7 +48,7 @@ impl AttachmentDownloadCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -72,7 +72,7 @@ impl AttachmentDownloadCommand {
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync

View file

@ -6,7 +6,7 @@ use email::message::copy::imap::CopyMessagesImap;
use email::message::copy::maildir::CopyMessagesMaildir;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -30,7 +30,7 @@ pub struct MessageCopyCommand {
#[command(flatten)]
pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -48,7 +48,7 @@ impl MessageCopyCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -70,7 +70,7 @@ impl MessageCopyCommand {
ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_copy_messages(|ctx| {
ctx.maildir_for_sync

View file

@ -6,7 +6,7 @@ use email::{flag::add::imap::AddFlagsImap, message::move_::imap::MoveMessagesIma
use email::{flag::add::maildir::AddFlagsMaildir, message::move_::maildir::MoveMessagesMaildir};
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -32,7 +32,7 @@ pub struct MessageDeleteCommand {
#[command(flatten)]
pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -49,7 +49,7 @@ impl MessageDeleteCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -74,7 +74,7 @@ impl MessageDeleteCommand {
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_move_messages(|ctx| {
ctx.maildir_for_sync

View file

@ -10,7 +10,7 @@ use email::message::send::sendmail::SendMessageSendmail;
use email::message::send::smtp::SendMessageSmtp;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -44,7 +44,7 @@ pub struct MessageForwardCommand {
#[command(flatten)]
pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -60,7 +60,7 @@ impl MessageForwardCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -84,7 +84,7 @@ impl MessageForwardCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -12,7 +12,7 @@ use log::{debug, info};
use mail_builder::MessageBuilder;
use url::Url;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -34,7 +34,7 @@ pub struct MessageMailtoCommand {
#[arg()]
pub url: Url,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -46,7 +46,7 @@ impl MessageMailtoCommand {
pub fn new(url: &str) -> Result<Self> {
Ok(Self {
url: Url::parse(url)?,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
cache: Default::default(),
account: Default::default(),
})
@ -57,7 +57,7 @@ impl MessageMailtoCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -81,7 +81,7 @@ impl MessageMailtoCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -6,7 +6,7 @@ use email::message::move_::imap::MoveMessagesImap;
use email::message::move_::maildir::MoveMessagesMaildir;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -30,7 +30,7 @@ pub struct MessageMoveCommand {
#[command(flatten)]
pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -48,7 +48,7 @@ impl MessageMoveCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -70,7 +70,7 @@ impl MessageMoveCommand {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_move_messages(|ctx| {
ctx.maildir_for_sync

View file

@ -7,7 +7,7 @@ use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMes
use log::info;
use mml::message::FilterParts;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -76,7 +76,7 @@ pub struct MessageReadCommand {
#[arg(conflicts_with = "no_headers")]
pub headers: Vec<String>,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -93,7 +93,7 @@ impl MessageReadCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -119,7 +119,7 @@ impl MessageReadCommand {
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync

View file

@ -10,7 +10,7 @@ use email::message::send::sendmail::SendMessageSendmail;
use email::message::send::smtp::SendMessageSmtp;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -47,7 +47,7 @@ pub struct MessageReplyCommand {
#[command(flatten)]
pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -62,7 +62,7 @@ impl MessageReplyCommand {
let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -86,7 +86,7 @@ impl MessageReplyCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -7,7 +7,7 @@ use email::message::add::maildir::AddMaildirMessage;
use log::info;
use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -30,7 +30,7 @@ pub struct MessageSaveCommand {
#[command(flatten)]
pub message: MessageRawArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -46,7 +46,7 @@ impl MessageSaveCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -67,7 +67,7 @@ impl MessageSaveCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -11,7 +11,7 @@ use email::message::send::smtp::SendMessageSmtp;
use log::info;
use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -31,7 +31,7 @@ pub struct MessageSendCommand {
#[command(flatten)]
pub message: MessageRawArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -45,7 +45,7 @@ impl MessageSendCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -75,7 +75,7 @@ impl MessageSendCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -11,7 +11,7 @@ use email::message::send::smtp::SendMessageSmtp;
use email::message::Message;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -37,7 +37,7 @@ pub struct MessageWriteCommand {
#[command(flatten)]
pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -51,7 +51,7 @@ impl MessageWriteCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -75,7 +75,7 @@ impl MessageWriteCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -6,7 +6,7 @@ use email::message::get::imap::GetMessagesImap;
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -38,7 +38,7 @@ pub struct TemplateForwardCommand {
#[command(flatten)]
pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -54,7 +54,7 @@ impl TemplateForwardCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -78,7 +78,7 @@ impl TemplateForwardCommand {
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync

View file

@ -6,7 +6,7 @@ use email::message::get::imap::GetMessagesImap;
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -42,7 +42,7 @@ pub struct TemplateReplyCommand {
#[command(flatten)]
pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -59,7 +59,7 @@ impl TemplateReplyCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -83,7 +83,7 @@ impl TemplateReplyCommand {
builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync

View file

@ -8,7 +8,7 @@ use log::info;
use mml::MmlCompilerBuilder;
use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -34,7 +34,7 @@ pub struct TemplateSaveCommand {
#[command(flatten)]
pub template: TemplateRawArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -50,7 +50,7 @@ impl TemplateSaveCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -71,7 +71,7 @@ impl TemplateSaveCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -12,7 +12,7 @@ use log::info;
use mml::MmlCompilerBuilder;
use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
#[allow(unused)]
use crate::{
@ -34,7 +34,7 @@ pub struct TemplateSendCommand {
#[command(flatten)]
pub template: TemplateRawArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -48,7 +48,7 @@ impl TemplateSendCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -78,7 +78,7 @@ impl TemplateSendCommand {
ctx.maildir.as_ref().and_then(AddMaildirMessage::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message(|ctx| {
ctx.maildir_for_sync

View file

@ -3,7 +3,7 @@ use clap::Parser;
use email::message::Message;
use log::info;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag, config::TomlConfig,
@ -23,7 +23,7 @@ pub struct TemplateWriteCommand {
#[command(flatten)]
pub body: TemplateRawBodyArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -37,7 +37,7 @@ impl TemplateWriteCommand {
let (_, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;

View file

@ -6,9 +6,9 @@ use email::folder::add::imap::AddFolderImap;
use email::folder::add::maildir::AddFolderMaildir;
use log::info;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
#[cfg(any(feature = "imap", feature = "maildir", feature = "account-sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
@ -24,7 +24,7 @@ pub struct AddFolderCommand {
#[command(flatten)]
pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -39,7 +39,7 @@ impl AddFolderCommand {
let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -59,7 +59,7 @@ impl AddFolderCommand {
builder
.set_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new));
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_folder(|ctx| {
ctx.maildir_for_sync

View file

@ -8,9 +8,9 @@ use email::folder::delete::maildir::DeleteFolderMaildir;
use log::info;
use std::process;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
#[cfg(any(feature = "imap", feature = "maildir", feature = "account-sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
@ -26,7 +26,7 @@ pub struct FolderDeleteCommand {
#[command(flatten)]
pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -52,7 +52,7 @@ impl FolderDeleteCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -74,7 +74,7 @@ impl FolderDeleteCommand {
ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_delete_folder(|ctx| {
ctx.maildir_for_sync

View file

@ -6,9 +6,9 @@ use email::folder::expunge::imap::ExpungeFolderImap;
use email::folder::expunge::maildir::ExpungeFolderMaildir;
use log::info;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
#[cfg(any(feature = "imap", feature = "maildir", feature = "account-sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
@ -25,7 +25,7 @@ pub struct FolderExpungeCommand {
#[command(flatten)]
pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -40,7 +40,7 @@ impl FolderExpungeCommand {
let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -63,7 +63,7 @@ impl FolderExpungeCommand {
ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_expunge_folder(|ctx| {
ctx.maildir_for_sync

View file

@ -6,9 +6,9 @@ use email::folder::list::imap::ListFoldersImap;
use email::folder::list::maildir::ListFoldersMaildir;
use log::info;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
#[cfg(any(feature = "imap", feature = "maildir", feature = "account-sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag,
@ -27,7 +27,7 @@ pub struct FolderListCommand {
#[command(flatten)]
pub table: TableMaxWidthFlag,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -41,7 +41,7 @@ impl FolderListCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -63,7 +63,7 @@ impl FolderListCommand {
ctx.maildir.as_ref().and_then(ListFoldersMaildir::new)
});
}
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_list_folders(|ctx| {
ctx.maildir_for_sync

View file

@ -6,9 +6,9 @@ use email::folder::purge::imap::PurgeFolderImap;
use log::info;
use std::process;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
#[cfg(any(feature = "imap", feature = "maildir", feature = "account-sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
@ -24,7 +24,7 @@ pub struct FolderPurgeCommand {
#[command(flatten)]
pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
#[command(flatten)]
pub cache: CacheDisableFlag,
@ -50,7 +50,7 @@ impl FolderPurgeCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
#[cfg(feature = "account-sync")]
self.cache.disable,
)?;
@ -73,7 +73,7 @@ impl FolderPurgeCommand {
// ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new)
// });
// }
// #[cfg(feature = "sync")]
// #[cfg(feature = "account-sync")]
// Some(BackendKind::MaildirForSync) => {
// builder.set_purge_folder(|ctx| {
// ctx.maildir_for_sync

View file

@ -1,62 +0,0 @@
//! Module related to IMAP CLI.
//!
//! This module provides subcommands and a command matcher related to IMAP.
use anyhow::Result;
use clap::{value_parser, Arg, ArgMatches, Command};
use log::debug;
const ARG_KEEPALIVE: &str = "keepalive";
const CMD_NOTIFY: &str = "notify";
const CMD_WATCH: &str = "watch";
type Keepalive = u64;
/// IMAP commands.
pub enum Cmd {
/// Start the IMAP notify mode with the give keepalive duration.
Notify(Keepalive),
/// Start the IMAP watch mode with the give keepalive duration.
Watch(Keepalive),
}
/// IMAP command matcher.
pub fn matches(m: &ArgMatches) -> Result<Option<Cmd>> {
if let Some(m) = m.subcommand_matches(CMD_NOTIFY) {
let keepalive = m.get_one::<u64>(ARG_KEEPALIVE).unwrap();
debug!("keepalive: {}", keepalive);
return Ok(Some(Cmd::Notify(*keepalive)));
}
if let Some(m) = m.subcommand_matches(CMD_WATCH) {
let keepalive = m.get_one::<u64>(ARG_KEEPALIVE).unwrap();
debug!("keepalive: {}", keepalive);
return Ok(Some(Cmd::Watch(*keepalive)));
}
Ok(None)
}
/// IMAP subcommands.
pub fn subcmds<'a>() -> Vec<Command> {
vec![
Command::new(CMD_NOTIFY)
.about("Notifies when new messages arrive in the given folder")
.alias("idle")
.arg(keepalive_arg()),
Command::new(CMD_WATCH)
.about("Watches IMAP server changes")
.arg(keepalive_arg()),
]
}
/// Represents the keepalive argument.
pub fn keepalive_arg() -> Arg {
Arg::new(ARG_KEEPALIVE)
.help("Specifies the keepalive duration.")
.long("keepalive")
.short('k')
.value_name("SECS")
.default_value("500")
.value_parser(value_parser!(u64))
}

View file

@ -1,15 +0,0 @@
//! Module related to IMAP handling.
//!
//! This module gathers all IMAP handlers triggered by the CLI.
use anyhow::Result;
pub async fn notify(imap: &mut ImapBackend, folder: &str, keepalive: u64) -> Result<()> {
imap.notify(keepalive, folder).await?;
Ok(())
}
pub async fn watch(imap: &mut ImapBackend, folder: &str, keepalive: u64) -> Result<()> {
imap.watch(keepalive, folder).await?;
Ok(())
}

View file

@ -1,3 +1,2 @@
// pub mod args;
// pub mod handlers;
#[cfg(feature = "wizard")]
pub(crate) mod wizard;

View file

@ -12,7 +12,7 @@ use secret::Secret;
use crate::{
backend::config::BackendConfig,
config::wizard::{prompt_passwd, THEME},
ui::{prompt, THEME},
wizard_log, wizard_prompt,
};
@ -93,12 +93,12 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
let config = match secret {
Some(idx) if SECRETS[idx] == KEYRING => {
Secret::new_keyring_entry(format!("{account_name}-imap-passwd"))
.set_keyring_entry_secret(prompt_passwd("IMAP password")?)
.set_keyring_entry_secret(prompt::passwd("IMAP password")?)
.await?;
PasswdConfig::default()
}
Some(idx) if SECRETS[idx] == RAW => PasswdConfig {
passwd: Secret::Raw(prompt_passwd("IMAP password")?),
passwd: Secret::Raw(prompt::passwd("IMAP password")?),
},
Some(idx) if SECRETS[idx] == CMD => PasswdConfig {
passwd: Secret::new_cmd(

View file

@ -1 +1,2 @@
#[cfg(feature = "wizard")]
pub(crate) mod wizard;

View file

@ -3,7 +3,7 @@ use dialoguer::Input;
use dirs::home_dir;
use email::maildir::config::MaildirConfig;
use crate::{backend::config::BackendConfig, config::wizard::THEME};
use crate::{backend::config::BackendConfig, ui::THEME};
pub(crate) fn configure() -> Result<BackendConfig> {
let mut config = MaildirConfig::default();

View file

@ -1 +1,2 @@
#[cfg(feature = "wizard")]
pub(crate) mod wizard;

View file

@ -1 +1,2 @@
#[cfg(feature = "wizard")]
pub(crate) mod wizard;

View file

@ -2,7 +2,7 @@ use anyhow::Result;
use dialoguer::Input;
use email::sendmail::config::SendmailConfig;
use crate::{backend::config::BackendConfig, config::wizard::THEME};
use crate::{backend::config::BackendConfig, ui::THEME};
pub(crate) fn configure() -> Result<BackendConfig> {
let mut config = SendmailConfig::default();

View file

@ -1 +1,2 @@
#[cfg(feature = "wizard")]
pub(crate) mod wizard;

View file

@ -12,7 +12,7 @@ use secret::Secret;
use crate::{
backend::config::BackendConfig,
config::wizard::{prompt_passwd, THEME},
ui::{prompt, THEME},
wizard_log, wizard_prompt,
};
@ -93,12 +93,12 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
let config = match secret {
Some(idx) if SECRETS[idx] == KEYRING => {
Secret::new_keyring_entry(format!("{account_name}-smtp-passwd"))
.set_keyring_entry_secret(prompt_passwd("SMTP password")?)
.set_keyring_entry_secret(prompt::passwd("SMTP password")?)
.await?;
PasswdConfig::default()
}
Some(idx) if SECRETS[idx] == RAW => PasswdConfig {
passwd: Secret::Raw(prompt_passwd("SMTP password")?),
passwd: Secret::Raw(prompt::passwd("SMTP password")?),
},
Some(idx) if SECRETS[idx] == CMD => PasswdConfig {
passwd: Secret::new_cmd(

View file

@ -1,5 +1,11 @@
pub mod choice;
pub mod editor;
pub(crate) mod prompt;
pub mod table;
use dialoguer::theme::ColorfulTheme;
use once_cell::sync::Lazy;
pub use self::table::*;
pub(crate) static THEME: Lazy<ColorfulTheme> = Lazy::new(ColorfulTheme::default);

23
src/ui/prompt.rs Normal file
View file

@ -0,0 +1,23 @@
use dialoguer::Password;
use std::io;
use super::THEME;
#[allow(unused)]
pub(crate) fn passwd(prompt: &str) -> io::Result<String> {
Password::with_theme(&*THEME)
.with_prompt(prompt)
.with_confirmation(
"Confirm password",
"Passwords do not match, please try again.",
)
.interact()
}
#[allow(unused)]
pub(crate) fn secret(prompt: &str) -> io::Result<String> {
Password::with_theme(&*THEME)
.with_prompt(prompt)
.report(false)
.interact()
}