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::{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<MaildirSessionBuilder>,
maildir: Option<MaildirSessionBuilder>,
maildir_for_sync: Option<MaildirSessionBuilder>,
#[cfg(feature = "imap-backend")]
imap: Option<ImapSessionBuilder>,
#[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<MaildirSessionSync>,
pub maildir: Option<MaildirSessionSync>,
pub maildir_for_sync: Option<MaildirSessionSync>,
#[cfg(feature = "imap-backend")]
pub imap: Option<ImapSessionSync>,
#[cfg(feature = "smtp-sender")]
@ -119,55 +122,178 @@ pub struct BackendContext {
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 {
pub async fn new(
deserialized_account_config: DeserializedAccountConfig,
toml_account_config: DeserializedAccountConfig,
account_config: AccountConfig,
disable_cache: bool,
) -> Result<Self> {
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<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 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<Self> {
Ok(IdMapper::Dummy)
pub fn new(account_config: &AccountConfig, folder: &str, db_path: PathBuf) -> Result<Self> {
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::<ImapBackend>() {
// 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::<MaildirBackend>() {
// 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::<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))
Ok(Self::Mapper(table, conn))
}
pub fn create_alias<I>(&self, id: I) -> Result<String>

View file

@ -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,

View file

@ -86,3 +86,141 @@ pub struct DeserializedAccountConfig {
#[serde(default, with = "OptionPgpConfigDef")]
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,
printer::{PrintTableOpts, Printer},
ui::editor,
Envelopes, IdMapper,
};
pub async fn attachments<P: Printer>(
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<P: Printer>(
pub async fn copy<P: Printer>(
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<P: Printer>(
pub async fn delete<P: Printer>(
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<P: Printer>(
pub async fn forward<P: Printer>(
config: &AccountConfig,
printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend,
folder: &str,
id: &str,
headers: Option<Vec<(&str, &str)>>,
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<P: Printer>(
pub async fn list<P: Printer>(
config: &AccountConfig,
printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend,
folder: &str,
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());
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<P: Printer>(
pub async fn move_<P: Printer>(
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_<P: Printer>(
pub async fn read<P: Printer>(
config: &AccountConfig,
printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend,
folder: &str,
ids: Vec<&str>,
@ -214,7 +197,6 @@ pub async fn read<P: Printer>(
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<P: Printer>(
pub async fn reply<P: Printer>(
config: &AccountConfig,
printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend,
folder: &str,
id: &str,
@ -257,9 +238,8 @@ pub async fn reply<P: Printer>(
headers: Option<Vec<(&str, &str)>>,
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<P: Printer>(
.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<P: Printer>(
printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend,
folder: &str,
raw_email: String,
@ -295,10 +276,9 @@ pub async fn save<P: Printer>(
.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<P: Printer>(
pub async fn search<P: Printer>(
_config: &AccountConfig,
_printer: &mut P,
_id_mapper: &IdMapper,
_backend: &Backend,
_folder: &str,
_query: String,
@ -334,7 +313,6 @@ pub async fn search<P: Printer>(
pub async fn sort<P: Printer>(
_config: &AccountConfig,
_printer: &mut P,
_id_mapper: &IdMapper,
_backend: &Backend,
_folder: &str,
_sort: String,

View file

@ -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<P: Printer>(
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<P: Printer>(
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<P: Printer>(
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!"))
}

View file

@ -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<P: Printer>(
config: &AccountConfig,
printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend,
folder: &str,
id: &str,
headers: Option<Vec<(&str, &str)>>,
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<P: Printer>(
pub async fn reply<P: Printer>(
config: &AccountConfig,
printer: &mut P,
id_mapper: &IdMapper,
backend: &Backend,
folder: &str,
id: &str,
@ -47,10 +43,8 @@ pub async fn reply<P: Printer>(
headers: Option<Vec<(&str, &str)>>,
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<P: Printer>(
pub async fn save<P: Printer>(
#[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<P: Printer>(
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!")
}

View file

@ -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;
}