refactor template with clap derive api

This commit is contained in:
Clément DOUIN 2023-12-07 22:37:28 +01:00
parent b28f12c367
commit fff11fbe20
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
18 changed files with 406 additions and 405 deletions

View file

@ -10,7 +10,10 @@ use crate::{
flag::command::FlagSubcommand,
folder::command::FolderSubcommand,
manual::command::ManualGenerateCommand,
message::{attachment::command::AttachmentSubcommand, command::MessageSubcommand},
message::{
attachment::command::AttachmentSubcommand, command::MessageSubcommand,
template::command::TemplateSubcommand,
},
output::{ColorFmt, OutputFmt},
printer::Printer,
};
@ -105,6 +108,11 @@ pub enum HimalayaCommand {
#[command(alias = "messages", alias = "msgs", alias = "msg")]
Message(MessageSubcommand),
/// Manage templates
#[command(subcommand)]
#[command(alias = "templates", alias = "tpls", alias = "tpl")]
Template(TemplateSubcommand),
/// Manage attachments
#[command(subcommand)]
Attachment(AttachmentSubcommand),
@ -128,6 +136,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::Template(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,

View file

@ -1,6 +1,5 @@
use std::ops::Deref;
use clap::Parser;
use std::ops::Deref;
/// The raw message body argument parser
#[derive(Debug, Parser)]

View file

@ -1,2 +1,3 @@
pub mod body;
pub mod header;
pub mod reply;

View file

@ -0,0 +1,9 @@
use clap::Parser;
/// The reply to all argument parser
#[derive(Debug, Parser)]
pub struct MessageReplyAllArg {
/// Reply to all recipients
#[arg(long, short = 'A')]
pub all: bool,
}

View file

@ -36,7 +36,7 @@ impl AttachmentDownloadCommand {
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 backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
let ids = &self.envelopes.ids;
let emails = backend.get_messages(&folder, ids).await?;

View file

@ -12,7 +12,7 @@ use crate::{
config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg,
folder::arg::name::FolderNameArg,
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
message::arg::{body::BodyRawArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
printer::Printer,
ui::editor,
};
@ -26,9 +26,8 @@ pub struct MessageReplyCommand {
#[command(flatten)]
pub envelope: EnvelopeIdArg,
/// Reply to all recipients
#[arg(long, short = 'A')]
pub all: bool,
#[command(flatten)]
pub reply: MessageReplyAllArg,
#[command(flatten)]
pub headers: HeaderRawArgs,
@ -73,11 +72,11 @@ impl MessageReplyCommand {
.get_messages(folder, &[id])
.await?
.first()
.ok_or(anyhow!("cannot find message"))?
.ok_or(anyhow!("cannot find message {id}"))?
.to_reply_tpl_builder(&account_config)
.with_headers(self.headers.raw)
.with_body(body)
.with_reply_all(self.all)
.with_reply_all(self.reply.all)
.build()
.await?;
editor::edit_tpl_with_editor(&account_config, printer, &backend, tpl).await?;

View file

@ -2,4 +2,4 @@ pub mod arg;
pub mod attachment;
pub mod command;
pub mod config;
// pub mod template;
pub mod template;

View file

@ -1,154 +0,0 @@
//! Module related to email template CLI.
//!
//! This module provides subcommands, arguments and a command matcher
//! related to email templating.
use anyhow::Result;
use clap::{Arg, ArgAction, ArgMatches, Command};
use log::warn;
use crate::message;
const ARG_BODY: &str = "body";
const ARG_HEADERS: &str = "headers";
const ARG_TPL: &str = "template";
const CMD_FORWARD: &str = "forward";
const CMD_REPLY: &str = "reply";
const CMD_SAVE: &str = "save";
const CMD_SEND: &str = "send";
const CMD_WRITE: &str = "write";
pub const CMD_TPL: &str = "template";
pub type RawTpl = String;
pub type Headers<'a> = Option<Vec<(&'a str, &'a str)>>;
pub type Body<'a> = Option<&'a str>;
/// Represents the template commands.
#[derive(Debug, PartialEq, Eq)]
pub enum Cmd<'a> {
Forward(message::args::Id<'a>, Headers<'a>, Body<'a>),
Write(Headers<'a>, Body<'a>),
Reply(
message::args::Id<'a>,
message::args::All,
Headers<'a>,
Body<'a>,
),
Save(RawTpl),
Send(RawTpl),
}
/// Represents the template command matcher.
pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Cmd<'a>>> {
let cmd = if let Some(m) = m.subcommand_matches(CMD_FORWARD) {
let id = message::args::parse_id_arg(m);
let headers = parse_headers_arg(m);
let body = parse_body_arg(m);
Some(Cmd::Forward(id, headers, body))
} else if let Some(m) = m.subcommand_matches(CMD_REPLY) {
let id = message::args::parse_id_arg(m);
let all = message::args::parse_reply_all_flag(m);
let headers = parse_headers_arg(m);
let body = parse_body_arg(m);
Some(Cmd::Reply(id, all, headers, body))
} else if let Some(m) = m.subcommand_matches(CMD_SAVE) {
let raw_tpl = parse_raw_arg(m);
Some(Cmd::Save(raw_tpl))
} else if let Some(m) = m.subcommand_matches(CMD_SEND) {
let raw_tpl = parse_raw_arg(m);
Some(Cmd::Send(raw_tpl))
} else if let Some(m) = m.subcommand_matches(CMD_WRITE) {
let headers = parse_headers_arg(m);
let body = parse_body_arg(m);
Some(Cmd::Write(headers, body))
} else {
None
};
Ok(cmd)
}
/// Represents the template subcommands.
pub fn subcmd() -> Command {
Command::new(CMD_TPL)
.alias("tpl")
.about("Subcommand to manage templates")
.long_about("Subcommand to manage templates like write, reply, send or save")
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(
Command::new(CMD_FORWARD)
.alias("fwd")
.about("Generate a template for forwarding an email")
.arg(message::args::id_arg())
.args(&args()),
)
.subcommand(
Command::new(CMD_REPLY)
.about("Generate a template for replying to an email")
.arg(message::args::id_arg())
.arg(message::args::reply_all_flag())
.args(&args()),
)
.subcommand(
Command::new(CMD_SAVE)
.about("Compile the template into a valid email then saves it")
.arg(Arg::new(ARG_TPL).raw(true)),
)
.subcommand(
Command::new(CMD_SEND)
.about("Compile the template into a valid email then sends it")
.arg(Arg::new(ARG_TPL).raw(true)),
)
.subcommand(
Command::new(CMD_WRITE)
.aliases(["new", "n"])
.about("Generate a template for writing a new email")
.args(&args()),
)
}
/// Represents the template arguments.
pub fn args() -> Vec<Arg> {
vec![
Arg::new(ARG_HEADERS)
.help("Override a specific header")
.short('H')
.long("header")
.value_name("KEY:VAL")
.action(ArgAction::Append),
Arg::new(ARG_BODY)
.help("Override the body")
.short('B')
.long("body")
.value_name("STRING"),
]
}
/// Represents the template headers argument parser.
pub fn parse_headers_arg(m: &ArgMatches) -> Headers<'_> {
m.get_many::<String>(ARG_HEADERS).map(|h| {
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.
pub fn parse_body_arg(matches: &ArgMatches) -> Body<'_> {
matches.get_one::<String>(ARG_BODY).map(String::as_str)
}
/// Represents the raw template argument parser.
pub fn parse_raw_arg(matches: &ArgMatches) -> RawTpl {
matches
.get_one::<String>(ARG_TPL)
.cloned()
.unwrap_or_default()
}

View file

@ -0,0 +1,65 @@
use anyhow::{anyhow, Result};
use clap::Parser;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
cache::arg::disable::DisableCacheFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg,
folder::arg::name::FolderNameArg,
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
printer::Printer,
};
/// Generate a forward message template
#[derive(Debug, Parser)]
pub struct TemplateForwardCommand {
#[command(flatten)]
pub folder: FolderNameArg,
#[command(flatten)]
pub envelope: EnvelopeIdArg,
#[command(flatten)]
pub headers: HeaderRawArgs,
#[command(flatten)]
pub body: BodyRawArg,
#[command(flatten)]
pub cache: DisableCacheFlag,
#[command(flatten)]
pub account: AccountNameFlag,
}
impl TemplateForwardCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template forward 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(), false).await?;
let id = self.envelope.id;
let tpl: String = backend
.get_messages(folder, &[id])
.await?
.first()
.ok_or(anyhow!("cannot find message {id}"))?
.to_forward_tpl_builder(&account_config)
.with_headers(self.headers.raw)
.with_body(self.body.raw())
.build()
.await?
.into();
printer.print(tpl)
}
}

View file

@ -0,0 +1,52 @@
pub mod forward;
pub mod reply;
pub mod save;
pub mod send;
pub mod write;
use anyhow::Result;
use clap::Subcommand;
use crate::{config::TomlConfig, printer::Printer};
use self::{
forward::TemplateForwardCommand, reply::TemplateReplyCommand, save::TemplateSaveCommand,
send::TemplateSendCommand, write::TemplateWriteCommand,
};
/// Subcommand to manage templates
#[derive(Debug, Subcommand)]
pub enum TemplateSubcommand {
/// Write a new template
#[command(alias = "new", alias = "compose")]
Write(TemplateWriteCommand),
/// Reply to a template
#[command()]
Reply(TemplateReplyCommand),
/// Generate a template for forwarding an email
#[command(alias = "fwd")]
Forward(TemplateForwardCommand),
/// Save a template to a folder
#[command(arg_required_else_help = true)]
#[command(alias = "add", alias = "create")]
Save(TemplateSaveCommand),
/// Send a template
#[command(arg_required_else_help = true)]
Send(TemplateSendCommand),
}
impl TemplateSubcommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
match self {
Self::Write(cmd) => cmd.execute(printer, config).await,
Self::Reply(cmd) => cmd.execute(printer, config).await,
Self::Forward(cmd) => cmd.execute(printer, config).await,
Self::Save(cmd) => cmd.execute(printer, config).await,
Self::Send(cmd) => cmd.execute(printer, config).await,
}
}
}

View file

@ -0,0 +1,69 @@
use anyhow::{anyhow, Result};
use clap::Parser;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
backend::Backend,
cache::arg::disable::DisableCacheFlag,
config::TomlConfig,
envelope::arg::ids::EnvelopeIdArg,
folder::arg::name::FolderNameArg,
message::arg::{body::BodyRawArg, header::HeaderRawArgs, reply::MessageReplyAllArg},
printer::Printer,
};
/// Generate a reply message template
#[derive(Debug, Parser)]
pub struct TemplateReplyCommand {
#[command(flatten)]
pub folder: FolderNameArg,
#[command(flatten)]
pub envelope: EnvelopeIdArg,
#[command(flatten)]
pub reply: MessageReplyAllArg,
#[command(flatten)]
pub headers: HeaderRawArgs,
#[command(flatten)]
pub body: BodyRawArg,
#[command(flatten)]
pub cache: DisableCacheFlag,
#[command(flatten)]
pub account: AccountNameFlag,
}
impl TemplateReplyCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template reply command");
let folder = &self.folder.name;
let id = self.envelope.id;
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(), false).await?;
let tpl: String = backend
.get_messages(folder, &[id])
.await?
.first()
.ok_or(anyhow!("cannot find message {id}"))?
.to_reply_tpl_builder(&account_config)
.with_headers(self.headers.raw)
.with_body(self.body.raw())
.with_reply_all(self.reply.all)
.build()
.await?
.into();
printer.print(tpl)
}
}

View file

@ -0,0 +1,66 @@
use anyhow::Result;
use atty::Stream;
use clap::Parser;
use log::info;
use mml::MmlCompilerBuilder;
use std::io::{self, BufRead};
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
};
/// Save a template to a folder
#[derive(Debug, Parser)]
pub struct TemplateSaveCommand {
#[command(flatten)]
pub folder: FolderNameArg,
/// The raw template to save
#[arg(raw = true, value_delimiter = ' ')]
pub raw: Vec<String>,
#[command(flatten)]
pub cache: DisableCacheFlag,
#[command(flatten)]
pub account: AccountNameFlag,
}
impl TemplateSaveCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template save 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(), false).await?;
let is_tty = atty::is(Stream::Stdin);
let is_json = printer.is_json();
let tpl = if is_tty || is_json {
self.raw.join(" ").replace("\r", "")
} else {
io::stdin()
.lock()
.lines()
.filter_map(Result::ok)
.collect::<Vec<String>>()
.join("\n")
};
#[allow(unused_mut)]
let mut compiler = MmlCompilerBuilder::new();
#[cfg(feature = "pgp")]
compiler.set_some_pgp(config.pgp.clone());
let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend.add_raw_message(folder, &msg).await?;
printer.print(format!("Template successfully saved to {folder}!"))
}
}

View file

@ -0,0 +1,73 @@
use anyhow::Result;
use atty::Stream;
use clap::Parser;
use email::flag::Flag;
use log::info;
use mml::MmlCompilerBuilder;
use std::io::{self, BufRead};
use crate::{
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::DisableCacheFlag,
config::TomlConfig, printer::Printer,
};
/// Send a template
#[derive(Debug, Parser)]
pub struct TemplateSendCommand {
/// The raw template to save
#[arg(raw = true, value_delimiter = ' ')]
pub raw: Vec<String>,
#[command(flatten)]
pub cache: DisableCacheFlag,
#[command(flatten)]
pub account: AccountNameFlag,
}
impl TemplateSendCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template send command");
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 folder = account_config.sent_folder_alias()?;
let is_tty = atty::is(Stream::Stdin);
let is_json = printer.is_json();
let tpl = if is_tty || is_json {
self.raw.join(" ").replace("\r", "")
} else {
io::stdin()
.lock()
.lines()
.filter_map(Result::ok)
.collect::<Vec<String>>()
.join("\r\n")
};
#[allow(unused_mut)]
let mut compiler = MmlCompilerBuilder::new();
#[cfg(feature = "pgp")]
compiler.set_some_pgp(config.pgp.clone());
let msg = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend.send_raw_message(&msg).await?;
if account_config.email_sending_save_copy.unwrap_or_default() {
backend
.add_raw_message_with_flag(&folder, &msg, Flag::Seen)
.await?;
printer.print(format!("Template successfully sent and saved to {folder}!"))
} else {
printer.print("Template successfully sent!")
}
}
}

View file

@ -0,0 +1,48 @@
use anyhow::Result;
use clap::Parser;
use email::message::Message;
use log::info;
use crate::{
account::arg::name::AccountNameFlag,
cache::arg::disable::DisableCacheFlag,
config::TomlConfig,
message::arg::{body::BodyRawArg, header::HeaderRawArgs},
printer::Printer,
};
/// Write a new template
#[derive(Debug, Parser)]
pub struct TemplateWriteCommand {
#[command(flatten)]
pub headers: HeaderRawArgs,
#[command(flatten)]
pub body: BodyRawArg,
#[command(flatten)]
pub cache: DisableCacheFlag,
#[command(flatten)]
pub account: AccountNameFlag,
}
impl TemplateWriteCommand {
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
info!("executing template write command");
let account = self.account.name.as_ref().map(String::as_str);
let cache = self.cache.disable;
let (_, account_config) = config.clone().into_account_configs(account, cache)?;
let tpl: String = Message::new_tpl_builder(&account_config)
.with_headers(self.headers.raw)
.with_body(self.body.raw())
.build()
.await?
.into();
printer.print(tpl)
}
}

View file

@ -1,143 +0,0 @@
use anyhow::{anyhow, Result};
use atty::Stream;
use email::{account::config::AccountConfig, flag::Flag, message::Message};
use mml::MmlCompilerBuilder;
use std::io::{stdin, BufRead};
use crate::{backend::Backend, printer::Printer};
pub async fn forward<P: Printer>(
config: &AccountConfig,
printer: &mut P,
backend: &Backend,
folder: &str,
id: &str,
headers: Option<Vec<(&str, &str)>>,
body: Option<&str>,
) -> Result<()> {
let tpl: String = backend
.get_messages(folder, &[id])
.await?
.first()
.ok_or_else(|| anyhow!("cannot find email {}", id))?
.to_forward_tpl_builder(config)
.with_some_headers(headers)
.with_some_body(body)
.build()
.await?
.into();
printer.print(tpl)
}
pub async fn reply<P: Printer>(
config: &AccountConfig,
printer: &mut P,
backend: &Backend,
folder: &str,
id: &str,
all: bool,
headers: Option<Vec<(&str, &str)>>,
body: Option<&str>,
) -> Result<()> {
let tpl: String = backend
.get_messages(folder, &[id])
.await?
.first()
.ok_or_else(|| anyhow!("cannot find email {}", id))?
.to_reply_tpl_builder(config)
.with_some_headers(headers)
.with_some_body(body)
.with_reply_all(all)
.build()
.await?
.into();
printer.print(tpl)
}
pub async fn save<P: Printer>(
#[allow(unused_variables)] config: &AccountConfig,
printer: &mut P,
backend: &Backend,
folder: &str,
tpl: String,
) -> Result<()> {
let tpl = if atty::is(Stream::Stdin) || printer.is_json() {
tpl.replace("\r", "")
} else {
stdin()
.lock()
.lines()
.filter_map(Result::ok)
.collect::<Vec<String>>()
.join("\n")
};
#[allow(unused_mut)]
let mut compiler = MmlCompilerBuilder::new();
#[cfg(feature = "pgp")]
compiler.set_some_pgp(config.pgp.clone());
let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend.add_raw_message(folder, &email).await?;
printer.print("Template successfully saved!")
}
pub async fn send<P: Printer>(
config: &AccountConfig,
printer: &mut P,
backend: &Backend,
tpl: String,
) -> Result<()> {
let folder = config.sent_folder_alias()?;
let tpl = if atty::is(Stream::Stdin) || printer.is_json() {
tpl.replace("\r", "")
} else {
stdin()
.lock()
.lines()
.filter_map(Result::ok)
.collect::<Vec<String>>()
.join("\n")
};
#[allow(unused_mut)]
let mut compiler = MmlCompilerBuilder::new();
#[cfg(feature = "pgp")]
compiler.set_some_pgp(config.pgp.clone());
let email = compiler.build(tpl.as_str())?.compile().await?.into_vec()?;
backend.send_raw_message(&email).await?;
if config.email_sending_save_copy.unwrap_or_default() {
backend
.add_raw_message_with_flag(&folder, &email, Flag::Seen)
.await?;
}
printer.print("Template successfully sent!")?;
Ok(())
}
pub async fn write<P: Printer>(
config: &AccountConfig,
printer: &mut P,
headers: Option<Vec<(&str, &str)>>,
body: Option<&str>,
) -> Result<()> {
let tpl: String = Message::new_tpl_builder(config)
.with_some_headers(headers)
.with_some_body(body)
.build()
.await?
.into();
printer.print(tpl)
}

View file

@ -1,2 +1 @@
pub mod args;
pub mod handlers;
pub mod command;

View file

@ -2,5 +2,7 @@ pub mod envelope;
pub mod message;
#[doc(inline)]
// pub use self::{envelope::flag, message::template};
pub use self::envelope::flag;
pub use self::{
envelope::flag,
message::{attachment, template},
};

View file

@ -36,96 +36,3 @@ async fn main() -> Result<()> {
cli.command.execute(&mut printer, &config).await
}
// fn create_app() -> clap::Command {
// clap::Command::new(env!("CARGO_PKG_NAME"))
// .subcommand(message::args::subcmd())
// .subcommand(template::args::subcmd())
// }
// #[tokio::main]
// async fn main() -> Result<()> {
// // check mailto command before app initialization
// let raw_args: Vec<String> = env::args().collect();
// if raw_args.len() > 1 && raw_args[1].starts_with("mailto:") {
// let url = Url::parse(&raw_args[1])?;
// let (toml_account_config, account_config) = TomlConfig::from_default_paths()
// .await?
// .into_account_configs(None, false)?;
// let backend_builder =
// BackendBuilder::new(toml_account_config, account_config.clone(), true).await?;
// let backend = backend_builder.build().await?;
// let mut printer = StdoutPrinter::default();
// return message::handlers::mailto(&account_config, &backend, &mut printer, &url).await;
// }
// match message::args::matches(&m)? {
// Some(message::args::Cmd::Attachments(ids)) => {
// let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
// let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
// return message::handlers::attachments(
// &account_config,
// &mut printer,
// &backend,
// &folder,
// ids,
// )
// .await;
// }
// _ => (),
// }
// match template::args::matches(&m)? {
// Some(template::args::Cmd::Forward(id, headers, body)) => {
// let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
// let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
// return template::handlers::forward(
// &account_config,
// &mut printer,
// &backend,
// &folder,
// id,
// headers,
// body,
// )
// .await;
// }
// Some(template::args::Cmd::Write(headers, body)) => {
// return template::handlers::write(&account_config, &mut printer, headers, body).await;
// }
// Some(template::args::Cmd::Reply(id, all, headers, body)) => {
// let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
// let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
// return template::handlers::reply(
// &account_config,
// &mut printer,
// &backend,
// &folder,
// id,
// all,
// headers,
// body,
// )
// .await;
// }
// Some(template::args::Cmd::Save(template)) => {
// let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER);
// let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
// return template::handlers::save(
// &account_config,
// &mut printer,
// &backend,
// &folder,
// template,
// )
// .await;
// }
// Some(template::args::Cmd::Send(template)) => {
// let backend = Backend::new(toml_account_config, account_config.clone(), true).await?;
// return template::handlers::send(&account_config, &mut printer, &backend, template)
// .await;
// }
// _ => (),
// }
// }