mirror of
https://github.com/soywod/himalaya.git
synced 2025-04-17 14:53:37 +00:00
refactor attachment with clap derive api
This commit is contained in:
parent
b8ef771614
commit
b28f12c367
7 changed files with 117 additions and 460 deletions
|
@ -10,7 +10,7 @@ use crate::{
|
|||
flag::command::FlagSubcommand,
|
||||
folder::command::FolderSubcommand,
|
||||
manual::command::ManualGenerateCommand,
|
||||
message::command::MessageSubcommand,
|
||||
message::{attachment::command::AttachmentSubcommand, command::MessageSubcommand},
|
||||
output::{ColorFmt, OutputFmt},
|
||||
printer::Printer,
|
||||
};
|
||||
|
@ -105,6 +105,10 @@ pub enum HimalayaCommand {
|
|||
#[command(alias = "messages", alias = "msgs", alias = "msg")]
|
||||
Message(MessageSubcommand),
|
||||
|
||||
/// Manage attachments
|
||||
#[command(subcommand)]
|
||||
Attachment(AttachmentSubcommand),
|
||||
|
||||
/// Generate manual pages to a directory
|
||||
#[command(arg_required_else_help = true)]
|
||||
#[command(alias = "manuals", alias = "mans")]
|
||||
|
@ -124,6 +128,7 @@ impl HimalayaCommand {
|
|||
Self::Envelope(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Flag(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Message(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Attachment(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Manual(cmd) => cmd.execute(printer).await,
|
||||
Self::Completion(cmd) => cmd.execute(printer).await,
|
||||
}
|
||||
|
|
|
@ -1,356 +0,0 @@
|
|||
//! Email CLI module.
|
||||
//!
|
||||
//! This module contains the command matcher, the subcommands and the
|
||||
//! arguments related to the email domain.
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command};
|
||||
|
||||
use crate::template;
|
||||
|
||||
const ARG_CRITERIA: &str = "criterion";
|
||||
const ARG_HEADERS: &str = "headers";
|
||||
const ARG_ID: &str = "id";
|
||||
const ARG_IDS: &str = "ids";
|
||||
const ARG_MIME_TYPE: &str = "mime-type";
|
||||
const ARG_QUERY: &str = "query";
|
||||
const ARG_RAW: &str = "raw";
|
||||
const ARG_REPLY_ALL: &str = "reply-all";
|
||||
const CMD_ATTACHMENTS: &str = "attachments";
|
||||
const CMD_COPY: &str = "copy";
|
||||
const CMD_DELETE: &str = "delete";
|
||||
const CMD_FORWARD: &str = "forward";
|
||||
const CMD_MESSAGE: &str = "message";
|
||||
const CMD_MOVE: &str = "move";
|
||||
const CMD_READ: &str = "read";
|
||||
const CMD_REPLY: &str = "reply";
|
||||
const CMD_SAVE: &str = "save";
|
||||
const CMD_SEND: &str = "send";
|
||||
const CMD_WRITE: &str = "write";
|
||||
|
||||
pub type All = bool;
|
||||
pub type Criteria = String;
|
||||
pub type Folder<'a> = &'a str;
|
||||
pub type Headers<'a> = Vec<&'a str>;
|
||||
pub type Id<'a> = &'a str;
|
||||
pub type Ids<'a> = Vec<&'a str>;
|
||||
pub type Query = String;
|
||||
pub type Raw = bool;
|
||||
pub type RawEmail = String;
|
||||
pub type TextMime<'a> = &'a str;
|
||||
|
||||
/// Represents the email commands.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Cmd<'a> {
|
||||
Attachments(Ids<'a>),
|
||||
Copy(Ids<'a>, Folder<'a>),
|
||||
Delete(Ids<'a>),
|
||||
Forward(
|
||||
Id<'a>,
|
||||
template::args::Headers<'a>,
|
||||
template::args::Body<'a>,
|
||||
),
|
||||
Move(Ids<'a>, Folder<'a>),
|
||||
Read(Ids<'a>, TextMime<'a>, Raw, Headers<'a>),
|
||||
Reply(
|
||||
Id<'a>,
|
||||
All,
|
||||
template::args::Headers<'a>,
|
||||
template::args::Body<'a>,
|
||||
),
|
||||
Save(RawEmail),
|
||||
Send(RawEmail),
|
||||
Write(template::args::Headers<'a>, template::args::Body<'a>),
|
||||
}
|
||||
|
||||
/// Email command matcher.
|
||||
pub fn matches(m: &ArgMatches) -> Result<Option<Cmd>> {
|
||||
let cmd = if let Some(m) = m.subcommand_matches(CMD_MESSAGE) {
|
||||
if let Some(m) = m.subcommand_matches(CMD_ATTACHMENTS) {
|
||||
let ids = parse_ids_arg(m);
|
||||
Some(Cmd::Attachments(ids))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_COPY) {
|
||||
let ids = parse_ids_arg(m);
|
||||
let folder = "INBOX";
|
||||
Some(Cmd::Copy(ids, folder))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_DELETE) {
|
||||
let ids = parse_ids_arg(m);
|
||||
Some(Cmd::Delete(ids))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_FORWARD) {
|
||||
let id = parse_id_arg(m);
|
||||
let headers = template::args::parse_headers_arg(m);
|
||||
let body = template::args::parse_body_arg(m);
|
||||
Some(Cmd::Forward(id, headers, body))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_MOVE) {
|
||||
let ids = parse_ids_arg(m);
|
||||
let folder = "INBOX";
|
||||
Some(Cmd::Move(ids, folder))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_READ) {
|
||||
let ids = parse_ids_arg(m);
|
||||
let mime = parse_mime_type_arg(m);
|
||||
let raw = parse_raw_flag(m);
|
||||
let headers = parse_headers_arg(m);
|
||||
Some(Cmd::Read(ids, mime, raw, headers))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_REPLY) {
|
||||
let id = parse_id_arg(m);
|
||||
let all = parse_reply_all_flag(m);
|
||||
let headers = template::args::parse_headers_arg(m);
|
||||
let body = template::args::parse_body_arg(m);
|
||||
Some(Cmd::Reply(id, all, headers, body))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_SAVE) {
|
||||
let email = parse_raw_arg(m);
|
||||
Some(Cmd::Save(email))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_SEND) {
|
||||
let email = parse_raw_arg(m);
|
||||
Some(Cmd::Send(email))
|
||||
} else if let Some(m) = m.subcommand_matches(CMD_WRITE) {
|
||||
let headers = template::args::parse_headers_arg(m);
|
||||
let body = template::args::parse_body_arg(m);
|
||||
Some(Cmd::Write(headers, body))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(cmd)
|
||||
}
|
||||
|
||||
/// Represents the email subcommands.
|
||||
pub fn subcmd() -> Command {
|
||||
Command::new(CMD_MESSAGE)
|
||||
.about("Subcommand to manage messages")
|
||||
.long_about("Subcommand to manage messages like read, write, reply or send")
|
||||
.aliases(["msg"])
|
||||
.subcommand_required(true)
|
||||
.arg_required_else_help(true)
|
||||
.subcommands([
|
||||
Command::new(CMD_ATTACHMENTS)
|
||||
.about("Downloads all emails attachments")
|
||||
.arg(ids_arg()),
|
||||
Command::new(CMD_WRITE)
|
||||
.about("Write a new email")
|
||||
.aliases(["new", "n"])
|
||||
.args(template::args::args()),
|
||||
Command::new(CMD_SEND)
|
||||
.about("Send a raw email")
|
||||
.arg(raw_arg()),
|
||||
Command::new(CMD_SAVE)
|
||||
.about("Save a raw email")
|
||||
.arg(raw_arg()),
|
||||
Command::new(CMD_READ)
|
||||
.about("Read text bodies of emails")
|
||||
.arg(mime_type_arg())
|
||||
.arg(raw_flag())
|
||||
.arg(headers_arg())
|
||||
.arg(ids_arg()),
|
||||
Command::new(CMD_REPLY)
|
||||
.about("Answer to an email")
|
||||
.arg(reply_all_flag())
|
||||
.args(template::args::args())
|
||||
.arg(id_arg()),
|
||||
Command::new(CMD_FORWARD)
|
||||
.aliases(["fwd", "f"])
|
||||
.about("Forward an email")
|
||||
.args(template::args::args())
|
||||
.arg(id_arg()),
|
||||
Command::new(CMD_COPY)
|
||||
.alias("cp")
|
||||
.about("Copy emails to the given folder")
|
||||
// .arg(folder::args::target_arg())
|
||||
.arg(ids_arg()),
|
||||
Command::new(CMD_MOVE)
|
||||
.alias("mv")
|
||||
.about("Move emails to the given folder")
|
||||
// .arg(folder::args::target_arg())
|
||||
.arg(ids_arg()),
|
||||
Command::new(CMD_DELETE)
|
||||
.aliases(["remove", "rm"])
|
||||
.about("Delete emails")
|
||||
.arg(ids_arg()),
|
||||
])
|
||||
}
|
||||
|
||||
/// Represents the email id argument.
|
||||
pub fn id_arg() -> Arg {
|
||||
Arg::new(ARG_ID)
|
||||
.help("Specifies the target email")
|
||||
.value_name("ID")
|
||||
.required(true)
|
||||
}
|
||||
|
||||
/// Represents the email id argument parser.
|
||||
pub fn parse_id_arg(matches: &ArgMatches) -> &str {
|
||||
matches.get_one::<String>(ARG_ID).unwrap()
|
||||
}
|
||||
|
||||
/// Represents the email ids argument.
|
||||
pub fn ids_arg() -> Arg {
|
||||
Arg::new(ARG_IDS)
|
||||
.help("Email ids")
|
||||
.value_name("IDS")
|
||||
.num_args(1..)
|
||||
.required(true)
|
||||
}
|
||||
|
||||
/// Represents the email ids argument parser.
|
||||
pub fn parse_ids_arg(matches: &ArgMatches) -> Vec<&str> {
|
||||
matches
|
||||
.get_many::<String>(ARG_IDS)
|
||||
.unwrap()
|
||||
.map(String::as_str)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Represents the email sort criteria argument.
|
||||
pub fn criteria_arg<'a>() -> Arg {
|
||||
Arg::new(ARG_CRITERIA)
|
||||
.help("Email sorting preferences")
|
||||
.long("criterion")
|
||||
.short('c')
|
||||
.value_name("CRITERION:ORDER")
|
||||
.action(ArgAction::Append)
|
||||
.value_parser([
|
||||
"arrival",
|
||||
"arrival:asc",
|
||||
"arrival:desc",
|
||||
"cc",
|
||||
"cc:asc",
|
||||
"cc:desc",
|
||||
"date",
|
||||
"date:asc",
|
||||
"date:desc",
|
||||
"from",
|
||||
"from:asc",
|
||||
"from:desc",
|
||||
"size",
|
||||
"size:asc",
|
||||
"size:desc",
|
||||
"subject",
|
||||
"subject:asc",
|
||||
"subject:desc",
|
||||
"to",
|
||||
"to:asc",
|
||||
"to:desc",
|
||||
])
|
||||
}
|
||||
|
||||
/// Represents the email sort criteria argument parser.
|
||||
pub fn parse_criteria_arg(matches: &ArgMatches) -> String {
|
||||
matches
|
||||
.get_many::<String>(ARG_CRITERIA)
|
||||
.unwrap_or_default()
|
||||
.map(ToOwned::to_owned)
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
}
|
||||
|
||||
/// Represents the email reply all argument.
|
||||
pub fn reply_all_flag() -> Arg {
|
||||
Arg::new(ARG_REPLY_ALL)
|
||||
.help("Include all recipients")
|
||||
.long("all")
|
||||
.short('A')
|
||||
.action(ArgAction::SetTrue)
|
||||
}
|
||||
|
||||
/// Represents the email reply all argument parser.
|
||||
pub fn parse_reply_all_flag(matches: &ArgMatches) -> bool {
|
||||
matches.get_flag(ARG_REPLY_ALL)
|
||||
}
|
||||
|
||||
/// Represents the email headers argument.
|
||||
pub fn headers_arg() -> Arg {
|
||||
Arg::new(ARG_HEADERS)
|
||||
.help("Shows additional headers with the email")
|
||||
.long("header")
|
||||
.short('H')
|
||||
.value_name("STRING")
|
||||
.action(ArgAction::Append)
|
||||
}
|
||||
|
||||
/// Represents the email headers argument parser.
|
||||
pub fn parse_headers_arg(m: &ArgMatches) -> Vec<&str> {
|
||||
m.get_many::<String>(ARG_HEADERS)
|
||||
.unwrap_or_default()
|
||||
.map(String::as_str)
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
/// Represents the raw flag.
|
||||
pub fn raw_flag() -> Arg {
|
||||
Arg::new(ARG_RAW)
|
||||
.help("Returns raw version of email")
|
||||
.long("raw")
|
||||
.short('r')
|
||||
.action(ArgAction::SetTrue)
|
||||
}
|
||||
|
||||
/// Represents the raw flag parser.
|
||||
pub fn parse_raw_flag(m: &ArgMatches) -> bool {
|
||||
m.get_flag(ARG_RAW)
|
||||
}
|
||||
|
||||
/// Represents the email raw argument.
|
||||
pub fn raw_arg() -> Arg {
|
||||
Arg::new(ARG_RAW).raw(true)
|
||||
}
|
||||
|
||||
/// Represents the email raw argument parser.
|
||||
pub fn parse_raw_arg(m: &ArgMatches) -> String {
|
||||
m.get_one::<String>(ARG_RAW).cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Represents the email MIME type argument.
|
||||
pub fn mime_type_arg() -> Arg {
|
||||
Arg::new(ARG_MIME_TYPE)
|
||||
.help("MIME type to use")
|
||||
.short('t')
|
||||
.long("mime-type")
|
||||
.value_name("MIME")
|
||||
.value_parser(["plain", "html"])
|
||||
.default_value("plain")
|
||||
}
|
||||
|
||||
/// Represents the email MIME type argument parser.
|
||||
pub fn parse_mime_type_arg(matches: &ArgMatches) -> &str {
|
||||
matches.get_one::<String>(ARG_MIME_TYPE).unwrap()
|
||||
}
|
||||
|
||||
/// Represents the email query argument.
|
||||
pub fn query_arg() -> Arg {
|
||||
Arg::new(ARG_QUERY)
|
||||
.long_help("The query system depends on the backend, see the wiki for more details")
|
||||
.value_name("QUERY")
|
||||
.num_args(1..)
|
||||
.required(true)
|
||||
}
|
||||
|
||||
/// Represents the email query argument parser.
|
||||
pub fn parse_query_arg(matches: &ArgMatches) -> String {
|
||||
matches
|
||||
.get_many::<String>(ARG_QUERY)
|
||||
.unwrap_or_default()
|
||||
.fold((false, vec![]), |(escape, mut cmds), cmd| {
|
||||
match (cmd.as_str(), escape) {
|
||||
// Next command is an arg and needs to be escaped
|
||||
("subject", _) | ("body", _) | ("text", _) => {
|
||||
cmds.push(cmd.to_string());
|
||||
(true, cmds)
|
||||
}
|
||||
// Escaped arg commands
|
||||
(_, true) => {
|
||||
cmds.push(format!("\"{}\"", cmd));
|
||||
(false, cmds)
|
||||
}
|
||||
// Regular commands
|
||||
(_, false) => {
|
||||
cmds.push(cmd.to_string());
|
||||
(false, cmds)
|
||||
}
|
||||
}
|
||||
})
|
||||
.1
|
||||
.join(" ")
|
||||
}
|
85
src/email/message/attachment/command/download.rs
Normal file
85
src/email/message/attachment/command/download.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
use std::fs;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
|
||||
config::TomlConfig, envelope::arg::ids::EnvelopeIdsArgs, folder::arg::name::FolderNameArg,
|
||||
printer::Printer,
|
||||
};
|
||||
|
||||
/// Download attachments of a message
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct AttachmentDownloadCommand {
|
||||
#[command(flatten)]
|
||||
pub folder: FolderNameArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub envelopes: EnvelopeIdsArgs,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: DisableCacheFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl AttachmentDownloadCommand {
|
||||
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
||||
info!("executing attachment download command");
|
||||
|
||||
let folder = &self.folder.name;
|
||||
let account = self.account.name.as_ref().map(String::as_str);
|
||||
let cache = self.cache.disable;
|
||||
|
||||
let (toml_account_config, account_config) =
|
||||
config.clone().into_account_configs(account, cache)?;
|
||||
let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
|
||||
|
||||
let ids = &self.envelopes.ids;
|
||||
let emails = backend.get_messages(&folder, ids).await?;
|
||||
|
||||
let mut emails_count = 0;
|
||||
let mut attachments_count = 0;
|
||||
|
||||
let mut ids = ids.iter();
|
||||
for email in emails.to_vec() {
|
||||
let id = ids.next().unwrap();
|
||||
let attachments = email.attachments()?;
|
||||
|
||||
if attachments.is_empty() {
|
||||
printer.print_log(format!("No attachment found for message {id}!"))?;
|
||||
continue;
|
||||
} else {
|
||||
emails_count += 1;
|
||||
}
|
||||
|
||||
printer.print_log(format!(
|
||||
"{} attachment(s) found for message {id}!",
|
||||
attachments.len()
|
||||
))?;
|
||||
|
||||
for attachment in attachments {
|
||||
let filename = attachment
|
||||
.filename
|
||||
.unwrap_or_else(|| Uuid::new_v4().to_string());
|
||||
let filepath = account_config.download_fpath(&filename)?;
|
||||
printer.print_log(format!("Downloading {:?}…", filepath))?;
|
||||
fs::write(&filepath, &attachment.body)
|
||||
.with_context(|| format!("cannot save attachment at {filepath:?}"))?;
|
||||
attachments_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
match attachments_count {
|
||||
0 => printer.print("No attachment found!"),
|
||||
1 => printer.print("Downloaded 1 attachment!"),
|
||||
n => printer.print(format!(
|
||||
"Downloaded {} attachment(s) from {} messages(s)!",
|
||||
n, emails_count,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
24
src/email/message/attachment/command/mod.rs
Normal file
24
src/email/message/attachment/command/mod.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
pub mod download;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Subcommand;
|
||||
|
||||
use crate::{config::TomlConfig, printer::Printer};
|
||||
|
||||
use self::download::AttachmentDownloadCommand;
|
||||
|
||||
/// Subcommand dedicated to attachments
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum AttachmentSubcommand {
|
||||
/// Download all attachments of one or more messages
|
||||
#[command(arg_required_else_help = true)]
|
||||
Download(AttachmentDownloadCommand),
|
||||
}
|
||||
|
||||
impl AttachmentSubcommand {
|
||||
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
||||
match self {
|
||||
Self::Download(cmd) => cmd.execute(printer, config).await,
|
||||
}
|
||||
}
|
||||
}
|
1
src/email/message/attachment/mod.rs
Normal file
1
src/email/message/attachment/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod command;
|
|
@ -1,101 +0,0 @@
|
|||
use anyhow::{anyhow, Context, Result};
|
||||
use atty::Stream;
|
||||
use email::{
|
||||
account::config::AccountConfig, envelope::Id, flag::Flag, message::Message,
|
||||
template::FilterParts,
|
||||
};
|
||||
use log::trace;
|
||||
use mail_builder::MessageBuilder;
|
||||
use std::{
|
||||
fs,
|
||||
io::{self, BufRead},
|
||||
};
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{backend::Backend, printer::Printer, ui::editor};
|
||||
|
||||
pub async fn attachments<P: Printer>(
|
||||
config: &AccountConfig,
|
||||
printer: &mut P,
|
||||
backend: &Backend,
|
||||
folder: &str,
|
||||
ids: Vec<&str>,
|
||||
) -> Result<()> {
|
||||
let emails = backend.get_messages(&folder, &ids).await?;
|
||||
let mut index = 0;
|
||||
|
||||
let mut emails_count = 0;
|
||||
let mut attachments_count = 0;
|
||||
|
||||
let mut ids = ids.iter();
|
||||
for email in emails.to_vec() {
|
||||
let id = ids.next().unwrap();
|
||||
let attachments = email.attachments()?;
|
||||
|
||||
index = index + 1;
|
||||
|
||||
if attachments.is_empty() {
|
||||
printer.print_log(format!("No attachment found for email #{}", id))?;
|
||||
continue;
|
||||
} else {
|
||||
emails_count = emails_count + 1;
|
||||
}
|
||||
|
||||
printer.print_log(format!(
|
||||
"{} attachment(s) found for email #{}…",
|
||||
attachments.len(),
|
||||
id
|
||||
))?;
|
||||
|
||||
for attachment in attachments {
|
||||
let filename = attachment
|
||||
.filename
|
||||
.unwrap_or_else(|| Uuid::new_v4().to_string());
|
||||
let filepath = config.download_fpath(&filename)?;
|
||||
printer.print_log(format!("Downloading {:?}…", filepath))?;
|
||||
fs::write(&filepath, &attachment.body).context("cannot download attachment")?;
|
||||
attachments_count = attachments_count + 1;
|
||||
}
|
||||
}
|
||||
|
||||
match attachments_count {
|
||||
0 => printer.print("No attachment found!"),
|
||||
1 => printer.print("Downloaded 1 attachment!"),
|
||||
n => printer.print(format!(
|
||||
"Downloaded {} attachment(s) from {} email(s)!",
|
||||
n, emails_count,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses and edits a message from a [mailto] URL string.
|
||||
///
|
||||
/// [mailto]: https://en.wikipedia.org/wiki/Mailto
|
||||
pub async fn mailto<P: Printer>(
|
||||
config: &AccountConfig,
|
||||
backend: &Backend,
|
||||
printer: &mut P,
|
||||
url: &Url,
|
||||
) -> Result<()> {
|
||||
let mut builder = MessageBuilder::new().to(url.path());
|
||||
|
||||
for (key, val) in url.query_pairs() {
|
||||
match key.to_lowercase().as_bytes() {
|
||||
b"cc" => builder = builder.cc(val.to_string()),
|
||||
b"bcc" => builder = builder.bcc(val.to_string()),
|
||||
b"subject" => builder = builder.subject(val),
|
||||
b"body" => builder = builder.text_body(val),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let tpl = config
|
||||
.generate_tpl_interpreter()
|
||||
.with_show_only_headers(config.email_writing_headers())
|
||||
.build()
|
||||
.from_msg_builder(builder)
|
||||
.await?;
|
||||
|
||||
editor::edit_tpl_with_editor(config, printer, backend, tpl).await
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
// pub mod args;
|
||||
pub mod arg;
|
||||
pub mod attachment;
|
||||
pub mod command;
|
||||
pub mod config;
|
||||
// pub mod handlers;
|
||||
// pub mod template;
|
||||
|
|
Loading…
Add table
Reference in a new issue