mirror of
https://github.com/soywod/himalaya.git
synced 2024-07-08 10:35:13 +00:00
improve entities and services from and try_from
This commit is contained in:
parent
0ed1147f3d
commit
248240f52d
|
@ -1,6 +1,6 @@
|
|||
use anyhow::{anyhow, Context, Error, Result};
|
||||
use lettre::transport::smtp::authentication::Credentials as SmtpCredentials;
|
||||
use log::debug;
|
||||
use log::{debug, trace};
|
||||
use std::{convert::TryFrom, env, fs, path::PathBuf};
|
||||
|
||||
use crate::{domain::config::entity::Config, output::utils::run_cmd};
|
||||
|
@ -210,6 +210,7 @@ impl<'a> TryFrom<(&'a Config, Option<&str>)> for Account {
|
|||
type Error = Error;
|
||||
|
||||
fn try_from((config, account_name): (&'a Config, Option<&str>)) -> Result<Self, Self::Error> {
|
||||
debug!("init account `{}`", account_name.unwrap_or("default"));
|
||||
let (name, account) = match account_name {
|
||||
Some("") | None => config
|
||||
.accounts
|
||||
|
@ -265,7 +266,7 @@ impl<'a> TryFrom<(&'a Config, Option<&str>)> for Account {
|
|||
.map(|sig| format!("\n{}{}", signature_delim, sig))
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Account {
|
||||
let account = Account {
|
||||
name,
|
||||
from: account.name.as_ref().unwrap_or(&config.name).to_owned(),
|
||||
downloads_dir,
|
||||
|
@ -291,6 +292,9 @@ impl<'a> TryFrom<(&'a Config, Option<&str>)> for Account {
|
|||
smtp_insecure: account.smtp_insecure.unwrap_or_default(),
|
||||
smtp_login: account.smtp_login.to_owned(),
|
||||
smtp_passwd_cmd: account.smtp_passwd_cmd.to_owned(),
|
||||
})
|
||||
};
|
||||
|
||||
trace!("{:#?}", account);
|
||||
Ok(account)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::{anyhow, Context, Error, Result};
|
||||
use log::debug;
|
||||
use log::{debug, trace};
|
||||
use serde::Deserialize;
|
||||
use shellexpand;
|
||||
use std::{collections::HashMap, convert::TryFrom, env, fs, path::PathBuf, thread};
|
||||
|
@ -284,12 +284,16 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PathBuf> for Config {
|
||||
impl TryFrom<Option<&str>> for Config {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
|
||||
let file_content = fs::read_to_string(path).context("cannot read config file")?;
|
||||
Ok(toml::from_str(&file_content).context("cannot parse config file")?)
|
||||
fn try_from(path: Option<&str>) -> Result<Self, Self::Error> {
|
||||
debug!("init config from `{:?}`", path);
|
||||
let path = path.map(|s| s.into()).unwrap_or(Config::path()?);
|
||||
let content = fs::read_to_string(path).context("cannot read config file")?;
|
||||
let config = toml::from_str(&content).context("cannot parse config file")?;
|
||||
trace!("{:#?}", config);
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@ use native_tls::{self, TlsConnector, TlsStream};
|
|||
use std::{collections::HashSet, convert::TryFrom, iter::FromIterator, net::TcpStream};
|
||||
|
||||
use crate::{
|
||||
domain::{account::entity::Account, config::entity::Config, msg::entity::Msg},
|
||||
domain::{
|
||||
account::entity::Account, config::entity::Config, mbox::entity::Mbox, msg::entity::Msg,
|
||||
},
|
||||
flag::model::Flags,
|
||||
};
|
||||
|
||||
|
@ -25,7 +27,7 @@ pub trait ImapServiceInterface {
|
|||
page: &usize,
|
||||
) -> Result<Option<ImapMsgs>>;
|
||||
fn get_msg(&mut self, uid: &str) -> Result<Msg>;
|
||||
fn append_msg(&mut self, mbox: &str, msg: &mut Msg) -> Result<()>;
|
||||
fn append_msg(&mut self, mbox: &Mbox, msg: &mut Msg) -> Result<()>;
|
||||
fn add_flags(&mut self, uid_seq: &str, flags: Flags) -> Result<()>;
|
||||
fn set_flags(&mut self, uid_seq: &str, flags: Flags) -> Result<()>;
|
||||
fn remove_flags(&mut self, uid_seq: &str, flags: Flags) -> Result<()>;
|
||||
|
@ -35,20 +37,11 @@ pub trait ImapServiceInterface {
|
|||
|
||||
pub struct ImapService<'a> {
|
||||
account: &'a Account,
|
||||
mbox: &'a str,
|
||||
mbox: &'a Mbox,
|
||||
sess: Option<ImapSession>,
|
||||
}
|
||||
|
||||
impl<'a> ImapService<'a> {
|
||||
pub fn new(account: &'a Account, mbox: &'a str) -> Result<Self> {
|
||||
debug!("create new service");
|
||||
Ok(Self {
|
||||
account,
|
||||
mbox,
|
||||
sess: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn sess(&mut self) -> Result<&mut ImapSession> {
|
||||
if let None = self.sess {
|
||||
debug!("create TLS builder");
|
||||
|
@ -116,8 +109,8 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
let mbox = self.mbox.to_owned();
|
||||
let last_seq = self
|
||||
.sess()?
|
||||
.select(mbox)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox))?
|
||||
.select(&mbox.name)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox.name))?
|
||||
.exists as i64;
|
||||
|
||||
if last_seq == 0 {
|
||||
|
@ -150,8 +143,8 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
) -> Result<Option<ImapMsgs>> {
|
||||
let mbox = self.mbox.to_owned();
|
||||
self.sess()?
|
||||
.select(mbox)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox))?;
|
||||
.select(&mbox.name)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox.name))?;
|
||||
|
||||
let begin = page * page_size;
|
||||
let end = begin + (page_size - 1);
|
||||
|
@ -160,7 +153,7 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
.search(query)
|
||||
.context(format!(
|
||||
"cannot search in `{}` with query `{}`",
|
||||
self.mbox, query
|
||||
self.mbox.name, query
|
||||
))?
|
||||
.iter()
|
||||
.map(|seq| seq.to_string())
|
||||
|
@ -182,8 +175,8 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
fn get_msg(&mut self, uid: &str) -> Result<Msg> {
|
||||
let mbox = self.mbox.to_owned();
|
||||
self.sess()?
|
||||
.select(mbox)
|
||||
.context(format!("cannot select mbox `{}`", self.mbox))?;
|
||||
.select(&mbox.name)
|
||||
.context(format!("cannot select mbox `{}`", self.mbox.name))?;
|
||||
match self
|
||||
.sess()?
|
||||
.uid_fetch(uid, "(FLAGS BODY[] ENVELOPE INTERNALDATE)")
|
||||
|
@ -195,14 +188,14 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn append_msg(&mut self, mbox: &str, msg: &mut Msg) -> Result<()> {
|
||||
fn append_msg(&mut self, mbox: &Mbox, msg: &mut Msg) -> Result<()> {
|
||||
let body = msg.into_bytes()?;
|
||||
let flags: HashSet<imap::types::Flag<'static>> = (*msg.flags).clone();
|
||||
self.sess()?
|
||||
.append(mbox, &body)
|
||||
.append(&mbox.name, &body)
|
||||
.flags(flags)
|
||||
.finish()
|
||||
.context(format!("cannot append message to `{}`", mbox))?;
|
||||
.context(format!("cannot append message to `{}`", mbox.name))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -230,8 +223,8 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
let mbox = self.mbox.to_owned();
|
||||
let flags: String = flags.to_string();
|
||||
self.sess()?
|
||||
.select(mbox)
|
||||
.context(format!("cannot select mbox `{}`", self.mbox))?;
|
||||
.select(&mbox.name)
|
||||
.context(format!("cannot select mbox `{}`", self.mbox.name))?;
|
||||
self.sess()?
|
||||
.uid_store(uid_seq, format!("+FLAGS ({})", flags))
|
||||
.context(format!("cannot add flags `{}`", &flags))?;
|
||||
|
@ -263,8 +256,8 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
let mbox = self.mbox.to_owned();
|
||||
let flags: String = flags.to_string();
|
||||
self.sess()?
|
||||
.select(mbox)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox))?;
|
||||
.select(&mbox.name)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox.name))?;
|
||||
self.sess()?
|
||||
.uid_store(uid_seq, format!("FLAGS ({})", flags))
|
||||
.context(format!("cannot set flags `{}`", &flags))?;
|
||||
|
@ -277,8 +270,8 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
let mbox = self.mbox.to_owned();
|
||||
let flags = flags.to_string();
|
||||
self.sess()?
|
||||
.select(mbox)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox))?;
|
||||
.select(&mbox.name)
|
||||
.context(format!("cannot select mailbox `{}`", self.mbox.name))?;
|
||||
self.sess()?
|
||||
.uid_store(uid_seq, format!("-FLAGS ({})", flags))
|
||||
.context(format!("cannot remove flags `{}`", &flags))?;
|
||||
|
@ -288,17 +281,17 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
fn expunge(&mut self) -> Result<()> {
|
||||
self.sess()?
|
||||
.expunge()
|
||||
.context(format!("cannot expunge `{}`", self.mbox))?;
|
||||
.context(format!("cannot expunge `{}`", self.mbox.name))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notify(&mut self, config: &Config, keepalive: u64) -> Result<()> {
|
||||
let mbox = self.mbox.to_owned();
|
||||
|
||||
debug!("examine mailbox: {}", mbox);
|
||||
debug!("examine mailbox: {}", mbox.name);
|
||||
self.sess()?
|
||||
.examine(mbox)
|
||||
.context(format!("cannot examine mailbox `{}`", &self.mbox))?;
|
||||
.examine(&mbox.name)
|
||||
.context(format!("cannot examine mailbox `{}`", &self.mbox.name))?;
|
||||
|
||||
debug!("init messages hashset");
|
||||
let mut msgs_set: HashSet<u32> =
|
||||
|
@ -361,12 +354,12 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
}
|
||||
|
||||
fn watch(&mut self, keepalive: u64) -> Result<()> {
|
||||
debug!("examine mailbox: {}", &self.mbox);
|
||||
debug!("examine mailbox: {}", &self.mbox.name);
|
||||
let mbox = self.mbox.to_owned();
|
||||
|
||||
self.sess()?
|
||||
.examine(mbox)
|
||||
.context(format!("cannot examine mailbox `{}`", &self.mbox))?;
|
||||
.examine(&mbox.name)
|
||||
.context(format!("cannot examine mailbox `{}`", &self.mbox.name))?;
|
||||
|
||||
loop {
|
||||
debug!("begin loop");
|
||||
|
@ -396,6 +389,12 @@ impl<'a> ImapServiceInterface for ImapService<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
//impl<'a> ImapConnector<'a> {
|
||||
|
||||
//}
|
||||
impl<'a> From<(&'a Account, &'a Mbox)> for ImapService<'a> {
|
||||
fn from((account, mbox): (&'a Account, &'a Mbox)) -> Self {
|
||||
Self {
|
||||
account,
|
||||
mbox,
|
||||
sess: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use anyhow::{anyhow, Error, Result};
|
||||
use imap::types::NameAttribute;
|
||||
use log::debug;
|
||||
use serde::{
|
||||
ser::{self, SerializeSeq},
|
||||
Serialize,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::{borrow::Cow, convert::TryFrom};
|
||||
|
||||
use crate::ui::table::{Cell, Row, Table};
|
||||
|
||||
|
@ -99,6 +101,41 @@ pub struct Mbox {
|
|||
pub attributes: Attributes,
|
||||
}
|
||||
|
||||
impl Mbox {
|
||||
pub fn new<S: AsRef<str>>(name: S) -> Self {
|
||||
Self {
|
||||
name: name.as_ref().to_owned(),
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Mbox {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
delim: String::default(),
|
||||
name: String::default(),
|
||||
attributes: Attributes::from(&[] as &[NameAttribute]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Mbox {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Mbox {
|
||||
fn from(mbox: &str) -> Self {
|
||||
debug!("init mailbox from `{:?}`", mbox);
|
||||
Self {
|
||||
name: mbox.to_owned(),
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a imap::types::Name> for Mbox {
|
||||
fn from(name: &'a imap::types::Name) -> Self {
|
||||
Self {
|
||||
|
@ -109,6 +146,18 @@ impl<'a> From<&'a imap::types::Name> for Mbox {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Option<&str>> for Mbox {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(mbox: Option<&str>) -> Result<Self, Self::Error> {
|
||||
debug!("init mailbox from `{:?}`", mbox);
|
||||
Ok(Self {
|
||||
name: mbox.ok_or(anyhow!("cannot parse mailbox"))?.to_string(),
|
||||
..Self::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Table for Mbox {
|
||||
fn head() -> Row {
|
||||
Row::new()
|
||||
|
|
|
@ -20,7 +20,9 @@ use super::{
|
|||
};
|
||||
use crate::{
|
||||
domain::{
|
||||
account::entity::Account, imap::service::ImapServiceInterface, mbox::cli::mbox_target_arg,
|
||||
account::entity::Account,
|
||||
imap::service::ImapServiceInterface,
|
||||
mbox::{cli::mbox_target_arg, entity::Mbox},
|
||||
smtp::service::SmtpServiceInterface,
|
||||
},
|
||||
flag::model::Flags,
|
||||
|
@ -130,7 +132,7 @@ pub fn subcmds<'a>() -> Vec<clap::App<'a, 'a>> {
|
|||
|
||||
pub fn matches<ImapService: ImapServiceInterface, SmtpService: SmtpServiceInterface>(
|
||||
arg_matches: &clap::ArgMatches,
|
||||
mbox: &str,
|
||||
mbox: &Mbox,
|
||||
account: &Account,
|
||||
output: &OutputService,
|
||||
imap: &mut ImapService,
|
||||
|
@ -578,14 +580,13 @@ fn msg_matches_copy<ImapService: ImapServiceInterface>(
|
|||
// fetch the message to be copyied
|
||||
let uid = matches.value_of("uid").unwrap();
|
||||
debug!("uid: {}", &uid);
|
||||
let target = matches.value_of("target").unwrap();
|
||||
debug!("target: {}", &target);
|
||||
let target = Mbox::try_from(matches.value_of("target"))?;
|
||||
|
||||
let mut msg = imap.get_msg(&uid)?;
|
||||
// the message, which will be in the new mailbox doesn't need to be seen
|
||||
msg.flags.insert(Flag::Seen);
|
||||
|
||||
imap.append_msg(target, &mut msg)?;
|
||||
imap.append_msg(&target, &mut msg)?;
|
||||
|
||||
debug!("message {} successfully copied to folder `{}`", uid, target);
|
||||
|
||||
|
@ -608,13 +609,12 @@ fn msg_matches_move<ImapService: ImapServiceInterface>(
|
|||
// fetch the msg which should be moved
|
||||
let uid = matches.value_of("uid").unwrap();
|
||||
debug!("uid: {}", &uid);
|
||||
let target = matches.value_of("target").unwrap();
|
||||
debug!("target: {}", &target);
|
||||
let target = Mbox::try_from(matches.value_of("target"))?;
|
||||
|
||||
let mut msg = imap.get_msg(&uid)?;
|
||||
// create the msg in the target-msgbox
|
||||
msg.flags.insert(Flag::Seen);
|
||||
imap.append_msg(target, &mut msg)?;
|
||||
imap.append_msg(&target, &mut msg)?;
|
||||
|
||||
debug!("message {} successfully moved to folder `{}`", uid, target);
|
||||
output.print(format!(
|
||||
|
@ -683,7 +683,8 @@ fn msg_matches_send<ImapService: ImapServiceInterface, SmtpService: SmtpServiceI
|
|||
|
||||
// add the message/msg to the Sent-Mailbox of the user
|
||||
msg.flags.insert(Flag::Seen);
|
||||
imap.append_msg("Sent", &mut msg)?;
|
||||
let mbox = Mbox::from("Sent");
|
||||
imap.append_msg(&mbox, &mut msg)?;
|
||||
|
||||
imap.logout()?;
|
||||
|
||||
|
@ -691,7 +692,7 @@ fn msg_matches_send<ImapService: ImapServiceInterface, SmtpService: SmtpServiceI
|
|||
}
|
||||
|
||||
fn msg_matches_save<ImapService: ImapServiceInterface>(
|
||||
mbox: &str,
|
||||
mbox: &Mbox,
|
||||
matches: &clap::ArgMatches,
|
||||
imap: &mut ImapService,
|
||||
) -> Result<bool> {
|
||||
|
@ -894,7 +895,8 @@ fn msg_interaction<ImapService: ImapServiceInterface, SmtpService: SmtpServiceIn
|
|||
|
||||
// let the server know, that the user sent a msg
|
||||
msg.flags.insert(Flag::Seen);
|
||||
imap.append_msg("Sent", msg)?;
|
||||
let mbox = Mbox::from("Sent");
|
||||
imap.append_msg(&mbox, msg)?;
|
||||
|
||||
// remove the draft, since we sent it
|
||||
input::remove_draft()?;
|
||||
|
@ -919,7 +921,8 @@ fn msg_interaction<ImapService: ImapServiceInterface, SmtpService: SmtpServiceIn
|
|||
|
||||
msg.flags.insert(Flag::Seen);
|
||||
|
||||
match imap.append_msg("Drafts", msg) {
|
||||
let mbox = Mbox::from("Drafts");
|
||||
match imap.append_msg(&mbox, msg) {
|
||||
Ok(_) => {
|
||||
input::remove_draft()?;
|
||||
output.print("Message successfully saved to Drafts")?;
|
||||
|
|
|
@ -7,6 +7,7 @@ use lettre::{
|
|||
},
|
||||
Transport,
|
||||
};
|
||||
use log::debug;
|
||||
|
||||
use crate::domain::account::entity::Account;
|
||||
|
||||
|
@ -20,13 +21,6 @@ pub struct SmtpService<'a> {
|
|||
}
|
||||
|
||||
impl<'a> SmtpService<'a> {
|
||||
pub fn new(account: &'a Account) -> Result<Self> {
|
||||
Ok(Self {
|
||||
account,
|
||||
transport: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn transport(&mut self) -> Result<&SmtpTransport> {
|
||||
if let Some(ref transport) = self.transport {
|
||||
Ok(transport)
|
||||
|
@ -66,3 +60,13 @@ impl<'a> SmtpServiceInterface for SmtpService<'a> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Account> for SmtpService<'a> {
|
||||
fn from(account: &'a Account) -> Self {
|
||||
debug!("init SMTP service");
|
||||
Self {
|
||||
account,
|
||||
transport: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
48
src/main.rs
48
src/main.rs
|
@ -1,8 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use clap;
|
||||
use env_logger;
|
||||
use log::{debug, trace};
|
||||
use std::{convert::TryFrom, env, path::PathBuf};
|
||||
use std::{convert::TryFrom, env};
|
||||
|
||||
use himalaya::{
|
||||
compl,
|
||||
|
@ -11,7 +10,8 @@ use himalaya::{
|
|||
account::entity::Account,
|
||||
config::entity::Config,
|
||||
imap::{self, service::ImapService},
|
||||
mbox, msg,
|
||||
mbox::{self, entity::Mbox},
|
||||
msg,
|
||||
smtp::service::SmtpService,
|
||||
},
|
||||
flag,
|
||||
|
@ -35,13 +35,13 @@ fn create_app<'a>() -> clap::App<'a, 'a> {
|
|||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
// Init env logger
|
||||
env_logger::init_from_env(
|
||||
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "off"),
|
||||
);
|
||||
|
||||
// TODO: put in a `mailto` module
|
||||
// let raw_args: Vec<String> = env::args().collect();
|
||||
|
||||
// // This is used if you click on a mailaddress in the webbrowser
|
||||
// if raw_args.len() > 1 && raw_args[1].starts_with("mailto:") {
|
||||
// let config = Config::new(None)?;
|
||||
// let account = config.find_account_by_name(None)?.clone();
|
||||
|
@ -59,41 +59,21 @@ fn main() -> Result<()> {
|
|||
|
||||
// Check shell completion BEFORE any entity or service initialization.
|
||||
if let Some(compl::arg::Match::Generate(shell)) = compl::arg::matches(&m)? {
|
||||
let app = create_app();
|
||||
compl::handler::generate(shell, app)?;
|
||||
return Ok(());
|
||||
return compl::handler::generate(shell, create_app());
|
||||
}
|
||||
|
||||
let output = OutputService::new(m.value_of("output").unwrap())?;
|
||||
let mbox = Mbox::try_from(m.value_of("mailbox"))?;
|
||||
let config = Config::try_from(m.value_of("config"))?;
|
||||
let account = Account::try_from((&config, m.value_of("account")))?;
|
||||
let output = OutputService::try_from(m.value_of("output"))?;
|
||||
let mut imap = ImapService::from((&account, &mbox));
|
||||
let mut smtp = SmtpService::from(&account);
|
||||
|
||||
debug!("init mbox");
|
||||
let mbox = m.value_of("mailbox").unwrap();
|
||||
debug!("mbox: {}", mbox);
|
||||
|
||||
let config_path: PathBuf = m
|
||||
.value_of("config")
|
||||
.map(|s| s.into())
|
||||
.unwrap_or(Config::path()?);
|
||||
debug!("init config from `{:?}`", config_path);
|
||||
let config = Config::try_from(config_path.clone())?;
|
||||
trace!("{:#?}", config);
|
||||
|
||||
let account_name = m.value_of("account");
|
||||
debug!("init account `{}`", account_name.unwrap_or("default"));
|
||||
let account = Account::try_from((&config, account_name))?;
|
||||
trace!("{:#?}", account);
|
||||
|
||||
debug!("init IMAP service");
|
||||
let mut imap = ImapService::new(&account, &mbox)?;
|
||||
|
||||
debug!("init SMTP service");
|
||||
let mut smtp = SmtpService::new(&account)?;
|
||||
|
||||
debug!("begin matching");
|
||||
// TODO: use same system as compl
|
||||
let _matched = mbox::cli::matches(&m, &output, &mut imap)?
|
||||
|| flag::cli::matches(&m, &mut imap)?
|
||||
|| imap::cli::matches(&m, &config, &mut imap)?
|
||||
|| msg::cli::matches(&m, mbox, &account, &output, &mut imap, &mut smtp)?;
|
||||
|| msg::cli::matches(&m, &mbox, &account, &output, &mut imap, &mut smtp)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use anyhow::{anyhow, Error, Result};
|
||||
use log::debug;
|
||||
use serde::Serialize;
|
||||
use std::{fmt, str::FromStr};
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
fmt,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum OutputFmt {
|
||||
|
@ -9,13 +12,15 @@ pub enum OutputFmt {
|
|||
Json,
|
||||
}
|
||||
|
||||
impl FromStr for OutputFmt {
|
||||
type Err = Error;
|
||||
fn from_str(slice: &str) -> Result<Self, Self::Err> {
|
||||
match slice {
|
||||
"JSON" | _ if slice.eq_ignore_ascii_case("json") => Ok(Self::Json),
|
||||
"PLAIN" | _ if slice.eq_ignore_ascii_case("plain") => Ok(Self::Plain),
|
||||
_ => Err(anyhow!("cannot parse output `{}`", slice)),
|
||||
impl TryFrom<Option<&str>> for OutputFmt {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(fmt: Option<&str>) -> Result<Self, Self::Error> {
|
||||
match fmt {
|
||||
Some(slice) if slice.eq_ignore_ascii_case("json") => Ok(Self::Json),
|
||||
Some(slice) if slice.eq_ignore_ascii_case("plain") => Ok(Self::Plain),
|
||||
None => Ok(Self::Plain),
|
||||
Some(slice) => Err(anyhow!("cannot parse output `{}`", slice)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,9 +60,7 @@ pub struct OutputService {
|
|||
impl OutputService {
|
||||
/// Create a new output-handler by setting the given formatting style.
|
||||
pub fn new(slice: &str) -> Result<Self> {
|
||||
debug!("init output service");
|
||||
debug!("output: {}", slice);
|
||||
let fmt = OutputFmt::from_str(slice)?;
|
||||
let fmt = OutputFmt::try_from(Some(slice))?;
|
||||
Ok(Self { fmt })
|
||||
}
|
||||
|
||||
|
@ -95,3 +98,14 @@ impl Default for OutputService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Option<&str>> for OutputService {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(fmt: Option<&str>) -> Result<Self, Self::Error> {
|
||||
debug!("init output service");
|
||||
debug!("output: `{:?}`", fmt);
|
||||
let fmt = fmt.try_into()?;
|
||||
Ok(Self { fmt })
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue