From fb8f356e8c14a6c419abcb22ace7c0070c082016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Tue, 28 Nov 2023 22:28:28 +0100 Subject: [PATCH] fix id mapper --- src/backend.rs | 546 +++++++++++++++++++---------------- src/cache/id_mapper.rs | 58 ++-- src/config/config.rs | 8 + src/domain/account/config.rs | 138 +++++++++ src/domain/email/handlers.rs | 36 +-- src/domain/flag/handlers.rs | 16 +- src/domain/tpl/handlers.rs | 18 +- src/main.rs | 248 +++------------- 8 files changed, 518 insertions(+), 550 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index aed145c..eef8843 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,7 +1,6 @@ -use std::{collections::HashMap, ops::Deref}; - -use anyhow::{anyhow, Result}; +use anyhow::Result; use async_trait::async_trait; +use std::ops::Deref; #[cfg(feature = "imap-backend")] use email::imap::{ImapSessionBuilder, ImapSessionSync}; @@ -9,7 +8,6 @@ use email::imap::{ImapSessionBuilder, ImapSessionSync}; use email::smtp::{SmtpClientBuilder, SmtpClientSync}; use email::{ account::AccountConfig, - config::Config, email::{ envelope::{ get::{imap::GetEnvelopeImap, maildir::GetEnvelopeMaildir}, @@ -32,6 +30,8 @@ use email::{ send_raw::{sendmail::SendRawMessageSendmail, smtp::SendRawMessageSmtp}, }, }, + envelope::{Id, SingleId}, + flag::Flags, folder::{ add::{imap::AddFolderImap, maildir::AddFolderMaildir}, delete::{imap::DeleteFolderImap, maildir::DeleteFolderMaildir}, @@ -40,16 +40,19 @@ use email::{ purge::imap::PurgeFolderImap, }, maildir::{MaildirConfig, MaildirSessionBuilder, MaildirSessionSync}, + message::Messages, sendmail::SendmailContext, }; use serde::{Deserialize, Serialize}; -use crate::{account::DeserializedAccountConfig, config::DeserializedConfig}; +use crate::{account::DeserializedAccountConfig, Envelopes, IdMapper}; #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum BackendKind { Maildir, + #[serde(skip_deserializing)] + MaildirForSync, #[cfg(feature = "imap-backend")] Imap, #[cfg(feature = "notmuch-backend")] @@ -61,8 +64,8 @@ pub enum BackendKind { #[derive(Clone, Default)] pub struct BackendContextBuilder { - sync_cache: Option, maildir: Option, + maildir_for_sync: Option, #[cfg(feature = "imap-backend")] imap: Option, #[cfg(feature = "smtp-sender")] @@ -81,8 +84,8 @@ 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?); + if let Some(maildir) = self.maildir_for_sync { + ctx.maildir_for_sync = Some(maildir.build().await?); } #[cfg(feature = "imap-backend")] @@ -110,8 +113,8 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder { #[derive(Default)] pub struct BackendContext { - pub sync_cache: Option, pub maildir: Option, + pub maildir_for_sync: Option, #[cfg(feature = "imap-backend")] pub imap: Option, #[cfg(feature = "smtp-sender")] @@ -119,55 +122,178 @@ pub struct BackendContext { pub sendmail: Option, } -pub struct BackendBuilder(pub email::backend::BackendBuilder); +pub struct Backend { + toml_account_config: DeserializedAccountConfig, + backend: email::backend::Backend, +} -pub type Backend = email::backend::Backend; +impl Backend { + fn build_id_mapper( + &self, + folder: &str, + backend_kind: Option<&BackendKind>, + ) -> Result { + let mut id_mapper = IdMapper::Dummy; + + match backend_kind { + Some(BackendKind::Maildir) => { + if let Some(mdir_config) = &self.toml_account_config.maildir { + id_mapper = IdMapper::new( + &self.backend.account_config, + folder, + mdir_config.root_dir.clone(), + )?; + } + } + Some(BackendKind::MaildirForSync) => { + id_mapper = IdMapper::new( + &self.backend.account_config, + folder, + self.backend.account_config.sync_dir()?, + )?; + } + #[cfg(feature = "notmuch-backend")] + Some(BackendKind::Notmuch) => { + if let Some(notmuch_config) = &self.toml_account_config.notmuch { + id_mapper = IdMapper::new( + &self.backend.account_config, + folder, + mdir_config.root_dir.clone(), + )?; + } + } + _ => (), + }; + + Ok(id_mapper) + } + + pub async fn list_envelopes( + &self, + folder: &str, + page_size: usize, + page: usize, + ) -> Result { + let backend_kind = self.toml_account_config.list_envelopes_kind(); + let id_mapper = self.build_id_mapper(folder, backend_kind)?; + let envelopes = self.backend.list_envelopes(folder, page_size, page).await?; + let envelopes = Envelopes::from_backend(&self.account_config, &id_mapper, envelopes)?; + Ok(envelopes) + } + + pub async fn add_flags(&self, folder: &str, ids: &[&str], flags: &Flags) -> Result<()> { + let backend_kind = self.toml_account_config.add_flags_kind(); + let id_mapper = self.build_id_mapper(folder, backend_kind)?; + let ids = Id::multiple(id_mapper.get_ids(ids)?); + self.backend.add_flags(folder, &ids, flags).await + } + + pub async fn set_flags(&self, folder: &str, ids: &[&str], flags: &Flags) -> Result<()> { + let backend_kind = self.toml_account_config.set_flags_kind(); + let id_mapper = self.build_id_mapper(folder, backend_kind)?; + let ids = Id::multiple(id_mapper.get_ids(ids)?); + self.backend.set_flags(folder, &ids, flags).await + } + + pub async fn remove_flags(&self, folder: &str, ids: &[&str], flags: &Flags) -> Result<()> { + let backend_kind = self.toml_account_config.remove_flags_kind(); + let id_mapper = self.build_id_mapper(folder, backend_kind)?; + let ids = Id::multiple(id_mapper.get_ids(ids)?); + self.backend.remove_flags(folder, &ids, flags).await + } + + pub async fn get_messages(&self, folder: &str, ids: &[&str]) -> Result { + let backend_kind = self.toml_account_config.get_messages_kind(); + let id_mapper = self.build_id_mapper(folder, backend_kind)?; + let ids = Id::multiple(id_mapper.get_ids(ids)?); + self.backend.get_messages(folder, &ids).await + } + + pub async fn copy_messages( + &self, + from_folder: &str, + to_folder: &str, + ids: &[&str], + ) -> Result<()> { + let backend_kind = self.toml_account_config.move_messages_kind(); + let id_mapper = self.build_id_mapper(from_folder, backend_kind)?; + let ids = Id::multiple(id_mapper.get_ids(ids)?); + self.backend + .copy_messages(from_folder, to_folder, &ids) + .await + } + + pub async fn move_messages( + &self, + from_folder: &str, + to_folder: &str, + ids: &[&str], + ) -> Result<()> { + let backend_kind = self.toml_account_config.move_messages_kind(); + let id_mapper = self.build_id_mapper(from_folder, backend_kind)?; + let ids = Id::multiple(id_mapper.get_ids(ids)?); + self.backend + .move_messages(from_folder, to_folder, &ids) + .await + } + + pub async fn delete_messages(&self, folder: &str, ids: &[&str]) -> Result<()> { + let backend_kind = self.toml_account_config.delete_messages_kind(); + let id_mapper = self.build_id_mapper(folder, backend_kind)?; + let ids = Id::multiple(id_mapper.get_ids(ids)?); + self.backend.delete_messages(folder, &ids).await + } + + pub async fn add_raw_message(&self, folder: &str, email: &[u8]) -> Result { + let backend_kind = self.toml_account_config.add_raw_message_kind(); + let id_mapper = self.build_id_mapper(folder, backend_kind)?; + let id = self.backend.add_raw_message(folder, email).await?; + id_mapper.create_alias(&*id)?; + Ok(id) + } +} + +impl Deref for Backend { + type Target = email::backend::Backend; + + fn deref(&self) -> &Self::Target { + &self.backend + } +} + +pub struct BackendBuilder { + toml_account_config: DeserializedAccountConfig, + builder: email::backend::BackendBuilder, +} impl BackendBuilder { pub async fn new( - deserialized_account_config: DeserializedAccountConfig, + toml_account_config: DeserializedAccountConfig, account_config: AccountConfig, - disable_cache: bool, ) -> Result { let backend_ctx_builder = BackendContextBuilder { - maildir: deserialized_account_config - .maildir - .as_ref() - .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 - }, + maildir: toml_account_config.maildir.as_ref().map(|mdir_config| { + MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone()) + }), + maildir_for_sync: Some(MaildirSessionBuilder::new( + account_config.clone(), + MaildirConfig { + root_dir: account_config.sync_dir()?, + }, + )), #[cfg(feature = "imap-backend")] - imap: deserialized_account_config - .imap - .as_ref() - .map(|imap_config| { - ImapSessionBuilder::new(account_config.clone(), imap_config.clone()) - }), + imap: toml_account_config.imap.as_ref().map(|imap_config| { + ImapSessionBuilder::new(account_config.clone(), imap_config.clone()) + }), #[cfg(feature = "notmuch-backend")] - notmuch: deserialized_account_config - .notmuch - .as_ref() - .map(|notmuch_config| { - NotmuchSessionBuilder::new(account_config.clone(), notmuch_config.clone()) - }), + notmuch: toml_account_config.notmuch.as_ref().map(|notmuch_config| { + NotmuchSessionBuilder::new(account_config.clone(), notmuch_config.clone()) + }), #[cfg(feature = "smtp-sender")] - smtp: deserialized_account_config - .smtp - .as_ref() - .map(|smtp_config| { - SmtpClientBuilder::new(account_config.clone(), smtp_config.clone()) - }), - sendmail: deserialized_account_config + smtp: toml_account_config.smtp.as_ref().map(|smtp_config| { + SmtpClientBuilder::new(account_config.clone(), smtp_config.clone()) + }), + sendmail: toml_account_config .sendmail .as_ref() .map(|sendmail_config| { @@ -178,22 +304,18 @@ impl BackendBuilder { let mut backend_builder = email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder); - let add_folder = deserialized_account_config - .folder - .as_ref() - .and_then(|folder| folder.add.as_ref()) - .and_then(|add| add.backend.as_ref()) - .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)); - } + match toml_account_config.add_folder_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder .with_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new)); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_add_folder(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(AddFolderMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -207,24 +329,19 @@ impl BackendBuilder { _ => (), } - let list_folders = deserialized_account_config - .folder - .as_ref() - .and_then(|folder| folder.list.as_ref()) - .and_then(|list| list.backend.as_ref()) - .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) - }); - } + match toml_account_config.list_folders_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_list_folders(|ctx| { ctx.maildir.as_ref().and_then(ListFoldersMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_list_folders(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(ListFoldersMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -239,24 +356,19 @@ impl BackendBuilder { _ => (), } - let expunge_folder = deserialized_account_config - .folder - .as_ref() - .and_then(|folder| folder.expunge.as_ref()) - .and_then(|expunge| expunge.backend.as_ref()) - .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) - }); - } + match toml_account_config.expunge_folder_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_expunge_folder(|ctx| { ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_expunge_folder(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(ExpungeFolderMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -271,25 +383,17 @@ impl BackendBuilder { _ => (), } - let purge_folder = deserialized_account_config - .folder - .as_ref() - .and_then(|folder| folder.purge.as_ref()) - .and_then(|purge| purge.backend.as_ref()) - .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) - // }); - // } + match toml_account_config.purge_folder_kind() { // TODO // Some(BackendKind::Maildir) => { // backend_builder = backend_builder // .with_purge_folder(|ctx| ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new)); // } + // TODO + // Some(BackendKind::MaildirForSync) => { + // backend_builder = backend_builder + // .with_purge_folder(|ctx| ctx.maildir_for_sync.as_ref().and_then(PurgeFolderMaildir::new)); + // } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -304,24 +408,19 @@ impl BackendBuilder { _ => (), } - let delete_folder = deserialized_account_config - .folder - .as_ref() - .and_then(|folder| folder.delete.as_ref()) - .and_then(|delete| delete.backend.as_ref()) - .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) - }); - } + match toml_account_config.delete_folder_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_delete_folder(|ctx| { ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_delete_folder(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(DeleteFolderMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -336,24 +435,19 @@ impl BackendBuilder { _ => (), } - let get_envelope = deserialized_account_config - .envelope - .as_ref() - .and_then(|envelope| envelope.get.as_ref()) - .and_then(|get| get.backend.as_ref()) - .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) - }); - } + match toml_account_config.get_envelope_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_get_envelope(|ctx| { ctx.maildir.as_ref().and_then(GetEnvelopeMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_get_envelope(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(GetEnvelopeMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -368,24 +462,19 @@ impl BackendBuilder { _ => (), } - let list_envelopes = deserialized_account_config - .envelope - .as_ref() - .and_then(|envelope| envelope.list.as_ref()) - .and_then(|send| send.backend.as_ref()) - .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) - }); - } + match toml_account_config.list_envelopes_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_list_envelopes(|ctx| { ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_list_envelopes(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(ListEnvelopesMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -400,22 +489,16 @@ impl BackendBuilder { _ => (), } - let add_flags = deserialized_account_config - .flag - .as_ref() - .and_then(|flag| flag.add.as_ref()) - .and_then(|add| add.backend.as_ref()) - .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)); - } + match toml_account_config.add_flags_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder .with_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_add_flags(|ctx| { + ctx.maildir_for_sync.as_ref().and_then(AddFlagsMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -429,22 +512,16 @@ impl BackendBuilder { _ => (), } - let set_flags = deserialized_account_config - .flag - .as_ref() - .and_then(|flag| flag.set.as_ref()) - .and_then(|set| set.backend.as_ref()) - .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)); - } + match toml_account_config.set_flags_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder .with_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new)); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_set_flags(|ctx| { + ctx.maildir_for_sync.as_ref().and_then(SetFlagsMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -458,24 +535,19 @@ impl BackendBuilder { _ => (), } - let remove_flags = deserialized_account_config - .flag - .as_ref() - .and_then(|flag| flag.remove.as_ref()) - .and_then(|remove| remove.backend.as_ref()) - .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) - }); - } + match toml_account_config.remove_flags_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_remove_flags(|ctx| { ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_remove_flags(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(RemoveFlagsMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -490,14 +562,7 @@ impl BackendBuilder { _ => (), } - let send_msg = deserialized_account_config - .message - .as_ref() - .and_then(|msg| msg.send.as_ref()) - .and_then(|send| send.backend.as_ref()) - .or_else(|| deserialized_account_config.backend.as_ref()); - - match send_msg { + match toml_account_config.send_raw_message_kind() { #[cfg(feature = "smtp-sender")] Some(BackendKind::Smtp) => { backend_builder = backend_builder.with_send_raw_message(|ctx| { @@ -512,24 +577,17 @@ impl BackendBuilder { _ => (), } - let add_msg = deserialized_account_config - .message - .as_ref() - .and_then(|msg| msg.add.as_ref()) - .and_then(|add| add.backend.as_ref()) - .or_else(|| deserialized_account_config.backend.as_ref()); - - match add_msg { - Some(_) if account_config.sync && !disable_cache => { + match toml_account_config.add_raw_message_kind() { + Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| { - ctx.sync_cache + ctx.maildir .as_ref() .and_then(AddRawMessageWithFlagsMaildir::new) }); } - Some(BackendKind::Maildir) => { + Some(BackendKind::MaildirForSync) => { backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| { - ctx.maildir + ctx.maildir_for_sync .as_ref() .and_then(AddRawMessageWithFlagsMaildir::new) }); @@ -551,24 +609,19 @@ impl BackendBuilder { _ => (), } - let peek_msgs = deserialized_account_config - .message - .as_ref() - .and_then(|msg| msg.peek.as_ref()) - .and_then(|peek| peek.backend.as_ref()) - .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) - }); - } + match toml_account_config.peek_messages_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_peek_messages(|ctx| { ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_peek_messages(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(PeekMessagesMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -583,14 +636,7 @@ impl BackendBuilder { _ => (), } - let get_msgs = deserialized_account_config - .message - .as_ref() - .and_then(|msg| msg.get.as_ref()) - .and_then(|get| get.backend.as_ref()) - .or_else(|| deserialized_account_config.backend.as_ref()); - - match get_msgs { + match toml_account_config.get_messages_kind() { #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -605,24 +651,19 @@ impl BackendBuilder { _ => (), } - let copy_msgs = deserialized_account_config - .message - .as_ref() - .and_then(|msg| msg.copy.as_ref()) - .and_then(|copy| copy.backend.as_ref()) - .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) - }); - } + match toml_account_config.copy_messages_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_copy_messages(|ctx| { ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_copy_messages(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(CopyMessagesMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -637,24 +678,19 @@ impl BackendBuilder { _ => (), } - let move_msgs = deserialized_account_config - .message - .as_ref() - .and_then(|msg| msg.move_.as_ref()) - .and_then(|move_| move_.backend.as_ref()) - .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) - }); - } + match toml_account_config.move_messages_kind() { Some(BackendKind::Maildir) => { backend_builder = backend_builder.with_move_messages(|ctx| { ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new) }); } + Some(BackendKind::MaildirForSync) => { + backend_builder = backend_builder.with_move_messages(|ctx| { + ctx.maildir_for_sync + .as_ref() + .and_then(MoveMessagesMaildir::new) + }); + } #[cfg(feature = "imap-backend")] Some(BackendKind::Imap) => { backend_builder = backend_builder @@ -669,10 +705,30 @@ impl BackendBuilder { _ => (), } - Ok(Self(backend_builder)) + Ok(Self { + toml_account_config, + builder: backend_builder, + }) } pub async fn build(self) -> Result { - self.0.build().await + Ok(Backend { + toml_account_config: self.toml_account_config, + backend: self.builder.build().await?, + }) + } +} + +impl Deref for BackendBuilder { + type Target = email::backend::BackendBuilder; + + fn deref(&self) -> &Self::Target { + &self.builder + } +} + +impl Into> for BackendBuilder { + fn into(self) -> email::backend::BackendBuilder { + self.builder } } diff --git a/src/cache/id_mapper.rs b/src/cache/id_mapper.rs index 5193e46..fb2ff86 100644 --- a/src/cache/id_mapper.rs +++ b/src/cache/id_mapper.rs @@ -1,12 +1,8 @@ use anyhow::{anyhow, Context, Result}; use email::account::AccountConfig; -#[cfg(feature = "notmuch-backend")] -use email::backend::NotmuchBackend; use log::{debug, trace}; use std::path::{Path, PathBuf}; -use crate::backend::Backend; - const ID_MAPPER_DB_FILE_NAME: &str = ".id-mapper.sqlite"; #[derive(Debug)] @@ -36,46 +32,28 @@ impl IdMapper { db_path } - // FIXME - pub fn new(backend: &Backend, account_config: &AccountConfig, folder: &str) -> Result { - Ok(IdMapper::Dummy) + pub fn new(account_config: &AccountConfig, folder: &str, db_path: PathBuf) -> Result { + let folder = account_config.get_folder_alias(folder)?; + let digest = md5::compute(account_config.name.clone() + &folder); + let table = format!("id_mapper_{digest:x}"); + debug!("creating id mapper table {table} at {db_path:?}…"); - // #[cfg(feature = "imap-backend")] - // if backend.as_any().is::() { - // return Ok(IdMapper::Dummy); - // } + let db_path = Self::find_closest_db_path(db_path); + let conn = rusqlite::Connection::open(&db_path) + .with_context(|| format!("cannot open id mapper database at {db_path:?}"))?; - // let mut db_path = PathBuf::new(); + let query = format!( + "CREATE TABLE IF NOT EXISTS {table} ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + internal_id TEXT UNIQUE + )", + ); + trace!("create table query: {query:#?}"); - // if let Some(backend) = backend.as_any().downcast_ref::() { - // db_path = Self::find_closest_db_path(backend.path()) - // } + conn.execute(&query, []) + .context("cannot create id mapper table")?; - // #[cfg(feature = "notmuch-backend")] - // if let Some(backend) = backend.as_any().downcast_ref::() { - // db_path = Self::find_closest_db_path(backend.path()) - // } - - // let folder = account_config.get_folder_alias(folder)?; - // let digest = md5::compute(account_config.name.clone() + &folder); - // let table = format!("id_mapper_{digest:x}"); - // debug!("creating id mapper table {table} at {db_path:?}…"); - - // let conn = rusqlite::Connection::open(&db_path) - // .with_context(|| format!("cannot open id mapper database at {db_path:?}"))?; - - // let query = format!( - // "CREATE TABLE IF NOT EXISTS {table} ( - // id INTEGER PRIMARY KEY AUTOINCREMENT, - // internal_id TEXT UNIQUE - // )", - // ); - // trace!("create table query: {query:#?}"); - - // conn.execute(&query, []) - // .context("cannot create id mapper table")?; - - // Ok(Self::Mapper(table, conn)) + Ok(Self::Mapper(table, conn)) } pub fn create_alias(&self, id: I) -> Result diff --git a/src/config/config.rs b/src/config/config.rs index a62aaa0..c45f159 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -18,6 +18,7 @@ use toml; use crate::{ account::DeserializedAccountConfig, + backend::BackendKind, config::{prelude::*, wizard}, wizard_prompt, wizard_warn, }; @@ -106,6 +107,7 @@ impl DeserializedConfig { pub fn into_account_configs( self, account_name: Option<&str>, + disable_cache: bool, ) -> Result<(DeserializedAccountConfig, AccountConfig)> { let (account_name, mut toml_account_config) = match account_name { Some("default") | Some("") | None => self @@ -139,6 +141,12 @@ impl DeserializedConfig { .replace_undefined_keyring_entries(&account_name); } + if let Some(true) = toml_account_config.sync { + if !disable_cache { + toml_account_config.backend = Some(BackendKind::MaildirForSync); + } + } + let config = Config { display_name: self.display_name, signature_delim: self.signature_delim, diff --git a/src/domain/account/config.rs b/src/domain/account/config.rs index 529d9cb..df915e7 100644 --- a/src/domain/account/config.rs +++ b/src/domain/account/config.rs @@ -86,3 +86,141 @@ pub struct DeserializedAccountConfig { #[serde(default, with = "OptionPgpConfigDef")] pub pgp: Option, } + +impl DeserializedAccountConfig { + pub fn add_folder_kind(&self) -> Option<&BackendKind> { + self.folder + .as_ref() + .and_then(|folder| folder.add.as_ref()) + .and_then(|add| add.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn list_folders_kind(&self) -> Option<&BackendKind> { + self.folder + .as_ref() + .and_then(|folder| folder.list.as_ref()) + .and_then(|list| list.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn expunge_folder_kind(&self) -> Option<&BackendKind> { + self.folder + .as_ref() + .and_then(|folder| folder.expunge.as_ref()) + .and_then(|expunge| expunge.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn purge_folder_kind(&self) -> Option<&BackendKind> { + self.folder + .as_ref() + .and_then(|folder| folder.purge.as_ref()) + .and_then(|purge| purge.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn delete_folder_kind(&self) -> Option<&BackendKind> { + self.folder + .as_ref() + .and_then(|folder| folder.delete.as_ref()) + .and_then(|delete| delete.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn get_envelope_kind(&self) -> Option<&BackendKind> { + self.envelope + .as_ref() + .and_then(|envelope| envelope.get.as_ref()) + .and_then(|get| get.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn list_envelopes_kind(&self) -> Option<&BackendKind> { + self.envelope + .as_ref() + .and_then(|envelope| envelope.list.as_ref()) + .and_then(|list| list.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn add_flags_kind(&self) -> Option<&BackendKind> { + self.flag + .as_ref() + .and_then(|flag| flag.add.as_ref()) + .and_then(|add| add.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn set_flags_kind(&self) -> Option<&BackendKind> { + self.flag + .as_ref() + .and_then(|flag| flag.set.as_ref()) + .and_then(|set| set.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn remove_flags_kind(&self) -> Option<&BackendKind> { + self.flag + .as_ref() + .and_then(|flag| flag.remove.as_ref()) + .and_then(|remove| remove.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn add_raw_message_kind(&self) -> Option<&BackendKind> { + self.message + .as_ref() + .and_then(|msg| msg.add.as_ref()) + .and_then(|add| add.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn peek_messages_kind(&self) -> Option<&BackendKind> { + self.message + .as_ref() + .and_then(|message| message.peek.as_ref()) + .and_then(|peek| peek.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn get_messages_kind(&self) -> Option<&BackendKind> { + self.message + .as_ref() + .and_then(|message| message.get.as_ref()) + .and_then(|get| get.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn copy_messages_kind(&self) -> Option<&BackendKind> { + self.message + .as_ref() + .and_then(|message| message.copy.as_ref()) + .and_then(|copy| copy.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn move_messages_kind(&self) -> Option<&BackendKind> { + self.message + .as_ref() + .and_then(|message| message.move_.as_ref()) + .and_then(|move_| move_.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn delete_messages_kind(&self) -> Option<&BackendKind> { + self.flag + .as_ref() + .and_then(|flag| flag.remove.as_ref()) + .and_then(|remove| remove.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } + + pub fn send_raw_message_kind(&self) -> Option<&BackendKind> { + self.message + .as_ref() + .and_then(|msg| msg.send.as_ref()) + .and_then(|send| send.backend.as_ref()) + .or_else(|| self.backend.as_ref()) + } +} diff --git a/src/domain/email/handlers.rs b/src/domain/email/handlers.rs index 3589ea7..fb15a2b 100644 --- a/src/domain/email/handlers.rs +++ b/src/domain/email/handlers.rs @@ -16,18 +16,15 @@ use crate::{ backend::Backend, printer::{PrintTableOpts, Printer}, ui::editor, - Envelopes, IdMapper, }; pub async fn attachments( config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, ids: Vec<&str>, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); let emails = backend.get_messages(&folder, &ids).await?; let mut index = 0; @@ -77,13 +74,11 @@ pub async fn attachments( pub async fn copy( printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, from_folder: &str, to_folder: &str, ids: Vec<&str>, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); backend .copy_messages(&from_folder, &to_folder, &ids) .await?; @@ -92,12 +87,10 @@ pub async fn copy( pub async fn delete( printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, ids: Vec<&str>, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); backend.delete_messages(&folder, &ids).await?; printer.print("Email(s) successfully deleted!") } @@ -105,16 +98,14 @@ pub async fn delete( pub async fn forward( config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, id: &str, headers: Option>, body: Option<&str>, ) -> Result<()> { - let id = Id::single(id_mapper.get_id(id)?); let tpl = backend - .get_messages(&folder, &id) + .get_messages(&folder, &[id]) .await? .first() .ok_or_else(|| anyhow!("cannot find email {}", id))? @@ -131,7 +122,6 @@ pub async fn forward( pub async fn list( config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, max_width: Option, @@ -141,11 +131,7 @@ pub async fn list( let page_size = page_size.unwrap_or(config.email_listing_page_size()); debug!("page size: {}", page_size); - let envelopes = Envelopes::from_backend( - config, - id_mapper, - backend.list_envelopes(&folder, page_size, page).await?, - )?; + let envelopes = backend.list_envelopes(&folder, page_size, page).await?; trace!("envelopes: {:?}", envelopes); printer.print_table( @@ -190,13 +176,11 @@ pub async fn mailto( pub async fn move_( printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, from_folder: &str, to_folder: &str, ids: Vec<&str>, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); backend .move_messages(&from_folder, &to_folder, &ids) .await?; @@ -206,7 +190,6 @@ pub async fn move_( pub async fn read( config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, ids: Vec<&str>, @@ -214,7 +197,6 @@ pub async fn read( raw: bool, headers: Vec<&str>, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); let emails = backend.get_messages(&folder, &ids).await?; let mut glue = ""; @@ -249,7 +231,6 @@ pub async fn read( pub async fn reply( config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, id: &str, @@ -257,9 +238,8 @@ pub async fn reply( headers: Option>, body: Option<&str>, ) -> Result<()> { - let id = Id::single(id_mapper.get_id(id)?); let tpl = backend - .get_messages(folder, &id) + .get_messages(folder, &[id]) .await? .first() .ok_or_else(|| anyhow!("cannot find email {}", id))? @@ -271,13 +251,14 @@ pub async fn reply( .await?; trace!("initial template: {tpl}"); editor::edit_tpl_with_editor(config, printer, backend, tpl).await?; - backend.add_flag(&folder, &id, Flag::Answered).await?; + backend + .add_flag(&folder, &Id::single(id), Flag::Answered) + .await?; Ok(()) } pub async fn save( printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, raw_email: String, @@ -295,10 +276,9 @@ pub async fn save( .join("\r\n") }; - let id = backend + backend .add_raw_message(&folder, raw_email.as_bytes()) .await?; - id_mapper.create_alias(&*id)?; Ok(()) } @@ -306,7 +286,6 @@ pub async fn save( pub async fn search( _config: &AccountConfig, _printer: &mut P, - _id_mapper: &IdMapper, _backend: &Backend, _folder: &str, _query: String, @@ -334,7 +313,6 @@ pub async fn search( pub async fn sort( _config: &AccountConfig, _printer: &mut P, - _id_mapper: &IdMapper, _backend: &Backend, _folder: &str, _sort: String, diff --git a/src/domain/flag/handlers.rs b/src/domain/flag/handlers.rs index 875718f..5316316 100644 --- a/src/domain/flag/handlers.rs +++ b/src/domain/flag/handlers.rs @@ -1,43 +1,37 @@ use anyhow::Result; -use email::email::{envelope::Id, Flags}; +use email::email::Flags; -use crate::{backend::Backend, printer::Printer, IdMapper}; +use crate::{backend::Backend, printer::Printer}; pub async fn add( printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, ids: Vec<&str>, flags: &Flags, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); backend.add_flags(folder, &ids, flags).await?; - printer.print("Flag(s) successfully added!") + printer.print(format!("Flag(s) {flags} successfully added!")) } pub async fn set( printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, ids: Vec<&str>, flags: &Flags, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); backend.set_flags(folder, &ids, flags).await?; - printer.print("Flag(s) successfully set!") + printer.print(format!("Flag(s) {flags} successfully set!")) } pub async fn remove( printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, ids: Vec<&str>, flags: &Flags, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids(ids)?); backend.remove_flags(folder, &ids, flags).await?; - printer.print("Flag(s) successfully removed!") + printer.print(format!("Flag(s) {flags} successfully removed!")) } diff --git a/src/domain/tpl/handlers.rs b/src/domain/tpl/handlers.rs index a7515e4..f59b2f7 100644 --- a/src/domain/tpl/handlers.rs +++ b/src/domain/tpl/handlers.rs @@ -2,27 +2,24 @@ use anyhow::{anyhow, Result}; use atty::Stream; use email::{ account::AccountConfig, - email::{envelope::Id, Flag, Message}, + email::{Flag, Message}, }; use mml::MmlCompilerBuilder; use std::io::{stdin, BufRead}; -use crate::{backend::Backend, printer::Printer, IdMapper}; +use crate::{backend::Backend, printer::Printer}; pub async fn forward( config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, id: &str, headers: Option>, body: Option<&str>, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids([id])?); - let tpl: String = backend - .get_messages(folder, &ids) + .get_messages(folder, &[id]) .await? .first() .ok_or_else(|| anyhow!("cannot find email {}", id))? @@ -39,7 +36,6 @@ pub async fn forward( pub async fn reply( config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, id: &str, @@ -47,10 +43,8 @@ pub async fn reply( headers: Option>, body: Option<&str>, ) -> Result<()> { - let ids = Id::multiple(id_mapper.get_ids([id])?); - let tpl: String = backend - .get_messages(folder, &ids) + .get_messages(folder, &[id]) .await? .first() .ok_or_else(|| anyhow!("cannot find email {}", id))? @@ -68,7 +62,6 @@ pub async fn reply( pub async fn save( #[allow(unused_variables)] config: &AccountConfig, printer: &mut P, - id_mapper: &IdMapper, backend: &Backend, folder: &str, tpl: String, @@ -91,8 +84,7 @@ pub async fn save( let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; - let id = backend.add_raw_message(folder, &email).await?; - id_mapper.create_alias(&*id)?; + backend.add_raw_message(folder, &email).await?; printer.print("Template successfully saved!") } diff --git a/src/main.rs b/src/main.rs index 3eed799..43c6fcb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ use himalaya::{ config::{self, DeserializedConfig}, email, flag, folder, man, output, printer::StdoutPrinter, - tpl, IdMapper, + tpl, }; fn create_app() -> Command { @@ -59,9 +59,9 @@ async fn main() -> Result<()> { let url = Url::parse(&raw_args[1])?; let (toml_account_config, account_config) = DeserializedConfig::from_opt_path(None) .await? - .into_account_configs(None)?; + .into_account_configs(None, false)?; let backend_builder = - BackendBuilder::new(toml_account_config, account_config.clone(), false).await?; + BackendBuilder::new(toml_account_config, account_config.clone()).await?; let backend = backend_builder.build().await?; let mut printer = StdoutPrinter::default(); @@ -88,14 +88,11 @@ async fn main() -> Result<()> { _ => (), } - 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 maybe_account_name = account::args::parse_arg(&m); + + let toml_config = DeserializedConfig::from_opt_path(config::args::parse_arg(&m)).await?; let mut printer = StdoutPrinter::try_from(&m)?; @@ -122,64 +119,57 @@ async fn main() -> Result<()> { match account::args::matches(&m)? { Some(account::args::Cmd::List(max_width)) => { - account::handlers::list(max_width, &account_config, &toml_config, &mut printer)?; - return Ok(()); + let (_, account_config) = toml_config + .clone() + .into_account_configs(maybe_account_name, disable_cache)?; + return account::handlers::list(max_width, &account_config, &toml_config, &mut printer); } Some(account::args::Cmd::Sync(strategy, dry_run)) => { + let (toml_account_config, account_config) = toml_config + .clone() + .into_account_configs(maybe_account_name, true)?; let backend_builder = - BackendBuilder::new(toml_account_config, account_config.clone(), true).await?; - let sync_builder = AccountSyncBuilder::new(backend_builder.0) + BackendBuilder::new(toml_account_config, account_config.clone()).await?; + let sync_builder = AccountSyncBuilder::new(backend_builder.into()) .await? .with_some_folders_strategy(strategy) .with_dry_run(dry_run); - account::handlers::sync(&mut printer, sync_builder, dry_run).await?; - return Ok(()); + return account::handlers::sync(&mut printer, sync_builder, dry_run).await; } Some(account::args::Cmd::Configure(reset)) => { - account::handlers::configure(&account_config, reset).await?; - return Ok(()); + let (_, account_config) = toml_config + .clone() + .into_account_configs(maybe_account_name, disable_cache)?; + return account::handlers::configure(&account_config, reset).await; } _ => (), } + let (toml_account_config, account_config) = toml_config + .clone() + .into_account_configs(maybe_account_name, disable_cache)?; + println!("toml_account_config: {:#?}", toml_account_config); + let backend_builder = BackendBuilder::new(toml_account_config, account_config.clone()).await?; + let backend = backend_builder.build().await?; + // checks folder commands match folder::args::matches(&m)? { Some(folder::args::Cmd::Create) => { let folder = folder .ok_or_else(|| anyhow!("the folder argument is missing")) .context("cannot create folder")?; - 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_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_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_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; } _ => (), @@ -189,16 +179,9 @@ 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_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)?; - return email::handlers::attachments( &account_config, &mut printer, - &id_mapper, &backend, &folder, ids, @@ -207,44 +190,17 @@ async fn main() -> Result<()> { } Some(email::args::Cmd::Copy(ids, to_folder)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - - return email::handlers::copy( - &mut printer, - &id_mapper, - &backend, - &folder, - to_folder, - ids, - ) - .await; + return email::handlers::copy(&mut printer, &backend, &folder, to_folder, ids).await; } Some(email::args::Cmd::Delete(ids)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - - return email::handlers::delete(&mut printer, &id_mapper, &backend, &folder, ids).await; + return email::handlers::delete(&mut printer, &backend, &folder, ids).await; } Some(email::args::Cmd::Forward(id, headers, body)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - return email::handlers::forward( &account_config, &mut printer, - &id_mapper, &backend, &folder, id, @@ -255,16 +211,9 @@ async fn main() -> Result<()> { } Some(email::args::Cmd::List(max_width, page_size, page)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - return email::handlers::list( &account_config, &mut printer, - &id_mapper, &backend, &folder, max_width, @@ -275,34 +224,13 @@ async fn main() -> Result<()> { } Some(email::args::Cmd::Move(ids, to_folder)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - - return email::handlers::move_( - &mut printer, - &id_mapper, - &backend, - &folder, - to_folder, - ids, - ) - .await; + return email::handlers::move_(&mut printer, &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_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)?; - return email::handlers::read( &account_config, &mut printer, - &id_mapper, &backend, &folder, ids, @@ -314,16 +242,9 @@ async fn main() -> Result<()> { } Some(email::args::Cmd::Reply(id, all, headers, body)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - return email::handlers::reply( &account_config, &mut printer, - &id_mapper, &backend, &folder, id, @@ -335,27 +256,13 @@ async fn main() -> Result<()> { } Some(email::args::Cmd::Save(raw_email)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - - return email::handlers::save(&mut printer, &id_mapper, &backend, &folder, raw_email) - .await; + return email::handlers::save(&mut printer, &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_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)?; - return email::handlers::search( &account_config, &mut printer, - &id_mapper, &backend, &folder, query, @@ -367,16 +274,9 @@ async fn main() -> Result<()> { } Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - return email::handlers::sort( &account_config, &mut printer, - &id_mapper, &backend, &folder, criteria, @@ -388,79 +288,29 @@ async fn main() -> Result<()> { .await; } Some(email::args::Cmd::Send(raw_email)) => { - 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_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)?; - return flag::handlers::set( - &mut printer, - &id_mapper, - &backend, - &folder, - ids, - flags, - ) - .await; + return flag::handlers::set(&mut printer, &backend, &folder, ids, flags).await; } Some(flag::args::Cmd::Add(ids, ref flags)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - return flag::handlers::add( - &mut printer, - &id_mapper, - &backend, - &folder, - ids, - flags, - ) - .await; + return flag::handlers::add(&mut printer, &backend, &folder, ids, flags).await; } Some(flag::args::Cmd::Remove(ids, ref flags)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - - return flag::handlers::remove( - &mut printer, - &id_mapper, - &backend, - &folder, - ids, - flags, - ) - .await; + return flag::handlers::remove(&mut printer, &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_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)?; return tpl::handlers::forward( &account_config, &mut printer, - &id_mapper, &backend, &folder, id, @@ -475,15 +325,9 @@ async fn main() -> Result<()> { } Some(tpl::args::Cmd::Reply(id, all, headers, body)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; return tpl::handlers::reply( &account_config, &mut printer, - &id_mapper, &backend, &folder, id, @@ -495,35 +339,15 @@ async fn main() -> Result<()> { } Some(tpl::args::Cmd::Save(tpl)) => { let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); - 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)?; - return tpl::handlers::save( - &account_config, - &mut printer, - &id_mapper, - &backend, - &folder, - tpl, - ) - .await; + return tpl::handlers::save(&account_config, &mut printer, &backend, &folder, tpl) + .await; } Some(tpl::args::Cmd::Send(tpl)) => { - 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_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; }