From a0888067dafcc2f2ae5deccd5ecf555bcab547fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Tue, 28 Nov 2023 12:30:50 +0100 Subject: [PATCH] fix sync cache --- Cargo.lock | 48 +++---- Cargo.toml | 8 +- config.sample.toml | 10 +- src/backend.rs | 201 +++++++++++++------------- src/config/config.rs | 102 +++++++++++++- src/main.rs | 325 ++++++++++++++++++++++++++----------------- 6 files changed, 428 insertions(+), 266 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d220ddf..b3bfaa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -984,7 +984,6 @@ dependencies = [ [[package]] name = "email-lib" version = "0.15.3" -source = "git+https://git.sr.ht/~soywod/pimalaya#012d31179908063affe3eec77365e5ac86c436fe" dependencies = [ "advisory-lock", "anyhow", @@ -2070,15 +2069,15 @@ dependencies = [ "keyring-lib", "log", "md5", - "mml-lib 1.0.1 (git+https://git.sr.ht/~soywod/pimalaya)", - "oauth-lib 0.1.0 (git+https://git.sr.ht/~soywod/pimalaya)", + "mml-lib 1.0.1", + "oauth-lib 0.1.0", "once_cell", "process-lib", "rusqlite", "secret-lib", "serde", "serde_json", - "shellexpand-utils 0.1.0 (git+https://git.sr.ht/~soywod/pimalaya)", + "shellexpand-utils 0.1.0", "tempfile", "termcolor", "terminal_size", @@ -2685,6 +2684,21 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mml-lib" +version = "1.0.1" +dependencies = [ + "async-recursion", + "chumsky", + "log", + "mail-builder", + "mail-parser", + "nanohtml2text", + "shellexpand-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror", + "tree_magic_mini", +] + [[package]] name = "mml-lib" version = "1.0.1" @@ -2707,22 +2721,6 @@ dependencies = [ "tree_magic_mini", ] -[[package]] -name = "mml-lib" -version = "1.0.1" -source = "git+https://git.sr.ht/~soywod/pimalaya#012d31179908063affe3eec77365e5ac86c436fe" -dependencies = [ - "async-recursion", - "chumsky", - "log", - "mail-builder", - "mail-parser", - "nanohtml2text", - "shellexpand-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror", - "tree_magic_mini", -] - [[package]] name = "nanohtml2text" version = "0.1.4" @@ -2848,8 +2846,6 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "oauth-lib" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1484d9864dbf6b55b3785380631a253fa0ff7f8e1bbb078bfd7effd11283d61" dependencies = [ "log", "oauth2", @@ -2862,7 +2858,8 @@ dependencies = [ [[package]] name = "oauth-lib" version = "0.1.0" -source = "git+https://git.sr.ht/~soywod/pimalaya#012d31179908063affe3eec77365e5ac86c436fe" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1484d9864dbf6b55b3785380631a253fa0ff7f8e1bbb078bfd7effd11283d61" dependencies = [ "log", "oauth2", @@ -3859,8 +3856,6 @@ dependencies = [ [[package]] name = "shellexpand-utils" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b44114d15a72740d3049e739929d0f4af335ba2eb855ea0f1fa2bfb4d7066215" dependencies = [ "log", "shellexpand", @@ -3870,7 +3865,8 @@ dependencies = [ [[package]] name = "shellexpand-utils" version = "0.1.0" -source = "git+https://git.sr.ht/~soywod/pimalaya#012d31179908063affe3eec77365e5ac86c436fe" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b44114d15a72740d3049e739929d0f4af335ba2eb855ea0f1fa2bfb4d7066215" dependencies = [ "log", "shellexpand", diff --git a/Cargo.toml b/Cargo.toml index 2686546..e8f25e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,21 +93,21 @@ version = "1.16.0" [dependencies.email-lib] # version = "=0.15.3" default-features = false -git = "https://git.sr.ht/~soywod/pimalaya" +path = "/home/soywod/sourcehut/pimalaya/email" [dependencies.keyring-lib] version = "=0.1.0" [dependencies.oauth-lib] # version = "=0.1.0" -git = "https://git.sr.ht/~soywod/pimalaya" +path = "/home/soywod/sourcehut/pimalaya/oauth" [dependencies.process-lib] version = "=0.1.0" [dependencies.mml-lib] # version = "=1.0.1" -git = "https://git.sr.ht/~soywod/pimalaya" +path = "/home/soywod/sourcehut/pimalaya/mml" [dependencies.secret-lib] version = "=0.1.0" @@ -121,7 +121,7 @@ version = "1.0" [dependencies.shellexpand-utils] # version = "=0.1.0" -git = "https://git.sr.ht/~soywod/pimalaya" +path = "/home/soywod/sourcehut/pimalaya/shellexpand-utils" [dependencies.termcolor] version = "1.1" diff --git a/config.sample.toml b/config.sample.toml index 956e5e5..b59b07e 100644 --- a/config.sample.toml +++ b/config.sample.toml @@ -6,13 +6,13 @@ default = true display-name = "My example account" email = "example@localhost" +sync = true +sync-dir = "./.sync" + # The default backend used for all the features like adding folders, # listing envelopes or copying messages. backend = "imap" -# Override the backend used for sending messages. -message.send.backend = "smtp" - # IMAP config imap.host = "localhost" imap.port = 3143 @@ -23,6 +23,9 @@ imap.insecure = true imap.auth = "passwd" imap.passwd.raw = "example" +# Override the backend used for sending messages. +message.send.backend = "smtp" + # SMTP config smtp.host = "localhost" smtp.port = 3025 @@ -32,4 +35,3 @@ smtp.starttls = false smtp.insecure = true smtp.auth = "passwd" smtp.passwd.raw = "example" - diff --git a/src/backend.rs b/src/backend.rs index c30805a..aed145c 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -39,12 +39,12 @@ use email::{ list::{imap::ListFoldersImap, maildir::ListFoldersMaildir}, purge::imap::PurgeFolderImap, }, - maildir::{MaildirSessionBuilder, MaildirSessionSync}, + maildir::{MaildirConfig, MaildirSessionBuilder, MaildirSessionSync}, sendmail::SendmailContext, }; use serde::{Deserialize, Serialize}; -use crate::config::DeserializedConfig; +use crate::{account::DeserializedAccountConfig, config::DeserializedConfig}; #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] @@ -61,9 +61,10 @@ pub enum BackendKind { #[derive(Clone, Default)] pub struct BackendContextBuilder { + sync_cache: Option, + maildir: Option, #[cfg(feature = "imap-backend")] imap: Option, - maildir: Option, #[cfg(feature = "smtp-sender")] smtp: Option, sendmail: Option, @@ -80,6 +81,10 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder { ctx.maildir = Some(maildir.build().await?); } + if let Some(maildir) = self.sync_cache { + ctx.sync_cache = Some(maildir.build().await?); + } + #[cfg(feature = "imap-backend")] if let Some(imap) = self.imap { ctx.imap = Some(imap.build().await?); @@ -105,9 +110,10 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder { #[derive(Default)] pub struct BackendContext { + pub sync_cache: Option, + pub maildir: Option, #[cfg(feature = "imap-backend")] pub imap: Option, - pub maildir: Option, #[cfg(feature = "smtp-sender")] pub smtp: Option, pub sendmail: Option, @@ -115,97 +121,14 @@ pub struct BackendContext { pub struct BackendBuilder(pub email::backend::BackendBuilder); +pub type Backend = email::backend::Backend; + impl BackendBuilder { - pub async fn new(config: DeserializedConfig, account_name: Option<&str>) -> Result { - let (account_name, mut deserialized_account_config) = match account_name { - Some("default") | Some("") | None => config - .accounts - .iter() - .find_map(|(name, account)| { - account - .default - .filter(|default| *default == true) - .map(|_| (name.to_owned(), account.clone())) - }) - .ok_or_else(|| anyhow!("cannot find default account")), - Some(name) => config - .accounts - .get(name) - .map(|account| (name.to_owned(), account.clone())) - .ok_or_else(|| anyhow!("cannot find account {name}")), - }?; - - #[cfg(feature = "imap-backend")] - if let Some(imap_config) = deserialized_account_config.imap.as_mut() { - imap_config - .auth - .replace_undefined_keyring_entries(&account_name); - } - - #[cfg(feature = "smtp-sender")] - if let Some(smtp_config) = deserialized_account_config.smtp.as_mut() { - smtp_config - .auth - .replace_undefined_keyring_entries(&account_name); - } - - let config = Config { - display_name: config.display_name, - signature_delim: config.signature_delim, - signature: config.signature, - downloads_dir: config.downloads_dir, - - folder_listing_page_size: config.folder_listing_page_size, - folder_aliases: config.folder_aliases, - - email_listing_page_size: config.email_listing_page_size, - email_listing_datetime_fmt: config.email_listing_datetime_fmt, - email_listing_datetime_local_tz: config.email_listing_datetime_local_tz, - email_reading_headers: config.email_reading_headers, - email_reading_format: config.email_reading_format, - email_writing_headers: config.email_writing_headers, - email_sending_save_copy: config.email_sending_save_copy, - email_hooks: config.email_hooks, - - accounts: HashMap::from_iter(config.accounts.clone().into_iter().map( - |(name, config)| { - ( - name.clone(), - AccountConfig { - name, - email: config.email, - display_name: config.display_name, - signature_delim: config.signature_delim, - signature: config.signature, - downloads_dir: config.downloads_dir, - - folder_listing_page_size: config.folder_listing_page_size, - folder_aliases: config.folder_aliases.unwrap_or_default(), - - email_listing_page_size: config.email_listing_page_size, - email_listing_datetime_fmt: config.email_listing_datetime_fmt, - email_listing_datetime_local_tz: config.email_listing_datetime_local_tz, - - email_reading_headers: config.email_reading_headers, - email_reading_format: config.email_reading_format.unwrap_or_default(), - email_writing_headers: config.email_writing_headers, - email_sending_save_copy: config.email_sending_save_copy, - email_hooks: config.email_hooks.unwrap_or_default(), - - sync: config.sync, - sync_dir: config.sync_dir, - sync_folders_strategy: config.sync_folders_strategy.unwrap_or_default(), - - #[cfg(feature = "pgp")] - pgp: config.pgp, - }, - ) - }, - )), - }; - - let account_config = config.account(&account_name)?; - + pub async fn new( + deserialized_account_config: DeserializedAccountConfig, + account_config: AccountConfig, + disable_cache: bool, + ) -> Result { let backend_ctx_builder = BackendContextBuilder { maildir: deserialized_account_config .maildir @@ -213,6 +136,16 @@ impl BackendBuilder { .map(|mdir_config| { MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone()) }), + sync_cache: if account_config.sync && !disable_cache { + Some(MaildirSessionBuilder::new( + account_config.clone(), + MaildirConfig { + root_dir: account_config.sync_dir()?, + }, + )) + } else { + None + }, #[cfg(feature = "imap-backend")] imap: deserialized_account_config .imap @@ -253,6 +186,10 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match add_folder { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder + .with_add_folder(|ctx| ctx.sync_cache.as_ref().and_then(AddFolderMaildir::new)); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder .with_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new)); @@ -278,6 +215,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match list_folders { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_list_folders(|ctx| { + ctx.sync_cache.as_ref().and_then(ListFoldersMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_list_folders(|ctx| { ctx.maildir.as_ref().and_then(ListFoldersMaildir::new) @@ -305,6 +247,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match expunge_folder { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_expunge_folder(|ctx| { + ctx.sync_cache.as_ref().and_then(ExpungeFolderMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_expunge_folder(|ctx| { ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new) @@ -332,6 +279,12 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match purge_folder { + // TODO + // Some(_) if account_config.sync && !disable_cache => { + // backend_builder = backend_builder.with_purge_folder(|ctx| { + // ctx.sync_cache.as_ref().and_then(PurgeFolderMaildir::new) + // }); + // } // TODO // Some(BackendKind::Maildir) => { // backend_builder = backend_builder @@ -359,6 +312,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match delete_folder { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_delete_folder(|ctx| { + ctx.sync_cache.as_ref().and_then(DeleteFolderMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_delete_folder(|ctx| { ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new) @@ -386,6 +344,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match get_envelope { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_get_envelope(|ctx| { + ctx.sync_cache.as_ref().and_then(GetEnvelopeMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_get_envelope(|ctx| { ctx.maildir.as_ref().and_then(GetEnvelopeMaildir::new) @@ -413,6 +376,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match list_envelopes { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_list_envelopes(|ctx| { + ctx.sync_cache.as_ref().and_then(ListEnvelopesMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_list_envelopes(|ctx| { ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new) @@ -440,6 +408,10 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match add_flags { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder + .with_add_flags(|ctx| ctx.sync_cache.as_ref().and_then(AddFlagsMaildir::new)); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder .with_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); @@ -465,6 +437,10 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match set_flags { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder + .with_set_flags(|ctx| ctx.sync_cache.as_ref().and_then(SetFlagsMaildir::new)); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder .with_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new)); @@ -490,6 +466,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match remove_flags { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_remove_flags(|ctx| { + ctx.sync_cache.as_ref().and_then(RemoveFlagsMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_remove_flags(|ctx| { ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new) @@ -539,6 +520,13 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match add_msg { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| { + ctx.sync_cache + .as_ref() + .and_then(AddRawMessageWithFlagsMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| { ctx.maildir @@ -571,6 +559,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match peek_msgs { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_peek_messages(|ctx| { + ctx.sync_cache.as_ref().and_then(PeekMessagesMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_peek_messages(|ctx| { ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) @@ -620,6 +613,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match copy_msgs { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_copy_messages(|ctx| { + ctx.sync_cache.as_ref().and_then(CopyMessagesMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_copy_messages(|ctx| { ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new) @@ -647,6 +645,11 @@ impl BackendBuilder { .or_else(|| deserialized_account_config.backend.as_ref()); match move_msgs { + Some(_) if account_config.sync && !disable_cache => { + backend_builder = backend_builder.with_move_messages(|ctx| { + ctx.sync_cache.as_ref().and_then(MoveMessagesMaildir::new) + }); + } Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_move_messages(|ctx| { ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new) @@ -668,14 +671,8 @@ impl BackendBuilder { Ok(Self(backend_builder)) } -} -impl Deref for BackendBuilder { - type Target = email::backend::BackendBuilder; - - fn deref(&self) -> &Self::Target { - &self.0 + pub async fn build(self) -> Result { + self.0.build().await } } - -pub type Backend = email::backend::Backend; diff --git a/src/config/config.rs b/src/config/config.rs index 4ece9b8..a62aaa0 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -6,7 +6,11 @@ use anyhow::{anyhow, Context, Result}; use dialoguer::Confirm; use dirs::{config_dir, home_dir}; -use email::email::{EmailHooks, EmailTextPlainFormat}; +use email::{ + account::AccountConfig, + config::Config, + email::{EmailHooks, EmailTextPlainFormat}, +}; use log::{debug, trace}; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fs, path::PathBuf, process::exit}; @@ -98,6 +102,102 @@ impl DeserializedConfig { .or_else(|| home_dir().map(|p| p.join(".himalayarc"))) .filter(|p| p.exists()) } + + pub fn into_account_configs( + self, + account_name: Option<&str>, + ) -> Result<(DeserializedAccountConfig, AccountConfig)> { + let (account_name, mut toml_account_config) = match account_name { + Some("default") | Some("") | None => self + .accounts + .iter() + .find_map(|(name, account)| { + account + .default + .filter(|default| *default == true) + .map(|_| (name.to_owned(), account.clone())) + }) + .ok_or_else(|| anyhow!("cannot find default account")), + Some(name) => self + .accounts + .get(name) + .map(|account| (name.to_owned(), account.clone())) + .ok_or_else(|| anyhow!("cannot find account {name}")), + }?; + + #[cfg(feature = "imap-backend")] + if let Some(imap_config) = toml_account_config.imap.as_mut() { + imap_config + .auth + .replace_undefined_keyring_entries(&account_name); + } + + #[cfg(feature = "smtp-sender")] + if let Some(smtp_config) = toml_account_config.smtp.as_mut() { + smtp_config + .auth + .replace_undefined_keyring_entries(&account_name); + } + + let config = Config { + display_name: self.display_name, + signature_delim: self.signature_delim, + signature: self.signature, + downloads_dir: self.downloads_dir, + + folder_listing_page_size: self.folder_listing_page_size, + folder_aliases: self.folder_aliases, + + email_listing_page_size: self.email_listing_page_size, + email_listing_datetime_fmt: self.email_listing_datetime_fmt, + email_listing_datetime_local_tz: self.email_listing_datetime_local_tz, + email_reading_headers: self.email_reading_headers, + email_reading_format: self.email_reading_format, + email_writing_headers: self.email_writing_headers, + email_sending_save_copy: self.email_sending_save_copy, + email_hooks: self.email_hooks, + + accounts: HashMap::from_iter(self.accounts.clone().into_iter().map( + |(name, config)| { + ( + name.clone(), + AccountConfig { + name, + email: config.email, + display_name: config.display_name, + signature_delim: config.signature_delim, + signature: config.signature, + downloads_dir: config.downloads_dir, + + folder_listing_page_size: config.folder_listing_page_size, + folder_aliases: config.folder_aliases.unwrap_or_default(), + + email_listing_page_size: config.email_listing_page_size, + email_listing_datetime_fmt: config.email_listing_datetime_fmt, + email_listing_datetime_local_tz: config.email_listing_datetime_local_tz, + + email_reading_headers: config.email_reading_headers, + email_reading_format: config.email_reading_format.unwrap_or_default(), + email_writing_headers: config.email_writing_headers, + email_sending_save_copy: config.email_sending_save_copy, + email_hooks: config.email_hooks.unwrap_or_default(), + + sync: config.sync.unwrap_or_default(), + sync_dir: config.sync_dir, + sync_folders_strategy: config.sync_folders_strategy.unwrap_or_default(), + + #[cfg(feature = "pgp")] + pgp: config.pgp, + }, + ) + }, + )), + }; + + let account_config = config.account(&account_name)?; + + Ok((toml_account_config, account_config)) + } } #[cfg(test)] diff --git a/src/main.rs b/src/main.rs index 5256932..3eed799 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,21 +56,16 @@ async fn main() -> Result<()> { // checks mailto command before app initialization let raw_args: Vec = env::args().collect(); if raw_args.len() > 1 && raw_args[1].starts_with("mailto:") { - // let url = Url::parse(&raw_args[1])?; - // let config = DeserializedConfig::from_opt_path(None).await?; - // let account_config = config.to_account_config(None)?; - // let backend = BackendBuilder::new(account_config.clone()).build().await?; - // let mut printer = StdoutPrinter::default(); + let url = Url::parse(&raw_args[1])?; + let (toml_account_config, account_config) = DeserializedConfig::from_opt_path(None) + .await? + .into_account_configs(None)?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), false).await?; + let backend = backend_builder.build().await?; + let mut printer = StdoutPrinter::default(); - // email::handlers::mailto( - // &account_config, - // &backend, - // &mut printer, - // &url, - // ) - // .await?; - - return Ok(()); + return email::handlers::mailto(&account_config, &backend, &mut printer, &url).await; } let app = create_app(); @@ -93,15 +88,18 @@ async fn main() -> Result<()> { _ => (), } - let config = DeserializedConfig::from_opt_path(config::args::parse_arg(&m)).await?; let maybe_account_name = account::args::parse_arg(&m); + let toml_config = DeserializedConfig::from_opt_path(config::args::parse_arg(&m)).await?; + let (toml_account_config, account_config) = toml_config + .clone() + .into_account_configs(maybe_account_name)?; + let folder = folder::args::parse_source_arg(&m); let disable_cache = cache::args::parse_disable_cache_flag(&m); - let backend_builder = BackendBuilder::new(config.clone(), maybe_account_name).await?; - let account_config = &backend_builder.account_config; let mut printer = StdoutPrinter::try_from(&m)?; + // FIXME // #[cfg(feature = "imap-backend")] // if let BackendConfig::Imap(imap_config) = &account_config.backend { // let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); @@ -124,10 +122,12 @@ async fn main() -> Result<()> { match account::args::matches(&m)? { Some(account::args::Cmd::List(max_width)) => { - account::handlers::list(max_width, &account_config, &config, &mut printer)?; + account::handlers::list(max_width, &account_config, &toml_config, &mut printer)?; return Ok(()); } Some(account::args::Cmd::Sync(strategy, dry_run)) => { + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), true).await?; let sync_builder = AccountSyncBuilder::new(backend_builder.0) .await? .with_some_folders_strategy(strategy) @@ -148,26 +148,39 @@ async fn main() -> Result<()> { let folder = folder .ok_or_else(|| anyhow!("the folder argument is missing")) .context("cannot create folder")?; - let backend = backend_builder.clone().build().await?; - folder::handlers::create(&mut printer, &backend, &folder).await?; - return Ok(()); + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; + + return folder::handlers::create(&mut printer, &backend, &folder).await; } Some(folder::args::Cmd::List(max_width)) => { - let backend = backend_builder.clone().build().await?; - folder::handlers::list(&account_config, &mut printer, &backend, max_width).await?; - return Ok(()); + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; + + return folder::handlers::list(&account_config, &mut printer, &backend, max_width) + .await; } Some(folder::args::Cmd::Expunge) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; - folder::handlers::expunge(&mut printer, &backend, &folder).await?; - return Ok(()); + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; + + return folder::handlers::expunge(&mut printer, &backend, &folder).await; } Some(folder::args::Cmd::Delete) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; - folder::handlers::delete(&mut printer, &backend, &folder).await?; - return Ok(()); + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; + + return folder::handlers::delete(&mut printer, &backend, &folder).await; } _ => (), } @@ -176,9 +189,13 @@ async fn main() -> Result<()> { match email::args::matches(&m)? { Some(email::args::Cmd::Attachments(ids)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::attachments( + + return email::handlers::attachments( &account_config, &mut printer, &id_mapper, @@ -186,34 +203,45 @@ async fn main() -> Result<()> { &folder, ids, ) - .await?; - return Ok(()); + .await; } Some(email::args::Cmd::Copy(ids, to_folder)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::copy(&mut printer, &id_mapper, &backend, &folder, to_folder, ids) - .await?; - - return Ok(()); + return email::handlers::copy( + &mut printer, + &id_mapper, + &backend, + &folder, + to_folder, + ids, + ) + .await; } Some(email::args::Cmd::Delete(ids)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::delete(&mut printer, &id_mapper, &backend, &folder, ids).await?; - - return Ok(()); + return email::handlers::delete(&mut printer, &id_mapper, &backend, &folder, ids).await; } Some(email::args::Cmd::Forward(id, headers, body)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::forward( + return email::handlers::forward( &account_config, &mut printer, &id_mapper, @@ -223,16 +251,17 @@ async fn main() -> Result<()> { headers, body, ) - .await?; - - return Ok(()); + .await; } Some(email::args::Cmd::List(max_width, page_size, page)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::list( + return email::handlers::list( &account_config, &mut printer, &id_mapper, @@ -242,26 +271,35 @@ async fn main() -> Result<()> { page_size, page, ) - .await?; - - return Ok(()); + .await; } Some(email::args::Cmd::Move(ids, to_folder)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::move_(&mut printer, &id_mapper, &backend, &folder, to_folder, ids) - .await?; - - return Ok(()); + return email::handlers::move_( + &mut printer, + &id_mapper, + &backend, + &folder, + to_folder, + ids, + ) + .await; } Some(email::args::Cmd::Read(ids, text_mime, raw, headers)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::read( + return email::handlers::read( &account_config, &mut printer, &id_mapper, @@ -272,16 +310,17 @@ async fn main() -> Result<()> { raw, headers, ) - .await?; - - return Ok(()); + .await; } Some(email::args::Cmd::Reply(id, all, headers, body)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::reply( + return email::handlers::reply( &account_config, &mut printer, &id_mapper, @@ -292,25 +331,28 @@ async fn main() -> Result<()> { headers, body, ) - .await?; - - return Ok(()); + .await; } Some(email::args::Cmd::Save(raw_email)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::save(&mut printer, &id_mapper, &backend, &folder, raw_email).await?; - - return Ok(()); + return email::handlers::save(&mut printer, &id_mapper, &backend, &folder, raw_email) + .await; } Some(email::args::Cmd::Search(query, max_width, page_size, page)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::search( + return email::handlers::search( &account_config, &mut printer, &id_mapper, @@ -321,16 +363,17 @@ async fn main() -> Result<()> { page_size, page, ) - .await?; - - return Ok(()); + .await; } Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - email::handlers::sort( + return email::handlers::sort( &account_config, &mut printer, &id_mapper, @@ -342,56 +385,79 @@ async fn main() -> Result<()> { page_size, page, ) - .await?; - - return Ok(()); + .await; } Some(email::args::Cmd::Send(raw_email)) => { - let backend = backend_builder.clone().build().await?; - email::handlers::send(&account_config, &mut printer, &backend, raw_email).await?; - - return Ok(()); + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; + return email::handlers::send(&account_config, &mut printer, &backend, raw_email).await; } Some(email::args::Cmd::Flag(m)) => match m { Some(flag::args::Cmd::Set(ids, ref flags)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - - flag::handlers::set(&mut printer, &id_mapper, &backend, &folder, ids, flags) - .await?; - - return Ok(()); + return flag::handlers::set( + &mut printer, + &id_mapper, + &backend, + &folder, + ids, + flags, + ) + .await; } Some(flag::args::Cmd::Add(ids, ref flags)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - - flag::handlers::add(&mut printer, &id_mapper, &backend, &folder, ids, flags) - .await?; - - return Ok(()); + return flag::handlers::add( + &mut printer, + &id_mapper, + &backend, + &folder, + ids, + flags, + ) + .await; } Some(flag::args::Cmd::Remove(ids, ref flags)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - flag::handlers::remove(&mut printer, &id_mapper, &backend, &folder, ids, flags) - .await?; - - return Ok(()); + return flag::handlers::remove( + &mut printer, + &id_mapper, + &backend, + &folder, + ids, + flags, + ) + .await; } _ => (), }, Some(email::args::Cmd::Tpl(m)) => match m { Some(tpl::args::Cmd::Forward(id, headers, body)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - - tpl::handlers::forward( + return tpl::handlers::forward( &account_config, &mut printer, &id_mapper, @@ -401,9 +467,7 @@ async fn main() -> Result<()> { headers, body, ) - .await?; - - return Ok(()); + .await; } Some(tpl::args::Cmd::Write(headers, body)) => { tpl::handlers::write(&account_config, &mut printer, headers, body).await?; @@ -411,10 +475,12 @@ async fn main() -> Result<()> { } Some(tpl::args::Cmd::Reply(id, all, headers, body)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - - tpl::handlers::reply( + return tpl::handlers::reply( &account_config, &mut printer, &id_mapper, @@ -425,16 +491,16 @@ async fn main() -> Result<()> { headers, body, ) - .await?; - - return Ok(()); + .await; } Some(tpl::args::Cmd::Save(tpl)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - let backend = backend_builder.clone().build().await?; + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; let id_mapper = IdMapper::new(&backend, &account_config, &folder)?; - - tpl::handlers::save( + return tpl::handlers::save( &account_config, &mut printer, &id_mapper, @@ -442,23 +508,24 @@ async fn main() -> Result<()> { &folder, tpl, ) - .await?; - - return Ok(()); + .await; } Some(tpl::args::Cmd::Send(tpl)) => { - let backend = backend_builder.clone().build().await?; - tpl::handlers::send(&account_config, &mut printer, &backend, tpl).await?; - - return Ok(()); + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; + return tpl::handlers::send(&account_config, &mut printer, &backend, tpl).await; } _ => (), }, Some(email::args::Cmd::Write(headers, body)) => { - let backend = backend_builder.clone().build().await?; - email::handlers::write(&account_config, &mut printer, &backend, headers, body).await?; - - return Ok(()); + let backend_builder = + BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) + .await?; + let backend = backend_builder.build().await?; + return email::handlers::write(&account_config, &mut printer, &backend, headers, body) + .await; } _ => (), }