mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-24 20:10:23 +00:00
use tokio async runtime
last fixes before merge
This commit is contained in:
parent
f8ca248bce
commit
cac8280c8c
31 changed files with 538 additions and 332 deletions
31
Cargo.lock
generated
31
Cargo.lock
generated
|
@ -1218,6 +1218,7 @@ name = "himalaya"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"async-trait",
|
||||||
"atty",
|
"atty",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -2199,12 +2200,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-email"
|
name = "pimalaya-email"
|
||||||
version = "0.11.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#5250a4c906228da7f2d1ca1d58468a760c69c720"
|
||||||
checksum = "8375dc804686e9e03a8b6f87d80b9038b5a734efb4b77f81b90b07b8ac1d4499"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"advisory-lock",
|
"advisory-lock",
|
||||||
"ammonia",
|
"ammonia",
|
||||||
|
"async-trait",
|
||||||
"chrono",
|
"chrono",
|
||||||
"convert_case",
|
"convert_case",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
@ -2244,10 +2245,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-email-tpl"
|
name = "pimalaya-email-tpl"
|
||||||
version = "0.2.3"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a838dd91468bf79997ead555d6a5b93f066e363259925ec931d49591b1ebb79"
|
checksum = "c536455f778ed7aa0948b755281e8e6a61650a857a3f610ff7e60b097a681838"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-recursion",
|
||||||
"chumsky 0.9.0",
|
"chumsky 0.9.0",
|
||||||
"log",
|
"log",
|
||||||
"mail-builder",
|
"mail-builder",
|
||||||
|
@ -2285,19 +2287,20 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-process"
|
name = "pimalaya-process"
|
||||||
version = "0.0.2"
|
version = "0.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d8d2853bf2f0efbe397ce22bb4e6d53a7464f6dcc0abe7e2936f6f4e8e2726a"
|
checksum = "1a9d1e1ab6334d4e4d06613cd65f3fed34e5d2d7b1488f3d1a0d2fdffdba5d1c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-secret"
|
name = "pimalaya-secret"
|
||||||
version = "0.0.2"
|
version = "0.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9338dc84e5ec9fc25f3a36d82ed68ffe4888ad728ca1aa42228e27648ddff01f"
|
checksum = "0f975cafe977327bb215cf71e953dd1f1bfa45d3cf4ab5e806493d917e0a0cd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"pimalaya-keyring",
|
"pimalaya-keyring",
|
||||||
|
@ -2925,6 +2928,15 @@ dependencies = [
|
||||||
"dirs",
|
"dirs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "0.3.10"
|
version = "0.3.10"
|
||||||
|
@ -3181,6 +3193,7 @@ dependencies = [
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.42.0",
|
"windows-sys 0.42.0",
|
||||||
|
|
|
@ -25,6 +25,7 @@ notmuch-backend = ["pimalaya-email/notmuch-backend"]
|
||||||
smtp-sender = ["pimalaya-email/smtp-sender"]
|
smtp-sender = ["pimalaya-email/smtp-sender"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
async-trait = "0.1"
|
||||||
tempfile = "3.3"
|
tempfile = "3.3"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -44,17 +45,17 @@ indicatif = "0.17"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
md5 = "0.7.0"
|
md5 = "0.7.0"
|
||||||
once_cell = "1.16.0"
|
once_cell = "1.16.0"
|
||||||
pimalaya-email = { version = "=0.11.0", default-features = false }
|
pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya", default-features = false }
|
||||||
pimalaya-keyring = "=0.0.4"
|
pimalaya-keyring = "=0.0.4"
|
||||||
pimalaya-oauth2 = "=0.0.3"
|
pimalaya-oauth2 = "=0.0.3"
|
||||||
pimalaya-process = "=0.0.2"
|
pimalaya-process = "=0.0.5"
|
||||||
pimalaya-secret = "=0.0.2"
|
pimalaya-secret = "=0.0.4"
|
||||||
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"
|
||||||
termcolor = "1.1"
|
termcolor = "1.1"
|
||||||
terminal_size = "0.1"
|
terminal_size = "0.1"
|
||||||
tokio = { version = "1.23", default-features = false, features = ["macros"] }
|
tokio = { version = "1.23", default-features = false, features = ["macros", "rt-multi-thread"] }
|
||||||
toml = "0.7.4"
|
toml = "0.7.4"
|
||||||
toml_edit = "0.19.8"
|
toml_edit = "0.19.8"
|
||||||
unicode-width = "0.1"
|
unicode-width = "0.1"
|
||||||
|
|
6
src/cache/id_mapper.rs
vendored
6
src/cache/id_mapper.rs
vendored
|
@ -1,10 +1,10 @@
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
#[cfg(feature = "imap-backend")]
|
#[cfg(feature = "imap-backend")]
|
||||||
use pimalaya_email::ImapBackend;
|
use pimalaya_email::backend::ImapBackend;
|
||||||
#[cfg(feature = "notmuch-backend")]
|
#[cfg(feature = "notmuch-backend")]
|
||||||
use pimalaya_email::NotmuchBackend;
|
use pimalaya_email::backend::NotmuchBackend;
|
||||||
use pimalaya_email::{Backend, MaildirBackend};
|
use pimalaya_email::backend::{Backend, MaildirBackend};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
const ID_MAPPER_DB_FILE_NAME: &str = ".id-mapper.sqlite";
|
const ID_MAPPER_DB_FILE_NAME: &str = ".id-mapper.sqlite";
|
||||||
|
|
|
@ -7,7 +7,10 @@ use anyhow::{anyhow, Context, Result};
|
||||||
use dialoguer::Confirm;
|
use dialoguer::Confirm;
|
||||||
use dirs::{config_dir, home_dir};
|
use dirs::{config_dir, home_dir};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use pimalaya_email::{AccountConfig, EmailHooks, EmailTextPlainFormat};
|
use pimalaya_email::{
|
||||||
|
account::AccountConfig,
|
||||||
|
email::{EmailHooks, EmailTextPlainFormat},
|
||||||
|
};
|
||||||
use pimalaya_process::Cmd;
|
use pimalaya_process::Cmd;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{collections::HashMap, fs, path::PathBuf, process};
|
use std::{collections::HashMap, fs, path::PathBuf, process};
|
||||||
|
@ -158,16 +161,18 @@ impl DeserializedConfig {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
BackendConfig, MaildirConfig, PasswdConfig, SenderConfig, SendmailConfig,
|
account::PasswdConfig,
|
||||||
|
backend::{BackendConfig, MaildirConfig},
|
||||||
|
sender::{SenderConfig, SendmailConfig},
|
||||||
};
|
};
|
||||||
use pimalaya_secret::Secret;
|
use pimalaya_secret::Secret;
|
||||||
|
|
||||||
#[cfg(feature = "notmuch-backend")]
|
#[cfg(feature = "notmuch-backend")]
|
||||||
use pimalaya_email::NotmuchConfig;
|
use pimalaya_email::backend::NotmuchConfig;
|
||||||
#[cfg(feature = "imap-backend")]
|
#[cfg(feature = "imap-backend")]
|
||||||
use pimalaya_email::{ImapAuthConfig, ImapConfig};
|
use pimalaya_email::backend::{ImapAuthConfig, ImapConfig};
|
||||||
#[cfg(feature = "smtp-sender")]
|
#[cfg(feature = "smtp-sender")]
|
||||||
use pimalaya_email::{SmtpAuthConfig, SmtpConfig};
|
use pimalaya_email::sender::{SmtpAuthConfig, SmtpConfig};
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
@ -453,7 +458,7 @@ mod tests {
|
||||||
#[cfg(feature = "smtp-sender")]
|
#[cfg(feature = "smtp-sender")]
|
||||||
#[test]
|
#[test]
|
||||||
fn account_smtp_sender_minimum_config() {
|
fn account_smtp_sender_minimum_config() {
|
||||||
use pimalaya_email::SenderConfig;
|
use pimalaya_email::sender::SenderConfig;
|
||||||
|
|
||||||
let config = make_config(
|
let config = make_config(
|
||||||
"[account]
|
"[account]
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
|
#[cfg(feature = "imap-backend")]
|
||||||
|
use pimalaya_email::backend::{ImapAuthConfig, ImapConfig};
|
||||||
|
#[cfg(feature = "smtp-sender")]
|
||||||
|
use pimalaya_email::sender::{SmtpAuthConfig, SmtpConfig};
|
||||||
#[cfg(feature = "notmuch-backend")]
|
#[cfg(feature = "notmuch-backend")]
|
||||||
use pimalaya_email::NotmuchConfig;
|
use pimalaya_email::NotmuchConfig;
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
BackendConfig, EmailHooks, EmailTextPlainFormat, FolderSyncStrategy, MaildirConfig,
|
account::{OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig},
|
||||||
OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig, SenderConfig, SendmailConfig,
|
backend::{BackendConfig, MaildirConfig},
|
||||||
|
email::{EmailHooks, EmailTextPlainFormat},
|
||||||
|
folder::sync::FolderSyncStrategy,
|
||||||
|
sender::{SenderConfig, SendmailConfig},
|
||||||
};
|
};
|
||||||
#[cfg(feature = "imap-backend")]
|
|
||||||
use pimalaya_email::{ImapAuthConfig, ImapConfig};
|
|
||||||
#[cfg(feature = "smtp-sender")]
|
|
||||||
use pimalaya_email::{SmtpAuthConfig, SmtpConfig};
|
|
||||||
use pimalaya_keyring::Entry;
|
use pimalaya_keyring::Entry;
|
||||||
use pimalaya_process::{Cmd, Pipeline, SingleCmd};
|
use pimalaya_process::{Cmd, Pipeline, SingleCmd};
|
||||||
use pimalaya_secret::Secret;
|
use pimalaya_secret::Secret;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//! accounts from the config file.
|
//! accounts from the config file.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pimalaya_email::BackendConfig;
|
use pimalaya_email::backend::BackendConfig;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::{collections::hash_map::Iter, ops::Deref};
|
use std::{collections::hash_map::Iter, ops::Deref};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
use log::info;
|
use log::info;
|
||||||
use pimalaya_email::FolderSyncStrategy;
|
use pimalaya_email::folder::sync::FolderSyncStrategy;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::{folder, ui::table};
|
use crate::{folder, ui::table};
|
||||||
|
|
|
@ -4,12 +4,15 @@
|
||||||
//! account in the accounts section of the user configuration file.
|
//! account in the accounts section of the user configuration file.
|
||||||
|
|
||||||
#[cfg(feature = "imap-backend")]
|
#[cfg(feature = "imap-backend")]
|
||||||
use pimalaya_email::ImapAuthConfig;
|
use pimalaya_email::backend::ImapAuthConfig;
|
||||||
#[cfg(feature = "smtp-sender")]
|
#[cfg(feature = "smtp-sender")]
|
||||||
use pimalaya_email::SmtpAuthConfig;
|
use pimalaya_email::sender::SmtpAuthConfig;
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
AccountConfig, BackendConfig, EmailHooks, EmailTextPlainFormat, FolderSyncStrategy,
|
account::AccountConfig,
|
||||||
SenderConfig,
|
backend::BackendConfig,
|
||||||
|
email::{EmailHooks, EmailTextPlainFormat},
|
||||||
|
folder::sync::FolderSyncStrategy,
|
||||||
|
sender::SenderConfig,
|
||||||
};
|
};
|
||||||
use pimalaya_process::Cmd;
|
use pimalaya_process::Cmd;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
|
@ -7,11 +7,16 @@ use indicatif::{MultiProgress, ProgressBar, ProgressFinish, ProgressStyle};
|
||||||
use log::{info, trace, warn};
|
use log::{info, trace, warn};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
#[cfg(feature = "imap-backend")]
|
#[cfg(feature = "imap-backend")]
|
||||||
use pimalaya_email::ImapAuthConfig;
|
use pimalaya_email::backend::ImapAuthConfig;
|
||||||
#[cfg(feature = "smtp-sender")]
|
#[cfg(feature = "smtp-sender")]
|
||||||
use pimalaya_email::SmtpAuthConfig;
|
use pimalaya_email::sender::SmtpAuthConfig;
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
AccountConfig, BackendConfig, BackendSyncBuilder, BackendSyncProgressEvent, SenderConfig,
|
account::{
|
||||||
|
sync::{AccountSyncBuilder, AccountSyncProgressEvent},
|
||||||
|
AccountConfig,
|
||||||
|
},
|
||||||
|
backend::BackendConfig,
|
||||||
|
sender::SenderConfig,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, sync::Mutex};
|
use std::{collections::HashMap, sync::Mutex};
|
||||||
|
|
||||||
|
@ -40,7 +45,7 @@ const SUB_PROGRESS_DONE_STYLE: Lazy<ProgressStyle> = Lazy::new(|| {
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Configure the current selected account
|
/// Configure the current selected account
|
||||||
pub fn configure(config: &AccountConfig, reset: bool) -> Result<()> {
|
pub async fn configure(config: &AccountConfig, reset: bool) -> Result<()> {
|
||||||
info!("entering the configure account handler");
|
info!("entering the configure account handler");
|
||||||
|
|
||||||
if reset {
|
if reset {
|
||||||
|
@ -72,9 +77,13 @@ pub fn configure(config: &AccountConfig, reset: bool) -> Result<()> {
|
||||||
#[cfg(feature = "imap-backend")]
|
#[cfg(feature = "imap-backend")]
|
||||||
if let BackendConfig::Imap(imap_config) = &config.backend {
|
if let BackendConfig::Imap(imap_config) = &config.backend {
|
||||||
match &imap_config.auth {
|
match &imap_config.auth {
|
||||||
ImapAuthConfig::Passwd(passwd) => passwd.configure(|| prompt_passwd("IMAP password")),
|
ImapAuthConfig::Passwd(passwd) => {
|
||||||
|
passwd.configure(|| prompt_passwd("IMAP password")).await
|
||||||
|
}
|
||||||
ImapAuthConfig::OAuth2(oauth2) => {
|
ImapAuthConfig::OAuth2(oauth2) => {
|
||||||
oauth2.configure(|| prompt_secret("IMAP OAuth 2.0 client secret"))
|
oauth2
|
||||||
|
.configure(|| prompt_secret("IMAP OAuth 2.0 client secret"))
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
@ -82,9 +91,13 @@ pub fn configure(config: &AccountConfig, reset: bool) -> Result<()> {
|
||||||
#[cfg(feature = "smtp-sender")]
|
#[cfg(feature = "smtp-sender")]
|
||||||
if let SenderConfig::Smtp(smtp_config) = &config.sender {
|
if let SenderConfig::Smtp(smtp_config) = &config.sender {
|
||||||
match &smtp_config.auth {
|
match &smtp_config.auth {
|
||||||
SmtpAuthConfig::Passwd(passwd) => passwd.configure(|| prompt_passwd("SMTP password")),
|
SmtpAuthConfig::Passwd(passwd) => {
|
||||||
|
passwd.configure(|| prompt_passwd("SMTP password")).await
|
||||||
|
}
|
||||||
SmtpAuthConfig::OAuth2(oauth2) => {
|
SmtpAuthConfig::OAuth2(oauth2) => {
|
||||||
oauth2.configure(|| prompt_secret("SMTP OAuth 2.0 client secret"))
|
oauth2
|
||||||
|
.configure(|| prompt_secret("SMTP OAuth 2.0 client secret"))
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
@ -123,16 +136,16 @@ pub fn list<'a, P: Printer>(
|
||||||
|
|
||||||
/// Synchronizes the account defined using argument `-a|--account`. If
|
/// Synchronizes the account defined using argument `-a|--account`. If
|
||||||
/// no account given, synchronizes the default one.
|
/// no account given, synchronizes the default one.
|
||||||
pub fn sync<'a, P: Printer>(
|
pub async fn sync<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
sync_builder: BackendSyncBuilder<'a>,
|
sync_builder: AccountSyncBuilder,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
info!("entering the sync accounts handler");
|
info!("entering the sync accounts handler");
|
||||||
trace!("dry run: {dry_run}");
|
trace!("dry run: {dry_run}");
|
||||||
|
|
||||||
if dry_run {
|
if dry_run {
|
||||||
let report = sync_builder.sync()?;
|
let report = sync_builder.sync().await?;
|
||||||
let mut hunks_count = report.folders_patch.len();
|
let mut hunks_count = report.folders_patch.len();
|
||||||
|
|
||||||
if !report.folders_patch.is_empty() {
|
if !report.folders_patch.is_empty() {
|
||||||
|
@ -143,9 +156,9 @@ pub fn sync<'a, P: Printer>(
|
||||||
printer.print_log("")?;
|
printer.print_log("")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !report.envelopes_patch.is_empty() {
|
if !report.emails_patch.is_empty() {
|
||||||
printer.print_log("Envelopes patch:")?;
|
printer.print_log("Envelopes patch:")?;
|
||||||
for (hunk, _) in report.envelopes_patch {
|
for (hunk, _) in report.emails_patch {
|
||||||
hunks_count += 1;
|
hunks_count += 1;
|
||||||
printer.print_log(format!(" - {hunk}"))?;
|
printer.print_log(format!(" - {hunk}"))?;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +169,7 @@ pub fn sync<'a, P: Printer>(
|
||||||
"Estimated patch length for account to be synchronized: {hunks_count}",
|
"Estimated patch length for account to be synchronized: {hunks_count}",
|
||||||
))?;
|
))?;
|
||||||
} else if printer.is_json() {
|
} else if printer.is_json() {
|
||||||
sync_builder.sync()?;
|
sync_builder.sync().await?;
|
||||||
printer.print("Account successfully synchronized!")?;
|
printer.print("Account successfully synchronized!")?;
|
||||||
} else {
|
} else {
|
||||||
let multi = MultiProgress::new();
|
let multi = MultiProgress::new();
|
||||||
|
@ -172,7 +185,7 @@ pub fn sync<'a, P: Printer>(
|
||||||
|
|
||||||
let report = sync_builder
|
let report = sync_builder
|
||||||
.with_on_progress(move |evt| {
|
.with_on_progress(move |evt| {
|
||||||
use BackendSyncProgressEvent::*;
|
use AccountSyncProgressEvent::*;
|
||||||
Ok(match evt {
|
Ok(match evt {
|
||||||
ApplyFolderPatches(..) => {
|
ApplyFolderPatches(..) => {
|
||||||
main_progress.inc(3);
|
main_progress.inc(3);
|
||||||
|
@ -223,7 +236,8 @@ pub fn sync<'a, P: Printer>(
|
||||||
_ => (),
|
_ => (),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.sync()?;
|
.sync()
|
||||||
|
.await?;
|
||||||
|
|
||||||
let folders_patch_err = report
|
let folders_patch_err = report
|
||||||
.folders_patch
|
.folders_patch
|
||||||
|
@ -246,7 +260,7 @@ pub fn sync<'a, P: Printer>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let envelopes_patch_err = report
|
let envelopes_patch_err = report
|
||||||
.envelopes_patch
|
.emails_patch
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(hunk, err)| err.as_ref().map(|err| (hunk, err)))
|
.filter_map(|(hunk, err)| err.as_ref().map(|err| (hunk, err)))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -258,7 +272,7 @@ pub fn sync<'a, P: Printer>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(err) = report.envelopes_cache_patch.1 {
|
if let Some(err) = report.emails_cache_patch.1 {
|
||||||
printer.print_log("")?;
|
printer.print_log("")?;
|
||||||
printer.print_log(format!(
|
printer.print_log(format!(
|
||||||
"Error occurred while applying the envelopes cache patch: {err}"
|
"Error occurred while applying the envelopes cache patch: {err}"
|
||||||
|
@ -273,7 +287,7 @@ pub fn sync<'a, P: Printer>(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pimalaya_email::{AccountConfig, ImapConfig};
|
use pimalaya_email::{account::AccountConfig, backend::ImapConfig};
|
||||||
use std::{collections::HashMap, fmt::Debug, io};
|
use std::{collections::HashMap, fmt::Debug, io};
|
||||||
use termcolor::ColorSpec;
|
use termcolor::ColorSpec;
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
//! This module gathers all IMAP handlers triggered by the CLI.
|
//! This module gathers all IMAP handlers triggered by the CLI.
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pimalaya_email::ImapBackend;
|
use pimalaya_email::backend::ImapBackend;
|
||||||
|
|
||||||
pub fn notify(imap: &mut ImapBackend, folder: &str, keepalive: u64) -> Result<()> {
|
pub async fn notify(imap: &mut ImapBackend, folder: &str, keepalive: u64) -> Result<()> {
|
||||||
imap.notify(keepalive, folder)?;
|
imap.notify(keepalive, folder).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn watch(imap: &mut ImapBackend, folder: &str, keepalive: u64) -> Result<()> {
|
pub async fn watch(imap: &mut ImapBackend, folder: &str, keepalive: u64) -> Result<()> {
|
||||||
imap.watch(keepalive, folder)?;
|
imap.watch(keepalive, folder).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dialoguer::{Confirm, Input, Password, Select};
|
use dialoguer::{Confirm, Input, Password, Select};
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
BackendConfig, ImapAuthConfig, ImapConfig, OAuth2Config, OAuth2Method, OAuth2Scopes,
|
account::{OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig},
|
||||||
PasswdConfig,
|
backend::{BackendConfig, ImapAuthConfig, ImapConfig},
|
||||||
};
|
};
|
||||||
use pimalaya_oauth2::{AuthorizationCodeGrant, Client};
|
use pimalaya_oauth2::{AuthorizationCodeGrant, Client};
|
||||||
use pimalaya_secret::Secret;
|
use pimalaya_secret::Secret;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dialoguer::Input;
|
use dialoguer::Input;
|
||||||
use dirs::home_dir;
|
use dirs::home_dir;
|
||||||
use pimalaya_email::{BackendConfig, MaildirConfig};
|
use pimalaya_email::backend::{BackendConfig, MaildirConfig};
|
||||||
|
|
||||||
use crate::config::wizard::THEME;
|
use crate::config::wizard::THEME;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dialoguer::Select;
|
use dialoguer::Select;
|
||||||
use pimalaya_email::BackendConfig;
|
use pimalaya_email::backend::BackendConfig;
|
||||||
|
|
||||||
use crate::config::wizard::THEME;
|
use crate::config::wizard::THEME;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,10 @@ use anyhow::{anyhow, Context, Result};
|
||||||
use atty::Stream;
|
use atty::Stream;
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
AccountConfig, Backend, Email, EmailBuilder, FilterParts, Flag, Flags, Sender,
|
account::AccountConfig,
|
||||||
|
backend::Backend,
|
||||||
|
email::{template::FilterParts, Flag, Flags, Message, MessageBuilder},
|
||||||
|
sender::Sender,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
|
@ -17,7 +20,7 @@ use crate::{
|
||||||
Envelopes, IdMapper,
|
Envelopes, IdMapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn attachments<P: Printer>(
|
pub async fn attachments<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -28,7 +31,7 @@ pub fn attachments<P: Printer>(
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
let ids = id_mapper.get_ids(ids)?;
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
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()).await?;
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
|
|
||||||
let mut emails_count = 0;
|
let mut emails_count = 0;
|
||||||
|
@ -57,7 +60,7 @@ pub fn attachments<P: Printer>(
|
||||||
let filename = attachment
|
let filename = attachment
|
||||||
.filename
|
.filename
|
||||||
.unwrap_or_else(|| Uuid::new_v4().to_string());
|
.unwrap_or_else(|| Uuid::new_v4().to_string());
|
||||||
let filepath = config.get_download_file_path(&filename)?;
|
let filepath = config.download_fpath(&filename)?;
|
||||||
printer.print_log(format!("Downloading {:?}…", filepath))?;
|
printer.print_log(format!("Downloading {:?}…", filepath))?;
|
||||||
fs::write(&filepath, &attachment.body).context("cannot download attachment")?;
|
fs::write(&filepath, &attachment.body).context("cannot download attachment")?;
|
||||||
attachments_count = attachments_count + 1;
|
attachments_count = attachments_count + 1;
|
||||||
|
@ -74,7 +77,7 @@ pub fn attachments<P: Printer>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy<P: Printer>(
|
pub async fn copy<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -87,11 +90,11 @@ pub fn copy<P: Printer>(
|
||||||
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 = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
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).await?;
|
||||||
printer.print("Email(s) successfully copied!")
|
printer.print("Email(s) successfully copied!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete<P: Printer>(
|
pub async fn delete<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -102,11 +105,11 @@ pub fn delete<P: Printer>(
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
let ids = id_mapper.get_ids(ids)?;
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.delete_emails(&folder, ids)?;
|
backend.delete_emails(&folder, ids).await?;
|
||||||
printer.print("Email(s) successfully deleted!")
|
printer.print("Email(s) successfully deleted!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward<P: Printer>(
|
pub async fn forward<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -123,19 +126,21 @@ pub fn forward<P: Printer>(
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
|
|
||||||
let tpl = backend
|
let tpl = backend
|
||||||
.get_emails(&folder, ids)?
|
.get_emails(&folder, ids)
|
||||||
|
.await?
|
||||||
.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)
|
||||||
.some_headers(headers)
|
.with_some_headers(headers)
|
||||||
.some_body(body)
|
.with_some_body(body)
|
||||||
.build()?;
|
.build()
|
||||||
|
.await?;
|
||||||
trace!("initial template: {}", *tpl);
|
trace!("initial template: {}", *tpl);
|
||||||
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl)?;
|
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list<P: Printer>(
|
pub async fn list<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -152,7 +157,7 @@ pub fn list<P: Printer>(
|
||||||
let envelopes = Envelopes::from_backend(
|
let envelopes = Envelopes::from_backend(
|
||||||
config,
|
config,
|
||||||
id_mapper,
|
id_mapper,
|
||||||
backend.list_envelopes(&folder, page_size, page)?,
|
backend.list_envelopes(&folder, page_size, page).await?,
|
||||||
)?;
|
)?;
|
||||||
trace!("envelopes: {:?}", envelopes);
|
trace!("envelopes: {:?}", envelopes);
|
||||||
|
|
||||||
|
@ -168,14 +173,14 @@ pub fn list<P: Printer>(
|
||||||
/// 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>(
|
pub async fn mailto<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
sender: &mut dyn Sender,
|
sender: &mut dyn Sender,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut builder = EmailBuilder::new().to(url.path());
|
let mut builder = MessageBuilder::new().to(url.path());
|
||||||
|
|
||||||
for (key, val) in url.query_pairs() {
|
for (key, val) in url.query_pairs() {
|
||||||
match key.to_lowercase().as_bytes() {
|
match key.to_lowercase().as_bytes() {
|
||||||
|
@ -190,12 +195,13 @@ pub fn mailto<P: Printer>(
|
||||||
let tpl = config
|
let tpl = config
|
||||||
.generate_tpl_interpreter()
|
.generate_tpl_interpreter()
|
||||||
.show_only_headers(config.email_writing_headers())
|
.show_only_headers(config.email_writing_headers())
|
||||||
.interpret_msg_builder(builder)?;
|
.interpret_msg_builder(builder)
|
||||||
|
.await?;
|
||||||
|
|
||||||
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl)
|
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_<P: Printer>(
|
pub async fn move_<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -208,11 +214,11 @@ pub fn move_<P: Printer>(
|
||||||
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 = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
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).await?;
|
||||||
printer.print("Email(s) successfully moved!")
|
printer.print("Email(s) successfully moved!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read<P: Printer>(
|
pub async fn read<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -226,7 +232,7 @@ pub fn read<P: Printer>(
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
let ids = id_mapper.get_ids(ids)?;
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
let emails = backend.get_emails(&folder, ids)?;
|
let emails = backend.get_emails(&folder, ids).await?;
|
||||||
|
|
||||||
let mut glue = "";
|
let mut glue = "";
|
||||||
let mut bodies = String::default();
|
let mut bodies = String::default();
|
||||||
|
@ -245,7 +251,8 @@ pub fn read<P: Printer>(
|
||||||
.hide_all_headers()
|
.hide_all_headers()
|
||||||
.filter_parts(FilterParts::Only("text/html".into())),
|
.filter_parts(FilterParts::Only("text/html".into())),
|
||||||
_ => tpl.show_additional_headers(&headers),
|
_ => tpl.show_additional_headers(&headers),
|
||||||
})?
|
})
|
||||||
|
.await?
|
||||||
.into();
|
.into();
|
||||||
bodies.push_str(&tpl);
|
bodies.push_str(&tpl);
|
||||||
}
|
}
|
||||||
|
@ -256,7 +263,7 @@ pub fn read<P: Printer>(
|
||||||
printer.print(bodies)
|
printer.print(bodies)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply<P: Printer>(
|
pub async fn reply<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -274,21 +281,25 @@ pub fn reply<P: Printer>(
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
|
|
||||||
let tpl = backend
|
let tpl = backend
|
||||||
.get_emails(&folder, ids)?
|
.get_emails(&folder, ids)
|
||||||
|
.await?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_reply_tpl_builder(config)
|
.to_reply_tpl_builder(config)
|
||||||
.some_headers(headers)
|
.with_some_headers(headers)
|
||||||
.some_body(body)
|
.with_some_body(body)
|
||||||
.reply_all(all)
|
.with_reply_all(all)
|
||||||
.build()?;
|
.build()
|
||||||
|
.await?;
|
||||||
trace!("initial template: {}", *tpl);
|
trace!("initial template: {}", *tpl);
|
||||||
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl)?;
|
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl).await?;
|
||||||
backend.add_flags(&folder, vec![id], &Flags::from_iter([Flag::Answered]))?;
|
backend
|
||||||
|
.add_flags(&folder, vec![id], &Flags::from_iter([Flag::Answered]))
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save<P: Printer>(
|
pub async fn save<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -310,13 +321,15 @@ pub fn save<P: Printer>(
|
||||||
.join("\r\n")
|
.join("\r\n")
|
||||||
};
|
};
|
||||||
|
|
||||||
let id = backend.add_email(&folder, raw_email.as_bytes(), &Flags::default())?;
|
let id = backend
|
||||||
|
.add_email(&folder, raw_email.as_bytes(), &Flags::default())
|
||||||
|
.await?;
|
||||||
id_mapper.create_alias(id)?;
|
id_mapper.create_alias(id)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn search<P: Printer>(
|
pub async fn search<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -332,7 +345,9 @@ pub fn search<P: Printer>(
|
||||||
let envelopes = Envelopes::from_backend(
|
let envelopes = Envelopes::from_backend(
|
||||||
config,
|
config,
|
||||||
id_mapper,
|
id_mapper,
|
||||||
backend.search_envelopes(&folder, &query, "", page_size, page)?,
|
backend
|
||||||
|
.search_envelopes(&folder, &query, "", page_size, page)
|
||||||
|
.await?,
|
||||||
)?;
|
)?;
|
||||||
let opts = PrintTableOpts {
|
let opts = PrintTableOpts {
|
||||||
format: &config.email_reading_format,
|
format: &config.email_reading_format,
|
||||||
|
@ -342,7 +357,7 @@ pub fn search<P: Printer>(
|
||||||
printer.print_table(Box::new(envelopes), opts)
|
printer.print_table(Box::new(envelopes), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sort<P: Printer>(
|
pub async fn sort<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -359,7 +374,9 @@ pub fn sort<P: Printer>(
|
||||||
let envelopes = Envelopes::from_backend(
|
let envelopes = Envelopes::from_backend(
|
||||||
config,
|
config,
|
||||||
id_mapper,
|
id_mapper,
|
||||||
backend.search_envelopes(&folder, &query, &sort, page_size, page)?,
|
backend
|
||||||
|
.search_envelopes(&folder, &query, &sort, page_size, page)
|
||||||
|
.await?,
|
||||||
)?;
|
)?;
|
||||||
let opts = PrintTableOpts {
|
let opts = PrintTableOpts {
|
||||||
format: &config.email_reading_format,
|
format: &config.email_reading_format,
|
||||||
|
@ -369,7 +386,7 @@ pub fn sort<P: Printer>(
|
||||||
printer.print_table(Box::new(envelopes), opts)
|
printer.print_table(Box::new(envelopes), opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send<P: Printer>(
|
pub async fn send<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
|
@ -390,18 +407,20 @@ pub fn send<P: Printer>(
|
||||||
.join("\r\n")
|
.join("\r\n")
|
||||||
};
|
};
|
||||||
trace!("raw email: {:?}", raw_email);
|
trace!("raw email: {:?}", raw_email);
|
||||||
sender.send(raw_email.as_bytes())?;
|
sender.send(raw_email.as_bytes()).await?;
|
||||||
if config.email_sending_save_copy {
|
if config.email_sending_save_copy {
|
||||||
backend.add_email(
|
backend
|
||||||
&folder,
|
.add_email(
|
||||||
raw_email.as_bytes(),
|
&folder,
|
||||||
&Flags::from_iter([Flag::Seen]),
|
raw_email.as_bytes(),
|
||||||
)?;
|
&Flags::from_iter([Flag::Seen]),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<P: Printer>(
|
pub async fn write<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
|
@ -409,11 +428,12 @@ pub fn write<P: Printer>(
|
||||||
headers: Option<Vec<(&str, &str)>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let tpl = Email::new_tpl_builder(config)
|
let tpl = Message::new_tpl_builder(config)
|
||||||
.some_headers(headers)
|
.with_some_headers(headers)
|
||||||
.some_body(body)
|
.with_some_body(body)
|
||||||
.build()?;
|
.build()
|
||||||
|
.await?;
|
||||||
trace!("initial template: {}", *tpl);
|
trace!("initial template: {}", *tpl);
|
||||||
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl)?;
|
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pimalaya_email::AccountConfig;
|
use pimalaya_email::account::AccountConfig;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ impl Envelopes {
|
||||||
pub fn from_backend(
|
pub fn from_backend(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
envelopes: pimalaya_email::Envelopes,
|
envelopes: pimalaya_email::email::Envelopes,
|
||||||
) -> Result<Envelopes> {
|
) -> Result<Envelopes> {
|
||||||
let envelopes = envelopes
|
let envelopes = envelopes
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -58,10 +58,9 @@ impl PrintTable for Envelopes {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::env;
|
|
||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use pimalaya_email::AccountConfig;
|
use pimalaya_email::account::AccountConfig;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
use crate::{Envelopes, IdMapper};
|
use crate::{Envelopes, IdMapper};
|
||||||
|
|
||||||
|
@ -70,10 +69,11 @@ mod tests {
|
||||||
let config = AccountConfig::default();
|
let config = AccountConfig::default();
|
||||||
let id_mapper = IdMapper::Dummy;
|
let id_mapper = IdMapper::Dummy;
|
||||||
|
|
||||||
let envelopes = pimalaya_email::Envelopes::from_iter([pimalaya_email::Envelope {
|
let envelopes =
|
||||||
date: DateTime::parse_from_rfc3339("2023-06-15T09:42:00+04:00").unwrap(),
|
pimalaya_email::email::Envelopes::from_iter([pimalaya_email::email::Envelope {
|
||||||
..Default::default()
|
date: DateTime::parse_from_rfc3339("2023-06-15T09:42:00+04:00").unwrap(),
|
||||||
}]);
|
..Default::default()
|
||||||
|
}]);
|
||||||
let envelopes = Envelopes::from_backend(&config, &id_mapper, envelopes).unwrap();
|
let envelopes = Envelopes::from_backend(&config, &id_mapper, envelopes).unwrap();
|
||||||
|
|
||||||
let expected_date = "2023-06-15 09:42+04:00";
|
let expected_date = "2023-06-15 09:42+04:00";
|
||||||
|
@ -90,10 +90,11 @@ mod tests {
|
||||||
..AccountConfig::default()
|
..AccountConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let envelopes = pimalaya_email::Envelopes::from_iter([pimalaya_email::Envelope {
|
let envelopes =
|
||||||
date: DateTime::parse_from_rfc3339("2023-06-15T09:42:00+04:00").unwrap(),
|
pimalaya_email::email::Envelopes::from_iter([pimalaya_email::email::Envelope {
|
||||||
..Default::default()
|
date: DateTime::parse_from_rfc3339("2023-06-15T09:42:00+04:00").unwrap(),
|
||||||
}]);
|
..Default::default()
|
||||||
|
}]);
|
||||||
let envelopes = Envelopes::from_backend(&config, &id_mapper, envelopes).unwrap();
|
let envelopes = Envelopes::from_backend(&config, &id_mapper, envelopes).unwrap();
|
||||||
|
|
||||||
let expected_date = "15/06/2023 09h42";
|
let expected_date = "15/06/2023 09h42";
|
||||||
|
@ -113,10 +114,11 @@ mod tests {
|
||||||
..AccountConfig::default()
|
..AccountConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let envelopes = pimalaya_email::Envelopes::from_iter([pimalaya_email::Envelope {
|
let envelopes =
|
||||||
date: DateTime::parse_from_rfc3339("2023-06-15T09:42:00+04:00").unwrap(),
|
pimalaya_email::email::Envelopes::from_iter([pimalaya_email::email::Envelope {
|
||||||
..Default::default()
|
date: DateTime::parse_from_rfc3339("2023-06-15T09:42:00+04:00").unwrap(),
|
||||||
}]);
|
..Default::default()
|
||||||
|
}]);
|
||||||
let envelopes = Envelopes::from_backend(&config, &id_mapper, envelopes).unwrap();
|
let envelopes = Envelopes::from_backend(&config, &id_mapper, envelopes).unwrap();
|
||||||
|
|
||||||
let expected_date = "15/06/2023 05h42";
|
let expected_date = "15/06/2023 05h42";
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Arg, ArgMatches, Command};
|
use clap::{Arg, ArgMatches, Command};
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use pimalaya_email::{Flag, Flags};
|
use pimalaya_email::email::{Flag, Flags};
|
||||||
|
|
||||||
use crate::email;
|
use crate::email;
|
||||||
|
|
||||||
|
|
|
@ -11,15 +11,16 @@ pub enum Flag {
|
||||||
Custom(String),
|
Custom(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&pimalaya_email::Flag> for Flag {
|
impl From<&pimalaya_email::email::Flag> for Flag {
|
||||||
fn from(flag: &pimalaya_email::Flag) -> Self {
|
fn from(flag: &pimalaya_email::email::Flag) -> Self {
|
||||||
|
use pimalaya_email::email::Flag::*;
|
||||||
match flag {
|
match flag {
|
||||||
pimalaya_email::Flag::Seen => Flag::Seen,
|
Seen => Flag::Seen,
|
||||||
pimalaya_email::Flag::Answered => Flag::Answered,
|
Answered => Flag::Answered,
|
||||||
pimalaya_email::Flag::Flagged => Flag::Flagged,
|
Flagged => Flag::Flagged,
|
||||||
pimalaya_email::Flag::Deleted => Flag::Deleted,
|
Deleted => Flag::Deleted,
|
||||||
pimalaya_email::Flag::Draft => Flag::Draft,
|
Draft => Flag::Draft,
|
||||||
pimalaya_email::Flag::Custom(flag) => Flag::Custom(flag.clone()),
|
Custom(flag) => Flag::Custom(flag.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ impl ops::Deref for Flags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<pimalaya_email::Flags> for Flags {
|
impl From<pimalaya_email::email::Flags> for Flags {
|
||||||
fn from(flags: pimalaya_email::Flags) -> Self {
|
fn from(flags: pimalaya_email::email::Flags) -> Self {
|
||||||
Flags(flags.iter().map(Flag::from).collect())
|
Flags(flags.iter().map(Flag::from).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pimalaya_email::{Backend, Flags};
|
use pimalaya_email::{backend::Backend, email::Flags};
|
||||||
|
|
||||||
use crate::{printer::Printer, IdMapper};
|
use crate::{printer::Printer, IdMapper};
|
||||||
|
|
||||||
pub fn add<P: Printer>(
|
pub async fn add<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
|
@ -13,11 +13,11 @@ pub fn add<P: Printer>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ids = id_mapper.get_ids(ids)?;
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.add_flags(folder, ids, flags)?;
|
backend.add_flags(folder, ids, flags).await?;
|
||||||
printer.print("Flag(s) successfully added!")
|
printer.print("Flag(s) successfully added!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set<P: Printer>(
|
pub async fn set<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
|
@ -27,11 +27,11 @@ pub fn set<P: Printer>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ids = id_mapper.get_ids(ids)?;
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.set_flags(folder, ids, flags)?;
|
backend.set_flags(folder, ids, flags).await?;
|
||||||
printer.print("Flag(s) successfully set!")
|
printer.print("Flag(s) successfully set!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove<P: Printer>(
|
pub async fn remove<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
|
@ -41,6 +41,6 @@ pub fn remove<P: Printer>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ids = id_mapper.get_ids(ids)?;
|
let ids = id_mapper.get_ids(ids)?;
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
backend.remove_flags(folder, ids, flags)?;
|
backend.remove_flags(folder, ids, flags).await?;
|
||||||
printer.print("Flag(s) successfully removed!")
|
printer.print("Flag(s) successfully removed!")
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,13 @@ use crate::ui::{Cell, Row, Table};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize)]
|
#[derive(Clone, Debug, Default, Serialize)]
|
||||||
pub struct Folder {
|
pub struct Folder {
|
||||||
pub delim: String,
|
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub desc: String,
|
pub desc: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&pimalaya_email::Folder> for Folder {
|
impl From<&pimalaya_email::folder::Folder> for Folder {
|
||||||
fn from(folder: &pimalaya_email::Folder) -> Self {
|
fn from(folder: &pimalaya_email::folder::Folder) -> Self {
|
||||||
Folder {
|
Folder {
|
||||||
delim: folder.delim.clone(),
|
|
||||||
name: folder.name.clone(),
|
name: folder.name.clone(),
|
||||||
desc: folder.desc.clone(),
|
desc: folder.desc.clone(),
|
||||||
}
|
}
|
||||||
|
@ -22,14 +20,12 @@ impl From<&pimalaya_email::Folder> for Folder {
|
||||||
impl Table for Folder {
|
impl Table for Folder {
|
||||||
fn head() -> Row {
|
fn head() -> Row {
|
||||||
Row::new()
|
Row::new()
|
||||||
.cell(Cell::new("DELIM").bold().underline().white())
|
|
||||||
.cell(Cell::new("NAME").bold().underline().white())
|
.cell(Cell::new("NAME").bold().underline().white())
|
||||||
.cell(Cell::new("DESC").bold().underline().white())
|
.cell(Cell::new("DESC").bold().underline().white())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn row(&self) -> Row {
|
fn row(&self) -> Row {
|
||||||
Row::new()
|
Row::new()
|
||||||
.cell(Cell::new(&self.delim).white())
|
|
||||||
.cell(Cell::new(&self.name).blue())
|
.cell(Cell::new(&self.name).blue())
|
||||||
.cell(Cell::new(&self.desc).green())
|
.cell(Cell::new(&self.desc).green())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
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},
|
||||||
|
@ -20,8 +19,8 @@ impl ops::Deref for Folders {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<pimalaya_email::Folders> for Folders {
|
impl From<pimalaya_email::folder::Folders> for Folders {
|
||||||
fn from(folders: pimalaya_email::Folders) -> Self {
|
fn from(folders: pimalaya_email::folder::Folders) -> Self {
|
||||||
Folders(folders.iter().map(Folder::from).collect())
|
Folders(folders.iter().map(Folder::from).collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dialoguer::Confirm;
|
use dialoguer::Confirm;
|
||||||
use pimalaya_email::{AccountConfig, Backend};
|
use pimalaya_email::{account::AccountConfig, backend::Backend};
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -12,18 +12,22 @@ use crate::{
|
||||||
Folders,
|
Folders,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn expunge<P: Printer>(printer: &mut P, backend: &mut dyn Backend, folder: &str) -> Result<()> {
|
pub async fn expunge<P: Printer>(
|
||||||
backend.expunge_folder(folder)?;
|
printer: &mut P,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
|
folder: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
backend.expunge_folder(folder).await?;
|
||||||
printer.print(format!("Folder {folder} successfully expunged!"))
|
printer.print(format!("Folder {folder} successfully expunged!"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list<P: Printer>(
|
pub async fn list<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut dyn Backend,
|
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().await?.into();
|
||||||
printer.print_table(
|
printer.print_table(
|
||||||
// TODO: remove Box
|
// TODO: remove Box
|
||||||
Box::new(folders),
|
Box::new(folders),
|
||||||
|
@ -34,12 +38,20 @@ pub fn list<P: Printer>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create<P: Printer>(printer: &mut P, backend: &mut dyn Backend, folder: &str) -> Result<()> {
|
pub async fn create<P: Printer>(
|
||||||
backend.add_folder(folder)?;
|
printer: &mut P,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
|
folder: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
backend.add_folder(folder).await?;
|
||||||
printer.print("Folder successfully created!")
|
printer.print("Folder successfully created!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete<P: Printer>(printer: &mut P, backend: &mut dyn Backend, folder: &str) -> Result<()> {
|
pub async fn delete<P: Printer>(
|
||||||
|
printer: &mut P,
|
||||||
|
backend: &mut dyn Backend,
|
||||||
|
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)
|
||||||
|
@ -49,14 +61,18 @@ pub fn delete<P: Printer>(printer: &mut P, backend: &mut dyn Backend, folder: &s
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
backend.delete_folder(folder)?;
|
backend.delete_folder(folder).await?;
|
||||||
printer.print("Folder successfully deleted!")
|
printer.print("Folder successfully deleted!")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use async_trait::async_trait;
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
backend, AccountConfig, Backend, Emails, Envelope, Envelopes, Flags, Folder, Folders,
|
account::AccountConfig,
|
||||||
|
backend::Backend,
|
||||||
|
email::{Envelope, Envelopes, Flags, Messages},
|
||||||
|
folder::{Folder, Folders},
|
||||||
};
|
};
|
||||||
use std::{any::Any, fmt::Debug, io};
|
use std::{any::Any, fmt::Debug, io};
|
||||||
use termcolor::ColorSpec;
|
use termcolor::ColorSpec;
|
||||||
|
@ -65,8 +81,8 @@ mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[tokio::test]
|
||||||
fn it_should_list_mboxes() {
|
async fn it_should_list_mboxes() {
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
struct StringWriter {
|
struct StringWriter {
|
||||||
content: String,
|
content: String,
|
||||||
|
@ -131,82 +147,119 @@ mod tests {
|
||||||
|
|
||||||
struct TestBackend;
|
struct TestBackend;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl Backend for TestBackend {
|
impl Backend for TestBackend {
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn add_folder(&mut self, _: &str) -> backend::Result<()> {
|
async fn add_folder(&mut self, _: &str) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn list_folders(&mut self) -> backend::Result<Folders> {
|
async fn list_folders(&mut self) -> pimalaya_email::Result<Folders> {
|
||||||
Ok(Folders::from_iter([
|
Ok(Folders::from_iter([
|
||||||
Folder {
|
Folder {
|
||||||
delim: "/".into(),
|
|
||||||
name: "INBOX".into(),
|
name: "INBOX".into(),
|
||||||
desc: "desc".into(),
|
desc: "desc".into(),
|
||||||
},
|
},
|
||||||
Folder {
|
Folder {
|
||||||
delim: "/".into(),
|
|
||||||
name: "Sent".into(),
|
name: "Sent".into(),
|
||||||
desc: "desc".into(),
|
desc: "desc".into(),
|
||||||
},
|
},
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
fn expunge_folder(&mut self, _: &str) -> backend::Result<()> {
|
async fn expunge_folder(&mut self, _: &str) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn purge_folder(&mut self, _: &str) -> backend::Result<()> {
|
async fn purge_folder(&mut self, _: &str) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn delete_folder(&mut self, _: &str) -> backend::Result<()> {
|
async fn delete_folder(&mut self, _: &str) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn get_envelope(&mut self, _: &str, _: &str) -> backend::Result<Envelope> {
|
async fn get_envelope(&mut self, _: &str, _: &str) -> pimalaya_email::Result<Envelope> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
fn list_envelopes(
|
async fn list_envelopes(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &str,
|
_: &str,
|
||||||
_: usize,
|
_: usize,
|
||||||
_: usize,
|
_: usize,
|
||||||
) -> backend::Result<Envelopes> {
|
) -> pimalaya_email::Result<Envelopes> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn search_envelopes(
|
async fn search_envelopes(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &str,
|
_: &str,
|
||||||
_: &str,
|
_: &str,
|
||||||
_: &str,
|
_: &str,
|
||||||
_: usize,
|
_: usize,
|
||||||
_: usize,
|
_: usize,
|
||||||
) -> backend::Result<Envelopes> {
|
) -> pimalaya_email::Result<Envelopes> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn add_email(&mut self, _: &str, _: &[u8], _: &Flags) -> backend::Result<String> {
|
async fn add_email(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: &[u8],
|
||||||
|
_: &Flags,
|
||||||
|
) -> pimalaya_email::Result<String> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn get_emails(&mut self, _: &str, _: Vec<&str>) -> backend::Result<Emails> {
|
async fn get_emails(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: Vec<&str>,
|
||||||
|
) -> pimalaya_email::Result<Messages> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn preview_emails(&mut self, _: &str, _: Vec<&str>) -> backend::Result<Emails> {
|
async fn preview_emails(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: Vec<&str>,
|
||||||
|
) -> pimalaya_email::Result<Messages> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn copy_emails(&mut self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
async fn copy_emails(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: &str,
|
||||||
|
_: Vec<&str>,
|
||||||
|
) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn move_emails(&mut self, _: &str, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
async fn move_emails(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: &str,
|
||||||
|
_: Vec<&str>,
|
||||||
|
) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn delete_emails(&mut self, _: &str, _: Vec<&str>) -> backend::Result<()> {
|
async fn delete_emails(&mut self, _: &str, _: Vec<&str>) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn add_flags(&mut self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
async fn add_flags(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: Vec<&str>,
|
||||||
|
_: &Flags,
|
||||||
|
) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn set_flags(&mut self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
async fn set_flags(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: Vec<&str>,
|
||||||
|
_: &Flags,
|
||||||
|
) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn remove_flags(&mut self, _: &str, _: Vec<&str>, _: &Flags) -> backend::Result<()> {
|
async fn remove_flags(
|
||||||
|
&mut self,
|
||||||
|
_: &str,
|
||||||
|
_: Vec<&str>,
|
||||||
|
_: &Flags,
|
||||||
|
) -> pimalaya_email::Result<()> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
@ -218,13 +271,15 @@ mod tests {
|
||||||
let mut printer = PrinterServiceTest::default();
|
let mut printer = PrinterServiceTest::default();
|
||||||
let mut backend = TestBackend {};
|
let mut backend = TestBackend {};
|
||||||
|
|
||||||
assert!(list(&account_config, &mut printer, &mut backend, None).is_ok());
|
assert!(list(&account_config, &mut printer, &mut backend, None)
|
||||||
|
.await
|
||||||
|
.is_ok());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
concat![
|
concat![
|
||||||
"\n",
|
"\n",
|
||||||
"DELIM │NAME │DESC \n",
|
"NAME │DESC \n",
|
||||||
"/ │INBOX │desc \n",
|
"INBOX │desc \n",
|
||||||
"/ │Sent │desc \n",
|
"Sent │desc \n",
|
||||||
"\n"
|
"\n"
|
||||||
],
|
],
|
||||||
printer.writer.content
|
printer.writer.content
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dialoguer::Input;
|
use dialoguer::Input;
|
||||||
use pimalaya_email::{SenderConfig, SendmailConfig};
|
use pimalaya_email::sender::{SenderConfig, SendmailConfig};
|
||||||
|
|
||||||
use crate::config::wizard::THEME;
|
use crate::config::wizard::THEME;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dialoguer::{Confirm, Input, Select};
|
use dialoguer::{Confirm, Input, Select};
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig, SenderConfig, SmtpAuthConfig,
|
account::{OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig},
|
||||||
SmtpConfig,
|
sender::{SenderConfig, SmtpAuthConfig, SmtpConfig},
|
||||||
};
|
};
|
||||||
use pimalaya_oauth2::{AuthorizationCodeGrant, Client};
|
use pimalaya_oauth2::{AuthorizationCodeGrant, Client};
|
||||||
use pimalaya_secret::Secret;
|
use pimalaya_secret::Secret;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dialoguer::Select;
|
use dialoguer::Select;
|
||||||
use pimalaya_email::SenderConfig;
|
use pimalaya_email::sender::SenderConfig;
|
||||||
|
|
||||||
use crate::config::wizard::THEME;
|
use crate::config::wizard::THEME;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use atty::Stream;
|
use atty::Stream;
|
||||||
use pimalaya_email::{AccountConfig, Backend, Email, Flags, Sender, Tpl};
|
use pimalaya_email::{
|
||||||
|
account::AccountConfig,
|
||||||
|
backend::Backend,
|
||||||
|
email::{Flags, Message, Tpl},
|
||||||
|
sender::Sender,
|
||||||
|
};
|
||||||
use std::io::{stdin, BufRead};
|
use std::io::{stdin, BufRead};
|
||||||
|
|
||||||
use crate::{printer::Printer, IdMapper};
|
use crate::{printer::Printer, IdMapper};
|
||||||
|
|
||||||
pub fn forward<P: Printer>(
|
pub async fn forward<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -19,19 +24,21 @@ pub fn forward<P: Printer>(
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
|
|
||||||
let tpl: String = backend
|
let tpl: String = backend
|
||||||
.get_emails(folder, ids)?
|
.get_emails(folder, ids)
|
||||||
|
.await?
|
||||||
.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)
|
||||||
.some_headers(headers)
|
.with_some_headers(headers)
|
||||||
.some_body(body)
|
.with_some_body(body)
|
||||||
.build()?
|
.build()
|
||||||
|
.await?
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
printer.print(tpl)
|
printer.print(tpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply<P: Printer>(
|
pub async fn reply<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -46,20 +53,22 @@ pub fn reply<P: Printer>(
|
||||||
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
let ids = ids.iter().map(String::as_str).collect::<Vec<_>>();
|
||||||
|
|
||||||
let tpl: String = backend
|
let tpl: String = backend
|
||||||
.get_emails(folder, ids)?
|
.get_emails(folder, ids)
|
||||||
|
.await?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_reply_tpl_builder(config)
|
.to_reply_tpl_builder(config)
|
||||||
.some_headers(headers)
|
.with_some_headers(headers)
|
||||||
.some_body(body)
|
.with_some_body(body)
|
||||||
.reply_all(all)
|
.with_reply_all(all)
|
||||||
.build()?
|
.build()
|
||||||
|
.await?
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
printer.print(tpl)
|
printer.print(tpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save<P: Printer>(
|
pub async fn save<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
id_mapper: &IdMapper,
|
id_mapper: &IdMapper,
|
||||||
|
@ -79,16 +88,17 @@ pub fn save<P: Printer>(
|
||||||
})
|
})
|
||||||
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
||||||
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
||||||
.compile()?
|
.compile()
|
||||||
|
.await?
|
||||||
.write_to_vec()?;
|
.write_to_vec()?;
|
||||||
|
|
||||||
let id = backend.add_email(folder, &email, &Flags::default())?;
|
let id = backend.add_email(folder, &email, &Flags::default()).await?;
|
||||||
id_mapper.create_alias(id)?;
|
id_mapper.create_alias(id)?;
|
||||||
|
|
||||||
printer.print("Template successfully saved!")
|
printer.print("Template successfully saved!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send<P: Printer>(
|
pub async fn send<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
|
@ -108,26 +118,31 @@ pub fn send<P: Printer>(
|
||||||
})
|
})
|
||||||
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
||||||
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
||||||
.compile()?
|
.compile()
|
||||||
|
.await?
|
||||||
.write_to_vec()?;
|
.write_to_vec()?;
|
||||||
sender.send(&email)?;
|
|
||||||
|
sender.send(&email).await?;
|
||||||
|
|
||||||
if config.email_sending_save_copy {
|
if config.email_sending_save_copy {
|
||||||
backend.add_email(folder, &email, &Flags::default())?;
|
backend.add_email(folder, &email, &Flags::default()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
printer.print("Template successfully sent!")?;
|
printer.print("Template successfully sent!")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<P: Printer>(
|
pub async fn write<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
headers: Option<Vec<(&str, &str)>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let tpl: String = Email::new_tpl_builder(config)
|
let tpl: String = Message::new_tpl_builder(config)
|
||||||
.some_headers(headers)
|
.with_some_headers(headers)
|
||||||
.some_body(body)
|
.with_some_body(body)
|
||||||
.build()?
|
.build()
|
||||||
|
.await?
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
printer.print(tpl)
|
printer.print(tpl)
|
||||||
|
|
256
src/main.rs
256
src/main.rs
|
@ -1,9 +1,11 @@
|
||||||
use anyhow::{anyhow, Context, Result};
|
use anyhow::{anyhow, Context, Result};
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
#[cfg(feature = "imap-backend")]
|
#[cfg(feature = "imap-backend")]
|
||||||
use pimalaya_email::ImapBackend;
|
use pimalaya_email::backend::ImapBackend;
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
BackendBuilder, BackendConfig, BackendSyncBuilder, SenderBuilder, DEFAULT_INBOX_FOLDER,
|
account::{sync::AccountSyncBuilder, DEFAULT_INBOX_FOLDER},
|
||||||
|
backend::{BackendBuilder, BackendConfig},
|
||||||
|
sender::SenderBuilder,
|
||||||
};
|
};
|
||||||
use std::env;
|
use std::env;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -54,17 +56,20 @@ async 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 = config.to_account_config(None)?;
|
let account_config = config.to_account_config(None)?;
|
||||||
let mut backend = BackendBuilder::new(account_config.clone()).build()?;
|
let mut backend = BackendBuilder::new(account_config.clone()).build().await?;
|
||||||
let mut sender = SenderBuilder::new(account_config.clone()).build()?;
|
let mut sender = SenderBuilder::new(account_config.clone()).build().await?;
|
||||||
let mut printer = StdoutPrinter::default();
|
let mut printer = StdoutPrinter::default();
|
||||||
|
|
||||||
return email::handlers::mailto(
|
email::handlers::mailto(
|
||||||
&account_config,
|
&account_config,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
sender.as_mut(),
|
sender.as_mut(),
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&url,
|
&url,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let app = create_app();
|
let app = create_app();
|
||||||
|
@ -107,13 +112,15 @@ async fn main() -> Result<()> {
|
||||||
match imap::args::matches(&m)? {
|
match imap::args::matches(&m)? {
|
||||||
Some(imap::args::Cmd::Notify(keepalive)) => {
|
Some(imap::args::Cmd::Notify(keepalive)) => {
|
||||||
let mut backend =
|
let mut backend =
|
||||||
ImapBackend::new(account_config.clone(), imap_config.clone(), None)?;
|
ImapBackend::new(account_config.clone(), imap_config.clone(), None).await?;
|
||||||
return imap::handlers::notify(&mut backend, &folder, keepalive);
|
imap::handlers::notify(&mut backend, &folder, keepalive).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(imap::args::Cmd::Watch(keepalive)) => {
|
Some(imap::args::Cmd::Watch(keepalive)) => {
|
||||||
let mut backend =
|
let mut backend =
|
||||||
ImapBackend::new(account_config.clone(), imap_config.clone(), None)?;
|
ImapBackend::new(account_config.clone(), imap_config.clone(), None).await?;
|
||||||
return imap::handlers::watch(&mut backend, &folder, keepalive);
|
imap::handlers::watch(&mut backend, &folder, keepalive).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -121,17 +128,20 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
match account::args::matches(&m)? {
|
match account::args::matches(&m)? {
|
||||||
Some(account::args::Cmd::List(max_width)) => {
|
Some(account::args::Cmd::List(max_width)) => {
|
||||||
return account::handlers::list(max_width, &account_config, &config, &mut printer);
|
account::handlers::list(max_width, &account_config, &config, &mut printer)?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(account::args::Cmd::Sync(strategy, dry_run)) => {
|
Some(account::args::Cmd::Sync(strategy, dry_run)) => {
|
||||||
let sync_builder = BackendSyncBuilder::new(account_config, backend_builder)?
|
let sync_builder = AccountSyncBuilder::new(account_config, backend_builder)
|
||||||
|
.await?
|
||||||
.with_some_folders_strategy(strategy)
|
.with_some_folders_strategy(strategy)
|
||||||
.with_dry_run(dry_run);
|
.with_dry_run(dry_run);
|
||||||
account::handlers::sync(&mut printer, sync_builder, dry_run)?;
|
account::handlers::sync(&mut printer, sync_builder, dry_run).await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(account::args::Cmd::Configure(reset)) => {
|
Some(account::args::Cmd::Configure(reset)) => {
|
||||||
return account::handlers::configure(&account_config, reset);
|
account::handlers::configure(&account_config, reset).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -143,30 +153,30 @@ async fn main() -> Result<()> {
|
||||||
.ok_or_else(|| anyhow!("the folder argument is missing"))
|
.ok_or_else(|| anyhow!("the folder argument is missing"))
|
||||||
.context("cannot create folder")?;
|
.context("cannot create folder")?;
|
||||||
let folder = account_config.folder_alias(folder)?;
|
let folder = account_config.folder_alias(folder)?;
|
||||||
let mut backend = backend_builder.build()?;
|
let mut backend = backend_builder.build().await?;
|
||||||
return folder::handlers::create(&mut printer, backend.as_mut(), &folder);
|
folder::handlers::create(&mut printer, backend.as_mut(), &folder).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(folder::args::Cmd::List(max_width)) => {
|
Some(folder::args::Cmd::List(max_width)) => {
|
||||||
let mut backend = backend_builder.build()?;
|
let mut backend = backend_builder.build().await?;
|
||||||
return folder::handlers::list(
|
folder::handlers::list(&account_config, &mut printer, backend.as_mut(), max_width)
|
||||||
&account_config,
|
.await?;
|
||||||
&mut printer,
|
return Ok(());
|
||||||
backend.as_mut(),
|
|
||||||
max_width,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Some(folder::args::Cmd::Expunge) => {
|
Some(folder::args::Cmd::Expunge) => {
|
||||||
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 = backend_builder.build()?;
|
let mut backend = backend_builder.build().await?;
|
||||||
return folder::handlers::expunge(&mut printer, backend.as_mut(), &folder);
|
folder::handlers::expunge(&mut printer, backend.as_mut(), &folder).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(folder::args::Cmd::Delete) => {
|
Some(folder::args::Cmd::Delete) => {
|
||||||
let folder = folder
|
let folder = folder
|
||||||
.ok_or_else(|| anyhow!("the folder argument is missing"))
|
.ok_or_else(|| anyhow!("the folder argument is missing"))
|
||||||
.context("cannot delete folder")?;
|
.context("cannot delete folder")?;
|
||||||
let folder = account_config.folder_alias(folder)?;
|
let folder = account_config.folder_alias(folder)?;
|
||||||
let mut backend = backend_builder.build()?;
|
let mut backend = backend_builder.build().await?;
|
||||||
return folder::handlers::delete(&mut printer, backend.as_mut(), &folder);
|
folder::handlers::delete(&mut printer, backend.as_mut(), &folder).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -175,23 +185,25 @@ async fn main() -> Result<()> {
|
||||||
match email::args::matches(&m)? {
|
match email::args::matches(&m)? {
|
||||||
Some(email::args::Cmd::Attachments(ids)) => {
|
Some(email::args::Cmd::Attachments(ids)) => {
|
||||||
let folder = 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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
return email::handlers::attachments(
|
email::handlers::attachments(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Copy(ids, to_folder)) => {
|
Some(email::args::Cmd::Copy(ids, to_folder)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::copy(
|
email::handlers::copy(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -199,29 +211,35 @@ async fn main() -> Result<()> {
|
||||||
&folder,
|
&folder,
|
||||||
to_folder,
|
to_folder,
|
||||||
ids,
|
ids,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Delete(ids)) => {
|
Some(email::args::Cmd::Delete(ids)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::delete(
|
email::handlers::delete(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Forward(id, headers, body)) => {
|
Some(email::args::Cmd::Forward(id, headers, body)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let mut sender = sender_builder.build()?;
|
let mut sender = sender_builder.build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::forward(
|
email::handlers::forward(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -231,14 +249,17 @@ async fn main() -> Result<()> {
|
||||||
id,
|
id,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::List(max_width, page_size, page)) => {
|
Some(email::args::Cmd::List(max_width, page_size, page)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::list(
|
email::handlers::list(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -247,14 +268,17 @@ async fn main() -> Result<()> {
|
||||||
max_width,
|
max_width,
|
||||||
page_size,
|
page_size,
|
||||||
page,
|
page,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Move(ids, to_folder)) => {
|
Some(email::args::Cmd::Move(ids, to_folder)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::move_(
|
email::handlers::move_(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -262,14 +286,17 @@ async fn main() -> Result<()> {
|
||||||
&folder,
|
&folder,
|
||||||
to_folder,
|
to_folder,
|
||||||
ids,
|
ids,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Read(ids, text_mime, raw, headers)) => {
|
Some(email::args::Cmd::Read(ids, text_mime, raw, headers)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::read(
|
email::handlers::read(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -279,15 +306,18 @@ async fn main() -> Result<()> {
|
||||||
text_mime,
|
text_mime,
|
||||||
raw,
|
raw,
|
||||||
headers,
|
headers,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Reply(id, all, headers, body)) => {
|
Some(email::args::Cmd::Reply(id, all, headers, body)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let mut sender = sender_builder.build()?;
|
let mut sender = sender_builder.build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::reply(
|
email::handlers::reply(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -298,28 +328,34 @@ async fn main() -> Result<()> {
|
||||||
all,
|
all,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Save(raw_email)) => {
|
Some(email::args::Cmd::Save(raw_email)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::save(
|
email::handlers::save(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
raw_email,
|
raw_email,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Search(query, max_width, page_size, page)) => {
|
Some(email::args::Cmd::Search(query, max_width, page_size, page)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::search(
|
email::handlers::search(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -329,14 +365,17 @@ async fn main() -> Result<()> {
|
||||||
max_width,
|
max_width,
|
||||||
page_size,
|
page_size,
|
||||||
page,
|
page,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => {
|
Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => {
|
||||||
let folder = 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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return email::handlers::sort(
|
email::handlers::sort(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -347,71 +386,86 @@ async fn main() -> Result<()> {
|
||||||
max_width,
|
max_width,
|
||||||
page_size,
|
page_size,
|
||||||
page,
|
page,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Send(raw_email)) => {
|
Some(email::args::Cmd::Send(raw_email)) => {
|
||||||
let mut backend = backend_builder.build()?;
|
let mut backend = backend_builder.build().await?;
|
||||||
let mut sender = sender_builder.build()?;
|
let mut sender = sender_builder.build().await?;
|
||||||
return email::handlers::send(
|
email::handlers::send(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
sender.as_mut(),
|
sender.as_mut(),
|
||||||
raw_email,
|
raw_email,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(email::args::Cmd::Flag(m)) => match m {
|
Some(email::args::Cmd::Flag(m)) => match m {
|
||||||
Some(flag::args::Cmd::Set(ids, ref flags)) => {
|
Some(flag::args::Cmd::Set(ids, ref flags)) => {
|
||||||
let folder = 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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return flag::handlers::set(
|
flag::handlers::set(
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
flags,
|
flags,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return flag::handlers::add(
|
flag::handlers::add(
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
flags,
|
flags,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return flag::handlers::remove(
|
flag::handlers::remove(
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
ids,
|
ids,
|
||||||
flags,
|
flags,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
Some(email::args::Cmd::Tpl(m)) => match m {
|
Some(email::args::Cmd::Tpl(m)) => match m {
|
||||||
Some(tpl::args::Cmd::Forward(id, headers, body)) => {
|
Some(tpl::args::Cmd::Forward(id, headers, body)) => {
|
||||||
let folder = 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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return tpl::handlers::forward(
|
tpl::handlers::forward(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -420,17 +474,21 @@ async fn main() -> Result<()> {
|
||||||
id,
|
id,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(tpl::args::Cmd::Write(headers, body)) => {
|
Some(tpl::args::Cmd::Write(headers, body)) => {
|
||||||
return tpl::handlers::write(&account_config, &mut printer, headers, body);
|
tpl::handlers::write(&account_config, &mut printer, headers, body).await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(tpl::args::Cmd::Reply(id, all, headers, body)) => {
|
Some(tpl::args::Cmd::Reply(id, all, headers, body)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return tpl::handlers::reply(
|
tpl::handlers::reply(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
|
@ -440,48 +498,60 @@ async fn main() -> Result<()> {
|
||||||
all,
|
all,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(tpl::args::Cmd::Save(tpl)) => {
|
Some(tpl::args::Cmd::Save(tpl)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?;
|
||||||
|
|
||||||
return tpl::handlers::save(
|
tpl::handlers::save(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
&id_mapper,
|
&id_mapper,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
tpl,
|
tpl,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
Some(tpl::args::Cmd::Send(tpl)) => {
|
Some(tpl::args::Cmd::Send(tpl)) => {
|
||||||
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 = backend_builder.clone().into_build()?;
|
let mut backend = backend_builder.clone().into_build().await?;
|
||||||
let mut sender = sender_builder.build()?;
|
let mut sender = sender_builder.build().await?;
|
||||||
return tpl::handlers::send(
|
tpl::handlers::send(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
sender.as_mut(),
|
sender.as_mut(),
|
||||||
&folder,
|
&folder,
|
||||||
tpl,
|
tpl,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
Some(email::args::Cmd::Write(headers, body)) => {
|
Some(email::args::Cmd::Write(headers, body)) => {
|
||||||
let mut backend = backend_builder.build()?;
|
let mut backend = backend_builder.build().await?;
|
||||||
let mut sender = sender_builder.build()?;
|
let mut sender = sender_builder.build().await?;
|
||||||
return email::handlers::write(
|
email::handlers::write(
|
||||||
&account_config,
|
&account_config,
|
||||||
&mut printer,
|
&mut printer,
|
||||||
backend.as_mut(),
|
backend.as_mut(),
|
||||||
sender.as_mut(),
|
sender.as_mut(),
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
);
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use pimalaya_email::Tpl;
|
use pimalaya_email::email::Tpl;
|
||||||
|
|
||||||
use crate::printer::WriteColor;
|
use crate::printer::WriteColor;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use pimalaya_email::EmailTextPlainFormat;
|
use pimalaya_email::email::EmailTextPlainFormat;
|
||||||
use std::io;
|
use std::io;
|
||||||
use termcolor::{self, StandardStream};
|
use termcolor::{self, StandardStream};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
email::{local_draft_path, remove_local_draft},
|
account::AccountConfig,
|
||||||
AccountConfig, Backend, Flag, Flags, Sender, Tpl,
|
backend::Backend,
|
||||||
|
email::{local_draft_path, remove_local_draft, Flag, Flags, Tpl},
|
||||||
|
sender::Sender,
|
||||||
};
|
};
|
||||||
use std::{env, fs, process::Command};
|
use std::{env, fs, process::Command};
|
||||||
|
|
||||||
|
@ -37,7 +39,7 @@ 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>(
|
pub async fn edit_tpl_with_editor<P: Printer>(
|
||||||
config: &AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
|
@ -76,13 +78,16 @@ pub fn edit_tpl_with_editor<P: Printer>(
|
||||||
let email = tpl
|
let email = tpl
|
||||||
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
||||||
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
||||||
.compile()?
|
.compile()
|
||||||
|
.await?
|
||||||
.write_to_vec()?;
|
.write_to_vec()?;
|
||||||
sender.send(&email)?;
|
sender.send(&email).await?;
|
||||||
if config.email_sending_save_copy {
|
if config.email_sending_save_copy {
|
||||||
let sent_folder = config.sent_folder_alias()?;
|
let sent_folder = config.sent_folder_alias()?;
|
||||||
printer.print_log(format!("Adding email to the {} folder…", sent_folder))?;
|
printer.print_log(format!("Adding email to the {} folder…", sent_folder))?;
|
||||||
backend.add_email(&sent_folder, &email, &Flags::from_iter([Flag::Seen]))?;
|
backend
|
||||||
|
.add_email(&sent_folder, &email, &Flags::from_iter([Flag::Seen]))
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
remove_local_draft()?;
|
remove_local_draft()?;
|
||||||
printer.print("Done!")?;
|
printer.print("Done!")?;
|
||||||
|
@ -101,13 +106,16 @@ pub fn edit_tpl_with_editor<P: Printer>(
|
||||||
let email = tpl
|
let email = tpl
|
||||||
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
||||||
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
||||||
.compile()?
|
.compile()
|
||||||
|
.await?
|
||||||
.write_to_vec()?;
|
.write_to_vec()?;
|
||||||
backend.add_email(
|
backend
|
||||||
&draft_folder,
|
.add_email(
|
||||||
&email,
|
&draft_folder,
|
||||||
&Flags::from_iter([Flag::Seen, Flag::Draft]),
|
&email,
|
||||||
)?;
|
&Flags::from_iter([Flag::Seen, Flag::Draft]),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
remove_local_draft()?;
|
remove_local_draft()?;
|
||||||
printer.print(format!("Email successfully saved to {}", draft_folder))?;
|
printer.print(format!("Email successfully saved to {}", draft_folder))?;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use pimalaya_email::EmailTextPlainFormat;
|
use pimalaya_email::email::EmailTextPlainFormat;
|
||||||
use termcolor::{Color, ColorSpec};
|
use termcolor::{Color, ColorSpec};
|
||||||
use terminal_size::terminal_size;
|
use terminal_size::terminal_size;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
@ -267,6 +267,7 @@ where
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use pimalaya_email::email::EmailTextPlainFormat;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in a new issue