add one cargo feature per backend feature

This commit is contained in:
Clément DOUIN 2024-01-07 23:48:45 +01:00
parent 9ffac16e05
commit a6b863759c
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
55 changed files with 1248 additions and 598 deletions

View file

@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
- Added one cargo feature per backend feature:
- TODO
### Changed
- Renamed `folder create` to `folder add` in order to better match types. An alias has been set up, so both `create` and `add` still work.
### Fixed ### Fixed
- Fixed default command: running `himalaya` without argument lists envelopes, as it used to be in previous versions. - Fixed default command: running `himalaya` without argument lists envelopes, as it used to be in previous versions.

10
Cargo.lock generated
View file

@ -1216,9 +1216,8 @@ dependencies = [
[[package]] [[package]]
name = "email-lib" name = "email-lib"
version = "0.19.5" version = "0.19.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://git.sr.ht/~soywod/pimalaya#2933075a179bfff3349987e9620185799eeba907"
checksum = "9e4c31e26febefc822561fe388677cec106bbf0a7fe16608e7638daa3d1da9d9"
dependencies = [ dependencies = [
"advisory-lock", "advisory-lock",
"anyhow", "anyhow",
@ -1235,7 +1234,6 @@ dependencies = [
"mail-parser", "mail-parser",
"mail-send", "mail-send",
"maildirpp", "maildirpp",
"md5",
"mml-lib", "mml-lib",
"notify", "notify",
"notify-rust", "notify-rust",
@ -1248,8 +1246,6 @@ dependencies = [
"rayon", "rayon",
"regex", "regex",
"rusqlite", "rusqlite",
"rustls 0.22.1",
"rustls-native-certs",
"secret-lib", "secret-lib",
"serde", "serde",
"shellexpand-utils", "shellexpand-utils",
@ -1259,8 +1255,6 @@ dependencies = [
"tree_magic_mini", "tree_magic_mini",
"urlencoding", "urlencoding",
"utf7-imap", "utf7-imap",
"uuid",
"webpki-roots 0.25.3",
] ]
[[package]] [[package]]

View file

@ -17,24 +17,79 @@ rustdoc-args = ["--cfg", "docsrs"]
[features] [features]
default = [ default = [
"maildir",
"imap", "imap",
"maildir",
# "notmuch", # "notmuch",
"smtp", "smtp",
"sendmail", "sendmail",
"account",
"folder",
"envelope",
"flag",
"message",
"attachment",
"template",
"sync",
# "pgp-commands", # "pgp-commands",
# "pgp-gpg", # "pgp-gpg",
# "pgp-native", # "pgp-native",
] ]
maildir = ["email-lib/maildir"]
imap = ["email-lib/imap"] imap = ["email-lib/imap"]
maildir = ["email-lib/maildir"]
notmuch = ["email-lib/notmuch"] notmuch = ["email-lib/notmuch"]
smtp = ["email-lib/smtp"] smtp = ["email-lib/smtp"]
sendmail = ["email-lib/sendmail"] sendmail = ["email-lib/sendmail"]
account = ["account-configure", "account-list"]
account-command = []
account-configure = ["account-command"]
account-list = ["account-command"]
folder = ["folder-add", "folder-list", "folder-expunge", "folder-purge", "folder-delete"]
folder-command = []
folder-add = ["folder-command", "email-lib/folder-add"]
folder-list = ["folder-command", "email-lib/folder-list"]
folder-expunge = ["folder-command", "email-lib/folder-expunge"]
folder-purge = ["folder-command", "email-lib/folder-purge"]
folder-delete = ["folder-command", "email-lib/folder-delete"]
envelope = ["envelope-list", "envelope-watch", "envelope-get"]
envelope-command = []
envelope-list = ["envelope-command", "email-lib/envelope-list"]
envelope-watch = ["envelope-command", "email-lib/envelope-watch"]
envelope-get = ["envelope-command", "email-lib/envelope-get"]
flag = ["flag-add", "flag-set", "flag-remove"]
flag-command = []
flag-add = ["flag-command", "email-lib/flag-add"]
flag-set = ["flag-command", "email-lib/flag-set"]
flag-remove = ["flag-command", "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-command = []
message-add = ["email-lib/message-add"]
message-peek = ["email-lib/message-peek"]
message-get = ["email-lib/message-get"]
message-copy = ["message-command", "email-lib/message-copy"]
message-move = ["message-command", "email-lib/message-move"]
message-delete = ["message-command", "email-lib/message-delete"]
message-send = ["message-command", "email-lib/message-send"]
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"]
attachment = ["attachment-download"]
attachment-command = []
attachment-download = ["attachment-command", "message-read"]
template = ["template-write", "template-reply", "template-forward", "template-save", "template-send"]
template-command = []
template-write = ["template-command"]
template-reply = ["template-command", "email-lib/message-get"]
template-forward = ["template-command", "email-lib/message-get"]
template-save = ["template-command", "email-lib/message-add"]
template-send = ["template-command", "email-lib/message-send"]
sync = ["account-command", "email-lib/sync"]
pgp = [] pgp = []
pgp-commands = ["pgp", "mml-lib/pgp-commands", "email-lib/pgp-commands"] pgp-commands = ["email-lib/pgp-commands", "mml-lib/pgp-commands", "pgp"]
pgp-gpg = ["pgp", "mml-lib/pgp-gpg", "email-lib/pgp-gpg"] pgp-gpg = ["email-lib/pgp-gpg", "mml-lib/pgp-gpg", "pgp"]
pgp-native = ["pgp", "mml-lib/pgp-native", "email-lib/pgp-native"] pgp-native = ["email-lib/pgp-native", "mml-lib/pgp-native", "pgp"]
[dev-dependencies] [dev-dependencies]
async-trait = "0.1" async-trait = "0.1"
@ -50,7 +105,8 @@ clap_mangen = "0.2"
console = "0.15.2" console = "0.15.2"
dialoguer = "0.10.2" dialoguer = "0.10.2"
dirs = "4.0" dirs = "4.0"
email-lib = { version = "=0.19.5", default-features = false } # email-lib = { version = "=0.19.6", default-features = false }
email-lib = { git = "https://git.sr.ht/~soywod/pimalaya", default-features = false }
email_address = "0.2.4" email_address = "0.2.4"
env_logger = "0.8" env_logger = "0.8"
erased-serde = "0.3" erased-serde = "0.3"

View file

@ -4,16 +4,13 @@ use clap::Parser;
use email::imap::config::ImapAuthConfig; use email::imap::config::ImapAuthConfig;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::smtp::config::SmtpAuthConfig; use email::smtp::config::SmtpAuthConfig;
use log::{debug, info, warn}; use log::info;
#[cfg(any(feature = "imap", feature = "smtp"))]
use log::{debug, warn};
use crate::{ #[cfg(any(feature = "imap", feature = "smtp"))]
account::arg::name::AccountNameArg, use crate::config::wizard::{prompt_passwd, prompt_secret};
config::{ use crate::{account::arg::name::AccountNameArg, config::TomlConfig, printer::Printer};
wizard::{prompt_passwd, prompt_secret},
TomlConfig,
},
printer::Printer,
};
/// Configure an account. /// Configure an account.
/// ///

View file

@ -1,5 +1,8 @@
#[cfg(feature = "account-configure")]
mod configure; mod configure;
#[cfg(feature = "account-list")]
mod list; mod list;
#[cfg(feature = "sync")]
mod sync; mod sync;
use anyhow::Result; use anyhow::Result;
@ -7,9 +10,12 @@ use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer}; use crate::{config::TomlConfig, printer::Printer};
use self::{ #[cfg(feature = "account-configure")]
configure::AccountConfigureCommand, list::AccountListCommand, sync::AccountSyncCommand, use self::configure::AccountConfigureCommand;
}; #[cfg(feature = "account-list")]
use self::list::AccountListCommand;
#[cfg(feature = "sync")]
use self::sync::AccountSyncCommand;
/// Manage accounts. /// Manage accounts.
/// ///
@ -18,21 +24,28 @@ use self::{
/// file. This subcommand allows you to manage them. /// file. This subcommand allows you to manage them.
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum AccountSubcommand { pub enum AccountSubcommand {
#[cfg(feature = "account-configure")]
#[command(alias = "cfg")] #[command(alias = "cfg")]
Configure(AccountConfigureCommand), Configure(AccountConfigureCommand),
#[cfg(feature = "account-list")]
#[command(alias = "lst")] #[command(alias = "lst")]
List(AccountListCommand), List(AccountListCommand),
#[cfg(feature = "sync")]
#[command(alias = "synchronize", alias = "synchronise")] #[command(alias = "synchronize", alias = "synchronise")]
Sync(AccountSyncCommand), Sync(AccountSyncCommand),
} }
impl AccountSubcommand { impl AccountSubcommand {
#[allow(unused)]
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self { match self {
#[cfg(feature = "account-configure")]
Self::Configure(cmd) => cmd.execute(printer, config).await, Self::Configure(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "account-list")]
Self::List(cmd) => cmd.execute(printer, config).await, Self::List(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "sync")]
Self::Sync(cmd) => cmd.execute(printer, config).await, Self::Sync(cmd) => cmd.execute(printer, config).await,
} }
} }

View file

@ -5,14 +5,16 @@
#[cfg(feature = "pgp")] #[cfg(feature = "pgp")]
use email::account::config::pgp::PgpConfig; use email::account::config::pgp::PgpConfig;
#[cfg(feature = "sync")]
use email::account::sync::config::SyncConfig;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::imap::config::ImapConfig; use email::imap::config::ImapConfig;
#[cfg(feature = "maildir")]
use email::maildir::config::MaildirConfig;
#[cfg(feature = "sendmail")]
use email::sendmail::config::SendmailConfig;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::smtp::config::SmtpConfig; use email::smtp::config::SmtpConfig;
use email::{
account::sync::config::SyncConfig, maildir::config::MaildirConfig,
sendmail::config::SendmailConfig,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashSet, path::PathBuf}; use std::{collections::HashSet, path::PathBuf};
@ -33,6 +35,7 @@ pub struct TomlAccountConfig {
pub downloads_dir: Option<PathBuf>, pub downloads_dir: Option<PathBuf>,
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
#[cfg(feature = "sync")]
pub sync: Option<SyncConfig>, pub sync: Option<SyncConfig>,
#[cfg(feature = "pgp")] #[cfg(feature = "pgp")]
pub pgp: Option<PgpConfig>, pub pgp: Option<PgpConfig>,
@ -55,6 +58,7 @@ pub struct TomlAccountConfig {
} }
impl TomlAccountConfig { impl TomlAccountConfig {
#[cfg(feature = "folder-add")]
pub fn add_folder_kind(&self) -> Option<&BackendKind> { pub fn add_folder_kind(&self) -> Option<&BackendKind> {
self.folder self.folder
.as_ref() .as_ref()
@ -63,6 +67,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "folder-list")]
pub fn list_folders_kind(&self) -> Option<&BackendKind> { pub fn list_folders_kind(&self) -> Option<&BackendKind> {
self.folder self.folder
.as_ref() .as_ref()
@ -71,6 +76,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "folder-expunge")]
pub fn expunge_folder_kind(&self) -> Option<&BackendKind> { pub fn expunge_folder_kind(&self) -> Option<&BackendKind> {
self.folder self.folder
.as_ref() .as_ref()
@ -79,6 +85,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "folder-purge")]
pub fn purge_folder_kind(&self) -> Option<&BackendKind> { pub fn purge_folder_kind(&self) -> Option<&BackendKind> {
self.folder self.folder
.as_ref() .as_ref()
@ -87,6 +94,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "folder-delete")]
pub fn delete_folder_kind(&self) -> Option<&BackendKind> { pub fn delete_folder_kind(&self) -> Option<&BackendKind> {
self.folder self.folder
.as_ref() .as_ref()
@ -95,6 +103,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "envelope-get")]
pub fn get_envelope_kind(&self) -> Option<&BackendKind> { pub fn get_envelope_kind(&self) -> Option<&BackendKind> {
self.envelope self.envelope
.as_ref() .as_ref()
@ -103,6 +112,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "envelope-list")]
pub fn list_envelopes_kind(&self) -> Option<&BackendKind> { pub fn list_envelopes_kind(&self) -> Option<&BackendKind> {
self.envelope self.envelope
.as_ref() .as_ref()
@ -111,6 +121,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "envelope-watch")]
pub fn watch_envelopes_kind(&self) -> Option<&BackendKind> { pub fn watch_envelopes_kind(&self) -> Option<&BackendKind> {
self.envelope self.envelope
.as_ref() .as_ref()
@ -119,6 +130,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "flag-add")]
pub fn add_flags_kind(&self) -> Option<&BackendKind> { pub fn add_flags_kind(&self) -> Option<&BackendKind> {
self.flag self.flag
.as_ref() .as_ref()
@ -127,6 +139,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "flag-set")]
pub fn set_flags_kind(&self) -> Option<&BackendKind> { pub fn set_flags_kind(&self) -> Option<&BackendKind> {
self.flag self.flag
.as_ref() .as_ref()
@ -135,6 +148,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "flag-remove")]
pub fn remove_flags_kind(&self) -> Option<&BackendKind> { pub fn remove_flags_kind(&self) -> Option<&BackendKind> {
self.flag self.flag
.as_ref() .as_ref()
@ -143,7 +157,8 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
pub fn add_raw_message_kind(&self) -> Option<&BackendKind> { #[cfg(feature = "message-add")]
pub fn add_message_kind(&self) -> Option<&BackendKind> {
self.message self.message
.as_ref() .as_ref()
.and_then(|msg| msg.write.as_ref()) .and_then(|msg| msg.write.as_ref())
@ -151,6 +166,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "message-peek")]
pub fn peek_messages_kind(&self) -> Option<&BackendKind> { pub fn peek_messages_kind(&self) -> Option<&BackendKind> {
self.message self.message
.as_ref() .as_ref()
@ -159,6 +175,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "message-get")]
pub fn get_messages_kind(&self) -> Option<&BackendKind> { pub fn get_messages_kind(&self) -> Option<&BackendKind> {
self.message self.message
.as_ref() .as_ref()
@ -167,6 +184,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "message-copy")]
pub fn copy_messages_kind(&self) -> Option<&BackendKind> { pub fn copy_messages_kind(&self) -> Option<&BackendKind> {
self.message self.message
.as_ref() .as_ref()
@ -175,6 +193,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "message-move")]
pub fn move_messages_kind(&self) -> Option<&BackendKind> { pub fn move_messages_kind(&self) -> Option<&BackendKind> {
self.message self.message
.as_ref() .as_ref()
@ -183,6 +202,7 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
#[cfg(feature = "message-delete")]
pub fn delete_messages_kind(&self) -> Option<&BackendKind> { pub fn delete_messages_kind(&self) -> Option<&BackendKind> {
self.flag self.flag
.as_ref() .as_ref()
@ -191,7 +211,8 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
pub fn send_raw_message_kind(&self) -> Option<&BackendKind> { #[cfg(any(feature = "message-send", feature = "template-send"))]
pub fn send_message_kind(&self) -> Option<&BackendKind> {
self.message self.message
.as_ref() .as_ref()
.and_then(|msg| msg.send.as_ref()) .and_then(|msg| msg.send.as_ref())
@ -199,14 +220,6 @@ impl TomlAccountConfig {
.or_else(|| self.backend.as_ref()) .or_else(|| self.backend.as_ref())
} }
pub fn get_watch_message_kind(&self) -> Option<&BackendKind> {
self.envelope
.as_ref()
.and_then(|envelope| envelope.watch.as_ref())
.and_then(|watch| watch.backend.as_ref())
.or_else(|| self.backend.as_ref())
}
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut used_backends = HashSet::default(); let mut used_backends = HashSet::default();
@ -218,14 +231,17 @@ impl TomlAccountConfig {
used_backends.extend(folder.get_used_backends()); used_backends.extend(folder.get_used_backends());
} }
#[cfg(feature = "envelope-command")]
if let Some(ref envelope) = self.envelope { if let Some(ref envelope) = self.envelope {
used_backends.extend(envelope.get_used_backends()); used_backends.extend(envelope.get_used_backends());
} }
#[cfg(feature = "flag-command")]
if let Some(ref flag) = self.flag { if let Some(ref flag) = self.flag {
used_backends.extend(flag.get_used_backends()); used_backends.extend(flag.get_used_backends());
} }
#[cfg(feature = "message-command")]
if let Some(ref msg) = self.message { if let Some(ref msg) = self.message {
used_backends.extend(msg.get_used_backends()); used_backends.extend(msg.get_used_backends());
} }

View file

@ -83,6 +83,7 @@ impl From<Iter<'_, String, TomlAccountConfig>> for Accounts {
fn from(map: Iter<'_, String, TomlAccountConfig>) -> Self { fn from(map: Iter<'_, String, TomlAccountConfig>) -> Self {
let mut accounts: Vec<_> = map let mut accounts: Vec<_> = map
.map(|(name, account)| { .map(|(name, account)| {
#[allow(unused_mut)]
let mut backends = String::new(); let mut backends = String::new();
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
@ -90,6 +91,7 @@ impl From<Iter<'_, String, TomlAccountConfig>> for Accounts {
backends.push_str("imap"); backends.push_str("imap");
} }
#[cfg(feature = "maildir")]
if account.maildir.is_some() { if account.maildir.is_some() {
if !backends.is_empty() { if !backends.is_empty() {
backends.push_str(", ") backends.push_str(", ")

View file

@ -1,13 +1,19 @@
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use dialoguer::{Confirm, Input}; #[cfg(feature = "sync")]
use dialoguer::Confirm;
use dialoguer::Input;
#[cfg(feature = "sync")]
use email::account::sync::config::SyncConfig; use email::account::sync::config::SyncConfig;
use email_address::EmailAddress; use email_address::EmailAddress;
#[cfg(feature = "message-send")]
use crate::message::config::{MessageConfig, MessageSendConfig};
#[cfg(feature = "sync")]
use crate::wizard_prompt;
#[allow(unused)]
use crate::{ use crate::{
backend::{self, config::BackendConfig, BackendKind}, backend::{self, config::BackendConfig, BackendKind},
config::wizard::THEME, config::wizard::THEME,
message::config::{MessageConfig, MessageSendConfig},
wizard_prompt,
}; };
use super::TomlAccountConfig; use super::TomlAccountConfig;
@ -46,15 +52,16 @@ pub(crate) async fn configure() -> Result<Option<(String, TomlAccountConfig)>> {
); );
match backend::wizard::configure(&account_name, &config.email).await? { match backend::wizard::configure(&account_name, &config.email).await? {
Some(BackendConfig::Maildir(mdir_config)) => {
config.maildir = Some(mdir_config);
config.backend = Some(BackendKind::Maildir);
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendConfig::Imap(imap_config)) => { Some(BackendConfig::Imap(imap_config)) => {
config.imap = Some(imap_config); config.imap = Some(imap_config);
config.backend = Some(BackendKind::Imap); config.backend = Some(BackendKind::Imap);
} }
#[cfg(feature = "maildir")]
Some(BackendConfig::Maildir(mdir_config)) => {
config.maildir = Some(mdir_config);
config.backend = Some(BackendKind::Maildir);
}
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
Some(BackendConfig::Notmuch(notmuch_config)) => { Some(BackendConfig::Notmuch(notmuch_config)) => {
config.notmuch = Some(notmuch_config); config.notmuch = Some(notmuch_config);
@ -64,43 +71,55 @@ pub(crate) async fn configure() -> Result<Option<(String, TomlAccountConfig)>> {
}; };
match backend::wizard::configure_sender(&account_name, &config.email).await? { match backend::wizard::configure_sender(&account_name, &config.email).await? {
Some(BackendConfig::Sendmail(sendmail_config)) => {
config.sendmail = Some(sendmail_config);
config.message = Some(MessageConfig {
send: Some(MessageSendConfig {
backend: Some(BackendKind::Sendmail),
..Default::default()
}),
..Default::default()
});
}
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(BackendConfig::Smtp(smtp_config)) => { Some(BackendConfig::Smtp(smtp_config)) => {
config.smtp = Some(smtp_config); config.smtp = Some(smtp_config);
config.message = Some(MessageConfig {
send: Some(MessageSendConfig { #[cfg(feature = "message-send")]
backend: Some(BackendKind::Smtp), {
config.message = Some(MessageConfig {
send: Some(MessageSendConfig {
backend: Some(BackendKind::Smtp),
..Default::default()
}),
..Default::default() ..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()
}),
..Default::default()
});
}
} }
_ => (), _ => (),
}; };
let should_configure_sync = Confirm::new() #[cfg(feature = "sync")]
.with_prompt(wizard_prompt!( {
"Do you need an offline access to your account?" let should_configure_sync = Confirm::new()
)) .with_prompt(wizard_prompt!(
.default(false) "Do you need an offline access to your account?"
.interact_opt()? ))
.unwrap_or_default(); .default(false)
.interact_opt()?
.unwrap_or_default();
if should_configure_sync { if should_configure_sync {
config.sync = Some(SyncConfig { config.sync = Some(SyncConfig {
enable: Some(true), enable: Some(true),
..Default::default() ..Default::default()
}); });
}
} }
Ok(Some((account_name, config))) Ok(Some((account_name, config)))

View file

@ -1,19 +1,24 @@
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::imap::config::ImapConfig; use email::imap::config::ImapConfig;
#[cfg(feature = "maildir")]
use email::maildir::config::MaildirConfig;
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
use email::notmuch::config::NotmuchConfig; use email::notmuch::config::NotmuchConfig;
#[cfg(feature = "sendmail")]
use email::sendmail::config::SendmailConfig;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::smtp::config::SmtpConfig; use email::smtp::config::SmtpConfig;
use email::{maildir::config::MaildirConfig, sendmail::config::SendmailConfig};
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum BackendConfig { pub enum BackendConfig {
Maildir(MaildirConfig),
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Imap(ImapConfig), Imap(ImapConfig),
#[cfg(feature = "maildir")]
Maildir(MaildirConfig),
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
Notmuch(NotmuchConfig), Notmuch(NotmuchConfig),
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Smtp(SmtpConfig), Smtp(SmtpConfig),
#[cfg(feature = "sendmail")]
Sendmail(SendmailConfig), Sendmail(SendmailConfig),
} }

View file

@ -5,76 +5,128 @@ use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
use std::ops::Deref; use std::ops::Deref;
use email::account::config::AccountConfig;
#[cfg(all(feature = "envelope-get", feature = "imap"))]
use email::envelope::get::imap::GetEnvelopeImap;
#[cfg(all(feature = "envelope-get", feature = "maildir"))]
use email::envelope::get::maildir::GetEnvelopeMaildir;
#[cfg(all(feature = "envelope-list", feature = "imap"))]
use email::envelope::list::imap::ListEnvelopesImap;
#[cfg(all(feature = "envelope-list", feature = "maildir"))]
use email::envelope::list::maildir::ListEnvelopesMaildir;
#[cfg(all(feature = "envelope-watch", feature = "imap"))]
use email::envelope::watch::imap::WatchImapEnvelopes;
#[cfg(all(feature = "envelope-watch", feature = "maildir"))]
use email::envelope::watch::maildir::WatchMaildirEnvelopes;
#[cfg(feature = "message-add")]
use email::envelope::SingleId;
#[cfg(all(feature = "flag-add", feature = "imap"))]
use email::flag::add::imap::AddFlagsImap;
#[cfg(all(feature = "flag-add", feature = "maildir"))]
use email::flag::add::maildir::AddFlagsMaildir;
#[cfg(all(feature = "flag-remove", feature = "imap"))]
use email::flag::remove::imap::RemoveFlagsImap;
#[cfg(all(feature = "flag-remove", feature = "maildir"))]
use email::flag::remove::maildir::RemoveFlagsMaildir;
#[cfg(all(feature = "flag-set", feature = "imap"))]
use email::flag::set::imap::SetFlagsImap;
#[cfg(all(feature = "flag-set", feature = "maildir"))]
use email::flag::set::maildir::SetFlagsMaildir;
#[cfg(all(feature = "folder-add", feature = "imap"))]
use email::folder::add::imap::AddFolderImap;
#[cfg(all(feature = "folder-add", feature = "maildir"))]
use email::folder::add::maildir::AddFolderMaildir;
#[cfg(all(feature = "folder-delete", feature = "imap"))]
use email::folder::delete::imap::DeleteFolderImap;
#[cfg(all(feature = "folder-delete", feature = "maildir"))]
use email::folder::delete::maildir::DeleteFolderMaildir;
#[cfg(all(feature = "folder-expunge", feature = "imap"))]
use email::folder::expunge::imap::ExpungeFolderImap;
#[cfg(all(feature = "folder-expunge", feature = "maildir"))]
use email::folder::expunge::maildir::ExpungeFolderMaildir;
#[cfg(all(feature = "folder-list", feature = "imap"))]
use email::folder::list::imap::ListFoldersImap;
#[cfg(all(feature = "folder-list", feature = "maildir"))]
use email::folder::list::maildir::ListFoldersMaildir;
#[cfg(all(feature = "folder-purge", feature = "imap"))]
use email::folder::purge::imap::PurgeFolderImap;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::imap::{ImapSessionBuilder, ImapSessionSync}; use email::imap::{ImapSessionBuilder, ImapSessionSync};
#[cfg(feature = "sync")]
use email::maildir::config::MaildirConfig;
#[cfg(feature = "maildir")]
use email::maildir::{MaildirSessionBuilder, MaildirSessionSync};
#[cfg(all(feature = "message-add", feature = "maildir"))]
use email::message::add_with_flags::maildir::AddMessageWithFlagsMaildir;
#[cfg(all(feature = "message-copy", feature = "imap"))]
use email::message::copy::imap::CopyMessagesImap;
#[cfg(all(feature = "message-copy", feature = "maildir"))]
use email::message::copy::maildir::CopyMessagesMaildir;
#[cfg(all(feature = "message-get", feature = "imap"))]
use email::message::get::imap::GetMessagesImap;
#[cfg(all(feature = "message-move", feature = "imap"))]
use email::message::move_::imap::MoveMessagesImap;
#[cfg(all(feature = "message-move", feature = "maildir"))]
use email::message::move_::maildir::MoveMessagesMaildir;
#[cfg(all(feature = "message-peek", feature = "imap"))]
use email::message::peek::imap::PeekMessagesImap;
#[cfg(all(feature = "message-peek", feature = "maildir"))]
use email::message::peek::maildir::PeekMessagesMaildir;
#[cfg(any(feature = "message-peek", feature = "message-get"))]
use email::message::Messages;
#[cfg(all(feature = "message-add", feature = "imap"))]
use email::message::{add::imap::AddMessageImap, add_with_flags::imap::AddMessageWithFlagsImap};
#[cfg(feature = "sendmail")]
use email::sendmail::SendmailContext;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::smtp::{SmtpClientBuilder, SmtpClientSync}; use email::smtp::{SmtpClientBuilder, SmtpClientSync};
#[cfg(any(feature = "flag-command"))]
use email::{ use email::{
account::config::AccountConfig, envelope::Id,
envelope::{ flag::{Flag, Flags},
get::{imap::GetEnvelopeImap, maildir::GetEnvelopeMaildir},
list::{imap::ListEnvelopesImap, maildir::ListEnvelopesMaildir},
watch::{imap::WatchImapEnvelopes, maildir::WatchMaildirEnvelopes},
Id, SingleId,
},
flag::{
add::{imap::AddFlagsImap, maildir::AddFlagsMaildir},
remove::{imap::RemoveFlagsImap, maildir::RemoveFlagsMaildir},
set::{imap::SetFlagsImap, maildir::SetFlagsMaildir},
Flag, Flags,
},
folder::{
add::{imap::AddFolderImap, maildir::AddFolderMaildir},
delete::{imap::DeleteFolderImap, maildir::DeleteFolderMaildir},
expunge::{imap::ExpungeFolderImap, maildir::ExpungeFolderMaildir},
list::{imap::ListFoldersImap, maildir::ListFoldersMaildir},
purge::imap::PurgeFolderImap,
},
maildir::{config::MaildirConfig, MaildirSessionBuilder, MaildirSessionSync},
message::{
add_raw::imap::AddRawMessageImap,
add_raw_with_flags::{
imap::AddRawMessageWithFlagsImap, maildir::AddRawMessageWithFlagsMaildir,
},
copy::{imap::CopyMessagesImap, maildir::CopyMessagesMaildir},
get::imap::GetMessagesImap,
move_::{imap::MoveMessagesImap, maildir::MoveMessagesMaildir},
peek::{imap::PeekMessagesImap, maildir::PeekMessagesMaildir},
Messages,
},
sendmail::SendmailContext,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{account::config::TomlAccountConfig, cache::IdMapper, envelope::Envelopes}; #[cfg(feature = "envelope-list")]
use crate::envelope::Envelopes;
use crate::{account::config::TomlAccountConfig, cache::IdMapper};
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum BackendKind { pub enum BackendKind {
Maildir,
#[serde(skip_deserializing)]
MaildirForSync,
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Imap, Imap,
#[cfg(feature = "maildir")]
Maildir,
#[cfg(feature = "sync")]
#[serde(skip_deserializing)]
MaildirForSync,
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
Notmuch, Notmuch,
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Smtp, Smtp,
#[cfg(feature = "sendmail")]
Sendmail, Sendmail,
None,
} }
impl ToString for BackendKind { impl ToString for BackendKind {
fn to_string(&self) -> String { fn to_string(&self) -> String {
let kind = match self { let kind = match self {
Self::Maildir => "Maildir",
Self::MaildirForSync => "Maildir",
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Self::Imap => "IMAP", Self::Imap => "IMAP",
#[cfg(feature = "maildir")]
Self::Maildir => "Maildir",
#[cfg(feature = "sync")]
Self::MaildirForSync => "Maildir",
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
Self::Notmuch => "Notmuch", Self::Notmuch => "Notmuch",
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Self::Smtp => "SMTP", Self::Smtp => "SMTP",
#[cfg(feature = "sendmail")]
Self::Sendmail => "Sendmail", Self::Sendmail => "Sendmail",
Self::None => "None",
}; };
kind.to_string() kind.to_string()
@ -83,34 +135,26 @@ impl ToString for BackendKind {
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct BackendContextBuilder { pub struct BackendContextBuilder {
pub maildir: Option<MaildirSessionBuilder>,
pub maildir_for_sync: Option<MaildirSessionBuilder>,
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
pub imap: Option<ImapSessionBuilder>, pub imap: Option<ImapSessionBuilder>,
#[cfg(feature = "maildir")]
pub maildir: Option<MaildirSessionBuilder>,
#[cfg(feature = "sync")]
pub maildir_for_sync: Option<MaildirSessionBuilder>,
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
pub smtp: Option<SmtpClientBuilder>, pub smtp: Option<SmtpClientBuilder>,
#[cfg(feature = "sendmail")]
pub sendmail: Option<SendmailContext>, pub sendmail: Option<SendmailContext>,
} }
impl BackendContextBuilder { impl BackendContextBuilder {
#[allow(unused)]
pub async fn new( pub async fn new(
toml_account_config: &TomlAccountConfig, toml_account_config: &TomlAccountConfig,
account_config: &AccountConfig, account_config: &AccountConfig,
kinds: Vec<&BackendKind>, kinds: Vec<&BackendKind>,
) -> Result<Self> { ) -> Result<Self> {
Ok(Self { Ok(Self {
maildir: toml_account_config
.maildir
.as_ref()
.filter(|_| kinds.contains(&&BackendKind::Maildir))
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
.filter(|_| kinds.contains(&&BackendKind::MaildirForSync))
.map(|mdir_config| MaildirSessionBuilder::new(account_config.clone(), mdir_config)),
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
imap: { imap: {
let ctx_builder = toml_account_config let ctx_builder = toml_account_config
@ -126,6 +170,20 @@ impl BackendContextBuilder {
None => None, None => None,
} }
}, },
#[cfg(feature = "maildir")]
maildir: toml_account_config
.maildir
.as_ref()
.filter(|_| kinds.contains(&&BackendKind::Maildir))
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
#[cfg(feature = "sync")]
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
.filter(|_| kinds.contains(&&BackendKind::MaildirForSync))
.map(|mdir_config| MaildirSessionBuilder::new(account_config.clone(), mdir_config)),
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
notmuch: toml_account_config notmuch: toml_account_config
.notmuch .notmuch
@ -159,21 +217,24 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder {
type Context = BackendContext; type Context = BackendContext;
async fn build(self) -> Result<Self::Context> { async fn build(self) -> Result<Self::Context> {
#[allow(unused_mut)]
let mut ctx = BackendContext::default(); let mut ctx = BackendContext::default();
if let Some(maildir) = self.maildir {
ctx.maildir = Some(maildir.build().await?);
}
if let Some(maildir) = self.maildir_for_sync {
ctx.maildir_for_sync = Some(maildir.build().await?);
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
if let Some(imap) = self.imap { if let Some(imap) = self.imap {
ctx.imap = Some(imap.build().await?); ctx.imap = Some(imap.build().await?);
} }
#[cfg(feature = "maildir")]
if let Some(maildir) = self.maildir {
ctx.maildir = Some(maildir.build().await?);
}
#[cfg(feature = "sync")]
if let Some(maildir) = self.maildir_for_sync {
ctx.maildir_for_sync = Some(maildir.build().await?);
}
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
if let Some(notmuch) = self.notmuch { if let Some(notmuch) = self.notmuch {
ctx.notmuch = Some(notmuch.build().await?); ctx.notmuch = Some(notmuch.build().await?);
@ -184,6 +245,7 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder {
ctx.smtp = Some(smtp.build().await?); ctx.smtp = Some(smtp.build().await?);
} }
#[cfg(feature = "sendmail")]
if let Some(sendmail) = self.sendmail { if let Some(sendmail) = self.sendmail {
ctx.sendmail = Some(sendmail.build().await?); ctx.sendmail = Some(sendmail.build().await?);
} }
@ -194,12 +256,15 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder {
#[derive(Default)] #[derive(Default)]
pub struct BackendContext { pub struct BackendContext {
pub maildir: Option<MaildirSessionSync>,
pub maildir_for_sync: Option<MaildirSessionSync>,
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
pub imap: Option<ImapSessionSync>, pub imap: Option<ImapSessionSync>,
#[cfg(feature = "maildir")]
pub maildir: Option<MaildirSessionSync>,
#[cfg(feature = "sync")]
pub maildir_for_sync: Option<MaildirSessionSync>,
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
pub smtp: Option<SmtpClientSync>, pub smtp: Option<SmtpClientSync>,
#[cfg(feature = "sendmail")]
pub sendmail: Option<SendmailContext>, pub sendmail: Option<SendmailContext>,
} }
@ -213,27 +278,17 @@ impl BackendBuilder {
toml_account_config: TomlAccountConfig, toml_account_config: TomlAccountConfig,
account_config: AccountConfig, account_config: AccountConfig,
) -> Result<Self> { ) -> Result<Self> {
#[allow(unused)]
let used_backends = toml_account_config.get_used_backends(); let used_backends = toml_account_config.get_used_backends();
let is_maildir_used = used_backends.contains(&BackendKind::Maildir);
let is_maildir_for_sync_used = used_backends.contains(&BackendKind::MaildirForSync);
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
let is_imap_used = used_backends.contains(&BackendKind::Imap); let is_imap_used = used_backends.contains(&BackendKind::Imap);
#[cfg(feature = "maildir")]
let is_maildir_used = used_backends.contains(&BackendKind::Maildir);
#[cfg(feature = "sync")]
let is_maildir_for_sync_used = used_backends.contains(&BackendKind::MaildirForSync);
let backend_ctx_builder = BackendContextBuilder { let backend_ctx_builder = BackendContextBuilder {
maildir: toml_account_config
.maildir
.as_ref()
.filter(|_| is_maildir_used)
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
.filter(|_| is_maildir_for_sync_used)
.map(|mdir_config| MaildirSessionBuilder::new(account_config.clone(), mdir_config)),
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
imap: { imap: {
let ctx_builder = toml_account_config let ctx_builder = toml_account_config
@ -250,17 +305,35 @@ impl BackendBuilder {
None => None, None => None,
} }
}, },
#[cfg(feature = "maildir")]
maildir: toml_account_config
.maildir
.as_ref()
.filter(|_| is_maildir_used)
.map(|mdir_config| {
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
}),
#[cfg(feature = "sync")]
maildir_for_sync: Some(MaildirConfig {
root_dir: account_config.get_sync_dir()?,
})
.filter(|_| is_maildir_for_sync_used)
.map(|mdir_config| MaildirSessionBuilder::new(account_config.clone(), mdir_config)),
..Default::default() ..Default::default()
}; };
#[allow(unused_mut)]
let mut backend_builder = let mut backend_builder =
email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder); email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder);
#[cfg(feature = "folder-add")]
match toml_account_config.add_folder_kind() { match toml_account_config.add_folder_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder backend_builder = backend_builder
.with_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new)); .with_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_folder(|ctx| { backend_builder = backend_builder.with_add_folder(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -281,12 +354,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "folder-list")]
match toml_account_config.list_folders_kind() { match toml_account_config.list_folders_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_list_folders(|ctx| { backend_builder = backend_builder.with_list_folders(|ctx| {
ctx.maildir.as_ref().and_then(ListFoldersMaildir::new) ctx.maildir.as_ref().and_then(ListFoldersMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_list_folders(|ctx| { backend_builder = backend_builder.with_list_folders(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -308,12 +384,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "folder-expunge")]
match toml_account_config.expunge_folder_kind() { match toml_account_config.expunge_folder_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_expunge_folder(|ctx| { backend_builder = backend_builder.with_expunge_folder(|ctx| {
ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new) ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_expunge_folder(|ctx| { backend_builder = backend_builder.with_expunge_folder(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -335,13 +414,16 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "folder-purge")]
match toml_account_config.purge_folder_kind() { match toml_account_config.purge_folder_kind() {
// TODO // TODO
// #[cfg(feature = "maildir")]
// Some(BackendKind::Maildir) => { // Some(BackendKind::Maildir) => {
// backend_builder = backend_builder // backend_builder = backend_builder
// .with_purge_folder(|ctx| ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new)); // .with_purge_folder(|ctx| ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new));
// } // }
// TODO // TODO
// #[cfg(feature = "sync")]
// Some(BackendKind::MaildirForSync) => { // Some(BackendKind::MaildirForSync) => {
// backend_builder = backend_builder // backend_builder = backend_builder
// .with_purge_folder(|ctx| ctx.maildir_for_sync.as_ref().and_then(PurgeFolderMaildir::new)); // .with_purge_folder(|ctx| ctx.maildir_for_sync.as_ref().and_then(PurgeFolderMaildir::new));
@ -360,12 +442,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "folder-delete")]
match toml_account_config.delete_folder_kind() { match toml_account_config.delete_folder_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_delete_folder(|ctx| { backend_builder = backend_builder.with_delete_folder(|ctx| {
ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new) ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_delete_folder(|ctx| { backend_builder = backend_builder.with_delete_folder(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -387,12 +472,45 @@ impl BackendBuilder {
_ => (), _ => (),
} }
match toml_account_config.backend { #[cfg(feature = "envelope-list")]
match toml_account_config.list_envelopes_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(ListEnvelopesMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
backend_builder = backend_builder
.with_list_envelopes(|ctx| ctx.imap.as_ref().and_then(ListEnvelopesImap::new));
}
#[cfg(feature = "notmuch")]
Some(BackendKind::Notmuch) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.notmuch.as_ref().and_then(ListEnvelopesNotmuch::new)
});
}
_ => (),
}
#[cfg(feature = "envelope-watch")]
match toml_account_config.watch_envelopes_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_watch_envelopes(|ctx| { backend_builder = backend_builder.with_watch_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(WatchMaildirEnvelopes::new) ctx.maildir.as_ref().and_then(WatchMaildirEnvelopes::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_watch_envelopes(|ctx| { backend_builder = backend_builder.with_watch_envelopes(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -415,12 +533,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "envelope-get")]
match toml_account_config.get_envelope_kind() { match toml_account_config.get_envelope_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_get_envelope(|ctx| { backend_builder = backend_builder.with_get_envelope(|ctx| {
ctx.maildir.as_ref().and_then(GetEnvelopeMaildir::new) ctx.maildir.as_ref().and_then(GetEnvelopeMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_get_envelope(|ctx| { backend_builder = backend_builder.with_get_envelope(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -442,38 +563,14 @@ impl BackendBuilder {
_ => (), _ => (),
} }
match toml_account_config.list_envelopes_kind() { #[cfg(feature = "flag-add")]
Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(ListEnvelopesMaildir::new)
});
}
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
backend_builder = backend_builder
.with_list_envelopes(|ctx| ctx.imap.as_ref().and_then(ListEnvelopesImap::new));
}
#[cfg(feature = "notmuch")]
Some(BackendKind::Notmuch) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.notmuch.as_ref().and_then(ListEnvelopesNotmuch::new)
});
}
_ => (),
}
match toml_account_config.add_flags_kind() { match toml_account_config.add_flags_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder backend_builder = backend_builder
.with_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .with_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_flags(|ctx| { backend_builder = backend_builder.with_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
@ -492,11 +589,14 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "flag-set")]
match toml_account_config.set_flags_kind() { match toml_account_config.set_flags_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder backend_builder = backend_builder
.with_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new)); .with_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_set_flags(|ctx| { backend_builder = backend_builder.with_set_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new)
@ -515,12 +615,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "flag-remove")]
match toml_account_config.remove_flags_kind() { match toml_account_config.remove_flags_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_remove_flags(|ctx| { backend_builder = backend_builder.with_remove_flags(|ctx| {
ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new) ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_remove_flags(|ctx| { backend_builder = backend_builder.with_remove_flags(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -542,29 +645,32 @@ impl BackendBuilder {
_ => (), _ => (),
} }
match toml_account_config.add_raw_message_kind() { #[cfg(feature = "message-add")]
Some(BackendKind::Maildir) => { match toml_account_config.add_message_kind() {
backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
.with_add_raw_message(|ctx| ctx.imap.as_ref().and_then(AddRawMessageImap::new)) .with_add_message(|ctx| ctx.imap.as_ref().and_then(AddMessageImap::new))
.with_add_raw_message_with_flags(|ctx| { .with_add_message_with_flags(|ctx| {
ctx.imap.as_ref().and_then(AddRawMessageWithFlagsImap::new) ctx.imap.as_ref().and_then(AddMessageWithFlagsImap::new)
}); });
} }
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_add_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
Some(BackendKind::Notmuch) => { Some(BackendKind::Notmuch) => {
backend_builder = backend_builder.with_add_raw_message(|ctx| { backend_builder = backend_builder.with_add_raw_message(|ctx| {
@ -574,12 +680,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "message-peek")]
match toml_account_config.peek_messages_kind() { match toml_account_config.peek_messages_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_peek_messages(|ctx| { backend_builder = backend_builder.with_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_peek_messages(|ctx| { backend_builder = backend_builder.with_peek_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -601,6 +710,7 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "message-get")]
match toml_account_config.get_messages_kind() { match toml_account_config.get_messages_kind() {
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
@ -616,12 +726,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "message-copy")]
match toml_account_config.copy_messages_kind() { match toml_account_config.copy_messages_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_copy_messages(|ctx| { backend_builder = backend_builder.with_copy_messages(|ctx| {
ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new) ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_copy_messages(|ctx| { backend_builder = backend_builder.with_copy_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -643,12 +756,15 @@ impl BackendBuilder {
_ => (), _ => (),
} }
#[cfg(feature = "message-move")]
match toml_account_config.move_messages_kind() { match toml_account_config.move_messages_kind() {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_move_messages(|ctx| { backend_builder = backend_builder.with_move_messages(|ctx| {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new) ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_move_messages(|ctx| { backend_builder = backend_builder.with_move_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -699,6 +815,7 @@ impl Into<email::backend::BackendBuilder<BackendContextBuilder>> for BackendBuil
} }
pub struct Backend { pub struct Backend {
#[allow(unused)]
toml_account_config: TomlAccountConfig, toml_account_config: TomlAccountConfig,
backend: email::backend::Backend<BackendContext>, backend: email::backend::Backend<BackendContext>,
} }
@ -724,14 +841,17 @@ impl Backend {
}) })
} }
#[allow(unused)]
fn build_id_mapper( fn build_id_mapper(
&self, &self,
folder: &str, folder: &str,
backend_kind: Option<&BackendKind>, backend_kind: Option<&BackendKind>,
) -> Result<IdMapper> { ) -> Result<IdMapper> {
#[allow(unused_mut)]
let mut id_mapper = IdMapper::Dummy; let mut id_mapper = IdMapper::Dummy;
match backend_kind { match backend_kind {
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
if let Some(mdir_config) = &self.toml_account_config.maildir { if let Some(mdir_config) = &self.toml_account_config.maildir {
id_mapper = IdMapper::new( id_mapper = IdMapper::new(
@ -741,6 +861,7 @@ impl Backend {
)?; )?;
} }
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
id_mapper = IdMapper::new( id_mapper = IdMapper::new(
&self.backend.account_config, &self.backend.account_config,
@ -764,6 +885,7 @@ impl Backend {
Ok(id_mapper) Ok(id_mapper)
} }
#[cfg(feature = "envelope-list")]
pub async fn list_envelopes( pub async fn list_envelopes(
&self, &self,
folder: &str, folder: &str,
@ -777,6 +899,7 @@ impl Backend {
Ok(envelopes) Ok(envelopes)
} }
#[cfg(feature = "flag-add")]
pub async fn add_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> { pub async fn add_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> {
let backend_kind = self.toml_account_config.add_flags_kind(); let backend_kind = self.toml_account_config.add_flags_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?; let id_mapper = self.build_id_mapper(folder, backend_kind)?;
@ -784,6 +907,15 @@ impl Backend {
self.backend.add_flags(folder, &ids, flags).await self.backend.add_flags(folder, &ids, flags).await
} }
#[cfg(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)?;
let ids = Id::multiple(id_mapper.get_ids(ids)?);
self.backend.add_flag(folder, &ids, flag).await
}
#[cfg(feature = "flag-set")]
pub async fn set_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> { pub async fn set_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> {
let backend_kind = self.toml_account_config.set_flags_kind(); let backend_kind = self.toml_account_config.set_flags_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?; let id_mapper = self.build_id_mapper(folder, backend_kind)?;
@ -791,6 +923,15 @@ impl Backend {
self.backend.set_flags(folder, &ids, flags).await self.backend.set_flags(folder, &ids, flags).await
} }
#[cfg(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)?;
let ids = Id::multiple(id_mapper.get_ids(ids)?);
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<()> { pub async fn remove_flags(&self, folder: &str, ids: &[usize], flags: &Flags) -> Result<()> {
let backend_kind = self.toml_account_config.remove_flags_kind(); let backend_kind = self.toml_account_config.remove_flags_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?; let id_mapper = self.build_id_mapper(folder, backend_kind)?;
@ -798,6 +939,24 @@ impl Backend {
self.backend.remove_flags(folder, &ids, flags).await 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)?;
let ids = Id::multiple(id_mapper.get_ids(ids)?);
self.backend.remove_flag(folder, &ids, flag).await
}
#[cfg(feature = "message-add")]
pub async fn add_message(&self, folder: &str, email: &[u8]) -> Result<SingleId> {
let backend_kind = self.toml_account_config.add_message_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?;
let id = self.backend.add_message(folder, email).await?;
id_mapper.create_alias(&*id)?;
Ok(id)
}
#[cfg(feature = "message-peek")]
pub async fn peek_messages(&self, folder: &str, ids: &[usize]) -> Result<Messages> { pub async fn peek_messages(&self, folder: &str, ids: &[usize]) -> Result<Messages> {
let backend_kind = self.toml_account_config.get_messages_kind(); let backend_kind = self.toml_account_config.get_messages_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?; let id_mapper = self.build_id_mapper(folder, backend_kind)?;
@ -805,6 +964,7 @@ impl Backend {
self.backend.peek_messages(folder, &ids).await self.backend.peek_messages(folder, &ids).await
} }
#[cfg(feature = "message-get")]
pub async fn get_messages(&self, folder: &str, ids: &[usize]) -> Result<Messages> { pub async fn get_messages(&self, folder: &str, ids: &[usize]) -> Result<Messages> {
let backend_kind = self.toml_account_config.get_messages_kind(); let backend_kind = self.toml_account_config.get_messages_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?; let id_mapper = self.build_id_mapper(folder, backend_kind)?;
@ -812,6 +972,7 @@ impl Backend {
self.backend.get_messages(folder, &ids).await self.backend.get_messages(folder, &ids).await
} }
#[cfg(feature = "message-copy")]
pub async fn copy_messages( pub async fn copy_messages(
&self, &self,
from_folder: &str, from_folder: &str,
@ -826,6 +987,7 @@ impl Backend {
.await .await
} }
#[cfg(feature = "message-move")]
pub async fn move_messages( pub async fn move_messages(
&self, &self,
from_folder: &str, from_folder: &str,
@ -840,41 +1002,13 @@ impl Backend {
.await .await
} }
#[cfg(feature = "message-delete")]
pub async fn delete_messages(&self, folder: &str, ids: &[usize]) -> Result<()> { pub async fn delete_messages(&self, folder: &str, ids: &[usize]) -> Result<()> {
let backend_kind = self.toml_account_config.delete_messages_kind(); let backend_kind = self.toml_account_config.delete_messages_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?; let id_mapper = self.build_id_mapper(folder, backend_kind)?;
let ids = Id::multiple(id_mapper.get_ids(ids)?); let ids = Id::multiple(id_mapper.get_ids(ids)?);
self.backend.delete_messages(folder, &ids).await self.backend.delete_messages(folder, &ids).await
} }
pub async fn add_raw_message(&self, folder: &str, email: &[u8]) -> Result<SingleId> {
let backend_kind = self.toml_account_config.add_raw_message_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?;
let id = self.backend.add_raw_message(folder, email).await?;
id_mapper.create_alias(&*id)?;
Ok(id)
}
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)?;
let ids = Id::multiple(id_mapper.get_ids(ids)?);
self.backend.add_flag(folder, &ids, flag).await
}
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)?;
let ids = Id::multiple(id_mapper.get_ids(ids)?);
self.backend.set_flag(folder, &ids, flag).await
}
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)?;
let ids = Id::multiple(id_mapper.get_ids(ids)?);
self.backend.remove_flag(folder, &ids, flag).await
}
} }
impl Deref for Backend { impl Deref for Backend {

View file

@ -1,19 +1,24 @@
use anyhow::Result; use anyhow::Result;
use dialoguer::Select; use dialoguer::Select;
use crate::config::wizard::THEME;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use crate::imap; use crate::imap;
#[cfg(feature = "maildir")]
use crate::maildir;
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
use crate::notmuch; use crate::notmuch;
#[cfg(feature = "sendmail")]
use crate::sendmail;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use crate::smtp; use crate::smtp;
use crate::{config::wizard::THEME, maildir, sendmail};
use super::{config::BackendConfig, BackendKind}; use super::{config::BackendConfig, BackendKind};
const DEFAULT_BACKEND_KINDS: &[BackendKind] = &[ const DEFAULT_BACKEND_KINDS: &[BackendKind] = &[
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
BackendKind::Imap, BackendKind::Imap,
#[cfg(feature = "maildir")]
BackendKind::Maildir, BackendKind::Maildir,
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
BackendKind::Notmuch, BackendKind::Notmuch,
@ -22,10 +27,14 @@ const DEFAULT_BACKEND_KINDS: &[BackendKind] = &[
const SEND_MESSAGE_BACKEND_KINDS: &[BackendKind] = &[ const SEND_MESSAGE_BACKEND_KINDS: &[BackendKind] = &[
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
BackendKind::Smtp, BackendKind::Smtp,
#[cfg(feature = "sendmail")]
BackendKind::Sendmail, BackendKind::Sendmail,
]; ];
pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Option<BackendConfig>> { pub(crate) async fn configure(
#[allow(unused)] account_name: &str,
#[allow(unused)] email: &str,
) -> Result<Option<BackendConfig>> {
let kind = Select::with_theme(&*THEME) let kind = Select::with_theme(&*THEME)
.with_prompt("Default email backend") .with_prompt("Default email backend")
.items(DEFAULT_BACKEND_KINDS) .items(DEFAULT_BACKEND_KINDS)
@ -34,11 +43,12 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Option<
.and_then(|idx| DEFAULT_BACKEND_KINDS.get(idx).map(Clone::clone)); .and_then(|idx| DEFAULT_BACKEND_KINDS.get(idx).map(Clone::clone));
let config = match kind { let config = match kind {
Some(kind) if kind == BackendKind::Maildir => Some(maildir::wizard::configure()?),
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(kind) if kind == BackendKind::Imap => { Some(kind) if kind == BackendKind::Imap => {
Some(imap::wizard::configure(account_name, email).await?) Some(imap::wizard::configure(account_name, email).await?)
} }
#[cfg(feature = "maildir")]
Some(kind) if kind == BackendKind::Maildir => Some(maildir::wizard::configure()?),
#[cfg(feature = "notmuch")] #[cfg(feature = "notmuch")]
Some(kind) if kind == BackendKind::Notmuch => Some(notmuch::wizard::configure()?), Some(kind) if kind == BackendKind::Notmuch => Some(notmuch::wizard::configure()?),
_ => None, _ => None,
@ -48,8 +58,8 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Option<
} }
pub(crate) async fn configure_sender( pub(crate) async fn configure_sender(
account_name: &str, #[allow(unused)] account_name: &str,
email: &str, #[allow(unused)] email: &str,
) -> Result<Option<BackendConfig>> { ) -> Result<Option<BackendConfig>> {
let kind = Select::with_theme(&*THEME) let kind = Select::with_theme(&*THEME)
.with_prompt("Backend for sending messages") .with_prompt("Backend for sending messages")
@ -59,11 +69,12 @@ pub(crate) async fn configure_sender(
.and_then(|idx| SEND_MESSAGE_BACKEND_KINDS.get(idx).map(Clone::clone)); .and_then(|idx| SEND_MESSAGE_BACKEND_KINDS.get(idx).map(Clone::clone));
let config = match kind { let config = match kind {
Some(kind) if kind == BackendKind::Sendmail => Some(sendmail::wizard::configure()?),
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(kind) if kind == BackendKind::Smtp => { Some(kind) if kind == BackendKind::Smtp => {
Some(smtp::wizard::configure(account_name, email).await?) Some(smtp::wizard::configure(account_name, email).await?)
} }
#[cfg(feature = "sendmail")]
Some(kind) if kind == BackendKind::Sendmail => Some(sendmail::wizard::configure()?),
_ => None, _ => None,
}; };

View file

@ -2,18 +2,25 @@ use anyhow::Result;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use std::path::PathBuf; use std::path::PathBuf;
#[cfg(feature = "account-command")]
use crate::account::command::AccountSubcommand;
#[cfg(feature = "envelope-command")]
use crate::envelope::command::EnvelopeSubcommand;
#[cfg(feature = "flag-command")]
use crate::flag::command::FlagSubcommand;
#[cfg(feature = "folder-command")]
use crate::folder::command::FolderSubcommand;
#[cfg(feature = "attachment-command")]
use crate::message::attachment::command::AttachmentSubcommand;
#[cfg(feature = "message-command")]
use crate::message::command::MessageSubcommand;
#[cfg(feature = "template-command")]
use crate::message::template::command::TemplateSubcommand;
#[allow(unused)]
use crate::{ use crate::{
account::command::AccountSubcommand,
completion::command::CompletionGenerateCommand, completion::command::CompletionGenerateCommand,
config::{self, TomlConfig}, config::{self, TomlConfig},
envelope::command::EnvelopeSubcommand,
flag::command::FlagSubcommand,
folder::command::FolderSubcommand,
manual::command::ManualGenerateCommand, manual::command::ManualGenerateCommand,
message::{
attachment::command::AttachmentSubcommand, command::MessageSubcommand,
template::command::TemplateSubcommand,
},
output::{ColorFmt, OutputFmt}, output::{ColorFmt, OutputFmt},
printer::Printer, printer::Printer,
}; };
@ -22,8 +29,12 @@ use crate::{
#[command(name = "himalaya", author, version, about)] #[command(name = "himalaya", author, version, about)]
#[command(propagate_version = true, infer_subcommands = true)] #[command(propagate_version = true, infer_subcommands = true)]
pub struct Cli { pub struct Cli {
#[cfg(feature = "envelope-list")]
#[command(subcommand)] #[command(subcommand)]
pub command: Option<HimalayaCommand>, pub command: Option<HimalayaCommand>,
#[cfg(not(feature = "envelope-list"))]
#[command(subcommand)]
pub command: HimalayaCommand,
/// Override the default configuration file path /// Override the default configuration file path
/// ///
@ -77,31 +88,38 @@ pub struct Cli {
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
pub enum HimalayaCommand { pub enum HimalayaCommand {
#[cfg(feature = "account-command")]
#[command(subcommand)] #[command(subcommand)]
#[command(alias = "accounts")] #[command(alias = "accounts")]
Account(AccountSubcommand), Account(AccountSubcommand),
#[cfg(feature = "folder-command")]
#[command(subcommand)] #[command(subcommand)]
#[command(visible_alias = "mailbox", aliases = ["mailboxes", "mboxes", "mbox"])] #[command(visible_alias = "mailbox", aliases = ["mailboxes", "mboxes", "mbox"])]
#[command(alias = "folders")] #[command(alias = "folders")]
Folder(FolderSubcommand), Folder(FolderSubcommand),
#[cfg(feature = "envelope-command")]
#[command(subcommand)] #[command(subcommand)]
#[command(alias = "envelopes")] #[command(alias = "envelopes")]
Envelope(EnvelopeSubcommand), Envelope(EnvelopeSubcommand),
#[cfg(feature = "flag-command")]
#[command(subcommand)] #[command(subcommand)]
#[command(alias = "flags")] #[command(alias = "flags")]
Flag(FlagSubcommand), Flag(FlagSubcommand),
#[cfg(feature = "message-command")]
#[command(subcommand)] #[command(subcommand)]
#[command(alias = "messages", alias = "msgs", alias = "msg")] #[command(alias = "messages", alias = "msgs", alias = "msg")]
Message(MessageSubcommand), Message(MessageSubcommand),
#[cfg(feature = "attachment-command")]
#[command(subcommand)] #[command(subcommand)]
#[command(alias = "attachments")] #[command(alias = "attachments")]
Attachment(AttachmentSubcommand), Attachment(AttachmentSubcommand),
#[cfg(feature = "template-command")]
#[command(subcommand)] #[command(subcommand)]
#[command(alias = "templates", alias = "tpls", alias = "tpl")] #[command(alias = "templates", alias = "tpls", alias = "tpl")]
Template(TemplateSubcommand), Template(TemplateSubcommand),
@ -116,36 +134,44 @@ pub enum HimalayaCommand {
} }
impl HimalayaCommand { impl HimalayaCommand {
#[allow(unused)]
pub async fn execute( pub async fn execute(
self, self,
printer: &mut impl Printer, printer: &mut impl Printer,
config_path: Option<&PathBuf>, config_path: Option<&PathBuf>,
) -> Result<()> { ) -> Result<()> {
match self { match self {
#[cfg(feature = "account-command")]
Self::Account(cmd) => { Self::Account(cmd) => {
let config = TomlConfig::from_some_path_or_default(config_path).await?; let config = TomlConfig::from_some_path_or_default(config_path).await?;
cmd.execute(printer, &config).await cmd.execute(printer, &config).await
} }
#[cfg(feature = "folder-command")]
Self::Folder(cmd) => { Self::Folder(cmd) => {
let config = TomlConfig::from_some_path_or_default(config_path).await?; let config = TomlConfig::from_some_path_or_default(config_path).await?;
cmd.execute(printer, &config).await cmd.execute(printer, &config).await
} }
#[cfg(feature = "envelope-command")]
Self::Envelope(cmd) => { Self::Envelope(cmd) => {
let config = TomlConfig::from_some_path_or_default(config_path).await?; let config = TomlConfig::from_some_path_or_default(config_path).await?;
cmd.execute(printer, &config).await cmd.execute(printer, &config).await
} }
#[cfg(feature = "flag-command")]
Self::Flag(cmd) => { Self::Flag(cmd) => {
let config = TomlConfig::from_some_path_or_default(config_path).await?; let config = TomlConfig::from_some_path_or_default(config_path).await?;
cmd.execute(printer, &config).await cmd.execute(printer, &config).await
} }
#[cfg(feature = "message-command")]
Self::Message(cmd) => { Self::Message(cmd) => {
let config = TomlConfig::from_some_path_or_default(config_path).await?; let config = TomlConfig::from_some_path_or_default(config_path).await?;
cmd.execute(printer, &config).await cmd.execute(printer, &config).await
} }
#[cfg(feature = "attachment-command")]
Self::Attachment(cmd) => { Self::Attachment(cmd) => {
let config = TomlConfig::from_some_path_or_default(config_path).await?; let config = TomlConfig::from_some_path_or_default(config_path).await?;
cmd.execute(printer, &config).await cmd.execute(printer, &config).await
} }
#[cfg(feature = "template-command")]
Self::Template(cmd) => { Self::Template(cmd) => {
let config = TomlConfig::from_some_path_or_default(config_path).await?; let config = TomlConfig::from_some_path_or_default(config_path).await?;
cmd.execute(printer, &config).await cmd.execute(printer, &config).await

View file

@ -8,6 +8,7 @@ use email::{
account::config::AccountConfig, config::Config, envelope::config::EnvelopeConfig, account::config::AccountConfig, config::Config, envelope::config::EnvelopeConfig,
folder::config::FolderConfig, message::config::MessageConfig, folder::config::FolderConfig, message::config::MessageConfig,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use shellexpand_utils::{canonicalize, expand}; use shellexpand_utils::{canonicalize, expand};
use std::{ use std::{
@ -18,7 +19,9 @@ use std::{
}; };
use toml; use toml;
use crate::{account::config::TomlAccountConfig, backend::BackendKind, wizard_prompt, wizard_warn}; #[cfg(feature = "sync")]
use crate::backend::BackendKind;
use crate::{account::config::TomlAccountConfig, wizard_prompt, wizard_warn};
/// Represents the user config file. /// Represents the user config file.
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
@ -132,6 +135,7 @@ impl TomlConfig {
&self, &self,
account_name: Option<&str>, account_name: Option<&str>,
) -> Result<(String, TomlAccountConfig)> { ) -> Result<(String, TomlAccountConfig)> {
#[allow(unused_mut)]
let (account_name, mut toml_account_config) = match account_name { let (account_name, mut toml_account_config) = match account_name {
Some("default") | Some("") | None => self Some("default") | Some("") | None => self
.accounts .accounts
@ -171,11 +175,13 @@ impl TomlConfig {
pub fn into_account_configs( pub fn into_account_configs(
self, self,
account_name: Option<&str>, account_name: Option<&str>,
disable_cache: bool, #[cfg(feature = "sync")] disable_cache: bool,
) -> Result<(TomlAccountConfig, AccountConfig)> { ) -> Result<(TomlAccountConfig, AccountConfig)> {
#[cfg_attr(not(feature = "sync"), allow(unused_mut))]
let (account_name, mut toml_account_config) = let (account_name, mut toml_account_config) =
self.into_toml_account_config(account_name)?; self.into_toml_account_config(account_name)?;
#[cfg(feature = "sync")]
if let Some(true) = toml_account_config.sync.as_ref().and_then(|c| c.enable) { if let Some(true) = toml_account_config.sync.as_ref().and_then(|c| c.enable) {
if !disable_cache { if !disable_cache {
toml_account_config.backend = Some(BackendKind::MaildirForSync); toml_account_config.backend = Some(BackendKind::MaildirForSync);
@ -200,19 +206,29 @@ impl TomlConfig {
signature_delim: config.signature_delim, signature_delim: config.signature_delim,
downloads_dir: config.downloads_dir, downloads_dir: config.downloads_dir,
folder: config.folder.map(|c| FolderConfig { folder: config.folder.map(|#[allow(unused)] c| FolderConfig {
aliases: c.alias, aliases: c.alias,
#[cfg(feature = "folder-list")]
list: c.list.map(|c| c.remote), list: c.list.map(|c| c.remote),
..Default::default()
}), }),
envelope: config.envelope.map(|c| EnvelopeConfig { envelope: config.envelope.map(|#[allow(unused)] c| EnvelopeConfig {
#[cfg(feature = "envelope-list")]
list: c.list.map(|c| c.remote), list: c.list.map(|c| c.remote),
#[cfg(feature = "envelope-watch")]
watch: c.watch.map(|c| c.remote), watch: c.watch.map(|c| c.remote),
..Default::default()
}), }),
message: config.message.map(|c| MessageConfig { message: config.message.map(|#[allow(unused)] c| MessageConfig {
#[cfg(feature = "message-read")]
read: c.read.map(|c| c.remote), read: c.read.map(|c| c.remote),
#[cfg(feature = "message-write")]
write: c.write.map(|c| c.remote), write: c.write.map(|c| c.remote),
#[cfg(feature = "message-send")]
send: c.send.map(|c| c.remote), send: c.send.map(|c| c.remote),
..Default::default()
}), }),
#[cfg(feature = "sync")]
sync: config.sync, sync: config.sync,
#[cfg(feature = "pgp")] #[cfg(feature = "pgp")]
pgp: config.pgp, pgp: config.pgp,

View file

@ -172,6 +172,7 @@ fn set_tables_dotted<'a>(item: &'a mut Item, keys: impl IntoIterator<Item = &'a
} }
} }
#[allow(unused)]
pub(crate) fn prompt_passwd(prompt: &str) -> io::Result<String> { pub(crate) fn prompt_passwd(prompt: &str) -> io::Result<String> {
Password::with_theme(&*THEME) Password::with_theme(&*THEME)
.with_prompt(prompt) .with_prompt(prompt)
@ -182,6 +183,7 @@ pub(crate) fn prompt_passwd(prompt: &str) -> io::Result<String> {
.interact() .interact()
} }
#[allow(unused)]
pub(crate) fn prompt_secret(prompt: &str) -> io::Result<String> { pub(crate) fn prompt_secret(prompt: &str) -> io::Result<String> {
Password::with_theme(&*THEME) Password::with_theme(&*THEME)
.with_prompt(prompt) .with_prompt(prompt)

View file

@ -8,10 +8,11 @@ use email::envelope::list::maildir::ListEnvelopesMaildir;
use email::envelope::list::notmuch::ListEnvelopesNotmuch; use email::envelope::list::notmuch::ListEnvelopesNotmuch;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
folder::arg::name::FolderNameOptionalArg, folder::arg::name::FolderNameOptionalArg,
printer::{PrintTableOpts, Printer}, printer::{PrintTableOpts, Printer},
@ -43,6 +44,7 @@ pub struct ListEnvelopesCommand {
#[command(flatten)] #[command(flatten)]
pub table: TableMaxWidthFlag, pub table: TableMaxWidthFlag,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -57,6 +59,7 @@ impl Default for ListEnvelopesCommand {
page: 1, page: 1,
page_size: Default::default(), page_size: Default::default(),
table: Default::default(), table: Default::default(),
#[cfg(feature = "sync")]
cache: Default::default(), cache: Default::default(),
account: Default::default(), account: Default::default(),
} }
@ -69,6 +72,7 @@ impl ListEnvelopesCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -85,11 +89,19 @@ impl ListEnvelopesCommand {
&account_config, &account_config,
list_envelopes_kind, list_envelopes_kind,
|builder| match list_envelopes_kind { |builder| match list_envelopes_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_list_envelopes(|ctx| {
ctx.imap.as_ref().and_then(ListEnvelopesImap::new)
});
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_list_envelopes(|ctx| { builder.set_list_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new) ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_list_envelopes(|ctx| { builder.set_list_envelopes(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -97,12 +109,6 @@ impl ListEnvelopesCommand {
.and_then(ListEnvelopesMaildir::new) .and_then(ListEnvelopesMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_list_envelopes(|ctx| {
ctx.imap.as_ref().and_then(ListEnvelopesImap::new)
});
}
_ => (), _ => (),
}, },
) )

View file

@ -1,4 +1,6 @@
#[cfg(feature = "envelope-list")]
pub mod list; pub mod list;
#[cfg(feature = "envelope-watch")]
pub mod watch; pub mod watch;
use anyhow::Result; use anyhow::Result;
@ -6,7 +8,10 @@ use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer}; use crate::{config::TomlConfig, printer::Printer};
use self::{list::ListEnvelopesCommand, watch::WatchEnvelopesCommand}; #[cfg(feature = "envelope-list")]
use self::list::ListEnvelopesCommand;
#[cfg(feature = "envelope-watch")]
use self::watch::WatchEnvelopesCommand;
/// Manage envelopes. /// Manage envelopes.
/// ///
@ -16,17 +21,22 @@ use self::{list::ListEnvelopesCommand, watch::WatchEnvelopesCommand};
/// manage them. /// manage them.
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum EnvelopeSubcommand { pub enum EnvelopeSubcommand {
#[cfg(feature = "envelope-list")]
#[command(alias = "lst")] #[command(alias = "lst")]
List(ListEnvelopesCommand), List(ListEnvelopesCommand),
#[cfg(feature = "envelope-watch")]
#[command()] #[command()]
Watch(WatchEnvelopesCommand), Watch(WatchEnvelopesCommand),
} }
impl EnvelopeSubcommand { impl EnvelopeSubcommand {
#[allow(unused)]
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self { match self {
#[cfg(feature = "envelope-list")]
Self::List(cmd) => cmd.execute(printer, config).await, Self::List(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "envelope-watch")]
Self::Watch(cmd) => cmd.execute(printer, config).await, Self::Watch(cmd) => cmd.execute(printer, config).await,
} }
} }

View file

@ -8,10 +8,11 @@ use email::envelope::watch::maildir::WatchMaildirEnvelopes;
use email::envelope::watch::notmuch::WatchNotmuchEnvelopes; use email::envelope::watch::notmuch::WatchNotmuchEnvelopes;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
printer::Printer, printer::Printer,
@ -26,6 +27,7 @@ pub struct WatchEnvelopesCommand {
#[command(flatten)] #[command(flatten)]
pub folder: FolderNameOptionalFlag, pub folder: FolderNameOptionalFlag,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -40,6 +42,7 @@ impl WatchEnvelopesCommand {
let folder = &self.folder.name; let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -50,11 +53,19 @@ impl WatchEnvelopesCommand {
&account_config, &account_config,
watch_envelopes_kind, watch_envelopes_kind,
|builder| match watch_envelopes_kind { |builder| match watch_envelopes_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_watch_envelopes(|ctx| {
ctx.imap.as_ref().and_then(WatchImapEnvelopes::new)
});
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_watch_envelopes(|ctx| { builder.set_watch_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(WatchMaildirEnvelopes::new) ctx.maildir.as_ref().and_then(WatchMaildirEnvelopes::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_watch_envelopes(|ctx| { builder.set_watch_envelopes(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -62,12 +73,6 @@ impl WatchEnvelopesCommand {
.and_then(WatchMaildirEnvelopes::new) .and_then(WatchMaildirEnvelopes::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_watch_envelopes(|ctx| {
ctx.imap.as_ref().and_then(WatchImapEnvelopes::new)
});
}
_ => (), _ => (),
}, },
) )

View file

@ -5,31 +5,39 @@ use crate::backend::BackendKind;
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct EnvelopeConfig { pub struct EnvelopeConfig {
#[cfg(feature = "envelope-list")]
pub list: Option<ListEnvelopesConfig>, pub list: Option<ListEnvelopesConfig>,
#[cfg(feature = "envelope-watch")]
pub watch: Option<WatchEnvelopesConfig>, pub watch: Option<WatchEnvelopesConfig>,
#[cfg(feature = "envelope-get")]
pub get: Option<GetEnvelopeConfig>, pub get: Option<GetEnvelopeConfig>,
} }
impl EnvelopeConfig { impl EnvelopeConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
#[allow(unused_mut)]
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
#[cfg(feature = "envelope-list")]
if let Some(list) = &self.list { if let Some(list) = &self.list {
kinds.extend(list.get_used_backends()); kinds.extend(list.get_used_backends());
} }
if let Some(get) = &self.get { #[cfg(feature = "envelope-watch")]
kinds.extend(get.get_used_backends());
}
if let Some(watch) = &self.watch { if let Some(watch) = &self.watch {
kinds.extend(watch.get_used_backends()); kinds.extend(watch.get_used_backends());
} }
#[cfg(feature = "envelope-get")]
if let Some(get) = &self.get {
kinds.extend(get.get_used_backends());
}
kinds kinds
} }
} }
#[cfg(feature = "envelope-list")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct ListEnvelopesConfig { pub struct ListEnvelopesConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
@ -38,6 +46,7 @@ pub struct ListEnvelopesConfig {
pub remote: email::envelope::list::config::EnvelopeListConfig, pub remote: email::envelope::list::config::EnvelopeListConfig,
} }
#[cfg(feature = "envelope-list")]
impl ListEnvelopesConfig { impl ListEnvelopesConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -50,6 +59,7 @@ impl ListEnvelopesConfig {
} }
} }
#[cfg(feature = "envelope-watch")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct WatchEnvelopesConfig { pub struct WatchEnvelopesConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
@ -58,6 +68,7 @@ pub struct WatchEnvelopesConfig {
pub remote: email::envelope::watch::config::WatchEnvelopeConfig, pub remote: email::envelope::watch::config::WatchEnvelopeConfig,
} }
#[cfg(feature = "envelope-watch")]
impl WatchEnvelopesConfig { impl WatchEnvelopesConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -70,11 +81,13 @@ impl WatchEnvelopesConfig {
} }
} }
#[cfg(feature = "envelope-get")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct GetEnvelopeConfig { pub struct GetEnvelopeConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "envelope-get")]
impl GetEnvelopeConfig { impl GetEnvelopeConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();

View file

@ -8,10 +8,11 @@ use email::flag::add::maildir::AddFlagsMaildir;
use email::flag::add::notmuch::AddFlagsNotmuch; use email::flag::add::notmuch::AddFlagsNotmuch;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs}, flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -30,6 +31,7 @@ pub struct FlagAddCommand {
#[command(flatten)] #[command(flatten)]
pub args: IdsAndFlagsArgs, pub args: IdsAndFlagsArgs,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -45,6 +47,7 @@ impl FlagAddCommand {
let (ids, flags) = into_tuple(&self.args.ids_and_flags); let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -55,19 +58,21 @@ impl FlagAddCommand {
&account_config, &account_config,
add_flags_kind, add_flags_kind,
|builder| match add_flags_kind { |builder| match add_flags_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_flags(|ctx| ctx.imap.as_ref().and_then(AddFlagsImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_add_flags(|ctx| { builder.set_add_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_flags(|ctx| ctx.imap.as_ref().and_then(AddFlagsImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -1,5 +1,8 @@
#[cfg(feature = "flag-add")]
mod add; mod add;
#[cfg(feature = "flag-remove")]
mod remove; mod remove;
#[cfg(feature = "flag-set")]
mod set; mod set;
use anyhow::Result; use anyhow::Result;
@ -7,7 +10,12 @@ use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer}; use crate::{config::TomlConfig, printer::Printer};
use self::{add::FlagAddCommand, remove::FlagRemoveCommand, set::FlagSetCommand}; #[cfg(feature = "flag-add")]
use self::add::FlagAddCommand;
#[cfg(feature = "flag-remove")]
use self::remove::FlagRemoveCommand;
#[cfg(feature = "flag-set")]
use self::set::FlagSetCommand;
/// Manage flags. /// Manage flags.
/// ///
@ -17,24 +25,31 @@ use self::{add::FlagAddCommand, remove::FlagRemoveCommand, set::FlagSetCommand};
/// synchronization does not take care of them yet). /// synchronization does not take care of them yet).
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum FlagSubcommand { pub enum FlagSubcommand {
#[cfg(feature = "flag-add")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
#[command(alias = "create")] #[command(alias = "create")]
Add(FlagAddCommand), Add(FlagAddCommand),
#[cfg(feature = "flag-set")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
#[command(aliases = ["update", "change", "replace"])] #[command(aliases = ["update", "change", "replace"])]
Set(FlagSetCommand), Set(FlagSetCommand),
#[cfg(feature = "flag-remove")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
#[command(aliases = ["rm", "delete", "del"])] #[command(aliases = ["rm", "delete", "del"])]
Remove(FlagRemoveCommand), Remove(FlagRemoveCommand),
} }
impl FlagSubcommand { impl FlagSubcommand {
#[allow(unused)]
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self { match self {
#[cfg(feature = "flag-add")]
Self::Add(cmd) => cmd.execute(printer, config).await, Self::Add(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "flag-set")]
Self::Set(cmd) => cmd.execute(printer, config).await, Self::Set(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "flag-remove")]
Self::Remove(cmd) => cmd.execute(printer, config).await, Self::Remove(cmd) => cmd.execute(printer, config).await,
} }
} }

View file

@ -8,10 +8,11 @@ use email::flag::remove::maildir::RemoveFlagsMaildir;
use email::flag::remove::notmuch::RemoveFlagsNotmuch; use email::flag::remove::notmuch::RemoveFlagsNotmuch;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs}, flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -30,6 +31,7 @@ pub struct FlagRemoveCommand {
#[command(flatten)] #[command(flatten)]
pub args: IdsAndFlagsArgs, pub args: IdsAndFlagsArgs,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -45,6 +47,7 @@ impl FlagRemoveCommand {
let (ids, flags) = into_tuple(&self.args.ids_and_flags); let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -55,11 +58,18 @@ impl FlagRemoveCommand {
&account_config, &account_config,
remove_flags_kind, remove_flags_kind,
|builder| match remove_flags_kind { |builder| match remove_flags_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_remove_flags(|ctx| ctx.imap.as_ref().and_then(RemoveFlagsImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_remove_flags(|ctx| { builder.set_remove_flags(|ctx| {
ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new) ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_remove_flags(|ctx| { builder.set_remove_flags(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -67,11 +77,6 @@ impl FlagRemoveCommand {
.and_then(RemoveFlagsMaildir::new) .and_then(RemoveFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_remove_flags(|ctx| ctx.imap.as_ref().and_then(RemoveFlagsImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -8,10 +8,11 @@ use email::flag::set::maildir::SetFlagsMaildir;
use email::flag::set::notmuch::SetFlagsNotmuch; use email::flag::set::notmuch::SetFlagsNotmuch;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs}, flag::arg::ids_and_flags::{into_tuple, IdsAndFlagsArgs},
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -30,6 +31,7 @@ pub struct FlagSetCommand {
#[command(flatten)] #[command(flatten)]
pub args: IdsAndFlagsArgs, pub args: IdsAndFlagsArgs,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -45,6 +47,7 @@ impl FlagSetCommand {
let (ids, flags) = into_tuple(&self.args.ids_and_flags); let (ids, flags) = into_tuple(&self.args.ids_and_flags);
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -55,19 +58,21 @@ impl FlagSetCommand {
&account_config, &account_config,
set_flags_kind, set_flags_kind,
|builder| match set_flags_kind { |builder| match set_flags_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_set_flags(|ctx| ctx.imap.as_ref().and_then(SetFlagsImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder builder
.set_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new)); .set_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_set_flags(|ctx| { builder.set_set_flags(|ctx| {
ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_set_flags(|ctx| ctx.imap.as_ref().and_then(SetFlagsImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -5,23 +5,30 @@ use crate::backend::BackendKind;
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FlagConfig { pub struct FlagConfig {
#[cfg(feature = "flag-add")]
pub add: Option<FlagAddConfig>, pub add: Option<FlagAddConfig>,
#[cfg(feature = "flag-set")]
pub set: Option<FlagSetConfig>, pub set: Option<FlagSetConfig>,
#[cfg(feature = "flag-remove")]
pub remove: Option<FlagRemoveConfig>, pub remove: Option<FlagRemoveConfig>,
} }
impl FlagConfig { impl FlagConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
#[allow(unused_mut)]
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
#[cfg(feature = "flag-add")]
if let Some(add) = &self.add { if let Some(add) = &self.add {
kinds.extend(add.get_used_backends()); kinds.extend(add.get_used_backends());
} }
#[cfg(feature = "flag-set")]
if let Some(set) = &self.set { if let Some(set) = &self.set {
kinds.extend(set.get_used_backends()); kinds.extend(set.get_used_backends());
} }
#[cfg(feature = "flag-remove")]
if let Some(remove) = &self.remove { if let Some(remove) = &self.remove {
kinds.extend(remove.get_used_backends()); kinds.extend(remove.get_used_backends());
} }
@ -30,11 +37,13 @@ impl FlagConfig {
} }
} }
#[cfg(feature = "flag-add")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FlagAddConfig { pub struct FlagAddConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "flag-add")]
impl FlagAddConfig { impl FlagAddConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -47,11 +56,13 @@ impl FlagAddConfig {
} }
} }
#[cfg(feature = "flag-set")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FlagSetConfig { pub struct FlagSetConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "flag-set")]
impl FlagSetConfig { impl FlagSetConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -64,11 +75,13 @@ impl FlagSetConfig {
} }
} }
#[cfg(feature = "flag-remove")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FlagRemoveConfig { pub struct FlagRemoveConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "flag-remove")]
impl FlagRemoveConfig { impl FlagRemoveConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();

View file

@ -3,14 +3,19 @@ pub mod command;
pub mod config; pub mod config;
pub mod flag; pub mod flag;
#[cfg(feature = "envelope-list")]
use anyhow::Result; use anyhow::Result;
#[cfg(feature = "envelope-list")]
use email::account::config::AccountConfig; use email::account::config::AccountConfig;
use serde::Serialize; use serde::Serialize;
#[cfg(feature = "envelope-list")]
use std::ops; use std::ops;
use crate::flag::Flags;
#[cfg(feature = "envelope-list")]
use crate::{ use crate::{
cache::IdMapper, cache::IdMapper,
flag::{Flag, Flags}, flag::Flag,
printer::{PrintTable, PrintTableOpts, WriteColor}, printer::{PrintTable, PrintTableOpts, WriteColor},
ui::{Cell, Row, Table}, ui::{Cell, Row, Table},
}; };
@ -30,6 +35,7 @@ pub struct Envelope {
pub date: String, pub date: String,
} }
#[cfg(feature = "envelope-list")]
impl Table for Envelope { impl Table for Envelope {
fn head() -> Row { fn head() -> Row {
Row::new() Row::new()
@ -75,10 +81,12 @@ impl Table for Envelope {
} }
} }
#[cfg(feature = "envelope-list")]
/// Represents the list of envelopes. /// Represents the list of envelopes.
#[derive(Clone, Debug, Default, Serialize)] #[derive(Clone, Debug, Default, Serialize)]
pub struct Envelopes(Vec<Envelope>); pub struct Envelopes(Vec<Envelope>);
#[cfg(feature = "envelope-list")]
impl Envelopes { impl Envelopes {
pub fn from_backend( pub fn from_backend(
config: &AccountConfig, config: &AccountConfig,
@ -105,6 +113,7 @@ impl Envelopes {
} }
} }
#[cfg(feature = "envelope-list")]
impl ops::Deref for Envelopes { impl ops::Deref for Envelopes {
type Target = Vec<Envelope>; type Target = Vec<Envelope>;
@ -113,6 +122,7 @@ impl ops::Deref for Envelopes {
} }
} }
#[cfg(feature = "envelope-list")]
impl PrintTable for Envelopes { impl PrintTable for Envelopes {
fn print_table(&self, writer: &mut dyn WriteColor, opts: PrintTableOpts) -> Result<()> { fn print_table(&self, writer: &mut dyn WriteColor, opts: PrintTableOpts) -> Result<()> {
writeln!(writer)?; writeln!(writer)?;

View file

@ -1,17 +1,18 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::{get::imap::GetMessagesImap, peek::imap::PeekMessagesImap}; use email::message::get::imap::GetMessagesImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir}; use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info; use log::info;
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
use uuid::Uuid; use uuid::Uuid;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -30,6 +31,7 @@ pub struct AttachmentDownloadCommand {
#[command(flatten)] #[command(flatten)]
pub envelopes: EnvelopeIdsArgs, pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -46,6 +48,7 @@ impl AttachmentDownloadCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -56,6 +59,12 @@ impl AttachmentDownloadCommand {
&account_config, &account_config,
get_messages_kind, get_messages_kind,
|builder| match get_messages_kind { |builder| match get_messages_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
@ -63,6 +72,7 @@ impl AttachmentDownloadCommand {
builder builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -73,13 +83,6 @@ impl AttachmentDownloadCommand {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -1,3 +1,4 @@
#[cfg(feature = "attachment-download")]
pub mod download; pub mod download;
use anyhow::Result; use anyhow::Result;
@ -5,6 +6,7 @@ use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer}; use crate::{config::TomlConfig, printer::Printer};
#[cfg(feature = "attachment-download")]
use self::download::AttachmentDownloadCommand; use self::download::AttachmentDownloadCommand;
/// Manage attachments. /// Manage attachments.
@ -14,13 +16,16 @@ use self::download::AttachmentDownloadCommand;
/// body. /// body.
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum AttachmentSubcommand { pub enum AttachmentSubcommand {
#[cfg(feature = "attachment-download")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
Download(AttachmentDownloadCommand), Download(AttachmentDownloadCommand),
} }
impl AttachmentSubcommand { impl AttachmentSubcommand {
#[allow(unused)]
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self { match self {
#[cfg(feature = "attachment-download")]
Self::Download(cmd) => cmd.execute(printer, config).await, Self::Download(cmd) => cmd.execute(printer, config).await,
} }
} }

View file

@ -6,10 +6,11 @@ use email::message::copy::imap::CopyMessagesImap;
use email::message::copy::maildir::CopyMessagesMaildir; use email::message::copy::maildir::CopyMessagesMaildir;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::{SourceFolderNameOptionalFlag, TargetFolderNameArg}, folder::arg::name::{SourceFolderNameOptionalFlag, TargetFolderNameArg},
@ -28,6 +29,7 @@ pub struct MessageCopyCommand {
#[command(flatten)] #[command(flatten)]
pub envelopes: EnvelopeIdsArgs, pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -45,6 +47,7 @@ impl MessageCopyCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -55,11 +58,18 @@ impl MessageCopyCommand {
&account_config, &account_config,
copy_messages_kind, copy_messages_kind,
|builder| match copy_messages_kind { |builder| match copy_messages_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_copy_messages(|ctx| ctx.imap.as_ref().and_then(CopyMessagesImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_copy_messages(|ctx| { builder.set_copy_messages(|ctx| {
ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new) ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_copy_messages(|ctx| { builder.set_copy_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -67,11 +77,6 @@ impl MessageCopyCommand {
.and_then(CopyMessagesMaildir::new) .and_then(CopyMessagesMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_copy_messages(|ctx| ctx.imap.as_ref().and_then(CopyMessagesImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -6,10 +6,11 @@ use email::{flag::add::imap::AddFlagsImap, message::move_::imap::MoveMessagesIma
use email::{flag::add::maildir::AddFlagsMaildir, message::move_::maildir::MoveMessagesMaildir}; use email::{flag::add::maildir::AddFlagsMaildir, message::move_::maildir::MoveMessagesMaildir};
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -30,6 +31,7 @@ pub struct MessageDeleteCommand {
#[command(flatten)] #[command(flatten)]
pub envelopes: EnvelopeIdsArgs, pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -46,6 +48,7 @@ impl MessageDeleteCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -56,6 +59,13 @@ impl MessageDeleteCommand {
&account_config, &account_config,
delete_messages_kind, delete_messages_kind,
|builder| match delete_messages_kind { |builder| match delete_messages_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_move_messages(|ctx| ctx.imap.as_ref().and_then(MoveMessagesImap::new));
builder.set_add_flags(|ctx| ctx.imap.as_ref().and_then(AddFlagsImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_move_messages(|ctx| { builder.set_move_messages(|ctx| {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new) ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
@ -63,6 +73,7 @@ impl MessageDeleteCommand {
builder builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_move_messages(|ctx| { builder.set_move_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -73,12 +84,6 @@ impl MessageDeleteCommand {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_move_messages(|ctx| ctx.imap.as_ref().and_then(MoveMessagesImap::new));
builder.set_add_flags(|ctx| ctx.imap.as_ref().and_then(AddFlagsImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -1,19 +1,20 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap; use email::message::add::imap::AddMessageImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir; use email::message::add_with_flags::maildir::AddMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail; use email::message::send::sendmail::SendMessageSendmail;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp; use email::message::send::smtp::SendMessageSmtp;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg, envelope::arg::ids::EnvelopeIdArg,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -42,6 +43,7 @@ pub struct MessageForwardCommand {
#[command(flatten)] #[command(flatten)]
pub body: MessageRawBodyArg, pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -57,11 +59,12 @@ impl MessageForwardCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let add_message_kind = toml_account_config.add_raw_message_kind(); let add_message_kind = toml_account_config.add_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind(); let send_message_kind = toml_account_config.send_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
@ -69,24 +72,25 @@ impl MessageForwardCommand {
add_message_kind.into_iter().chain(send_message_kind), add_message_kind.into_iter().chain(send_message_kind),
|builder| { |builder| {
match add_message_kind { match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| { builder
ctx.imap.as_ref().and_then(AddRawMessageImap::new) .set_add_message(|ctx| ctx.imap.as_ref().and_then(AddMessageImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
}); });
} }
_ => (), _ => (),
@ -95,14 +99,14 @@ impl MessageForwardCommand {
match send_message_kind { match send_message_kind {
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => { Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new) ctx.smtp.as_ref().and_then(SendMessageSmtp::new)
}); });
} }
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => { Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new) ctx.sendmail.as_ref().and_then(SendMessageSendmail::new)
}); });
} }
_ => (), _ => (),

View file

@ -1,21 +1,22 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap; use email::message::add::imap::AddMessageImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir; use email::message::add_with_flags::maildir::AddMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail; use email::message::send::sendmail::SendMessageSendmail;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp; use email::message::send::smtp::SendMessageSmtp;
use log::{debug, info}; use log::{debug, info};
use mail_builder::MessageBuilder; use mail_builder::MessageBuilder;
use url::Url; use url::Url;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
printer::Printer, printer::Printer,
ui::editor, ui::editor,
@ -33,6 +34,7 @@ pub struct MessageMailtoCommand {
#[arg()] #[arg()]
pub url: Url, pub url: Url,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -44,6 +46,7 @@ impl MessageMailtoCommand {
pub fn new(url: &str) -> Result<Self> { pub fn new(url: &str) -> Result<Self> {
Ok(Self { Ok(Self {
url: Url::parse(url)?, url: Url::parse(url)?,
#[cfg(feature = "sync")]
cache: Default::default(), cache: Default::default(),
account: Default::default(), account: Default::default(),
}) })
@ -54,11 +57,12 @@ impl MessageMailtoCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let add_message_kind = toml_account_config.add_raw_message_kind(); let add_message_kind = toml_account_config.add_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind(); let send_message_kind = toml_account_config.send_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
@ -66,24 +70,25 @@ impl MessageMailtoCommand {
add_message_kind.into_iter().chain(send_message_kind), add_message_kind.into_iter().chain(send_message_kind),
|builder| { |builder| {
match add_message_kind { match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| { builder
ctx.imap.as_ref().and_then(AddRawMessageImap::new) .set_add_message(|ctx| ctx.imap.as_ref().and_then(AddMessageImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
}); });
} }
_ => (), _ => (),
@ -92,14 +97,14 @@ impl MessageMailtoCommand {
match send_message_kind { match send_message_kind {
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => { Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new) ctx.smtp.as_ref().and_then(SendMessageSmtp::new)
}); });
} }
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => { Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new) ctx.sendmail.as_ref().and_then(SendMessageSendmail::new)
}); });
} }
_ => (), _ => (),

View file

@ -1,12 +1,22 @@
#[cfg(feature = "message-copy")]
pub mod copy; pub mod copy;
#[cfg(feature = "message-delete")]
pub mod delete; pub mod delete;
#[cfg(feature = "message-forward")]
pub mod forward; pub mod forward;
#[cfg(feature = "message-mailto")]
pub mod mailto; pub mod mailto;
#[cfg(feature = "message-move")]
pub mod move_; pub mod move_;
#[cfg(feature = "message-read")]
pub mod read; pub mod read;
#[cfg(feature = "message-reply")]
pub mod reply; pub mod reply;
#[cfg(feature = "message-save")]
pub mod save; pub mod save;
#[cfg(feature = "message-send")]
pub mod send; pub mod send;
#[cfg(feature = "message-write")]
pub mod write; pub mod write;
use anyhow::Result; use anyhow::Result;
@ -14,12 +24,26 @@ use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer}; use crate::{config::TomlConfig, printer::Printer};
use self::{ #[cfg(feature = "message-copy")]
copy::MessageCopyCommand, delete::MessageDeleteCommand, forward::MessageForwardCommand, use self::copy::MessageCopyCommand;
mailto::MessageMailtoCommand, move_::MessageMoveCommand, read::MessageReadCommand, #[cfg(feature = "message-delete")]
reply::MessageReplyCommand, save::MessageSaveCommand, send::MessageSendCommand, use self::delete::MessageDeleteCommand;
write::MessageWriteCommand, #[cfg(feature = "message-forward")]
}; use self::forward::MessageForwardCommand;
#[cfg(feature = "message-mailto")]
use self::mailto::MessageMailtoCommand;
#[cfg(feature = "message-move")]
use self::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;
/// Manage messages. /// Manage messages.
/// ///
@ -29,52 +53,73 @@ use self::{
/// subcommand allows you to manage them. /// subcommand allows you to manage them.
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum MessageSubcommand { pub enum MessageSubcommand {
#[cfg(feature = "message-read")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
Read(MessageReadCommand), Read(MessageReadCommand),
#[cfg(feature = "message-write")]
#[command(aliases = ["add", "create", "new", "compose"])] #[command(aliases = ["add", "create", "new", "compose"])]
Write(MessageWriteCommand), Write(MessageWriteCommand),
#[cfg(feature = "message-reply")]
#[command()] #[command()]
Reply(MessageReplyCommand), Reply(MessageReplyCommand),
#[cfg(feature = "message-forward")]
#[command(aliases = ["fwd", "fd"])] #[command(aliases = ["fwd", "fd"])]
Forward(MessageForwardCommand), Forward(MessageForwardCommand),
#[cfg(feature = "message-mailto")]
#[command()] #[command()]
Mailto(MessageMailtoCommand), Mailto(MessageMailtoCommand),
#[cfg(feature = "message-save")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
Save(MessageSaveCommand), Save(MessageSaveCommand),
#[cfg(feature = "message-send")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
Send(MessageSendCommand), Send(MessageSendCommand),
#[cfg(feature = "message-copy")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
#[command(aliases = ["cpy", "cp"])] #[command(aliases = ["cpy", "cp"])]
Copy(MessageCopyCommand), Copy(MessageCopyCommand),
#[cfg(feature = "message-move")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
#[command(alias = "mv")] #[command(alias = "mv")]
Move(MessageMoveCommand), Move(MessageMoveCommand),
#[cfg(feature = "message-delete")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
#[command(aliases = ["remove", "rm"])] #[command(aliases = ["remove", "rm"])]
Delete(MessageDeleteCommand), Delete(MessageDeleteCommand),
} }
impl MessageSubcommand { impl MessageSubcommand {
#[allow(unused)]
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self { match self {
#[cfg(feature = "message-read")]
Self::Read(cmd) => cmd.execute(printer, config).await, Self::Read(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-write")]
Self::Write(cmd) => cmd.execute(printer, config).await, Self::Write(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-reply")]
Self::Reply(cmd) => cmd.execute(printer, config).await, Self::Reply(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-forward")]
Self::Forward(cmd) => cmd.execute(printer, config).await, Self::Forward(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-mailto")]
Self::Mailto(cmd) => cmd.execute(printer, config).await, Self::Mailto(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-save")]
Self::Save(cmd) => cmd.execute(printer, config).await, Self::Save(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-send")]
Self::Send(cmd) => cmd.execute(printer, config).await, Self::Send(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-copy")]
Self::Copy(cmd) => cmd.execute(printer, config).await, Self::Copy(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-move")]
Self::Move(cmd) => cmd.execute(printer, config).await, Self::Move(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "message-delete")]
Self::Delete(cmd) => cmd.execute(printer, config).await, Self::Delete(cmd) => cmd.execute(printer, config).await,
} }
} }

View file

@ -6,10 +6,11 @@ use email::message::move_::imap::MoveMessagesImap;
use email::message::move_::maildir::MoveMessagesMaildir; use email::message::move_::maildir::MoveMessagesMaildir;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::{SourceFolderNameOptionalFlag, TargetFolderNameArg}, folder::arg::name::{SourceFolderNameOptionalFlag, TargetFolderNameArg},
@ -28,6 +29,7 @@ pub struct MessageMoveCommand {
#[command(flatten)] #[command(flatten)]
pub envelopes: EnvelopeIdsArgs, pub envelopes: EnvelopeIdsArgs,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -45,6 +47,7 @@ impl MessageMoveCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -55,11 +58,18 @@ impl MessageMoveCommand {
&account_config, &account_config,
move_messages_kind, move_messages_kind,
|builder| match move_messages_kind { |builder| match move_messages_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_move_messages(|ctx| ctx.imap.as_ref().and_then(MoveMessagesImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_move_messages(|ctx| { builder.set_move_messages(|ctx| {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new) ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_move_messages(|ctx| { builder.set_move_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -67,11 +77,6 @@ impl MessageMoveCommand {
.and_then(MoveMessagesMaildir::new) .and_then(MoveMessagesMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_move_messages(|ctx| ctx.imap.as_ref().and_then(MoveMessagesImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -7,10 +7,11 @@ use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMes
use log::info; use log::info;
use mml::message::FilterParts; use mml::message::FilterParts;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdsArgs, envelope::arg::ids::EnvelopeIdsArgs,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -74,6 +75,7 @@ pub struct MessageReadCommand {
#[arg(conflicts_with = "no_headers")] #[arg(conflicts_with = "no_headers")]
pub headers: Vec<String>, pub headers: Vec<String>,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -90,6 +92,7 @@ impl MessageReadCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -100,6 +103,14 @@ impl MessageReadCommand {
&account_config, &account_config,
get_messages_kind, get_messages_kind,
|builder| match get_messages_kind { |builder| match get_messages_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
@ -107,6 +118,7 @@ impl MessageReadCommand {
builder builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -117,13 +129,6 @@ impl MessageReadCommand {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -2,19 +2,20 @@ use anyhow::{anyhow, Result};
use clap::Parser; use clap::Parser;
use email::flag::Flag; use email::flag::Flag;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap; use email::message::add::imap::AddMessageImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir; use email::message::add_with_flags::maildir::AddMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail; use email::message::send::sendmail::SendMessageSendmail;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp; use email::message::send::smtp::SendMessageSmtp;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg, envelope::arg::ids::EnvelopeIdArg,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -46,6 +47,7 @@ pub struct MessageReplyCommand {
#[command(flatten)] #[command(flatten)]
pub body: MessageRawBodyArg, pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -60,11 +62,12 @@ impl MessageReplyCommand {
let folder = &self.folder.name; let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let add_message_kind = toml_account_config.add_raw_message_kind(); let add_message_kind = toml_account_config.add_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind(); let send_message_kind = toml_account_config.send_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
@ -72,24 +75,25 @@ impl MessageReplyCommand {
add_message_kind.into_iter().chain(send_message_kind), add_message_kind.into_iter().chain(send_message_kind),
|builder| { |builder| {
match add_message_kind { match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| { builder
ctx.imap.as_ref().and_then(AddRawMessageImap::new) .set_add_message(|ctx| ctx.imap.as_ref().and_then(AddMessageImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
}); });
} }
_ => (), _ => (),
@ -98,14 +102,14 @@ impl MessageReplyCommand {
match send_message_kind { match send_message_kind {
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => { Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new) ctx.smtp.as_ref().and_then(SendMessageSmtp::new)
}); });
} }
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => { Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new) ctx.sendmail.as_ref().and_then(SendMessageSendmail::new)
}); });
} }
_ => (), _ => (),
@ -128,7 +132,7 @@ impl MessageReplyCommand {
.await?; .await?;
editor::edit_tpl_with_editor(&account_config, printer, &backend, tpl).await?; editor::edit_tpl_with_editor(&account_config, printer, &backend, tpl).await?;
// TODO: let backend.send_reply_raw_message adding the flag // TODO: let backend.send_reply_message adding the flag
backend.add_flag(&folder, &[id], Flag::Answered).await backend.add_flag(&folder, &[id], Flag::Answered).await
} }
} }

View file

@ -1,16 +1,17 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap; use email::message::add::imap::AddMessageImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir; use email::message::add_with_flags::maildir::AddMessageWithFlagsMaildir;
use log::info; use log::info;
use std::io::{self, BufRead, IsTerminal}; use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
message::arg::MessageRawArg, message::arg::MessageRawArg,
@ -28,6 +29,7 @@ pub struct MessageSaveCommand {
#[command(flatten)] #[command(flatten)]
pub message: MessageRawArg, pub message: MessageRawArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -43,34 +45,35 @@ impl MessageSaveCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let add_message_kind = toml_account_config.add_raw_message_kind(); let add_message_kind = toml_account_config.add_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
&account_config, &account_config,
add_message_kind, add_message_kind,
|builder| match add_message_kind { |builder| match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| { builder.set_add_message(|ctx| ctx.imap.as_ref().and_then(AddMessageImap::new));
ctx.imap.as_ref().and_then(AddRawMessageImap::new) }
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
}); });
} }
_ => (), _ => (),
@ -91,7 +94,7 @@ impl MessageSaveCommand {
.join("\r\n") .join("\r\n")
}; };
backend.add_raw_message(folder, msg.as_bytes()).await?; backend.add_message(folder, msg.as_bytes()).await?;
printer.print(format!("Message successfully saved to {folder}!")) printer.print(format!("Message successfully saved to {folder}!"))
} }

View file

@ -1,16 +1,17 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail; use email::message::send::sendmail::SendMessageSendmail;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp; use email::message::send::smtp::SendMessageSmtp;
use log::info; use log::info;
use std::io::{self, BufRead, IsTerminal}; use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
message::arg::MessageRawArg, message::arg::MessageRawArg,
printer::Printer, printer::Printer,
@ -25,6 +26,7 @@ pub struct MessageSendCommand {
#[command(flatten)] #[command(flatten)]
pub message: MessageRawArg, pub message: MessageRawArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -38,10 +40,11 @@ impl MessageSendCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let send_message_kind = toml_account_config.send_raw_message_kind(); let send_message_kind = toml_account_config.send_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
@ -51,14 +54,14 @@ impl MessageSendCommand {
match send_message_kind { match send_message_kind {
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => { Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new) ctx.smtp.as_ref().and_then(SendMessageSmtp::new)
}); });
} }
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => { Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new) ctx.sendmail.as_ref().and_then(SendMessageSendmail::new)
}); });
} }
_ => (), _ => (),
@ -78,7 +81,7 @@ impl MessageSendCommand {
.join("\r\n") .join("\r\n")
}; };
backend.send_raw_message(msg.as_bytes()).await?; backend.send_message(msg.as_bytes()).await?;
printer.print("Message successfully sent!") printer.print("Message successfully sent!")
} }

View file

@ -1,20 +1,21 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap; use email::message::add::imap::AddMessageImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir; use email::message::add_with_flags::maildir::AddMessageWithFlagsMaildir;
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail; use email::message::send::sendmail::SendMessageSendmail;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp; use email::message::send::smtp::SendMessageSmtp;
use email::message::Message; use email::message::Message;
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs}, message::arg::{body::MessageRawBodyArg, header::HeaderRawArgs},
printer::Printer, printer::Printer,
@ -35,6 +36,7 @@ pub struct MessageWriteCommand {
#[command(flatten)] #[command(flatten)]
pub body: MessageRawBodyArg, pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -48,11 +50,12 @@ impl MessageWriteCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let add_message_kind = toml_account_config.add_raw_message_kind(); let add_message_kind = toml_account_config.add_message_kind();
let send_message_kind = toml_account_config.send_raw_message_kind(); let send_message_kind = toml_account_config.send_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
@ -60,24 +63,25 @@ impl MessageWriteCommand {
add_message_kind.into_iter().chain(send_message_kind), add_message_kind.into_iter().chain(send_message_kind),
|builder| { |builder| {
match add_message_kind { match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| { builder
ctx.imap.as_ref().and_then(AddRawMessageImap::new) .set_add_message(|ctx| ctx.imap.as_ref().and_then(AddMessageImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
}); });
} }
_ => (), _ => (),
@ -86,14 +90,14 @@ impl MessageWriteCommand {
match send_message_kind { match send_message_kind {
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => { Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new) ctx.smtp.as_ref().and_then(SendMessageSmtp::new)
}); });
} }
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => { Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new) ctx.sendmail.as_ref().and_then(SendMessageSendmail::new)
}); });
} }
_ => (), _ => (),

View file

@ -5,39 +5,52 @@ use crate::backend::BackendKind;
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MessageConfig { pub struct MessageConfig {
#[cfg(any(feature = "message-add", feature = "message-write"))]
pub write: Option<MessageAddConfig>, pub write: Option<MessageAddConfig>,
#[cfg(any(feature = "message-send", feature = "template-send"))]
pub send: Option<MessageSendConfig>, pub send: Option<MessageSendConfig>,
#[cfg(feature = "message-peek")]
pub peek: Option<MessagePeekConfig>, pub peek: Option<MessagePeekConfig>,
#[cfg(any(feature = "message-get", feature = "message-read"))]
pub read: Option<MessageGetConfig>, pub read: Option<MessageGetConfig>,
#[cfg(feature = "message-copy")]
pub copy: Option<MessageCopyConfig>, pub copy: Option<MessageCopyConfig>,
#[cfg(feature = "message-move")]
#[serde(rename = "move")] #[serde(rename = "move")]
pub move_: Option<MessageMoveConfig>, pub move_: Option<MessageMoveConfig>,
} }
impl MessageConfig { impl MessageConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
#[allow(unused_mut)]
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
#[cfg(any(feature = "message-add", feature = "message-write"))]
if let Some(add) = &self.write { if let Some(add) = &self.write {
kinds.extend(add.get_used_backends()); kinds.extend(add.get_used_backends());
} }
#[cfg(any(feature = "message-send", feature = "template-send"))]
if let Some(send) = &self.send { if let Some(send) = &self.send {
kinds.extend(send.get_used_backends()); kinds.extend(send.get_used_backends());
} }
#[cfg(feature = "message-peek")]
if let Some(peek) = &self.peek { if let Some(peek) = &self.peek {
kinds.extend(peek.get_used_backends()); kinds.extend(peek.get_used_backends());
} }
#[cfg(any(feature = "message-get", feature = "message-read"))]
if let Some(get) = &self.read { if let Some(get) = &self.read {
kinds.extend(get.get_used_backends()); kinds.extend(get.get_used_backends());
} }
#[cfg(feature = "message-copy")]
if let Some(copy) = &self.copy { if let Some(copy) = &self.copy {
kinds.extend(copy.get_used_backends()); kinds.extend(copy.get_used_backends());
} }
#[cfg(feature = "message-move")]
if let Some(move_) = &self.move_ { if let Some(move_) = &self.move_ {
kinds.extend(move_.get_used_backends()); kinds.extend(move_.get_used_backends());
} }
@ -46,14 +59,16 @@ impl MessageConfig {
} }
} }
#[cfg(any(feature = "message-add", feature = "message-write"))]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MessageAddConfig { pub struct MessageAddConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
#[serde(flatten)] #[serde(flatten)]
pub remote: email::message::add_raw::config::MessageWriteConfig, pub remote: email::message::add::config::MessageWriteConfig,
} }
#[cfg(any(feature = "message-add", feature = "message-write"))]
impl MessageAddConfig { impl MessageAddConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -66,14 +81,16 @@ impl MessageAddConfig {
} }
} }
#[cfg(any(feature = "message-send", feature = "template-send"))]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MessageSendConfig { pub struct MessageSendConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
#[serde(flatten)] #[serde(flatten)]
pub remote: email::message::send_raw::config::MessageSendConfig, pub remote: email::message::send::config::MessageSendConfig,
} }
#[cfg(any(feature = "message-send", feature = "template-send"))]
impl MessageSendConfig { impl MessageSendConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -86,11 +103,13 @@ impl MessageSendConfig {
} }
} }
#[cfg(feature = "message-peek")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MessagePeekConfig { pub struct MessagePeekConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "message-peek")]
impl MessagePeekConfig { impl MessagePeekConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -103,6 +122,7 @@ impl MessagePeekConfig {
} }
} }
#[cfg(any(feature = "message-get", feature = "message-read"))]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MessageGetConfig { pub struct MessageGetConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
@ -111,6 +131,7 @@ pub struct MessageGetConfig {
pub remote: email::message::get::config::MessageReadConfig, pub remote: email::message::get::config::MessageReadConfig,
} }
#[cfg(any(feature = "message-get", feature = "message-read"))]
impl MessageGetConfig { impl MessageGetConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -123,11 +144,13 @@ impl MessageGetConfig {
} }
} }
#[cfg(feature = "message-copy")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MessageCopyConfig { pub struct MessageCopyConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "message-copy")]
impl MessageCopyConfig { impl MessageCopyConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -140,11 +163,13 @@ impl MessageCopyConfig {
} }
} }
#[cfg(feature = "message-move")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MessageMoveConfig { pub struct MessageMoveConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "message-move")]
impl MessageMoveConfig { impl MessageMoveConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();

View file

@ -1,15 +1,16 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::{get::imap::GetMessagesImap, peek::imap::PeekMessagesImap}; use email::message::get::imap::GetMessagesImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir}; use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg, envelope::arg::ids::EnvelopeIdArg,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -36,6 +37,7 @@ pub struct TemplateForwardCommand {
#[command(flatten)] #[command(flatten)]
pub body: MessageRawBodyArg, pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -51,6 +53,7 @@ impl TemplateForwardCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -61,6 +64,12 @@ impl TemplateForwardCommand {
&account_config, &account_config,
get_messages_kind, get_messages_kind,
|builder| match get_messages_kind { |builder| match get_messages_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
@ -68,6 +77,7 @@ impl TemplateForwardCommand {
builder builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -78,13 +88,6 @@ impl TemplateForwardCommand {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -1,7 +1,12 @@
#[cfg(feature = "template-forward")]
pub mod forward; pub mod forward;
#[cfg(feature = "template-reply")]
pub mod reply; pub mod reply;
#[cfg(feature = "template-save")]
pub mod save; pub mod save;
#[cfg(feature = "template-send")]
pub mod send; pub mod send;
#[cfg(feature = "template-write")]
pub mod write; pub mod write;
use anyhow::Result; use anyhow::Result;
@ -9,10 +14,16 @@ use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer}; use crate::{config::TomlConfig, printer::Printer};
use self::{ #[cfg(feature = "template-forward")]
forward::TemplateForwardCommand, reply::TemplateReplyCommand, save::TemplateSaveCommand, use self::forward::TemplateForwardCommand;
send::TemplateSendCommand, write::TemplateWriteCommand, #[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;
/// Manage templates. /// Manage templates.
/// ///
@ -25,30 +36,41 @@ use self::{
/// <https://crates.io/crates/mml-lib>. /// <https://crates.io/crates/mml-lib>.
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum TemplateSubcommand { pub enum TemplateSubcommand {
#[cfg(feature = "template-write")]
#[command(aliases = ["add", "create", "new", "compose"])] #[command(aliases = ["add", "create", "new", "compose"])]
Write(TemplateWriteCommand), Write(TemplateWriteCommand),
#[cfg(feature = "template-reply")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
Reply(TemplateReplyCommand), Reply(TemplateReplyCommand),
#[cfg(feature = "template-forward")]
#[command(arg_required_else_help = true)] #[command(arg_required_else_help = true)]
#[command(alias = "fwd")] #[command(alias = "fwd")]
Forward(TemplateForwardCommand), Forward(TemplateForwardCommand),
#[cfg(feature = "template-save")]
#[command()] #[command()]
Save(TemplateSaveCommand), Save(TemplateSaveCommand),
#[cfg(feature = "template-send")]
#[command()] #[command()]
Send(TemplateSendCommand), Send(TemplateSendCommand),
} }
impl TemplateSubcommand { impl TemplateSubcommand {
#[allow(unused)]
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self { match self {
#[cfg(feature = "template-write")]
Self::Write(cmd) => cmd.execute(printer, config).await, Self::Write(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "template-reply")]
Self::Reply(cmd) => cmd.execute(printer, config).await, Self::Reply(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "template-forward")]
Self::Forward(cmd) => cmd.execute(printer, config).await, Self::Forward(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "template-save")]
Self::Save(cmd) => cmd.execute(printer, config).await, Self::Save(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "template-send")]
Self::Send(cmd) => cmd.execute(printer, config).await, Self::Send(cmd) => cmd.execute(printer, config).await,
} }
} }

View file

@ -1,15 +1,16 @@
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::{get::imap::GetMessagesImap, peek::imap::PeekMessagesImap}; use email::message::get::imap::GetMessagesImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir}; use email::{flag::add::maildir::AddFlagsMaildir, message::peek::maildir::PeekMessagesMaildir};
use log::info; use log::info;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg, envelope::arg::ids::EnvelopeIdArg,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -40,6 +41,7 @@ pub struct TemplateReplyCommand {
#[command(flatten)] #[command(flatten)]
pub body: MessageRawBodyArg, pub body: MessageRawBodyArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -56,6 +58,7 @@ impl TemplateReplyCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -66,6 +69,12 @@ impl TemplateReplyCommand {
&account_config, &account_config,
get_messages_kind, get_messages_kind,
|builder| match get_messages_kind { |builder| match get_messages_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
@ -73,6 +82,7 @@ impl TemplateReplyCommand {
builder builder
.set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .set_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_peek_messages(|ctx| { builder.set_peek_messages(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -83,13 +93,6 @@ impl TemplateReplyCommand {
ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_peek_messages(|ctx| ctx.imap.as_ref().and_then(PeekMessagesImap::new));
builder
.set_get_messages(|ctx| ctx.imap.as_ref().and_then(GetMessagesImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -1,17 +1,18 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
use email::message::add_raw::imap::AddRawMessageImap; use email::message::add::imap::AddMessageImap;
#[cfg(feature = "maildir")] #[cfg(feature = "maildir")]
use email::message::add_raw_with_flags::maildir::AddRawMessageWithFlagsMaildir; use email::message::add_with_flags::maildir::AddMessageWithFlagsMaildir;
use log::info; use log::info;
use mml::MmlCompilerBuilder; use mml::MmlCompilerBuilder;
use std::io::{self, BufRead, IsTerminal}; use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
email::template::arg::TemplateRawArg, email::template::arg::TemplateRawArg,
folder::arg::name::FolderNameOptionalFlag, folder::arg::name::FolderNameOptionalFlag,
@ -32,6 +33,7 @@ pub struct TemplateSaveCommand {
#[command(flatten)] #[command(flatten)]
pub template: TemplateRawArg, pub template: TemplateRawArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -47,34 +49,35 @@ impl TemplateSaveCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let add_message_kind = toml_account_config.add_raw_message_kind(); let add_message_kind = toml_account_config.add_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
&account_config, &account_config,
add_message_kind, add_message_kind,
|builder| match add_message_kind { |builder| match add_message_kind {
Some(BackendKind::Maildir) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
Some(BackendKind::MaildirForSync) => {
builder.set_add_raw_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "imap")] #[cfg(feature = "imap")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
builder.set_add_raw_message(|ctx| { builder.set_add_message(|ctx| ctx.imap.as_ref().and_then(AddMessageImap::new));
ctx.imap.as_ref().and_then(AddRawMessageImap::new) }
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
});
}
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => {
builder.set_add_message_with_flags(|ctx| {
ctx.maildir_for_sync
.as_ref()
.and_then(AddMessageWithFlagsMaildir::new)
}); });
} }
_ => (), _ => (),
@ -102,7 +105,8 @@ impl TemplateSaveCommand {
compiler.set_some_pgp(account_config.pgp.clone()); compiler.set_some_pgp(account_config.pgp.clone());
let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend.add_raw_message(folder, &msg).await?;
backend.add_message(folder, &msg).await?;
printer.print(format!("Template successfully saved to {folder}!")) printer.print(format!("Template successfully saved to {folder}!"))
} }

View file

@ -1,17 +1,18 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
use email::message::send_raw::sendmail::SendRawMessageSendmail; use email::message::send::sendmail::SendMessageSendmail;
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
use email::message::send_raw::smtp::SendRawMessageSmtp; use email::message::send::smtp::SendMessageSmtp;
use log::info; use log::info;
use mml::MmlCompilerBuilder; use mml::MmlCompilerBuilder;
use std::io::{self, BufRead, IsTerminal}; use std::io::{self, BufRead, IsTerminal};
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::{Backend, BackendKind},
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
email::template::arg::TemplateRawArg, email::template::arg::TemplateRawArg,
printer::Printer, printer::Printer,
@ -28,6 +29,7 @@ pub struct TemplateSendCommand {
#[command(flatten)] #[command(flatten)]
pub template: TemplateRawArg, pub template: TemplateRawArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -41,10 +43,11 @@ impl TemplateSendCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
let send_message_kind = toml_account_config.send_raw_message_kind(); let send_message_kind = toml_account_config.send_message_kind();
let backend = Backend::new( let backend = Backend::new(
&toml_account_config, &toml_account_config,
@ -54,14 +57,14 @@ impl TemplateSendCommand {
match send_message_kind { match send_message_kind {
#[cfg(feature = "smtp")] #[cfg(feature = "smtp")]
Some(BackendKind::Smtp) => { Some(BackendKind::Smtp) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.smtp.as_ref().and_then(SendRawMessageSmtp::new) ctx.smtp.as_ref().and_then(SendMessageSmtp::new)
}); });
} }
#[cfg(feature = "sendmail")] #[cfg(feature = "sendmail")]
Some(BackendKind::Sendmail) => { Some(BackendKind::Sendmail) => {
builder.set_send_raw_message(|ctx| { builder.set_send_message(|ctx| {
ctx.sendmail.as_ref().and_then(SendRawMessageSendmail::new) ctx.sendmail.as_ref().and_then(SendMessageSendmail::new)
}); });
} }
_ => (), _ => (),
@ -89,8 +92,8 @@ impl TemplateSendCommand {
let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend.send_raw_message(&msg).await?; backend.send_message(&msg).await?;
printer.print("Template successfully sent!") printer.print("Message successfully sent!")
} }
} }

View file

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

View file

@ -6,13 +6,13 @@ use email::folder::add::imap::AddFolderImap;
use email::folder::add::maildir::AddFolderMaildir; use email::folder::add::maildir::AddFolderMaildir;
use log::info; use log::info;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
backend::{Backend, BackendKind}, folder::arg::name::FolderNameArg, printer::Printer,
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
}; };
/// Create a new folder. /// Create a new folder.
@ -20,10 +20,11 @@ use crate::{
/// This command allows you to create a new folder using the given /// This command allows you to create a new folder using the given
/// name. /// name.
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
pub struct FolderCreateCommand { pub struct AddFolderCommand {
#[command(flatten)] #[command(flatten)]
pub folder: FolderNameArg, pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -31,13 +32,14 @@ pub struct FolderCreateCommand {
pub account: AccountNameFlag, pub account: AccountNameFlag,
} }
impl FolderCreateCommand { impl AddFolderCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing create folder command"); info!("executing create folder command");
let folder = &self.folder.name; let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -48,10 +50,16 @@ impl FolderCreateCommand {
&account_config, &account_config,
add_folder_kind, add_folder_kind,
|builder| match add_folder_kind { |builder| match add_folder_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_folder(|ctx| ctx.imap.as_ref().and_then(AddFolderImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder builder
.set_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new)); .set_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new));
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_add_folder(|ctx| { builder.set_add_folder(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -59,10 +67,6 @@ impl FolderCreateCommand {
.and_then(AddFolderMaildir::new) .and_then(AddFolderMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_add_folder(|ctx| ctx.imap.as_ref().and_then(AddFolderImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -8,13 +8,13 @@ use email::folder::delete::maildir::DeleteFolderMaildir;
use log::info; use log::info;
use std::process; use std::process;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
backend::{Backend, BackendKind}, folder::arg::name::FolderNameArg, printer::Printer,
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
}; };
/// Delete a folder. /// Delete a folder.
@ -26,6 +26,7 @@ pub struct FolderDeleteCommand {
#[command(flatten)] #[command(flatten)]
pub folder: FolderNameArg, pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -51,6 +52,7 @@ impl FolderDeleteCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -61,11 +63,18 @@ impl FolderDeleteCommand {
&account_config, &account_config,
delete_folder_kind, delete_folder_kind,
|builder| match delete_folder_kind { |builder| match delete_folder_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_delete_folder(|ctx| ctx.imap.as_ref().and_then(DeleteFolderImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_delete_folder(|ctx| { builder.set_delete_folder(|ctx| {
ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new) ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_delete_folder(|ctx| { builder.set_delete_folder(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -73,11 +82,6 @@ impl FolderDeleteCommand {
.and_then(DeleteFolderMaildir::new) .and_then(DeleteFolderMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_delete_folder(|ctx| ctx.imap.as_ref().and_then(DeleteFolderImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -6,13 +6,13 @@ use email::folder::expunge::imap::ExpungeFolderImap;
use email::folder::expunge::maildir::ExpungeFolderMaildir; use email::folder::expunge::maildir::ExpungeFolderMaildir;
use log::info; use log::info;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
backend::{Backend, BackendKind}, folder::arg::name::FolderNameArg, printer::Printer,
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
}; };
/// Expunge a folder. /// Expunge a folder.
@ -25,6 +25,7 @@ pub struct FolderExpungeCommand {
#[command(flatten)] #[command(flatten)]
pub folder: FolderNameArg, pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -39,6 +40,7 @@ impl FolderExpungeCommand {
let folder = &self.folder.name; let folder = &self.folder.name;
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -49,11 +51,19 @@ impl FolderExpungeCommand {
&account_config, &account_config,
expunge_folder_kind, expunge_folder_kind,
|builder| match expunge_folder_kind { |builder| match expunge_folder_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_expunge_folder(|ctx| {
ctx.imap.as_ref().and_then(ExpungeFolderImap::new)
});
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_expunge_folder(|ctx| { builder.set_expunge_folder(|ctx| {
ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new) ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_expunge_folder(|ctx| { builder.set_expunge_folder(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -61,12 +71,6 @@ impl FolderExpungeCommand {
.and_then(ExpungeFolderMaildir::new) .and_then(ExpungeFolderMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder.set_expunge_folder(|ctx| {
ctx.imap.as_ref().and_then(ExpungeFolderImap::new)
});
}
_ => (), _ => (),
}, },
) )

View file

@ -6,10 +6,13 @@ use email::folder::list::imap::ListFoldersImap;
use email::folder::list::maildir::ListFoldersMaildir; use email::folder::list::maildir::ListFoldersMaildir;
use log::info; use log::info;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag,
backend::{Backend, BackendKind}, backend::Backend,
cache::arg::disable::CacheDisableFlag,
config::TomlConfig, config::TomlConfig,
folder::Folders, folder::Folders,
printer::{PrintTableOpts, Printer}, printer::{PrintTableOpts, Printer},
@ -24,6 +27,7 @@ pub struct FolderListCommand {
#[command(flatten)] #[command(flatten)]
pub table: TableMaxWidthFlag, pub table: TableMaxWidthFlag,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -37,6 +41,7 @@ impl FolderListCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -47,11 +52,18 @@ impl FolderListCommand {
&account_config, &account_config,
list_folders_kind, list_folders_kind,
|builder| match list_folders_kind { |builder| match list_folders_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_list_folders(|ctx| ctx.imap.as_ref().and_then(ListFoldersImap::new));
}
#[cfg(feature = "maildir")]
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
builder.set_list_folders(|ctx| { builder.set_list_folders(|ctx| {
ctx.maildir.as_ref().and_then(ListFoldersMaildir::new) ctx.maildir.as_ref().and_then(ListFoldersMaildir::new)
}); });
} }
#[cfg(feature = "sync")]
Some(BackendKind::MaildirForSync) => { Some(BackendKind::MaildirForSync) => {
builder.set_list_folders(|ctx| { builder.set_list_folders(|ctx| {
ctx.maildir_for_sync ctx.maildir_for_sync
@ -59,11 +71,6 @@ impl FolderListCommand {
.and_then(ListFoldersMaildir::new) .and_then(ListFoldersMaildir::new)
}); });
} }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_list_folders(|ctx| ctx.imap.as_ref().and_then(ListFoldersImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -1,7 +1,12 @@
#[cfg(feature = "folder-add")]
mod create; mod create;
#[cfg(feature = "folder-delete")]
mod delete; mod delete;
#[cfg(feature = "folder-expunge")]
mod expunge; mod expunge;
#[cfg(feature = "folder-list")]
mod list; mod list;
#[cfg(feature = "folder-purge")]
mod purge; mod purge;
use anyhow::Result; use anyhow::Result;
@ -9,10 +14,16 @@ use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer}; use crate::{config::TomlConfig, printer::Printer};
use self::{ #[cfg(feature = "folder-add")]
create::FolderCreateCommand, delete::FolderDeleteCommand, expunge::FolderExpungeCommand, use self::create::AddFolderCommand;
list::FolderListCommand, purge::FolderPurgeCommand, #[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;
/// Manage folders. /// Manage folders.
/// ///
@ -20,29 +31,40 @@ use self::{
/// emails. This subcommand allows you to manage them. /// emails. This subcommand allows you to manage them.
#[derive(Debug, Subcommand)] #[derive(Debug, Subcommand)]
pub enum FolderSubcommand { pub enum FolderSubcommand {
#[command(alias = "add", alias = "new")] #[cfg(feature = "folder-add")]
Create(FolderCreateCommand), #[command(visible_alias = "create", alias = "new")]
Add(AddFolderCommand),
#[cfg(feature = "folder-list")]
#[command(alias = "lst")] #[command(alias = "lst")]
List(FolderListCommand), List(FolderListCommand),
#[cfg(feature = "folder-expunge")]
#[command()] #[command()]
Expunge(FolderExpungeCommand), Expunge(FolderExpungeCommand),
#[cfg(feature = "folder-purge")]
#[command()] #[command()]
Purge(FolderPurgeCommand), Purge(FolderPurgeCommand),
#[cfg(feature = "folder-delete")]
#[command(alias = "remove", alias = "rm")] #[command(alias = "remove", alias = "rm")]
Delete(FolderDeleteCommand), Delete(FolderDeleteCommand),
} }
impl FolderSubcommand { impl FolderSubcommand {
#[allow(unused)]
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> { pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self { match self {
Self::Create(cmd) => cmd.execute(printer, config).await, #[cfg(feature = "folder-add")]
Self::Add(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "folder-list")]
Self::List(cmd) => cmd.execute(printer, config).await, Self::List(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "folder-expunge")]
Self::Expunge(cmd) => cmd.execute(printer, config).await, Self::Expunge(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "folder-purge")]
Self::Purge(cmd) => cmd.execute(printer, config).await, Self::Purge(cmd) => cmd.execute(printer, config).await,
#[cfg(feature = "folder-delete")]
Self::Delete(cmd) => cmd.execute(printer, config).await, Self::Delete(cmd) => cmd.execute(printer, config).await,
} }
} }

View file

@ -6,13 +6,13 @@ use email::folder::purge::imap::PurgeFolderImap;
use log::info; use log::info;
use std::process; use std::process;
#[cfg(any(feature = "imap", feature = "maildir", feature = "sync"))]
use crate::backend::BackendKind;
#[cfg(feature = "sync")]
use crate::cache::arg::disable::CacheDisableFlag;
use crate::{ use crate::{
account::arg::name::AccountNameFlag, account::arg::name::AccountNameFlag, backend::Backend, config::TomlConfig,
backend::{Backend, BackendKind}, folder::arg::name::FolderNameArg, printer::Printer,
cache::arg::disable::CacheDisableFlag,
config::TomlConfig,
folder::arg::name::FolderNameArg,
printer::Printer,
}; };
/// Purge a folder. /// Purge a folder.
@ -24,6 +24,7 @@ pub struct FolderPurgeCommand {
#[command(flatten)] #[command(flatten)]
pub folder: FolderNameArg, pub folder: FolderNameArg,
#[cfg(feature = "sync")]
#[command(flatten)] #[command(flatten)]
pub cache: CacheDisableFlag, pub cache: CacheDisableFlag,
@ -49,6 +50,7 @@ impl FolderPurgeCommand {
let (toml_account_config, account_config) = config.clone().into_account_configs( let (toml_account_config, account_config) = config.clone().into_account_configs(
self.account.name.as_ref().map(String::as_str), self.account.name.as_ref().map(String::as_str),
#[cfg(feature = "sync")]
self.cache.disable, self.cache.disable,
)?; )?;
@ -59,12 +61,19 @@ impl FolderPurgeCommand {
&account_config, &account_config,
purge_folder_kind, purge_folder_kind,
|builder| match purge_folder_kind { |builder| match purge_folder_kind {
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_purge_folder(|ctx| ctx.imap.as_ref().and_then(PurgeFolderImap::new));
}
// TODO // TODO
// #[cfg(feature = "maildir")]
// Some(BackendKind::Maildir) => { // Some(BackendKind::Maildir) => {
// builder.set_purge_folder(|ctx| { // builder.set_purge_folder(|ctx| {
// ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new) // ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new)
// }); // });
// } // }
// #[cfg(feature = "sync")]
// Some(BackendKind::MaildirForSync) => { // Some(BackendKind::MaildirForSync) => {
// builder.set_purge_folder(|ctx| { // builder.set_purge_folder(|ctx| {
// ctx.maildir_for_sync // ctx.maildir_for_sync
@ -72,11 +81,6 @@ impl FolderPurgeCommand {
// .and_then(PurgeFolderMaildir::new) // .and_then(PurgeFolderMaildir::new)
// }); // });
// } // }
#[cfg(feature = "imap")]
Some(BackendKind::Imap) => {
builder
.set_purge_folder(|ctx| ctx.imap.as_ref().and_then(PurgeFolderImap::new));
}
_ => (), _ => (),
}, },
) )

View file

@ -8,33 +8,44 @@ pub struct FolderConfig {
#[serde(alias = "aliases")] #[serde(alias = "aliases")]
pub alias: Option<HashMap<String, String>>, pub alias: Option<HashMap<String, String>>,
#[cfg(feature = "folder-add")]
pub add: Option<FolderAddConfig>, pub add: Option<FolderAddConfig>,
#[cfg(feature = "folder-list")]
pub list: Option<FolderListConfig>, pub list: Option<FolderListConfig>,
#[cfg(feature = "folder-expunge")]
pub expunge: Option<FolderExpungeConfig>, pub expunge: Option<FolderExpungeConfig>,
#[cfg(feature = "folder-purge")]
pub purge: Option<FolderPurgeConfig>, pub purge: Option<FolderPurgeConfig>,
#[cfg(feature = "folder-delete")]
pub delete: Option<FolderDeleteConfig>, pub delete: Option<FolderDeleteConfig>,
} }
impl FolderConfig { impl FolderConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
#[allow(unused_mut)]
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
#[cfg(feature = "folder-add")]
if let Some(add) = &self.add { if let Some(add) = &self.add {
kinds.extend(add.get_used_backends()); kinds.extend(add.get_used_backends());
} }
#[cfg(feature = "folder-list")]
if let Some(list) = &self.list { if let Some(list) = &self.list {
kinds.extend(list.get_used_backends()); kinds.extend(list.get_used_backends());
} }
#[cfg(feature = "folder-expunge")]
if let Some(expunge) = &self.expunge { if let Some(expunge) = &self.expunge {
kinds.extend(expunge.get_used_backends()); kinds.extend(expunge.get_used_backends());
} }
#[cfg(feature = "folder-purge")]
if let Some(purge) = &self.purge { if let Some(purge) = &self.purge {
kinds.extend(purge.get_used_backends()); kinds.extend(purge.get_used_backends());
} }
#[cfg(feature = "folder-delete")]
if let Some(delete) = &self.delete { if let Some(delete) = &self.delete {
kinds.extend(delete.get_used_backends()); kinds.extend(delete.get_used_backends());
} }
@ -43,11 +54,13 @@ impl FolderConfig {
} }
} }
#[cfg(feature = "folder-add")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FolderAddConfig { pub struct FolderAddConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "folder-add")]
impl FolderAddConfig { impl FolderAddConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -60,6 +73,7 @@ impl FolderAddConfig {
} }
} }
#[cfg(feature = "folder-list")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FolderListConfig { pub struct FolderListConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
@ -68,6 +82,7 @@ pub struct FolderListConfig {
pub remote: email::folder::list::config::FolderListConfig, pub remote: email::folder::list::config::FolderListConfig,
} }
#[cfg(feature = "folder-list")]
impl FolderListConfig { impl FolderListConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -80,11 +95,13 @@ impl FolderListConfig {
} }
} }
#[cfg(feature = "folder-expunge")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FolderExpungeConfig { pub struct FolderExpungeConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "folder-expunge")]
impl FolderExpungeConfig { impl FolderExpungeConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -97,11 +114,13 @@ impl FolderExpungeConfig {
} }
} }
#[cfg(feature = "folder-purge")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FolderPurgeConfig { pub struct FolderPurgeConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "folder-purge")]
impl FolderPurgeConfig { impl FolderPurgeConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();
@ -114,11 +133,13 @@ impl FolderPurgeConfig {
} }
} }
#[cfg(feature = "folder-delete")]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct FolderDeleteConfig { pub struct FolderDeleteConfig {
pub backend: Option<BackendKind>, pub backend: Option<BackendKind>,
} }
#[cfg(feature = "folder-delete")]
impl FolderDeleteConfig { impl FolderDeleteConfig {
pub fn get_used_backends(&self) -> HashSet<&BackendKind> { pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
let mut kinds = HashSet::default(); let mut kinds = HashSet::default();

View file

@ -1,22 +1,30 @@
#[cfg(feature = "folder-command")]
pub mod arg; pub mod arg;
#[cfg(feature = "folder-command")]
pub mod command; pub mod command;
pub mod config; pub mod config;
#[cfg(feature = "folder-command")]
use anyhow::Result; use anyhow::Result;
#[cfg(feature = "folder-command")]
use serde::Serialize; use serde::Serialize;
#[cfg(feature = "folder-command")]
use std::ops; use std::ops;
#[cfg(feature = "folder-command")]
use crate::{ use crate::{
printer::{PrintTable, PrintTableOpts, WriteColor}, printer::{PrintTable, PrintTableOpts, WriteColor},
ui::{Cell, Row, Table}, ui::{Cell, Row, Table},
}; };
#[cfg(feature = "folder-command")]
#[derive(Clone, Debug, Default, Serialize)] #[derive(Clone, Debug, Default, Serialize)]
pub struct Folder { pub struct Folder {
pub name: String, pub name: String,
pub desc: String, pub desc: String,
} }
#[cfg(feature = "folder-command")]
impl From<&email::folder::Folder> for Folder { impl From<&email::folder::Folder> for Folder {
fn from(folder: &email::folder::Folder) -> Self { fn from(folder: &email::folder::Folder) -> Self {
Folder { Folder {
@ -26,6 +34,7 @@ impl From<&email::folder::Folder> for Folder {
} }
} }
#[cfg(feature = "folder-command")]
impl Table for Folder { impl Table for Folder {
fn head() -> Row { fn head() -> Row {
Row::new() Row::new()
@ -40,9 +49,11 @@ impl Table for Folder {
} }
} }
#[cfg(feature = "folder-command")]
#[derive(Clone, Debug, Default, Serialize)] #[derive(Clone, Debug, Default, Serialize)]
pub struct Folders(Vec<Folder>); pub struct Folders(Vec<Folder>);
#[cfg(feature = "folder-command")]
impl ops::Deref for Folders { impl ops::Deref for Folders {
type Target = Vec<Folder>; type Target = Vec<Folder>;
@ -51,12 +62,14 @@ impl ops::Deref for Folders {
} }
} }
#[cfg(feature = "folder-command")]
impl From<email::folder::Folders> for Folders { impl From<email::folder::Folders> for Folders {
fn from(folders: email::folder::Folders) -> Self { fn from(folders: email::folder::Folders) -> Self {
Folders(folders.iter().map(Folder::from).collect()) Folders(folders.iter().map(Folder::from).collect())
} }
} }
#[cfg(feature = "folder-command")]
impl PrintTable for Folders { impl PrintTable for Folders {
fn print_table(&self, writer: &mut dyn WriteColor, opts: PrintTableOpts) -> Result<()> { fn print_table(&self, writer: &mut dyn WriteColor, opts: PrintTableOpts) -> Result<()> {
writeln!(writer)?; writeln!(writer)?;

View file

@ -1,12 +1,14 @@
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
use env_logger::{Builder as LoggerBuilder, Env, DEFAULT_FILTER_ENV}; use env_logger::{Builder as LoggerBuilder, Env, DEFAULT_FILTER_ENV};
use himalaya::{ #[cfg(any(feature = "envelope-list", feature = "message-mailto"))]
cli::Cli, config::TomlConfig, envelope::command::list::ListEnvelopesCommand, use himalaya::config::TomlConfig;
message::command::mailto::MessageMailtoCommand, printer::StdoutPrinter, #[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 log::{debug, warn};
use std::env;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
@ -21,9 +23,13 @@ async fn main() -> Result<()> {
.format_timestamp(None) .format_timestamp(None)
.init(); .init();
#[cfg(feature = "message-mailto")]
// if the first argument starts by "mailto:", execute straight the // if the first argument starts by "mailto:", execute straight the
// mailto message command // mailto message command
if let Some(ref url) = env::args().nth(1).filter(|arg| arg.starts_with("mailto:")) { if let Some(ref url) = std::env::args()
.nth(1)
.filter(|arg| arg.starts_with("mailto:"))
{
let mut printer = StdoutPrinter::default(); let mut printer = StdoutPrinter::default();
let config = TomlConfig::from_default_paths().await?; let config = TomlConfig::from_default_paths().await?;
@ -35,13 +41,20 @@ async fn main() -> Result<()> {
let cli = Cli::parse(); let cli = Cli::parse();
let mut printer = StdoutPrinter::new(cli.output, cli.color); let mut printer = StdoutPrinter::new(cli.output, cli.color);
#[cfg(feature = "envelope-list")]
match cli.command { match cli.command {
Some(cmd) => cmd.execute(&mut printer, cli.config_path.as_ref()).await, Some(cmd) => return cmd.execute(&mut printer, cli.config_path.as_ref()).await,
None => { None => {
let config = TomlConfig::from_some_path_or_default(cli.config_path.as_ref()).await?; let config = TomlConfig::from_some_path_or_default(cli.config_path.as_ref()).await?;
ListEnvelopesCommand::default() return ListEnvelopesCommand::default()
.execute(&mut printer, &config) .execute(&mut printer, &config)
.await .await;
} }
} }
#[cfg(not(feature = "envelope-list"))]
return cli
.command
.execute(&mut printer, cli.config_path.as_ref())
.await;
} }

View file

@ -1,4 +1,4 @@
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, bail, Context, Result};
use log::{debug, error}; use log::{debug, error};
use std::io::{self, Write}; use std::io::{self, Write};
@ -43,9 +43,11 @@ pub fn pre_edit() -> Result<PreEditChoice> {
} }
pub enum PostEditChoice { pub enum PostEditChoice {
#[cfg(feature = "message-send")]
Send, Send,
Edit, Edit,
LocalDraft, LocalDraft,
#[cfg(feature = "message-add")]
RemoteDraft, RemoteDraft,
Discard, Discard,
} }
@ -60,6 +62,7 @@ pub fn post_edit() -> Result<PostEditChoice> {
.context("cannot read stdin")?; .context("cannot read stdin")?;
match buf.bytes().next().map(|bytes| bytes as char) { match buf.bytes().next().map(|bytes| bytes as char) {
#[cfg(feature = "message-send")]
Some('s') => { Some('s') => {
debug!("send choice matched"); debug!("send choice matched");
Ok(PostEditChoice::Send) Ok(PostEditChoice::Send)
@ -68,6 +71,7 @@ pub fn post_edit() -> Result<PostEditChoice> {
debug!("save local draft choice matched"); debug!("save local draft choice matched");
Ok(PostEditChoice::LocalDraft) Ok(PostEditChoice::LocalDraft)
} }
#[cfg(feature = "message-add")]
Some('r') => { Some('r') => {
debug!("save remote draft matched"); debug!("save remote draft matched");
Ok(PostEditChoice::RemoteDraft) Ok(PostEditChoice::RemoteDraft)
@ -82,11 +86,11 @@ pub fn post_edit() -> Result<PostEditChoice> {
} }
Some(choice) => { Some(choice) => {
error!(r#"invalid choice "{}""#, choice); error!(r#"invalid choice "{}""#, choice);
Err(anyhow!(r#"invalid choice "{}""#, choice)) bail!("invalid choice {choice}");
} }
None => { None => {
error!("empty choice"); error!("empty choice");
Err(anyhow!("empty choice")) bail!("empty choice");
} }
} }
} }

View file

@ -2,10 +2,14 @@ use anyhow::{Context, Result};
use email::{ use email::{
account::config::AccountConfig, account::config::AccountConfig,
email::utils::{local_draft_path, remove_local_draft}, email::utils::{local_draft_path, remove_local_draft},
};
#[cfg(feature = "message-add")]
use email::{
flag::{Flag, Flags}, flag::{Flag, Flags},
folder::DRAFTS, folder::DRAFTS,
}; };
use log::debug; use log::debug;
#[cfg(any(feature = "message-send", feature = "template-send"))]
use mml::MmlCompilerBuilder; use mml::MmlCompilerBuilder;
use process::SingleCmd; use process::SingleCmd;
use std::{env, fs}; use std::{env, fs};
@ -44,8 +48,9 @@ pub async fn open_with_local_draft() -> Result<String> {
open_with_tpl(content).await open_with_tpl(content).await
} }
#[allow(unused)]
pub async fn edit_tpl_with_editor<P: Printer>( pub async fn edit_tpl_with_editor<P: Printer>(
#[allow(unused)] config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
backend: &Backend, backend: &Backend,
mut tpl: String, mut tpl: String,
@ -77,6 +82,7 @@ pub async fn edit_tpl_with_editor<P: Printer>(
loop { loop {
match choice::post_edit() { match choice::post_edit() {
#[cfg(feature = "message-send")]
Ok(PostEditChoice::Send) => { Ok(PostEditChoice::Send) => {
printer.print_log("Sending email…")?; printer.print_log("Sending email…")?;
@ -88,7 +94,7 @@ pub async fn edit_tpl_with_editor<P: Printer>(
let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend.send_raw_message(&email).await?; backend.send_message(&email).await?;
remove_local_draft()?; remove_local_draft()?;
printer.print("Done!")?; printer.print("Done!")?;
@ -102,6 +108,7 @@ pub async fn edit_tpl_with_editor<P: Printer>(
printer.print("Email successfully saved locally")?; printer.print("Email successfully saved locally")?;
break; break;
} }
#[cfg(feature = "message-add")]
Ok(PostEditChoice::RemoteDraft) => { Ok(PostEditChoice::RemoteDraft) => {
#[allow(unused_mut)] #[allow(unused_mut)]
let mut compiler = MmlCompilerBuilder::new(); let mut compiler = MmlCompilerBuilder::new();
@ -112,7 +119,7 @@ pub async fn edit_tpl_with_editor<P: Printer>(
let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend backend
.add_raw_message_with_flags( .add_message_with_flags(
DRAFTS, DRAFTS,
&email, &email,
&Flags::from_iter([Flag::Seen, Flag::Draft]), &Flags::from_iter([Flag::Seen, Flag::Draft]),