fix id mapper

This commit is contained in:
Clément DOUIN 2023-11-28 22:28:28 +01:00
parent a0888067da
commit fb8f356e8c
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
8 changed files with 518 additions and 550 deletions

View file

@ -1,7 +1,6 @@
use std::{collections::HashMap, ops::Deref}; use anyhow::Result;
use anyhow::{anyhow, Result};
use async_trait::async_trait; use async_trait::async_trait;
use std::ops::Deref;
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
use email::imap::{ImapSessionBuilder, ImapSessionSync}; use email::imap::{ImapSessionBuilder, ImapSessionSync};
@ -9,7 +8,6 @@ use email::imap::{ImapSessionBuilder, ImapSessionSync};
use email::smtp::{SmtpClientBuilder, SmtpClientSync}; use email::smtp::{SmtpClientBuilder, SmtpClientSync};
use email::{ use email::{
account::AccountConfig, account::AccountConfig,
config::Config,
email::{ email::{
envelope::{ envelope::{
get::{imap::GetEnvelopeImap, maildir::GetEnvelopeMaildir}, get::{imap::GetEnvelopeImap, maildir::GetEnvelopeMaildir},
@ -32,6 +30,8 @@ use email::{
send_raw::{sendmail::SendRawMessageSendmail, smtp::SendRawMessageSmtp}, send_raw::{sendmail::SendRawMessageSendmail, smtp::SendRawMessageSmtp},
}, },
}, },
envelope::{Id, SingleId},
flag::Flags,
folder::{ folder::{
add::{imap::AddFolderImap, maildir::AddFolderMaildir}, add::{imap::AddFolderImap, maildir::AddFolderMaildir},
delete::{imap::DeleteFolderImap, maildir::DeleteFolderMaildir}, delete::{imap::DeleteFolderImap, maildir::DeleteFolderMaildir},
@ -40,16 +40,19 @@ use email::{
purge::imap::PurgeFolderImap, purge::imap::PurgeFolderImap,
}, },
maildir::{MaildirConfig, MaildirSessionBuilder, MaildirSessionSync}, maildir::{MaildirConfig, MaildirSessionBuilder, MaildirSessionSync},
message::Messages,
sendmail::SendmailContext, sendmail::SendmailContext,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{account::DeserializedAccountConfig, config::DeserializedConfig}; use crate::{account::DeserializedAccountConfig, Envelopes, IdMapper};
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum BackendKind { pub enum BackendKind {
Maildir, Maildir,
#[serde(skip_deserializing)]
MaildirForSync,
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
Imap, Imap,
#[cfg(feature = "notmuch-backend")] #[cfg(feature = "notmuch-backend")]
@ -61,8 +64,8 @@ pub enum BackendKind {
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct BackendContextBuilder { pub struct BackendContextBuilder {
sync_cache: Option<MaildirSessionBuilder>,
maildir: Option<MaildirSessionBuilder>, maildir: Option<MaildirSessionBuilder>,
maildir_for_sync: Option<MaildirSessionBuilder>,
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
imap: Option<ImapSessionBuilder>, imap: Option<ImapSessionBuilder>,
#[cfg(feature = "smtp-sender")] #[cfg(feature = "smtp-sender")]
@ -81,8 +84,8 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder {
ctx.maildir = Some(maildir.build().await?); ctx.maildir = Some(maildir.build().await?);
} }
if let Some(maildir) = self.sync_cache { if let Some(maildir) = self.maildir_for_sync {
ctx.sync_cache = Some(maildir.build().await?); ctx.maildir_for_sync = Some(maildir.build().await?);
} }
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
@ -110,8 +113,8 @@ impl email::backend::BackendContextBuilder for BackendContextBuilder {
#[derive(Default)] #[derive(Default)]
pub struct BackendContext { pub struct BackendContext {
pub sync_cache: Option<MaildirSessionSync>,
pub maildir: Option<MaildirSessionSync>, pub maildir: Option<MaildirSessionSync>,
pub maildir_for_sync: Option<MaildirSessionSync>,
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
pub imap: Option<ImapSessionSync>, pub imap: Option<ImapSessionSync>,
#[cfg(feature = "smtp-sender")] #[cfg(feature = "smtp-sender")]
@ -119,55 +122,178 @@ pub struct BackendContext {
pub sendmail: Option<SendmailContext>, pub sendmail: Option<SendmailContext>,
} }
pub struct BackendBuilder(pub email::backend::BackendBuilder<BackendContextBuilder>); pub struct Backend {
toml_account_config: DeserializedAccountConfig,
backend: email::backend::Backend<BackendContext>,
}
pub type Backend = email::backend::Backend<BackendContext>; impl Backend {
fn build_id_mapper(
&self,
folder: &str,
backend_kind: Option<&BackendKind>,
) -> Result<IdMapper> {
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<Envelopes> {
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<Messages> {
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<SingleId> {
let backend_kind = self.toml_account_config.add_raw_message_kind();
let id_mapper = self.build_id_mapper(folder, backend_kind)?;
let id = self.backend.add_raw_message(folder, email).await?;
id_mapper.create_alias(&*id)?;
Ok(id)
}
}
impl Deref for Backend {
type Target = email::backend::Backend<BackendContext>;
fn deref(&self) -> &Self::Target {
&self.backend
}
}
pub struct BackendBuilder {
toml_account_config: DeserializedAccountConfig,
builder: email::backend::BackendBuilder<BackendContextBuilder>,
}
impl BackendBuilder { impl BackendBuilder {
pub async fn new( pub async fn new(
deserialized_account_config: DeserializedAccountConfig, toml_account_config: DeserializedAccountConfig,
account_config: AccountConfig, account_config: AccountConfig,
disable_cache: bool,
) -> Result<Self> { ) -> Result<Self> {
let backend_ctx_builder = BackendContextBuilder { let backend_ctx_builder = BackendContextBuilder {
maildir: deserialized_account_config maildir: toml_account_config.maildir.as_ref().map(|mdir_config| {
.maildir MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone())
.as_ref() }),
.map(|mdir_config| { maildir_for_sync: Some(MaildirSessionBuilder::new(
MaildirSessionBuilder::new(account_config.clone(), mdir_config.clone()) account_config.clone(),
}), MaildirConfig {
sync_cache: if account_config.sync && !disable_cache { root_dir: account_config.sync_dir()?,
Some(MaildirSessionBuilder::new( },
account_config.clone(), )),
MaildirConfig {
root_dir: account_config.sync_dir()?,
},
))
} else {
None
},
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
imap: deserialized_account_config imap: toml_account_config.imap.as_ref().map(|imap_config| {
.imap ImapSessionBuilder::new(account_config.clone(), imap_config.clone())
.as_ref() }),
.map(|imap_config| {
ImapSessionBuilder::new(account_config.clone(), imap_config.clone())
}),
#[cfg(feature = "notmuch-backend")] #[cfg(feature = "notmuch-backend")]
notmuch: deserialized_account_config notmuch: toml_account_config.notmuch.as_ref().map(|notmuch_config| {
.notmuch NotmuchSessionBuilder::new(account_config.clone(), notmuch_config.clone())
.as_ref() }),
.map(|notmuch_config| {
NotmuchSessionBuilder::new(account_config.clone(), notmuch_config.clone())
}),
#[cfg(feature = "smtp-sender")] #[cfg(feature = "smtp-sender")]
smtp: deserialized_account_config smtp: toml_account_config.smtp.as_ref().map(|smtp_config| {
.smtp SmtpClientBuilder::new(account_config.clone(), smtp_config.clone())
.as_ref() }),
.map(|smtp_config| { sendmail: toml_account_config
SmtpClientBuilder::new(account_config.clone(), smtp_config.clone())
}),
sendmail: deserialized_account_config
.sendmail .sendmail
.as_ref() .as_ref()
.map(|sendmail_config| { .map(|sendmail_config| {
@ -178,22 +304,18 @@ impl BackendBuilder {
let mut backend_builder = let mut backend_builder =
email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder); email::backend::BackendBuilder::new(account_config.clone(), backend_ctx_builder);
let add_folder = deserialized_account_config match toml_account_config.add_folder_kind() {
.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));
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder backend_builder = backend_builder
.with_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new)); .with_add_folder(|ctx| ctx.maildir.as_ref().and_then(AddFolderMaildir::new));
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -207,24 +329,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let list_folders = deserialized_account_config match toml_account_config.list_folders_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_list_folders(|ctx| { backend_builder = backend_builder.with_list_folders(|ctx| {
ctx.maildir.as_ref().and_then(ListFoldersMaildir::new) ctx.maildir.as_ref().and_then(ListFoldersMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -239,24 +356,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let expunge_folder = deserialized_account_config match toml_account_config.expunge_folder_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_expunge_folder(|ctx| { backend_builder = backend_builder.with_expunge_folder(|ctx| {
ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new) ctx.maildir.as_ref().and_then(ExpungeFolderMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -271,25 +383,17 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let purge_folder = deserialized_account_config match toml_account_config.purge_folder_kind() {
.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)
// });
// }
// TODO // TODO
// Some(BackendKind::Maildir) => { // Some(BackendKind::Maildir) => {
// backend_builder = backend_builder // backend_builder = backend_builder
// .with_purge_folder(|ctx| ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new)); // .with_purge_folder(|ctx| ctx.maildir.as_ref().and_then(PurgeFolderMaildir::new));
// } // }
// TODO
// 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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -304,24 +408,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let delete_folder = deserialized_account_config match toml_account_config.delete_folder_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_delete_folder(|ctx| { backend_builder = backend_builder.with_delete_folder(|ctx| {
ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new) ctx.maildir.as_ref().and_then(DeleteFolderMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -336,24 +435,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let get_envelope = deserialized_account_config match toml_account_config.get_envelope_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_get_envelope(|ctx| { backend_builder = backend_builder.with_get_envelope(|ctx| {
ctx.maildir.as_ref().and_then(GetEnvelopeMaildir::new) ctx.maildir.as_ref().and_then(GetEnvelopeMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -368,24 +462,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let list_envelopes = deserialized_account_config match toml_account_config.list_envelopes_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_list_envelopes(|ctx| { backend_builder = backend_builder.with_list_envelopes(|ctx| {
ctx.maildir.as_ref().and_then(ListEnvelopesMaildir::new) 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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -400,22 +489,16 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let add_flags = deserialized_account_config match toml_account_config.add_flags_kind() {
.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));
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder backend_builder = backend_builder
.with_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new)); .with_add_flags(|ctx| ctx.maildir.as_ref().and_then(AddFlagsMaildir::new));
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -429,22 +512,16 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let set_flags = deserialized_account_config match toml_account_config.set_flags_kind() {
.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));
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder backend_builder = backend_builder
.with_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new)); .with_set_flags(|ctx| ctx.maildir.as_ref().and_then(SetFlagsMaildir::new));
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -458,24 +535,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let remove_flags = deserialized_account_config match toml_account_config.remove_flags_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_remove_flags(|ctx| { backend_builder = backend_builder.with_remove_flags(|ctx| {
ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new) ctx.maildir.as_ref().and_then(RemoveFlagsMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -490,14 +562,7 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let send_msg = deserialized_account_config match toml_account_config.send_raw_message_kind() {
.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 {
#[cfg(feature = "smtp-sender")] #[cfg(feature = "smtp-sender")]
Some(BackendKind::Smtp) => { Some(BackendKind::Smtp) => {
backend_builder = backend_builder.with_send_raw_message(|ctx| { backend_builder = backend_builder.with_send_raw_message(|ctx| {
@ -512,24 +577,17 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let add_msg = deserialized_account_config match toml_account_config.add_raw_message_kind() {
.message Some(BackendKind::Maildir) => {
.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 => {
backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| { backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| {
ctx.sync_cache ctx.maildir
.as_ref() .as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new) .and_then(AddRawMessageWithFlagsMaildir::new)
}); });
} }
Some(BackendKind::Maildir) => { Some(BackendKind::MaildirForSync) => {
backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| { backend_builder = backend_builder.with_add_raw_message_with_flags(|ctx| {
ctx.maildir ctx.maildir_for_sync
.as_ref() .as_ref()
.and_then(AddRawMessageWithFlagsMaildir::new) .and_then(AddRawMessageWithFlagsMaildir::new)
}); });
@ -551,24 +609,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let peek_msgs = deserialized_account_config match toml_account_config.peek_messages_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_peek_messages(|ctx| { backend_builder = backend_builder.with_peek_messages(|ctx| {
ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new) ctx.maildir.as_ref().and_then(PeekMessagesMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -583,14 +636,7 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let get_msgs = deserialized_account_config match toml_account_config.get_messages_kind() {
.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 {
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -605,24 +651,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let copy_msgs = deserialized_account_config match toml_account_config.copy_messages_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_copy_messages(|ctx| { backend_builder = backend_builder.with_copy_messages(|ctx| {
ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new) ctx.maildir.as_ref().and_then(CopyMessagesMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder backend_builder = backend_builder
@ -637,24 +678,19 @@ impl BackendBuilder {
_ => (), _ => (),
} }
let move_msgs = deserialized_account_config match toml_account_config.move_messages_kind() {
.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)
});
}
Some(BackendKind::Maildir) => { Some(BackendKind::Maildir) => {
backend_builder = backend_builder.with_move_messages(|ctx| { backend_builder = backend_builder.with_move_messages(|ctx| {
ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new) ctx.maildir.as_ref().and_then(MoveMessagesMaildir::new)
}); });
} }
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")] #[cfg(feature = "imap-backend")]
Some(BackendKind::Imap) => { Some(BackendKind::Imap) => {
backend_builder = backend_builder 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<Backend> { pub async fn build(self) -> Result<Backend> {
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<BackendContextBuilder>;
fn deref(&self) -> &Self::Target {
&self.builder
}
}
impl Into<email::backend::BackendBuilder<BackendContextBuilder>> for BackendBuilder {
fn into(self) -> email::backend::BackendBuilder<BackendContextBuilder> {
self.builder
} }
} }

View file

@ -1,12 +1,8 @@
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use email::account::AccountConfig; use email::account::AccountConfig;
#[cfg(feature = "notmuch-backend")]
use email::backend::NotmuchBackend;
use log::{debug, trace}; use log::{debug, trace};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::backend::Backend;
const ID_MAPPER_DB_FILE_NAME: &str = ".id-mapper.sqlite"; const ID_MAPPER_DB_FILE_NAME: &str = ".id-mapper.sqlite";
#[derive(Debug)] #[derive(Debug)]
@ -36,46 +32,28 @@ impl IdMapper {
db_path db_path
} }
// FIXME pub fn new(account_config: &AccountConfig, folder: &str, db_path: PathBuf) -> Result<Self> {
pub fn new(backend: &Backend, account_config: &AccountConfig, folder: &str) -> Result<Self> { let folder = account_config.get_folder_alias(folder)?;
Ok(IdMapper::Dummy) 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")] let db_path = Self::find_closest_db_path(db_path);
// if backend.as_any().is::<ImapBackend>() { let conn = rusqlite::Connection::open(&db_path)
// return Ok(IdMapper::Dummy); .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::<MaildirBackend>() { conn.execute(&query, [])
// db_path = Self::find_closest_db_path(backend.path()) .context("cannot create id mapper table")?;
// }
// #[cfg(feature = "notmuch-backend")] Ok(Self::Mapper(table, conn))
// if let Some(backend) = backend.as_any().downcast_ref::<NotmuchBackend>() {
// 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))
} }
pub fn create_alias<I>(&self, id: I) -> Result<String> pub fn create_alias<I>(&self, id: I) -> Result<String>

View file

@ -18,6 +18,7 @@ use toml;
use crate::{ use crate::{
account::DeserializedAccountConfig, account::DeserializedAccountConfig,
backend::BackendKind,
config::{prelude::*, wizard}, config::{prelude::*, wizard},
wizard_prompt, wizard_warn, wizard_prompt, wizard_warn,
}; };
@ -106,6 +107,7 @@ impl DeserializedConfig {
pub fn into_account_configs( pub fn into_account_configs(
self, self,
account_name: Option<&str>, account_name: Option<&str>,
disable_cache: bool,
) -> Result<(DeserializedAccountConfig, AccountConfig)> { ) -> Result<(DeserializedAccountConfig, AccountConfig)> {
let (account_name, mut toml_account_config) = match account_name { let (account_name, mut toml_account_config) = match account_name {
Some("default") | Some("") | None => self Some("default") | Some("") | None => self
@ -139,6 +141,12 @@ impl DeserializedConfig {
.replace_undefined_keyring_entries(&account_name); .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 { let config = Config {
display_name: self.display_name, display_name: self.display_name,
signature_delim: self.signature_delim, signature_delim: self.signature_delim,

View file

@ -86,3 +86,141 @@ pub struct DeserializedAccountConfig {
#[serde(default, with = "OptionPgpConfigDef")] #[serde(default, with = "OptionPgpConfigDef")]
pub pgp: Option<PgpConfig>, pub pgp: Option<PgpConfig>,
} }
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())
}
}

View file

@ -16,18 +16,15 @@ use crate::{
backend::Backend, backend::Backend,
printer::{PrintTableOpts, Printer}, printer::{PrintTableOpts, Printer},
ui::editor, ui::editor,
Envelopes, IdMapper,
}; };
pub async fn attachments<P: Printer>( pub async fn attachments<P: Printer>(
config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
let emails = backend.get_messages(&folder, &ids).await?; let emails = backend.get_messages(&folder, &ids).await?;
let mut index = 0; let mut index = 0;
@ -77,13 +74,11 @@ pub async fn attachments<P: Printer>(
pub async fn copy<P: Printer>( pub async fn copy<P: Printer>(
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
from_folder: &str, from_folder: &str,
to_folder: &str, to_folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
backend backend
.copy_messages(&from_folder, &to_folder, &ids) .copy_messages(&from_folder, &to_folder, &ids)
.await?; .await?;
@ -92,12 +87,10 @@ pub async fn copy<P: Printer>(
pub async fn delete<P: Printer>( pub async fn delete<P: Printer>(
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
backend.delete_messages(&folder, &ids).await?; backend.delete_messages(&folder, &ids).await?;
printer.print("Email(s) successfully deleted!") printer.print("Email(s) successfully deleted!")
} }
@ -105,16 +98,14 @@ pub async fn delete<P: Printer>(
pub async fn forward<P: Printer>( pub async fn forward<P: Printer>(
config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
id: &str, id: &str,
headers: Option<Vec<(&str, &str)>>, headers: Option<Vec<(&str, &str)>>,
body: Option<&str>, body: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let id = Id::single(id_mapper.get_id(id)?);
let tpl = backend let tpl = backend
.get_messages(&folder, &id) .get_messages(&folder, &[id])
.await? .await?
.first() .first()
.ok_or_else(|| anyhow!("cannot find email {}", id))? .ok_or_else(|| anyhow!("cannot find email {}", id))?
@ -131,7 +122,6 @@ pub async fn forward<P: Printer>(
pub async fn list<P: Printer>( pub async fn list<P: Printer>(
config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
max_width: Option<usize>, max_width: Option<usize>,
@ -141,11 +131,7 @@ pub async fn list<P: Printer>(
let page_size = page_size.unwrap_or(config.email_listing_page_size()); let page_size = page_size.unwrap_or(config.email_listing_page_size());
debug!("page size: {}", page_size); debug!("page size: {}", page_size);
let envelopes = Envelopes::from_backend( let envelopes = backend.list_envelopes(&folder, page_size, page).await?;
config,
id_mapper,
backend.list_envelopes(&folder, page_size, page).await?,
)?;
trace!("envelopes: {:?}", envelopes); trace!("envelopes: {:?}", envelopes);
printer.print_table( printer.print_table(
@ -190,13 +176,11 @@ pub async fn mailto<P: Printer>(
pub async fn move_<P: Printer>( pub async fn move_<P: Printer>(
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
from_folder: &str, from_folder: &str,
to_folder: &str, to_folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
backend backend
.move_messages(&from_folder, &to_folder, &ids) .move_messages(&from_folder, &to_folder, &ids)
.await?; .await?;
@ -206,7 +190,6 @@ pub async fn move_<P: Printer>(
pub async fn read<P: Printer>( pub async fn read<P: Printer>(
config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
@ -214,7 +197,6 @@ pub async fn read<P: Printer>(
raw: bool, raw: bool,
headers: Vec<&str>, headers: Vec<&str>,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
let emails = backend.get_messages(&folder, &ids).await?; let emails = backend.get_messages(&folder, &ids).await?;
let mut glue = ""; let mut glue = "";
@ -249,7 +231,6 @@ pub async fn read<P: Printer>(
pub async fn reply<P: Printer>( pub async fn reply<P: Printer>(
config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
id: &str, id: &str,
@ -257,9 +238,8 @@ pub async fn reply<P: Printer>(
headers: Option<Vec<(&str, &str)>>, headers: Option<Vec<(&str, &str)>>,
body: Option<&str>, body: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let id = Id::single(id_mapper.get_id(id)?);
let tpl = backend let tpl = backend
.get_messages(folder, &id) .get_messages(folder, &[id])
.await? .await?
.first() .first()
.ok_or_else(|| anyhow!("cannot find email {}", id))? .ok_or_else(|| anyhow!("cannot find email {}", id))?
@ -271,13 +251,14 @@ pub async fn reply<P: Printer>(
.await?; .await?;
trace!("initial template: {tpl}"); trace!("initial template: {tpl}");
editor::edit_tpl_with_editor(config, printer, backend, tpl).await?; 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(()) Ok(())
} }
pub async fn save<P: Printer>( pub async fn save<P: Printer>(
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
raw_email: String, raw_email: String,
@ -295,10 +276,9 @@ pub async fn save<P: Printer>(
.join("\r\n") .join("\r\n")
}; };
let id = backend backend
.add_raw_message(&folder, raw_email.as_bytes()) .add_raw_message(&folder, raw_email.as_bytes())
.await?; .await?;
id_mapper.create_alias(&*id)?;
Ok(()) Ok(())
} }
@ -306,7 +286,6 @@ pub async fn save<P: Printer>(
pub async fn search<P: Printer>( pub async fn search<P: Printer>(
_config: &AccountConfig, _config: &AccountConfig,
_printer: &mut P, _printer: &mut P,
_id_mapper: &IdMapper,
_backend: &Backend, _backend: &Backend,
_folder: &str, _folder: &str,
_query: String, _query: String,
@ -334,7 +313,6 @@ pub async fn search<P: Printer>(
pub async fn sort<P: Printer>( pub async fn sort<P: Printer>(
_config: &AccountConfig, _config: &AccountConfig,
_printer: &mut P, _printer: &mut P,
_id_mapper: &IdMapper,
_backend: &Backend, _backend: &Backend,
_folder: &str, _folder: &str,
_sort: String, _sort: String,

View file

@ -1,43 +1,37 @@
use anyhow::Result; 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<P: Printer>( pub async fn add<P: Printer>(
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
flags: &Flags, flags: &Flags,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
backend.add_flags(folder, &ids, flags).await?; 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<P: Printer>( pub async fn set<P: Printer>(
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
flags: &Flags, flags: &Flags,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
backend.set_flags(folder, &ids, flags).await?; 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<P: Printer>( pub async fn remove<P: Printer>(
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
ids: Vec<&str>, ids: Vec<&str>,
flags: &Flags, flags: &Flags,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids(ids)?);
backend.remove_flags(folder, &ids, flags).await?; backend.remove_flags(folder, &ids, flags).await?;
printer.print("Flag(s) successfully removed!") printer.print(format!("Flag(s) {flags} successfully removed!"))
} }

View file

@ -2,27 +2,24 @@ use anyhow::{anyhow, Result};
use atty::Stream; use atty::Stream;
use email::{ use email::{
account::AccountConfig, account::AccountConfig,
email::{envelope::Id, Flag, Message}, email::{Flag, Message},
}; };
use mml::MmlCompilerBuilder; use mml::MmlCompilerBuilder;
use std::io::{stdin, BufRead}; use std::io::{stdin, BufRead};
use crate::{backend::Backend, printer::Printer, IdMapper}; use crate::{backend::Backend, printer::Printer};
pub async fn forward<P: Printer>( pub async fn forward<P: Printer>(
config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
id: &str, id: &str,
headers: Option<Vec<(&str, &str)>>, headers: Option<Vec<(&str, &str)>>,
body: Option<&str>, body: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids([id])?);
let tpl: String = backend let tpl: String = backend
.get_messages(folder, &ids) .get_messages(folder, &[id])
.await? .await?
.first() .first()
.ok_or_else(|| anyhow!("cannot find email {}", id))? .ok_or_else(|| anyhow!("cannot find email {}", id))?
@ -39,7 +36,6 @@ pub async fn forward<P: Printer>(
pub async fn reply<P: Printer>( pub async fn reply<P: Printer>(
config: &AccountConfig, config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
id: &str, id: &str,
@ -47,10 +43,8 @@ pub async fn reply<P: Printer>(
headers: Option<Vec<(&str, &str)>>, headers: Option<Vec<(&str, &str)>>,
body: Option<&str>, body: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let ids = Id::multiple(id_mapper.get_ids([id])?);
let tpl: String = backend let tpl: String = backend
.get_messages(folder, &ids) .get_messages(folder, &[id])
.await? .await?
.first() .first()
.ok_or_else(|| anyhow!("cannot find email {}", id))? .ok_or_else(|| anyhow!("cannot find email {}", id))?
@ -68,7 +62,6 @@ pub async fn reply<P: Printer>(
pub async fn save<P: Printer>( pub async fn save<P: Printer>(
#[allow(unused_variables)] config: &AccountConfig, #[allow(unused_variables)] config: &AccountConfig,
printer: &mut P, printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend, backend: &Backend,
folder: &str, folder: &str,
tpl: String, tpl: String,
@ -91,8 +84,7 @@ pub async fn save<P: Printer>(
let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?; let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
let id = backend.add_raw_message(folder, &email).await?; backend.add_raw_message(folder, &email).await?;
id_mapper.create_alias(&*id)?;
printer.print("Template successfully saved!") printer.print("Template successfully saved!")
} }

View file

@ -14,7 +14,7 @@ use himalaya::{
config::{self, DeserializedConfig}, config::{self, DeserializedConfig},
email, flag, folder, man, output, email, flag, folder, man, output,
printer::StdoutPrinter, printer::StdoutPrinter,
tpl, IdMapper, tpl,
}; };
fn create_app() -> Command { fn create_app() -> Command {
@ -59,9 +59,9 @@ async fn main() -> Result<()> {
let url = Url::parse(&raw_args[1])?; let url = Url::parse(&raw_args[1])?;
let (toml_account_config, account_config) = DeserializedConfig::from_opt_path(None) let (toml_account_config, account_config) = DeserializedConfig::from_opt_path(None)
.await? .await?
.into_account_configs(None)?; .into_account_configs(None, false)?;
let backend_builder = 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 backend = backend_builder.build().await?;
let mut printer = StdoutPrinter::default(); 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 folder = folder::args::parse_source_arg(&m);
let disable_cache = cache::args::parse_disable_cache_flag(&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)?; let mut printer = StdoutPrinter::try_from(&m)?;
@ -122,64 +119,57 @@ async fn main() -> Result<()> {
match account::args::matches(&m)? { match account::args::matches(&m)? {
Some(account::args::Cmd::List(max_width)) => { Some(account::args::Cmd::List(max_width)) => {
account::handlers::list(max_width, &account_config, &toml_config, &mut printer)?; let (_, account_config) = toml_config
return Ok(()); .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)) => { 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 = let backend_builder =
BackendBuilder::new(toml_account_config, account_config.clone(), true).await?; BackendBuilder::new(toml_account_config, account_config.clone()).await?;
let sync_builder = AccountSyncBuilder::new(backend_builder.0) let sync_builder = AccountSyncBuilder::new(backend_builder.into())
.await? .await?
.with_some_folders_strategy(strategy) .with_some_folders_strategy(strategy)
.with_dry_run(dry_run); .with_dry_run(dry_run);
account::handlers::sync(&mut printer, sync_builder, dry_run).await?; return account::handlers::sync(&mut printer, sync_builder, dry_run).await;
return Ok(());
} }
Some(account::args::Cmd::Configure(reset)) => { Some(account::args::Cmd::Configure(reset)) => {
account::handlers::configure(&account_config, reset).await?; let (_, account_config) = toml_config
return Ok(()); .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 // checks folder commands
match folder::args::matches(&m)? { match folder::args::matches(&m)? {
Some(folder::args::Cmd::Create) => { Some(folder::args::Cmd::Create) => {
let folder = folder let folder = folder
.ok_or_else(|| anyhow!("the folder argument is missing")) .ok_or_else(|| anyhow!("the folder argument is missing"))
.context("cannot create folder")?; .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; return folder::handlers::create(&mut printer, &backend, &folder).await;
} }
Some(folder::args::Cmd::List(max_width)) => { 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) return folder::handlers::list(&account_config, &mut printer, &backend, max_width)
.await; .await;
} }
Some(folder::args::Cmd::Expunge) => { Some(folder::args::Cmd::Expunge) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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?;
return folder::handlers::expunge(&mut printer, &backend, &folder).await; return folder::handlers::expunge(&mut printer, &backend, &folder).await;
} }
Some(folder::args::Cmd::Delete) => { Some(folder::args::Cmd::Delete) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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?;
return folder::handlers::delete(&mut printer, &backend, &folder).await; return folder::handlers::delete(&mut printer, &backend, &folder).await;
} }
_ => (), _ => (),
@ -189,16 +179,9 @@ async fn main() -> Result<()> {
match email::args::matches(&m)? { match email::args::matches(&m)? {
Some(email::args::Cmd::Attachments(ids)) => { Some(email::args::Cmd::Attachments(ids)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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::attachments( return email::handlers::attachments(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
ids, ids,
@ -207,44 +190,17 @@ async fn main() -> Result<()> {
} }
Some(email::args::Cmd::Copy(ids, to_folder)) => { Some(email::args::Cmd::Copy(ids, to_folder)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return email::handlers::copy(&mut printer, &backend, &folder, to_folder, ids).await;
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;
} }
Some(email::args::Cmd::Delete(ids)) => { Some(email::args::Cmd::Delete(ids)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return email::handlers::delete(&mut printer, &backend, &folder, ids).await;
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;
} }
Some(email::args::Cmd::Forward(id, headers, body)) => { Some(email::args::Cmd::Forward(id, headers, body)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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::forward( return email::handlers::forward(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
id, id,
@ -255,16 +211,9 @@ async fn main() -> Result<()> {
} }
Some(email::args::Cmd::List(max_width, page_size, page)) => { Some(email::args::Cmd::List(max_width, page_size, page)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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::list( return email::handlers::list(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
max_width, max_width,
@ -275,34 +224,13 @@ async fn main() -> Result<()> {
} }
Some(email::args::Cmd::Move(ids, to_folder)) => { Some(email::args::Cmd::Move(ids, to_folder)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return email::handlers::move_(&mut printer, &backend, &folder, to_folder, ids).await;
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;
} }
Some(email::args::Cmd::Read(ids, text_mime, raw, headers)) => { Some(email::args::Cmd::Read(ids, text_mime, raw, headers)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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::read( return email::handlers::read(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
ids, ids,
@ -314,16 +242,9 @@ async fn main() -> Result<()> {
} }
Some(email::args::Cmd::Reply(id, all, headers, body)) => { Some(email::args::Cmd::Reply(id, all, headers, body)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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::reply( return email::handlers::reply(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
id, id,
@ -335,27 +256,13 @@ async fn main() -> Result<()> {
} }
Some(email::args::Cmd::Save(raw_email)) => { Some(email::args::Cmd::Save(raw_email)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return email::handlers::save(&mut printer, &backend, &folder, raw_email).await;
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;
} }
Some(email::args::Cmd::Search(query, max_width, page_size, page)) => { Some(email::args::Cmd::Search(query, max_width, page_size, page)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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::search( return email::handlers::search(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
query, query,
@ -367,16 +274,9 @@ async fn main() -> Result<()> {
} }
Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => { Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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::sort( return email::handlers::sort(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
criteria, criteria,
@ -388,79 +288,29 @@ async fn main() -> Result<()> {
.await; .await;
} }
Some(email::args::Cmd::Send(raw_email)) => { 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; return email::handlers::send(&account_config, &mut printer, &backend, raw_email).await;
} }
Some(email::args::Cmd::Flag(m)) => match m { Some(email::args::Cmd::Flag(m)) => match m {
Some(flag::args::Cmd::Set(ids, ref flags)) => { Some(flag::args::Cmd::Set(ids, ref flags)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return flag::handlers::set(&mut printer, &backend, &folder, ids, flags).await;
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;
} }
Some(flag::args::Cmd::Add(ids, ref flags)) => { Some(flag::args::Cmd::Add(ids, ref flags)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return flag::handlers::add(&mut printer, &backend, &folder, ids, flags).await;
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;
} }
Some(flag::args::Cmd::Remove(ids, ref flags)) => { Some(flag::args::Cmd::Remove(ids, ref flags)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return flag::handlers::remove(&mut printer, &backend, &folder, ids, flags).await;
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;
} }
_ => (), _ => (),
}, },
Some(email::args::Cmd::Tpl(m)) => match m { Some(email::args::Cmd::Tpl(m)) => match m {
Some(tpl::args::Cmd::Forward(id, headers, body)) => { Some(tpl::args::Cmd::Forward(id, headers, body)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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 tpl::handlers::forward( return tpl::handlers::forward(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
id, id,
@ -475,15 +325,9 @@ async fn main() -> Result<()> {
} }
Some(tpl::args::Cmd::Reply(id, all, headers, body)) => { Some(tpl::args::Cmd::Reply(id, all, headers, body)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_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 tpl::handlers::reply( return tpl::handlers::reply(
&account_config, &account_config,
&mut printer, &mut printer,
&id_mapper,
&backend, &backend,
&folder, &folder,
id, id,
@ -495,35 +339,15 @@ async fn main() -> Result<()> {
} }
Some(tpl::args::Cmd::Save(tpl)) => { Some(tpl::args::Cmd::Save(tpl)) => {
let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
let backend_builder = return tpl::handlers::save(&account_config, &mut printer, &backend, &folder, tpl)
BackendBuilder::new(toml_account_config, account_config.clone(), disable_cache) .await;
.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;
} }
Some(tpl::args::Cmd::Send(tpl)) => { 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; return tpl::handlers::send(&account_config, &mut printer, &backend, tpl).await;
} }
_ => (), _ => (),
}, },
Some(email::args::Cmd::Write(headers, body)) => { 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) return email::handlers::write(&account_config, &mut printer, &backend, headers, body)
.await; .await;
} }