mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-22 02:50:19 +00:00
improve tpl builders api
This commit is contained in:
parent
5a2d842cbe
commit
65ac0c7702
7 changed files with 174 additions and 109 deletions
88
Cargo.lock
generated
88
Cargo.lock
generated
|
@ -1018,6 +1018,16 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gethostname"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a329e22866dd78b35d2c639a4a23d7b950aeae300dfd79f4fb19f74055c2404"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -1255,7 +1265,7 @@ checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
"rustls",
|
"rustls 0.20.8",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
]
|
]
|
||||||
|
@ -1440,7 +1450,7 @@ dependencies = [
|
||||||
"nom 7.1.1",
|
"nom 7.1.1",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"quoted_printable",
|
"quoted_printable",
|
||||||
"rustls",
|
"rustls 0.20.8",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"socket2",
|
"socket2",
|
||||||
|
@ -1530,11 +1540,19 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mail-builder"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "git+https://github.com/stalwartlabs/mail-builder.git#7986275cd89340eef2cb18daea25ced53f51db07"
|
||||||
|
dependencies = [
|
||||||
|
"gethostname 0.4.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mail-parser"
|
name = "mail-parser"
|
||||||
version = "0.8.1"
|
version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a2e03aa1d18528b45d0e79e46790f38cfeece6cce3af17a85912677272f36cd"
|
checksum = "e4158a1c18963244e083888b21465846dfb68d6170850ed1ab4742edd57c9d47"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
]
|
]
|
||||||
|
@ -1545,7 +1563,7 @@ version = "0.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d2d08d52a925272eda99f8fe9e91237b1cb958804ee0628cc398ebd1bbc426f"
|
checksum = "5d2d08d52a925272eda99f8fe9e91237b1cb958804ee0628cc398ebd1bbc426f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gethostname",
|
"gethostname 0.2.3",
|
||||||
"mailparse",
|
"mailparse",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
]
|
]
|
||||||
|
@ -2044,8 +2062,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-email"
|
name = "pimalaya-email"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#f62efe4f4f3fe4d1493056cef50d8ebdc28f681b"
|
||||||
checksum = "6ffcfdf5fbbca7539e3d762a5c5b3b2b6fd58fc3d996b2295f094c7f394553ad"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"advisory-lock",
|
"advisory-lock",
|
||||||
"ammonia",
|
"ammonia",
|
||||||
|
@ -2057,6 +2074,7 @@ dependencies = [
|
||||||
"imap-proto",
|
"imap-proto",
|
||||||
"lettre",
|
"lettre",
|
||||||
"log",
|
"log",
|
||||||
|
"mail-builder",
|
||||||
"mail-parser",
|
"mail-parser",
|
||||||
"maildir",
|
"maildir",
|
||||||
"mailparse",
|
"mailparse",
|
||||||
|
@ -2073,7 +2091,7 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"rfc2047-decoder",
|
"rfc2047-decoder",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
"rustls",
|
"rustls 0.21.1",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"shellexpand",
|
"shellexpand",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -2086,17 +2104,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pimalaya-email-tpl"
|
name = "pimalaya-email-tpl"
|
||||||
version = "0.1.1"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://git.sr.ht/~soywod/pimalaya#f62efe4f4f3fe4d1493056cef50d8ebdc28f681b"
|
||||||
checksum = "fd0a03c25c249b598bddd24a0fe1c06d044c9bb8362644792e902146c8b5b613"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
|
||||||
"chumsky 0.9.0",
|
"chumsky 0.9.0",
|
||||||
"html-escape",
|
|
||||||
"lettre",
|
|
||||||
"log",
|
"log",
|
||||||
|
"mail-builder",
|
||||||
|
"mail-parser",
|
||||||
"pimalaya-process",
|
"pimalaya-process",
|
||||||
"regex",
|
|
||||||
"shellexpand",
|
"shellexpand",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tree_magic",
|
"tree_magic",
|
||||||
|
@ -2401,7 +2416,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls",
|
"rustls 0.20.8",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -2506,6 +2521,18 @@ dependencies = [
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.21.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"ring",
|
||||||
|
"rustls-webpki",
|
||||||
|
"sct",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-connector"
|
name = "rustls-connector"
|
||||||
version = "0.16.1"
|
version = "0.16.1"
|
||||||
|
@ -2513,7 +2540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c6a18f8d10f71bce9bca6eaeb80429460e652f3bcf0381f0c5f8954abf7b3b8"
|
checksum = "9c6a18f8d10f71bce9bca6eaeb80429460e652f3bcf0381f0c5f8954abf7b3b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"rustls",
|
"rustls 0.20.8",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
@ -2539,6 +2566,16 @@ dependencies = [
|
||||||
"base64 0.21.0",
|
"base64 0.21.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.100.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b"
|
||||||
|
dependencies = [
|
||||||
|
"ring",
|
||||||
|
"untrusted",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -2966,7 +3003,7 @@ version = "0.23.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls 0.20.8",
|
||||||
"tokio",
|
"tokio",
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
@ -3341,6 +3378,21 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.43.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.42.2",
|
||||||
|
"windows_aarch64_msvc 0.42.2",
|
||||||
|
"windows_i686_gnu 0.42.2",
|
||||||
|
"windows_i686_msvc 0.42.2",
|
||||||
|
"windows_x86_64_gnu 0.42.2",
|
||||||
|
"windows_x86_64_gnullvm 0.42.2",
|
||||||
|
"windows_x86_64_msvc 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.36.1"
|
version = "0.36.1"
|
||||||
|
|
|
@ -51,7 +51,7 @@ 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 = "=0.8.0"
|
pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya" }
|
||||||
pimalaya-keyring = "=0.0.1"
|
pimalaya-keyring = "=0.0.1"
|
||||||
pimalaya-oauth2 = "=0.0.2"
|
pimalaya-oauth2 = "=0.0.2"
|
||||||
pimalaya-process = "=0.0.2"
|
pimalaya-process = "=0.0.2"
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use anyhow::{anyhow, Context, Result};
|
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, Flag, Flags, Sender};
|
||||||
AccountConfig, Backend, Email, Flag, Flags, Sender, ShowTextPartsStrategy, Tpl, TplBuilder,
|
|
||||||
};
|
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
io::{self, BufRead},
|
io::{self, BufRead},
|
||||||
|
@ -114,20 +112,22 @@ pub fn forward<P: Printer>(
|
||||||
sender: &mut dyn Sender,
|
sender: &mut dyn Sender,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
|
|
||||||
let ids = id_mapper.get_ids([id])?;
|
let ids = id_mapper.get_ids([id])?;
|
||||||
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)?
|
||||||
.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)
|
||||||
.set_some_raw_headers(headers)
|
.some_headers(headers)
|
||||||
.some_text_plain_part(body)
|
.some_body(body)
|
||||||
.build();
|
.build()?;
|
||||||
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)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -170,19 +170,24 @@ pub fn mailto<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
url: &Url,
|
url: &Url,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut tpl = TplBuilder::default().to(url.path());
|
let mut builder = EmailBuilder::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() {
|
||||||
b"cc" => tpl = tpl.cc(val),
|
b"cc" => builder = builder.cc(val.to_string()),
|
||||||
b"bcc" => tpl = tpl.bcc(val),
|
b"bcc" => builder = builder.bcc(val.to_string()),
|
||||||
b"subject" => tpl = tpl.subject(val),
|
b"subject" => builder = builder.subject(val),
|
||||||
b"body" => tpl = tpl.text_plain_part(val.as_bytes()),
|
b"body" => builder = builder.text_body(val),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl.build())
|
let tpl = config
|
||||||
|
.generate_tpl_interpreter()
|
||||||
|
.show_only_headers(config.email_writing_headers())
|
||||||
|
.interpret_msg_builder(builder)?;
|
||||||
|
|
||||||
|
editor::edit_tpl_with_editor(config, printer, backend, sender, tpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_<P: Printer>(
|
pub fn move_<P: Printer>(
|
||||||
|
@ -209,8 +214,9 @@ pub fn read<P: Printer>(
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
ids: Vec<&str>,
|
ids: Vec<&str>,
|
||||||
text_mime: &str,
|
// TODO: map this to ShowTextsStrategy
|
||||||
sanitize: bool,
|
_text_mime: &str,
|
||||||
|
_sanitize: bool,
|
||||||
raw: bool,
|
raw: bool,
|
||||||
headers: Vec<&str>,
|
headers: Vec<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
@ -230,20 +236,10 @@ pub fn read<P: Printer>(
|
||||||
// display what can be displayed
|
// display what can be displayed
|
||||||
bodies.push_str(&String::from_utf8_lossy(email.raw()?).into_owned());
|
bodies.push_str(&String::from_utf8_lossy(email.raw()?).into_owned());
|
||||||
} else {
|
} else {
|
||||||
let tpl = email
|
let tpl: String = email
|
||||||
.to_read_tpl_builder(config)?
|
.to_read_tpl(&config, |i| i.show_additional_headers(&headers))?
|
||||||
.show_headers(config.email_reading_headers())
|
.into();
|
||||||
.show_headers(&headers)
|
bodies.push_str(&tpl);
|
||||||
.show_text_parts_only(true)
|
|
||||||
.use_show_text_parts_strategy(if text_mime == "plain" {
|
|
||||||
ShowTextPartsStrategy::PlainOtherwiseHtml
|
|
||||||
} else {
|
|
||||||
ShowTextPartsStrategy::HtmlOtherwisePlain
|
|
||||||
})
|
|
||||||
.sanitize_text_parts(sanitize)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
bodies.push_str(&<Tpl as Into<String>>::into(tpl));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glue = "\n\n";
|
glue = "\n\n";
|
||||||
|
@ -261,20 +257,23 @@ pub fn reply<P: Printer>(
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
all: bool,
|
all: bool,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let folder = config.folder_alias(folder)?;
|
let folder = config.folder_alias(folder)?;
|
||||||
|
|
||||||
let ids = id_mapper.get_ids([id])?;
|
let ids = id_mapper.get_ids([id])?;
|
||||||
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)?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_reply_tpl_builder(config, all)?
|
.to_reply_tpl_builder(config)
|
||||||
.set_some_raw_headers(headers)
|
.some_headers(headers)
|
||||||
.some_text_plain_part(body)
|
.some_body(body)
|
||||||
.build();
|
.reply_all(all)
|
||||||
|
.build()?;
|
||||||
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)?;
|
||||||
backend.add_flags(&folder, vec![id], &Flags::from_iter([Flag::Answered]))?;
|
backend.add_flags(&folder, vec![id], &Flags::from_iter([Flag::Answered]))?;
|
||||||
|
@ -397,13 +396,13 @@ pub fn write<P: Printer>(
|
||||||
printer: &mut P,
|
printer: &mut P,
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
sender: &mut dyn Sender,
|
sender: &mut dyn Sender,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let tpl = Email::new_tpl_builder(config)?
|
let tpl = Email::new_tpl_builder(config)
|
||||||
.set_some_raw_headers(headers)
|
.some_headers(headers)
|
||||||
.some_text_plain_part(body)
|
.some_body(body)
|
||||||
.build();
|
.build()?;
|
||||||
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)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||||
|
use log::warn;
|
||||||
|
|
||||||
use crate::email;
|
use crate::email;
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ const CMD_WRITE: &str = "write";
|
||||||
pub const CMD_TPL: &str = "template";
|
pub const CMD_TPL: &str = "template";
|
||||||
|
|
||||||
pub type RawTpl = String;
|
pub type RawTpl = String;
|
||||||
pub type Headers<'a> = Option<Vec<&'a str>>;
|
pub type Headers<'a> = Option<Vec<(&'a str, &'a str)>>;
|
||||||
pub type Body<'a> = Option<&'a str>;
|
pub type Body<'a> = Option<&'a str>;
|
||||||
|
|
||||||
/// Represents the template commands.
|
/// Represents the template commands.
|
||||||
|
@ -121,8 +122,16 @@ pub fn args() -> Vec<Arg> {
|
||||||
|
|
||||||
/// Represents the template headers argument parser.
|
/// Represents the template headers argument parser.
|
||||||
pub fn parse_headers_arg(m: &ArgMatches) -> Headers<'_> {
|
pub fn parse_headers_arg(m: &ArgMatches) -> Headers<'_> {
|
||||||
m.get_many(ARG_HEADERS)
|
m.get_many::<String>(ARG_HEADERS).map(|h| {
|
||||||
.map(|h| h.map(String::as_str).collect::<Vec<_>>())
|
h.filter_map(|h| match h.split_once(':') {
|
||||||
|
Some((key, val)) => Some((key, val.trim())),
|
||||||
|
None => {
|
||||||
|
warn!("invalid raw header {h:?}, skipping it");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the template body argument parser.
|
/// Represents the template body argument parser.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use atty::Stream;
|
use atty::Stream;
|
||||||
use pimalaya_email::{AccountConfig, Backend, CompilerBuilder, Email, Flags, Sender, Tpl};
|
use pimalaya_email::{AccountConfig, Backend, Email, Flags, Sender, Tpl};
|
||||||
use std::io::{stdin, BufRead};
|
use std::io::{stdin, BufRead};
|
||||||
|
|
||||||
use crate::{printer::Printer, IdMapper};
|
use crate::{printer::Printer, IdMapper};
|
||||||
|
@ -12,21 +12,23 @@ pub fn forward<P: Printer>(
|
||||||
backend: &mut dyn Backend,
|
backend: &mut dyn Backend,
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ids = id_mapper.get_ids([id])?;
|
let ids = id_mapper.get_ids([id])?;
|
||||||
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: String = backend
|
||||||
.get_emails(folder, ids)?
|
.get_emails(folder, ids)?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_forward_tpl_builder(config)?
|
.to_forward_tpl_builder(config)
|
||||||
.set_some_raw_headers(headers)
|
.some_headers(headers)
|
||||||
.some_text_plain_part(body)
|
.some_body(body)
|
||||||
.build();
|
.build()?
|
||||||
|
.into();
|
||||||
|
|
||||||
printer.print(<Tpl as Into<String>>::into(tpl))
|
printer.print(tpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reply<P: Printer>(
|
pub fn reply<P: Printer>(
|
||||||
|
@ -37,21 +39,24 @@ pub fn reply<P: Printer>(
|
||||||
folder: &str,
|
folder: &str,
|
||||||
id: &str,
|
id: &str,
|
||||||
all: bool,
|
all: bool,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ids = id_mapper.get_ids([id])?;
|
let ids = id_mapper.get_ids([id])?;
|
||||||
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: String = backend
|
||||||
.get_emails(folder, ids)?
|
.get_emails(folder, ids)?
|
||||||
.first()
|
.first()
|
||||||
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
.ok_or_else(|| anyhow!("cannot find email {}", id))?
|
||||||
.to_reply_tpl_builder(config, all)?
|
.to_reply_tpl_builder(config)
|
||||||
.set_some_raw_headers(headers)
|
.some_headers(headers)
|
||||||
.some_text_plain_part(body)
|
.some_body(body)
|
||||||
.build();
|
.reply_all(all)
|
||||||
|
.build()?
|
||||||
|
.into();
|
||||||
|
|
||||||
printer.print(<Tpl as Into<String>>::into(tpl))
|
printer.print(tpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save<P: Printer>(
|
pub fn save<P: Printer>(
|
||||||
|
@ -72,11 +77,10 @@ pub fn save<P: Printer>(
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n")
|
.join("\n")
|
||||||
})
|
})
|
||||||
.compile(
|
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
||||||
CompilerBuilder::default()
|
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
||||||
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
.compile()?
|
||||||
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone()),
|
.write_to_vec()?;
|
||||||
)?;
|
|
||||||
|
|
||||||
let id = backend.add_email(folder, &email, &Flags::default())?;
|
let id = backend.add_email(folder, &email, &Flags::default())?;
|
||||||
id_mapper.create_alias(id)?;
|
id_mapper.create_alias(id)?;
|
||||||
|
@ -102,11 +106,10 @@ pub fn send<P: Printer>(
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n")
|
.join("\n")
|
||||||
})
|
})
|
||||||
.compile(
|
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
||||||
CompilerBuilder::default()
|
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone())
|
||||||
.some_pgp_sign_cmd(config.email_writing_sign_cmd.clone())
|
.compile()?
|
||||||
.some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone()),
|
.write_to_vec()?;
|
||||||
)?;
|
|
||||||
sender.send(&email)?;
|
sender.send(&email)?;
|
||||||
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())?;
|
||||||
|
@ -115,15 +118,17 @@ pub fn send<P: Printer>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write<'a, P: Printer>(
|
pub fn write<P: Printer>(
|
||||||
config: &'a AccountConfig,
|
config: &AccountConfig,
|
||||||
printer: &'a mut P,
|
printer: &mut P,
|
||||||
headers: Option<Vec<&str>>,
|
headers: Option<Vec<(&str, &str)>>,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let tpl = Email::new_tpl_builder(config)?
|
let tpl: String = Email::new_tpl_builder(config)
|
||||||
.set_some_raw_headers(headers)
|
.some_headers(headers)
|
||||||
.some_text_plain_part(body)
|
.some_body(body)
|
||||||
.build();
|
.build()?
|
||||||
printer.print(<Tpl as Into<String>>::into(tpl))
|
.into();
|
||||||
|
|
||||||
|
printer.print(tpl)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use anyhow::{Context, Result};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use pimalaya_email::{
|
use pimalaya_email::{
|
||||||
email::{local_draft_path, remove_local_draft},
|
email::{local_draft_path, remove_local_draft},
|
||||||
AccountConfig, Backend, CompilerBuilder, Flag, Flags, Sender, Tpl,
|
AccountConfig, Backend, Flag, Flags, Sender, Tpl,
|
||||||
};
|
};
|
||||||
use std::{env, fs, process::Command};
|
use std::{env, fs, process::Command};
|
||||||
|
|
||||||
|
@ -73,11 +73,11 @@ pub fn edit_tpl_with_editor<P: Printer>(
|
||||||
match choice::post_edit() {
|
match choice::post_edit() {
|
||||||
Ok(PostEditChoice::Send) => {
|
Ok(PostEditChoice::Send) => {
|
||||||
printer.print_log("Sending email…")?;
|
printer.print_log("Sending email…")?;
|
||||||
let email = tpl.compile(
|
let email = tpl
|
||||||
CompilerBuilder::default()
|
.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()?
|
||||||
)?;
|
.write_to_vec()?;
|
||||||
sender.send(&email)?;
|
sender.send(&email)?;
|
||||||
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()?;
|
||||||
|
@ -98,11 +98,11 @@ pub fn edit_tpl_with_editor<P: Printer>(
|
||||||
}
|
}
|
||||||
Ok(PostEditChoice::RemoteDraft) => {
|
Ok(PostEditChoice::RemoteDraft) => {
|
||||||
let draft_folder = config.folder_alias("drafts")?;
|
let draft_folder = config.folder_alias("drafts")?;
|
||||||
let email = tpl.compile(
|
let email = tpl
|
||||||
CompilerBuilder::default()
|
.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()?
|
||||||
)?;
|
.write_to_vec()?;
|
||||||
backend.add_email(
|
backend.add_email(
|
||||||
&draft_folder,
|
&draft_folder,
|
||||||
&email,
|
&email,
|
||||||
|
|
|
@ -8,7 +8,7 @@ use anyhow::{Context, Result};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use pimalaya_email::EmailTextPlainFormat;
|
use pimalaya_email::EmailTextPlainFormat;
|
||||||
use termcolor::{Color, ColorSpec};
|
use termcolor::{Color, ColorSpec};
|
||||||
use terminal_size;
|
use terminal_size::terminal_size;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
use crate::printer::{Print, PrintTableOpts, WriteColor};
|
use crate::printer::{Print, PrintTableOpts, WriteColor};
|
||||||
|
@ -175,7 +175,7 @@ where
|
||||||
EmailTextPlainFormat::Flowed => 0,
|
EmailTextPlainFormat::Flowed => 0,
|
||||||
EmailTextPlainFormat::Auto => opts
|
EmailTextPlainFormat::Auto => opts
|
||||||
.max_width
|
.max_width
|
||||||
.or_else(|| terminal_size::terminal_size().map(|(w, _)| w.0 as usize))
|
.or_else(|| terminal_size().map(|(w, _)| w.0 as usize))
|
||||||
.unwrap_or(DEFAULT_TERM_WIDTH),
|
.unwrap_or(DEFAULT_TERM_WIDTH),
|
||||||
};
|
};
|
||||||
let mut table = vec![Self::head()];
|
let mut table = vec![Self::head()];
|
||||||
|
|
Loading…
Reference in a new issue