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