mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-22 02:50:19 +00:00
move id mapper from lib to CLI
This commit is contained in:
parent
53538e36f9
commit
0ff77b5179
13 changed files with 429 additions and 168 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -1110,11 +1110,13 @@ dependencies = [
|
||||||
"erased-serde",
|
"erased-serde",
|
||||||
"indicatif",
|
"indicatif",
|
||||||
"log",
|
"log",
|
||||||
|
"md5",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pimalaya-email",
|
"pimalaya-email",
|
||||||
"pimalaya-keyring",
|
"pimalaya-keyring",
|
||||||
"pimalaya-process",
|
"pimalaya-process",
|
||||||
"pimalaya-secret",
|
"pimalaya-secret",
|
||||||
|
"rusqlite",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"shellexpand",
|
"shellexpand",
|
||||||
|
@ -2066,7 +2068,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-email"
|
name = "pimalaya-email"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
source = "git+https://git.sr.ht/~soywod/pimalaya#4fc9ef469ddb89728c42b13bbff928266307ed9b"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#715546fabf7246a7f4bff8371aff77f116ae9b9a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"advisory-lock",
|
"advisory-lock",
|
||||||
"ammonia",
|
"ammonia",
|
||||||
|
@ -2108,7 +2110,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-keyring"
|
name = "pimalaya-keyring"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://git.sr.ht/~soywod/pimalaya#4fc9ef469ddb89728c42b13bbff928266307ed9b"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#715546fabf7246a7f4bff8371aff77f116ae9b9a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"keyring",
|
"keyring",
|
||||||
"log",
|
"log",
|
||||||
|
@ -2118,7 +2120,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-oauth2"
|
name = "pimalaya-oauth2"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://git.sr.ht/~soywod/pimalaya#4fc9ef469ddb89728c42b13bbff928266307ed9b"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#715546fabf7246a7f4bff8371aff77f116ae9b9a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"oauth2",
|
"oauth2",
|
||||||
|
@ -2130,7 +2132,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-process"
|
name = "pimalaya-process"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://git.sr.ht/~soywod/pimalaya#4fc9ef469ddb89728c42b13bbff928266307ed9b"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#715546fabf7246a7f4bff8371aff77f116ae9b9a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -2139,7 +2141,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-secret"
|
name = "pimalaya-secret"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://git.sr.ht/~soywod/pimalaya#4fc9ef469ddb89728c42b13bbff928266307ed9b"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#715546fabf7246a7f4bff8371aff77f116ae9b9a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"pimalaya-keyring",
|
"pimalaya-keyring",
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -50,11 +50,16 @@ env_logger = "0.8"
|
||||||
erased-serde = "0.3"
|
erased-serde = "0.3"
|
||||||
indicatif = "0.17"
|
indicatif = "0.17"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
md5 = "0.7.0"
|
||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
||||||
pimalaya-keyring = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
pimalaya-keyring = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
||||||
pimalaya-process = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
pimalaya-process = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
||||||
pimalaya-secret = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
pimalaya-secret = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
||||||
|
# pimalaya-email = { path = "/home/soywod/sourcehut/pimalaya/email" }
|
||||||
|
# pimalaya-keyring = { path = "/home/soywod/sourcehut/pimalaya/keyring" }
|
||||||
|
# pimalaya-process = { path = "/home/soywod/sourcehut/pimalaya/process" }
|
||||||
|
# pimalaya-secret = { path = "/home/soywod/sourcehut/pimalaya/secret" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
shellexpand = "2.1"
|
shellexpand = "2.1"
|
||||||
|
@ -64,3 +69,8 @@ toml = "0.7.2"
|
||||||
unicode-width = "0.1"
|
unicode-width = "0.1"
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_env = "musl")'.dependencies]
|
||||||
|
rusqlite = { version = "0.29", features = [] }
|
||||||
|
[target.'cfg(not(target_env = "musl"))'.dependencies]
|
||||||
|
rusqlite = { version = "0.29", features = ["bundled"] }
|
||||||
|
|
|
@ -1,11 +1,4 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "stable"
|
channel = "stable"
|
||||||
profile = "default"
|
profile = "default"
|
||||||
components = [
|
components = [ "rust-src", "rust-analyzer" ]
|
||||||
"cargo",
|
|
||||||
"clippy",
|
|
||||||
"rust-analyzer",
|
|
||||||
"rust-std",
|
|
||||||
"rustc",
|
|
||||||
"rustfmt",
|
|
||||||
]
|
|
||||||
|
|
187
src/cache/id_mapper.rs
vendored
Normal file
187
src/cache/id_mapper.rs
vendored
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
use anyhow::{anyhow, Context, Result};
|
||||||
|
use log::{debug, trace};
|
||||||
|
#[cfg(feature = "imap-backend")]
|
||||||
|
use pimalaya_email::ImapBackend;
|
||||||
|
#[cfg(feature = "notmuch-backend")]
|
||||||
|
use pimalaya_email::NotmuchBackend;
|
||||||
|
use pimalaya_email::{Backend, MaildirBackend};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
const ID_MAPPER_DB_FILE_NAME: &str = ".id-mapper.sqlite";
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum IdMapper {
|
||||||
|
Dummy,
|
||||||
|
Mapper(String, rusqlite::Connection),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdMapper {
|
||||||
|
fn find_closest_db_path<D>(dir: D) -> PathBuf
|
||||||
|
where
|
||||||
|
D: AsRef<Path>,
|
||||||
|
{
|
||||||
|
let mut db_path = dir.as_ref().join(ID_MAPPER_DB_FILE_NAME);
|
||||||
|
let mut db_parent_dir = dir.as_ref().parent();
|
||||||
|
|
||||||
|
while !db_path.is_file() {
|
||||||
|
match db_parent_dir {
|
||||||
|
Some(dir) => {
|
||||||
|
db_path = dir.join(ID_MAPPER_DB_FILE_NAME);
|
||||||
|
db_parent_dir = dir.parent();
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
db_path = dir.as_ref().join(ID_MAPPER_DB_FILE_NAME);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
db_path
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(backend: &dyn Backend, account: &str, folder: &str) -> Result<Self> {
|
||||||
|
let mut db_path = PathBuf::default();
|
||||||
|
|
||||||
|
if let Some(backend) = backend.as_any().downcast_ref::<MaildirBackend>() {
|
||||||
|
db_path = Self::find_closest_db_path(&backend.path());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "imap-backend")]
|
||||||
|
if backend.as_any().is::<ImapBackend>() {
|
||||||
|
return Ok(Self::Dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "notmuch-backend")]
|
||||||
|
if let Some(backend) = backend.as_any().downcast_ref::<NotmuchBackend>() {
|
||||||
|
db_path = Self::find_closest_db_path(&backend.path());
|
||||||
|
}
|
||||||
|
|
||||||
|
let digest = md5::compute(account.to_string() + 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>
|
||||||
|
where
|
||||||
|
I: AsRef<str>,
|
||||||
|
{
|
||||||
|
let id = id.as_ref();
|
||||||
|
match self {
|
||||||
|
Self::Dummy => Ok(id.to_owned()),
|
||||||
|
Self::Mapper(table, conn) => {
|
||||||
|
debug!("creating alias for id {id}…");
|
||||||
|
|
||||||
|
let query = format!("INSERT OR IGNORE INTO {} (internal_id) VALUES (?)", table);
|
||||||
|
trace!("insert query: {query:#?}");
|
||||||
|
|
||||||
|
conn.execute(&query, [id])
|
||||||
|
.with_context(|| format!("cannot create id alias for id {id}"))?;
|
||||||
|
|
||||||
|
let alias = conn.last_insert_rowid().to_string();
|
||||||
|
debug!("created alias {alias} for id {id}");
|
||||||
|
|
||||||
|
Ok(alias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_create_alias<I>(&self, id: I) -> Result<String>
|
||||||
|
where
|
||||||
|
I: AsRef<str>,
|
||||||
|
{
|
||||||
|
let id = id.as_ref();
|
||||||
|
match self {
|
||||||
|
Self::Dummy => Ok(id.to_owned()),
|
||||||
|
Self::Mapper(table, conn) => {
|
||||||
|
debug!("getting alias for id {id}…");
|
||||||
|
|
||||||
|
let query = format!("SELECT id FROM {} WHERE internal_id = ?", table);
|
||||||
|
trace!("select query: {query:#?}");
|
||||||
|
|
||||||
|
let mut stmt = conn
|
||||||
|
.prepare(&query)
|
||||||
|
.with_context(|| format!("cannot get alias for id {id}"))?;
|
||||||
|
let aliases: Vec<i64> = stmt
|
||||||
|
.query_map([id], |row| row.get(0))
|
||||||
|
.with_context(|| format!("cannot get alias for id {id}"))?
|
||||||
|
.collect::<rusqlite::Result<_>>()
|
||||||
|
.with_context(|| format!("cannot get alias for id {id}"))?;
|
||||||
|
let alias = match aliases.first() {
|
||||||
|
Some(alias) => {
|
||||||
|
debug!("found alias {alias} for id {id}");
|
||||||
|
alias.to_string()
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
debug!("alias not found, creating it…");
|
||||||
|
self.create_alias(id)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(alias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_id<A>(&self, alias: A) -> Result<String>
|
||||||
|
where
|
||||||
|
A: AsRef<str>,
|
||||||
|
{
|
||||||
|
let alias = alias.as_ref();
|
||||||
|
let alias = alias
|
||||||
|
.parse::<i64>()
|
||||||
|
.context(format!("cannot parse id mapper alias {alias}"))?;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Self::Dummy => Ok(alias.to_string()),
|
||||||
|
Self::Mapper(table, conn) => {
|
||||||
|
debug!("getting id from alias {alias}…");
|
||||||
|
|
||||||
|
let query = format!("SELECT internal_id FROM {} WHERE id = ?", table);
|
||||||
|
trace!("select query: {query:#?}");
|
||||||
|
|
||||||
|
let mut stmt = conn
|
||||||
|
.prepare(&query)
|
||||||
|
.with_context(|| format!("cannot get id from alias {alias}"))?;
|
||||||
|
let ids: Vec<String> = stmt
|
||||||
|
.query_map([alias], |row| row.get(0))
|
||||||
|
.with_context(|| format!("cannot get id from alias {alias}"))?
|
||||||
|
.collect::<rusqlite::Result<_>>()
|
||||||
|
.with_context(|| format!("cannot get id from alias {alias}"))?;
|
||||||
|
let id = ids
|
||||||
|
.first()
|
||||||
|
.ok_or_else(|| anyhow!("cannot get id from alias {alias}"))?
|
||||||
|
.to_owned();
|
||||||
|
debug!("found id {id} from alias {alias}");
|
||||||
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ids<A, I>(&self, aliases: I) -> Result<Vec<String>>
|
||||||
|
where
|
||||||
|
A: AsRef<str>,
|
||||||
|
I: IntoIterator<Item = A>,
|
||||||
|
{
|
||||||
|
aliases
|
||||||
|
.into_iter()
|
||||||
|
.map(|alias| self.get_id(alias))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
3
src/cache/mod.rs
vendored
3
src/cache/mod.rs
vendored
|
@ -1 +1,4 @@
|
||||||
pub mod args;
|
pub mod args;
|
||||||
|
mod id_mapper;
|
||||||
|
|
||||||
|
pub use id_mapper::IdMapper;
|
||||||
|
|
|
@ -14,17 +14,20 @@ use uuid::Uuid;
|
||||||
use crate::{
|
use crate::{
|
||||||
printer::{PrintTableOpts, Printer},
|
printer::{PrintTableOpts, Printer},
|
||||||
ui::editor,
|
ui::editor,
|
||||||
Envelopes,
|
Envelopes, IdMapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn attachments<P: Printer, B: Backend + ?Sized>(
|
pub fn attachments<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
let emails = backend.get_emails(&folder, ids.clone())?;
|
let emails = backend.get_emails(&folder, ids.clone())?;
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
|
@ -71,45 +74,54 @@ pub fn attachments<P: Printer, B: Backend + ?Sized>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy<P: Printer, B: Backend + ?Sized>(
|
pub fn copy<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
from_folder: &str,
|
from_folder: &str,
|
||||||
to_folder: &str,
|
to_folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let from_folder = config.folder_alias(from_folder)?;
|
let from_folder = config.folder_alias(from_folder)?;
|
||||||
let to_folder = config.folder_alias(to_folder)?;
|
let to_folder = config.folder_alias(to_folder)?;
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.copy_emails(&from_folder, &to_folder, ids)?;
|
backend.copy_emails(&from_folder, &to_folder, ids)?;
|
||||||
printer.print("Email(s) successfully copied!")
|
printer.print("Email(s) successfully copied!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete<P: Printer, B: Backend + ?Sized>(
|
pub fn delete<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.delete_emails(&folder, ids)?;
|
backend.delete_emails(&folder, ids)?;
|
||||||
printer.print("Email(s) successfully deleted!")
|
printer.print("Email(s) successfully deleted!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
pub fn forward<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
sender: &mut S,
|
backend: &mut dyn Backend,
|
||||||
|
sender: &mut dyn Sender,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<&str>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
|
let ids = id_mapper.get_ids([id])?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
let tpl = backend
|
let tpl = backend
|
||||||
.get_emails(&folder, vec![id])?
|
.get_emails(&folder, ids)?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_forward_tpl_builder(config)?
|
.to_forward_tpl_builder(config)?
|
||||||
|
@ -121,10 +133,11 @@ pub fn forward<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list<P: Printer, B: Backend + ?Sized>(
|
pub fn list<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
max_width: Option<usize>,
|
max_width: Option<usize>,
|
||||||
page_size: Option<usize>,
|
page_size: Option<usize>,
|
||||||
|
@ -133,8 +146,11 @@ pub fn list<P: Printer, B: Backend + ?Sized>(
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
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 = backend.list_envelopes(&folder, page_size, page)?.into();
|
|
||||||
|
let mut envelopes: Envelopes = backend.list_envelopes(&folder, page_size, page)?.into();
|
||||||
|
envelopes.remap_ids(id_mapper)?;
|
||||||
trace!("envelopes: {:?}", envelopes);
|
trace!("envelopes: {:?}", envelopes);
|
||||||
|
|
||||||
printer.print_table(
|
printer.print_table(
|
||||||
Box::new(envelopes),
|
Box::new(envelopes),
|
||||||
PrintTableOpts {
|
PrintTableOpts {
|
||||||
|
@ -147,11 +163,11 @@ pub fn list<P: Printer, B: Backend + ?Sized>(
|
||||||
/// Parses and edits a message from a [mailto] URL string.
|
/// Parses and edits a message from a [mailto] URL string.
|
||||||
///
|
///
|
||||||
/// [mailto]: https://en.wikipedia.org/wiki/Mailto
|
/// [mailto]: https://en.wikipedia.org/wiki/Mailto
|
||||||
pub fn mailto<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
pub fn mailto<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
backend: &mut dyn Backend,
|
||||||
sender: &mut S,
|
sender: &mut dyn Sender,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut tpl = TplBuilder::default().to(url.path());
|
let mut tpl = TplBuilder::default().to(url.path());
|
||||||
|
@ -169,24 +185,28 @@ pub fn mailto<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
||||||
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl.build())
|
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_<P: Printer, B: Backend + ?Sized>(
|
pub fn move_<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
from_folder: &str,
|
from_folder: &str,
|
||||||
to_folder: &str,
|
to_folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let from_folder = config.folder_alias(from_folder)?;
|
let from_folder = config.folder_alias(from_folder)?;
|
||||||
let to_folder = config.folder_alias(to_folder)?;
|
let to_folder = config.folder_alias(to_folder)?;
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.move_emails(&from_folder, &to_folder, ids)?;
|
backend.move_emails(&from_folder, &to_folder, ids)?;
|
||||||
printer.print("Email(s) successfully moved!")
|
printer.print("Email(s) successfully moved!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<P: Printer, B: Backend + ?Sized>(
|
pub fn read<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
text_mime: &str,
|
text_mime: &str,
|
||||||
|
@ -195,6 +215,8 @@ pub fn read<P: Printer, B: Backend + ?Sized>(
|
||||||
headers: Vec<&str>,
|
headers: Vec<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
let emails = backend.get_emails(&folder, ids)?;
|
let emails = backend.get_emails(&folder, ids)?;
|
||||||
|
|
||||||
let mut glue = "";
|
let mut glue = "";
|
||||||
|
@ -230,11 +252,12 @@ pub fn read<P: Printer, B: Backend + ?Sized>(
|
||||||
printer.print(bodies)
|
printer.print(bodies)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
pub fn reply<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
sender: &mut S,
|
backend: &mut dyn Backend,
|
||||||
|
sender: &mut dyn Sender,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
all: bool,
|
all: bool,
|
||||||
|
@ -242,8 +265,10 @@ pub fn reply<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
|
let ids = id_mapper.get_ids([id])?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
let tpl = backend
|
let tpl = backend
|
||||||
.get_emails(&folder, vec![id])?
|
.get_emails(&folder, ids)?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_reply_tpl_builder(config, all)?
|
.to_reply_tpl_builder(config, all)?
|
||||||
|
@ -256,10 +281,11 @@ pub fn reply<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save<P: Printer, B: Backend + ?Sized>(
|
pub fn save<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
raw_email: String,
|
raw_email: String,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -276,14 +302,18 @@ pub fn save<P: Printer, B: Backend + ?Sized>(
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\r\n")
|
.join("\r\n")
|
||||||
};
|
};
|
||||||
backend.add_email(&folder, raw_email.as_bytes(), &Flags::default())?;
|
|
||||||
|
let id = backend.add_email(&folder, raw_email.as_bytes(), &Flags::default())?;
|
||||||
|
id_mapper.create_alias(id)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search<P: Printer, B: Backend + ?Sized>(
|
pub fn search<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
query: String,
|
query: String,
|
||||||
max_width: Option<usize>,
|
max_width: Option<usize>,
|
||||||
|
@ -292,9 +322,10 @@ pub fn search<P: Printer, B: Backend + ?Sized>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
let page_size = page_size.unwrap_or(config.email_listing_page_size());
|
let page_size = page_size.unwrap_or(config.email_listing_page_size());
|
||||||
let envelopes: Envelopes = backend
|
let mut envelopes: Envelopes = backend
|
||||||
.search_envelopes(&folder, &query, "", page_size, page)?
|
.search_envelopes(&folder, &query, "", page_size, page)?
|
||||||
.into();
|
.into();
|
||||||
|
envelopes.remap_ids(id_mapper)?;
|
||||||
let opts = PrintTableOpts {
|
let opts = PrintTableOpts {
|
||||||
format: &config.email_reading_format,
|
format: &config.email_reading_format,
|
||||||
max_width,
|
max_width,
|
||||||
|
@ -303,10 +334,11 @@ pub fn search<P: Printer, B: Backend + ?Sized>(
|
||||||
printer.print_table(Box::new(envelopes), opts)
|
printer.print_table(Box::new(envelopes), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sort<P: Printer, B: Backend + ?Sized>(
|
pub fn sort<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
sort: String,
|
sort: String,
|
||||||
query: String,
|
query: String,
|
||||||
|
@ -316,9 +348,10 @@ pub fn sort<P: Printer, B: Backend + ?Sized>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
let page_size = page_size.unwrap_or(config.email_listing_page_size());
|
let page_size = page_size.unwrap_or(config.email_listing_page_size());
|
||||||
let envelopes: Envelopes = backend
|
let mut envelopes: Envelopes = backend
|
||||||
.search_envelopes(&folder, &query, &sort, page_size, page)?
|
.search_envelopes(&folder, &query, &sort, page_size, page)?
|
||||||
.into();
|
.into();
|
||||||
|
envelopes.remap_ids(id_mapper)?;
|
||||||
let opts = PrintTableOpts {
|
let opts = PrintTableOpts {
|
||||||
format: &config.email_reading_format,
|
format: &config.email_reading_format,
|
||||||
max_width,
|
max_width,
|
||||||
|
@ -327,11 +360,11 @@ pub fn sort<P: Printer, B: Backend + ?Sized>(
|
||||||
printer.print_table(Box::new(envelopes), opts)
|
printer.print_table(Box::new(envelopes), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
pub fn send<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
backend: &mut dyn Backend,
|
||||||
sender: &mut S,
|
sender: &mut dyn Sender,
|
||||||
raw_email: String,
|
raw_email: String,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.sent_folder_alias()?;
|
let folder = config.sent_folder_alias()?;
|
||||||
|
@ -357,11 +390,11 @@ pub fn send<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
pub fn write<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
backend: &mut dyn Backend,
|
||||||
sender: &mut S,
|
sender: &mut dyn Sender,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<&str>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
use std::ops;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use std::ops;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
printer::{PrintTable, PrintTableOpts, WriteColor},
|
printer::{PrintTable, PrintTableOpts, WriteColor},
|
||||||
ui::Table,
|
ui::Table,
|
||||||
Envelope,
|
Envelope, IdMapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents the list of envelopes.
|
/// Represents the list of envelopes.
|
||||||
#[derive(Clone, Debug, Default, Serialize)]
|
#[derive(Clone, Debug, Default, Serialize)]
|
||||||
pub struct Envelopes(Vec<Envelope>);
|
pub struct Envelopes(Vec<Envelope>);
|
||||||
|
|
||||||
|
impl Envelopes {
|
||||||
|
pub fn remap_ids(&mut self, id_mapper: &IdMapper) -> Result<()> {
|
||||||
|
for envelope in &mut self.0 {
|
||||||
|
envelope.id = id_mapper.get_or_create_alias(&envelope.id)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ops::Deref for Envelopes {
|
impl ops::Deref for Envelopes {
|
||||||
type Target = Vec<Envelope>;
|
type Target = Vec<Envelope>;
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,46 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pimalaya_email::{Backend, Flags};
|
use pimalaya_email::{Backend, Flags};
|
||||||
|
|
||||||
use crate::printer::Printer;
|
use crate::{printer::Printer, IdMapper};
|
||||||
|
|
||||||
pub fn add<P: Printer, B: Backend + ?Sized>(
|
pub fn add<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
flags: &Flags,
|
flags: &Flags,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.add_flags(folder, ids, flags)?;
|
backend.add_flags(folder, ids, flags)?;
|
||||||
printer.print("Flag(s) successfully added!")
|
printer.print("Flag(s) successfully added!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set<P: Printer, B: Backend + ?Sized>(
|
pub fn set<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
flags: &Flags,
|
flags: &Flags,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.set_flags(folder, ids, flags)?;
|
backend.set_flags(folder, ids, flags)?;
|
||||||
printer.print("Flag(s) successfully set!")
|
printer.print("Flag(s) successfully set!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove<P: Printer, B: Backend + ?Sized>(
|
pub fn remove<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
flags: &Flags,
|
flags: &Flags,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.remove_flags(folder, ids, flags)?;
|
backend.remove_flags(folder, ids, flags)?;
|
||||||
printer.print("Flag(s) successfully removed!")
|
printer.print("Flag(s) successfully removed!")
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,19 +12,15 @@ use crate::{
|
||||||
Folders,
|
Folders,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn expunge<P: Printer, B: Backend + ?Sized>(
|
pub fn expunge<P: Printer>(printer: &mut P, backend: &mut dyn Backend, folder: &str) -> Result<()> {
|
||||||
printer: &mut P,
|
|
||||||
backend: &mut B,
|
|
||||||
folder: &str,
|
|
||||||
) -> Result<()> {
|
|
||||||
backend.expunge_folder(folder)?;
|
backend.expunge_folder(folder)?;
|
||||||
printer.print(format!("Folder {folder} successfully expunged!"))
|
printer.print(format!("Folder {folder} successfully expunged!"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list<P: Printer, B: Backend + ?Sized>(
|
pub fn list<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
backend: &mut dyn Backend,
|
||||||
max_width: Option<usize>,
|
max_width: Option<usize>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folders: Folders = backend.list_folders()?.into();
|
let folders: Folders = backend.list_folders()?.into();
|
||||||
|
@ -38,20 +34,12 @@ pub fn list<P: Printer, B: Backend + ?Sized>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create<P: Printer, B: Backend + ?Sized>(
|
pub fn create<P: Printer>(printer: &mut P, backend: &mut dyn Backend, folder: &str) -> Result<()> {
|
||||||
printer: &mut P,
|
|
||||||
backend: &mut B,
|
|
||||||
folder: &str,
|
|
||||||
) -> Result<()> {
|
|
||||||
backend.add_folder(folder)?;
|
backend.add_folder(folder)?;
|
||||||
printer.print("Folder successfully created!")
|
printer.print("Folder successfully created!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete<P: Printer, B: Backend + ?Sized>(
|
pub fn delete<P: Printer>(printer: &mut P, backend: &mut dyn Backend, folder: &str) -> Result<()> {
|
||||||
printer: &mut P,
|
|
||||||
backend: &mut B,
|
|
||||||
folder: &str,
|
|
||||||
) -> Result<()> {
|
|
||||||
if let Some(false) | None = Confirm::new()
|
if let Some(false) | None = Confirm::new()
|
||||||
.with_prompt(format!("Confirm deletion of folder {folder}?"))
|
.with_prompt(format!("Confirm deletion of folder {folder}?"))
|
||||||
.default(false)
|
.default(false)
|
||||||
|
@ -176,9 +164,6 @@ mod tests {
|
||||||
fn get_envelope(&self, _: &str, _: &str) -> backend::Result<Envelope> {
|
fn get_envelope(&self, _: &str, _: &str) -> backend::Result<Envelope> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn get_envelope_internal(&self, _: &str, _: &str) -> backend::Result<Envelope> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
fn list_envelopes(&self, _: &str, _: usize, _: usize) -> backend::Result<Envelopes> {
|
fn list_envelopes(&self, _: &str, _: usize, _: usize) -> backend::Result<Envelopes> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
@ -195,60 +180,31 @@ mod tests {
|
||||||
fn add_email(&self, _: &str, _: &[u8], _: &Flags) -> backend::Result<String> {
|
fn add_email(&self, _: &str, _: &[u8], _: &Flags) -> backend::Result<String> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn add_email_internal(&self, _: &str, _: &[u8], _: &Flags) -> backend::Result<String> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn get_emails(&self, _: &str, _: Vec<&str>) -> backend::Result<Emails> {
|
fn get_emails(&self, _: &str, _: Vec<&str>) -> backend::Result<Emails> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn preview_emails(&self, _: &str, _: Vec<&str>) -> backend::Result<Emails> {
|
fn preview_emails(&self, _: &str, _: Vec<&str>) -> backend::Result<Emails> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn get_emails_internal(&self, _: &str, _: Vec<&str>) -> backend::Result<Emails> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn copy_emails(&self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
fn copy_emails(&self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn copy_emails_internal(&self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn move_emails(&self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
fn move_emails(&self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn move_emails_internal(&self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn delete_emails(&self, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
fn delete_emails(&self, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn delete_emails_internal(&self, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn add_flags(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
fn add_flags(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn add_flags_internal(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn set_flags(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
fn set_flags(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn set_flags_internal(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn remove_flags(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
fn remove_flags(&self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn remove_flags_internal(
|
fn as_any(&self) -> &(dyn Any) {
|
||||||
&self,
|
|
||||||
_: &str,
|
|
||||||
_: Vec<&str>,
|
|
||||||
_: &Flags,
|
|
||||||
) -> backend::Result<()> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
fn as_any(&'static self) -> &(dyn Any) {
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,22 @@ use atty::Stream;
|
||||||
use pimalaya_email::{AccountConfig, Backend, CompilerBuilder, Email, Flags, Sender, Tpl};
|
use pimalaya_email::{AccountConfig, Backend, CompilerBuilder, Email, Flags, Sender, Tpl};
|
||||||
use std::io::{stdin, BufRead};
|
use std::io::{stdin, BufRead};
|
||||||
|
|
||||||
use crate::printer::Printer;
|
use crate::{printer::Printer, IdMapper};
|
||||||
|
|
||||||
pub fn forward<P: Printer, B: Backend + ?Sized>(
|
pub fn forward<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<&str>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let ids = id_mapper.get_ids([id])?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
let tpl = backend
|
let tpl = backend
|
||||||
.get_emails(folder, vec![id])?
|
.get_emails(folder, ids)?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_forward_tpl_builder(config)?
|
.to_forward_tpl_builder(config)?
|
||||||
|
@ -26,18 +29,21 @@ pub fn forward<P: Printer, B: Backend + ?Sized>(
|
||||||
printer.print(<Tpl as Into<String>>::into(tpl))
|
printer.print(<Tpl as Into<String>>::into(tpl))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply<P: Printer, B: Backend + ?Sized>(
|
pub fn reply<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
all: bool,
|
all: bool,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<&str>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let ids = id_mapper.get_ids([id])?;
|
||||||
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
let tpl = backend
|
let tpl = backend
|
||||||
.get_emails(folder, vec![id])?
|
.get_emails(folder, ids)?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_reply_tpl_builder(config, all)?
|
.to_reply_tpl_builder(config, all)?
|
||||||
|
@ -48,10 +54,11 @@ pub fn reply<P: Printer, B: Backend + ?Sized>(
|
||||||
printer.print(<Tpl as Into<String>>::into(tpl))
|
printer.print(<Tpl as Into<String>>::into(tpl))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save<P: Printer, B: Backend + ?Sized>(
|
pub fn save<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
id_mapper: &IdMapper,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
tpl: String,
|
tpl: String,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -71,15 +78,17 @@ pub fn save<P: Printer, B: Backend + ?Sized>(
|
||||||
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.as_ref()),
|
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.as_ref()),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
backend.add_email(folder, &email, &Flags::default())?;
|
let id = backend.add_email(folder, &email, &Flags::default())?;
|
||||||
|
id_mapper.create_alias(id)?;
|
||||||
|
|
||||||
printer.print("Template successfully saved!")
|
printer.print("Template successfully saved!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
pub fn send<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
backend: &mut dyn Backend,
|
||||||
sender: &mut S,
|
sender: &mut dyn Sender,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
tpl: String,
|
tpl: String,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -114,6 +123,5 @@ pub fn write<'a, P: Printer>(
|
||||||
.set_some_raw_headers(headers)
|
.set_some_raw_headers(headers)
|
||||||
.some_text_plain_part(body)
|
.some_text_plain_part(body)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
printer.print(<Tpl as Into<String>>::into(tpl))
|
printer.print(<Tpl as Into<String>>::into(tpl))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,5 @@ pub mod output;
|
||||||
pub mod printer;
|
pub mod printer;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
|
||||||
|
pub use cache::*;
|
||||||
pub use domain::*;
|
pub use domain::*;
|
||||||
|
|
127
src/main.rs
127
src/main.rs
|
@ -1,6 +1,9 @@
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use std::{borrow::Cow, env};
|
use pimalaya_email::{
|
||||||
|
BackendBuilder, BackendConfig, ImapBackend, SenderBuilder, DEFAULT_INBOX_FOLDER,
|
||||||
|
};
|
||||||
|
use std::env;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use himalaya::{
|
use himalaya::{
|
||||||
|
@ -8,10 +11,7 @@ use himalaya::{
|
||||||
config::{self, DeserializedConfig},
|
config::{self, DeserializedConfig},
|
||||||
email, flag, folder, man, output,
|
email, flag, folder, man, output,
|
||||||
printer::StdoutPrinter,
|
printer::StdoutPrinter,
|
||||||
tpl,
|
tpl, IdMapper,
|
||||||
};
|
|
||||||
use pimalaya_email::{
|
|
||||||
BackendBuilder, BackendConfig, ImapBackend, SenderBuilder, DEFAULT_INBOX_FOLDER,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "imap-backend")]
|
#[cfg(feature = "imap-backend")]
|
||||||
|
@ -52,7 +52,8 @@ fn main() -> Result<()> {
|
||||||
let url = Url::parse(&raw_args[1])?;
|
let url = Url::parse(&raw_args[1])?;
|
||||||
let config = DeserializedConfig::from_opt_path(None)?;
|
let config = DeserializedConfig::from_opt_path(None)?;
|
||||||
let (account_config, backend_config) = config.to_configs(None)?;
|
let (account_config, backend_config) = config.to_configs(None)?;
|
||||||
let mut backend = BackendBuilder::new().build(&account_config, &backend_config)?;
|
let mut backend =
|
||||||
|
BackendBuilder::new().build(account_config.clone(), backend_config.clone())?;
|
||||||
let mut sender = SenderBuilder::build(&account_config)?;
|
let mut sender = SenderBuilder::build(&account_config)?;
|
||||||
let mut printer = StdoutPrinter::default();
|
let mut printer = StdoutPrinter::default();
|
||||||
|
|
||||||
|
@ -99,13 +100,11 @@ fn main() -> Result<()> {
|
||||||
// recreating an instance.
|
// recreating an instance.
|
||||||
match imap::args::matches(&m)? {
|
match imap::args::matches(&m)? {
|
||||||
Some(imap::args::Cmd::Notify(keepalive)) => {
|
Some(imap::args::Cmd::Notify(keepalive)) => {
|
||||||
let imap =
|
let imap = ImapBackend::new(account_config.clone(), imap_config.clone())?;
|
||||||
ImapBackend::new(Cow::Borrowed(&account_config), Cow::Borrowed(&imap_config))?;
|
|
||||||
return imap::handlers::notify(&imap, &folder, keepalive);
|
return imap::handlers::notify(&imap, &folder, keepalive);
|
||||||
}
|
}
|
||||||
Some(imap::args::Cmd::Watch(keepalive)) => {
|
Some(imap::args::Cmd::Watch(keepalive)) => {
|
||||||
let imap =
|
let imap = ImapBackend::new(account_config.clone(), imap_config.clone())?;
|
||||||
ImapBackend::new(Cow::Borrowed(&account_config), Cow::Borrowed(&imap_config))?;
|
|
||||||
return imap::handlers::watch(&imap, &folder, keepalive);
|
return imap::handlers::watch(&imap, &folder, keepalive);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -126,7 +125,7 @@ fn main() -> Result<()> {
|
||||||
let backend = BackendBuilder::new()
|
let backend = BackendBuilder::new()
|
||||||
.sessions_pool_size(8)
|
.sessions_pool_size(8)
|
||||||
.disable_cache(true)
|
.disable_cache(true)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
account::handlers::sync(
|
account::handlers::sync(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
@ -152,13 +151,13 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder)?;
|
let folder = account_config.folder_alias(folder)?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return folder::handlers::create(&mut printer, backend.as_mut(), &folder);
|
return folder::handlers::create(&mut printer, backend.as_mut(), &folder);
|
||||||
}
|
}
|
||||||
Some(folder::args::Cmd::List(max_width)) => {
|
Some(folder::args::Cmd::List(max_width)) => {
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return folder::handlers::list(
|
return folder::handlers::list(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
@ -170,7 +169,7 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return folder::handlers::expunge(&mut printer, backend.as_mut(), &folder);
|
return folder::handlers::expunge(&mut printer, backend.as_mut(), &folder);
|
||||||
}
|
}
|
||||||
Some(folder::args::Cmd::Delete) => {
|
Some(folder::args::Cmd::Delete) => {
|
||||||
|
@ -180,7 +179,7 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder)?;
|
let folder = account_config.folder_alias(folder)?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return folder::handlers::delete(&mut printer, backend.as_mut(), &folder);
|
return folder::handlers::delete(&mut printer, backend.as_mut(), &folder);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
@ -192,10 +191,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::attachments(
|
return email::handlers::attachments(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
|
@ -205,10 +206,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::copy(
|
return email::handlers::copy(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
to_folder,
|
to_folder,
|
||||||
|
@ -219,10 +222,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::delete(
|
return email::handlers::delete(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
|
@ -232,10 +237,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::forward(
|
return email::handlers::forward(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
sender.as_mut(),
|
sender.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
|
@ -248,10 +255,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::list(
|
return email::handlers::list(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
max_width,
|
max_width,
|
||||||
|
@ -263,10 +272,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::move_(
|
return email::handlers::move_(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
to_folder,
|
to_folder,
|
||||||
|
@ -277,10 +288,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::read(
|
return email::handlers::read(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
|
@ -294,10 +307,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::reply(
|
return email::handlers::reply(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
sender.as_mut(),
|
sender.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
|
@ -311,10 +326,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::save(
|
return email::handlers::save(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
raw_email,
|
raw_email,
|
||||||
|
@ -324,10 +341,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::search(
|
return email::handlers::search(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
query,
|
query,
|
||||||
|
@ -340,10 +359,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return email::handlers::sort(
|
return email::handlers::sort(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
criteria,
|
criteria,
|
||||||
|
@ -356,7 +377,7 @@ fn main() -> Result<()> {
|
||||||
Some(email::args::Cmd::Send(raw_email)) => {
|
Some(email::args::Cmd::Send(raw_email)) => {
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return email::handlers::send(
|
return email::handlers::send(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
@ -370,22 +391,46 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return flag::handlers::set(&mut printer, backend.as_mut(), &folder, ids, flags);
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
|
return flag::handlers::set(
|
||||||
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
|
backend.as_mut(),
|
||||||
|
&folder,
|
||||||
|
ids,
|
||||||
|
flags,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Some(flag::args::Cmd::Add(ids, ref flags)) => {
|
Some(flag::args::Cmd::Add(ids, ref flags)) => {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return flag::handlers::add(&mut printer, backend.as_mut(), &folder, ids, flags);
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
|
return flag::handlers::add(
|
||||||
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
|
backend.as_mut(),
|
||||||
|
&folder,
|
||||||
|
ids,
|
||||||
|
flags,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Some(flag::args::Cmd::Remove(ids, ref flags)) => {
|
Some(flag::args::Cmd::Remove(ids, ref flags)) => {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return flag::handlers::remove(&mut printer, backend.as_mut(), &folder, ids, flags);
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
|
return flag::handlers::remove(
|
||||||
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
|
backend.as_mut(),
|
||||||
|
&folder,
|
||||||
|
ids,
|
||||||
|
flags,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
|
@ -394,10 +439,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return tpl::handlers::forward(
|
return tpl::handlers::forward(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
id,
|
id,
|
||||||
|
@ -412,10 +459,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return tpl::handlers::reply(
|
return tpl::handlers::reply(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
id,
|
id,
|
||||||
|
@ -428,10 +477,12 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_config.name, &folder)?;
|
||||||
return tpl::handlers::save(
|
return tpl::handlers::save(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
tpl,
|
tpl,
|
||||||
|
@ -441,7 +492,7 @@ fn main() -> Result<()> {
|
||||||
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?;
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return tpl::handlers::send(
|
return tpl::handlers::send(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
@ -456,7 +507,7 @@ fn main() -> Result<()> {
|
||||||
Some(email::args::Cmd::Write(headers, body)) => {
|
Some(email::args::Cmd::Write(headers, body)) => {
|
||||||
let mut backend = BackendBuilder::new()
|
let mut backend = BackendBuilder::new()
|
||||||
.disable_cache(disable_cache)
|
.disable_cache(disable_cache)
|
||||||
.build(&account_config, &backend_config)?;
|
.build(account_config.clone(), backend_config.clone())?;
|
||||||
return email::handlers::write(
|
return email::handlers::write(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
|
|
|
@ -37,11 +37,11 @@ pub fn open_with_local_draft() -> Result<Tpl> {
|
||||||
open_with_tpl(Tpl::from(content))
|
open_with_tpl(Tpl::from(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edit_tpl_with_editor<P: Printer, B: Backend + ?Sized, S: Sender + ?Sized>(
|
pub fn edit_tpl_with_editor<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut B,
|
backend: &mut dyn Backend,
|
||||||
sender: &mut S,
|
sender: &mut dyn Sender,
|
||||||
mut tpl: Tpl,
|
mut tpl: Tpl,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let draft = local_draft_path();
|
let draft = local_draft_path();
|
||||||
|
|
Loading…
Reference in a new issue