take passwds from command instead of clear

This commit is contained in:
Clément DOUIN
2021-01-17 11:52:31 +01:00
parent 84df58cf81
commit 34189ad8ad
6 changed files with 76 additions and 27 deletions
+2
View File
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- List command with pagination [#19]
- Icon in table when attachment is present [#16]
- Multi-account [#17]
- Password from command [#22]
[unreleased]: https://github.com/soywod/himalaya
@@ -45,3 +46,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#17]: https://github.com/soywod/himalaya/issues/17
[#19]: https://github.com/soywod/himalaya/issues/19
[#21]: https://github.com/soywod/himalaya/issues/21
[#22]: https://github.com/soywod/himalaya/issues/22
+28 -7
View File
@@ -10,6 +10,8 @@ use std::{
};
use toml;
use crate::io::run_cmd;
// Error wrapper
#[derive(Debug)]
@@ -21,11 +23,14 @@ pub enum Error {
GetPathNotFoundError,
GetAccountNotFoundError(String),
GetAccountDefaultNotFoundError,
ParseImapPasswdUtf8Error,
ParseSmtpPasswdUtf8Error,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(config): ")?;
write!(f, "config: ")?;
match self {
Error::IoError(err) => err.fmt(f),
Error::ParseTomlError(err) => err.fmt(f),
@@ -34,6 +39,8 @@ impl fmt::Display for Error {
Error::GetPathNotFoundError => write!(f, "path not found"),
Error::GetAccountNotFoundError(account) => write!(f, "account {} not found", account),
Error::GetAccountDefaultNotFoundError => write!(f, "no default account found"),
Error::ParseImapPasswdUtf8Error => write!(f, "imap passwd invalid utf8"),
Error::ParseSmtpPasswdUtf8Error => write!(f, "smtp passwd invalid utf8"),
}
}
}
@@ -75,21 +82,35 @@ pub struct Account {
pub imap_host: String,
pub imap_port: u16,
pub imap_login: String,
pub imap_password: String,
pub imap_passwd_cmd: String,
pub smtp_host: String,
pub smtp_port: u16,
pub smtp_login: String,
pub smtp_password: String,
pub smtp_passwd_cmd: String,
}
impl Account {
pub fn imap_addr(&self) -> (&str, u16) {
(&self.imap_host, self.imap_port)
pub fn imap_passwd(&self) -> Result<String> {
let cmd = run_cmd(&self.imap_passwd_cmd)?;
let passwd = String::from_utf8(cmd.stdout);
let passwd = passwd.map_err(|_| Error::ParseImapPasswdUtf8Error)?;
let passwd = passwd.trim_end_matches("\n").to_owned();
Ok(passwd)
}
pub fn smtp_creds(&self) -> SmtpCredentials {
SmtpCredentials::new(self.smtp_login.to_owned(), self.smtp_password.to_owned())
pub fn smtp_creds(&self) -> Result<SmtpCredentials> {
let cmd = run_cmd(&self.smtp_passwd_cmd)?;
let passwd = String::from_utf8(cmd.stdout);
let passwd = passwd.map_err(|_| Error::ParseImapPasswdUtf8Error)?;
let passwd = passwd.trim_end_matches("\n").to_owned();
Ok(SmtpCredentials::new(self.smtp_login.to_owned(), passwd))
}
pub fn imap_addr(&self) -> (&str, u16) {
(&self.imap_host, self.imap_port)
}
}
+12 -3
View File
@@ -2,7 +2,7 @@ use imap;
use native_tls::{self, TlsConnector, TlsStream};
use std::{fmt, net::TcpStream, result};
use crate::config::Account;
use crate::config::{self, Account};
use crate::mbox::Mbox;
use crate::msg::Msg;
@@ -16,15 +16,18 @@ pub enum Error {
ReadEmailNotFoundError(String),
ReadEmailEmptyPartError(String, String),
ExtractAttachmentsEmptyError(String),
ConfigError(config::Error),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(imap): ")?;
write!(f, "imap: ")?;
match self {
Error::CreateTlsConnectorError(err) => err.fmt(f),
Error::CreateImapSession(err) => err.fmt(f),
Error::ParseEmailError(err) => err.fmt(f),
Error::ConfigError(err) => err.fmt(f),
Error::ReadEmailNotFoundError(uid) => {
write!(f, "no email found for uid {}", uid)
}
@@ -56,6 +59,12 @@ impl From<mailparse::MailParseError> for Error {
}
}
impl From<config::Error> for Error {
fn from(err: config::Error) -> Error {
Error::ConfigError(err)
}
}
// Result wrapper
type Result<T> = result::Result<T, Error>;
@@ -73,7 +82,7 @@ impl<'a> ImapConnector<'a> {
let tls = TlsConnector::new()?;
let client = imap::connect(account.imap_addr(), &account.imap_host, &tls)?;
let sess = client
.login(&account.imap_login, &account.imap_password)
.login(&account.imap_login, &account.imap_passwd()?)
.map_err(|res| res.0)?;
Ok(Self { account, sess })
+11 -2
View File
@@ -3,7 +3,7 @@ use std::{
fmt,
fs::{remove_file, File},
io::{self, Read, Write},
process::Command,
process::{Command, Output},
result,
};
@@ -17,7 +17,8 @@ pub enum Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(input): ")?;
write!(f, "input: ")?;
match self {
Error::IoError(err) => err.fmt(f),
Error::AskForSendingConfirmationError => write!(f, "action cancelled"),
@@ -68,3 +69,11 @@ pub fn ask_for_confirmation(prompt: &str) -> Result<()> {
_ => Err(Error::AskForSendingConfirmationError),
}
}
pub fn run_cmd(cmd: &str) -> io::Result<Output> {
if cfg!(target_os = "windows") {
Command::new("cmd").args(&["/C", cmd]).output()
} else {
Command::new("sh").arg("-c").arg(cmd).output()
}
}
+13 -13
View File
@@ -1,6 +1,6 @@
mod config;
mod imap;
mod input;
mod io;
mod mbox;
mod msg;
mod smtp;
@@ -20,7 +20,7 @@ const DEFAULT_PAGE: usize = 0;
#[derive(Debug)]
pub enum Error {
ConfigError(config::Error),
InputError(input::Error),
IoError(io::Error),
MsgError(msg::Error),
ImapError(imap::Error),
SmtpError(smtp::Error),
@@ -30,7 +30,7 @@ impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::ConfigError(err) => err.fmt(f),
Error::InputError(err) => err.fmt(f),
Error::IoError(err) => err.fmt(f),
Error::MsgError(err) => err.fmt(f),
Error::ImapError(err) => err.fmt(f),
Error::SmtpError(err) => err.fmt(f),
@@ -44,9 +44,9 @@ impl From<config::Error> for Error {
}
}
impl From<input::Error> for Error {
fn from(err: input::Error) -> Error {
Error::InputError(err)
impl From<crate::io::Error> for Error {
fn from(err: crate::io::Error) -> Error {
Error::IoError(err)
}
}
@@ -329,10 +329,10 @@ fn run() -> Result<()> {
let mut imap_conn = ImapConnector::new(&account)?;
let tpl = Msg::build_new_tpl(&config, &account)?;
let content = input::open_editor_with_tpl(&tpl.as_bytes())?;
let content = io::open_editor_with_tpl(&tpl.as_bytes())?;
let msg = Msg::from(content);
input::ask_for_confirmation("Send the message?")?;
io::ask_for_confirmation("Send the message?")?;
println!("Sending …");
smtp::send(&account, &msg.to_sendable_msg()?)?;
@@ -357,10 +357,10 @@ fn run() -> Result<()> {
msg.build_reply_tpl(&config, &account)?
};
let content = input::open_editor_with_tpl(&tpl.as_bytes())?;
let content = io::open_editor_with_tpl(&tpl.as_bytes())?;
let msg = Msg::from(content);
input::ask_for_confirmation("Send the message?")?;
io::ask_for_confirmation("Send the message?")?;
println!("Sending …");
smtp::send(&account, &msg.to_sendable_msg()?)?;
@@ -380,10 +380,10 @@ fn run() -> Result<()> {
let msg = Msg::from(imap_conn.read_msg(&mbox, &uid)?);
let tpl = msg.build_forward_tpl(&config, &account)?;
let content = input::open_editor_with_tpl(&tpl.as_bytes())?;
let content = io::open_editor_with_tpl(&tpl.as_bytes())?;
let msg = Msg::from(content);
input::ask_for_confirmation("Send the message?")?;
io::ask_for_confirmation("Send the message?")?;
println!("Sending …");
smtp::send(&account, &msg.to_sendable_msg()?)?;
@@ -400,7 +400,7 @@ fn run() -> Result<()> {
fn main() {
if let Err(err) = run() {
eprintln!("Error {}", err);
eprintln!("Error: {}", err);
exit(1);
}
}
+10 -2
View File
@@ -1,13 +1,14 @@
use lettre;
use std::{fmt, result};
use crate::config::Account;
use crate::config::{self, Account};
// Error wrapper
#[derive(Debug)]
pub enum Error {
TransportError(lettre::transport::smtp::Error),
ConfigError(config::Error),
}
impl fmt::Display for Error {
@@ -15,6 +16,7 @@ impl fmt::Display for Error {
write!(f, "(smtp): ")?;
match self {
Error::TransportError(err) => err.fmt(f),
Error::ConfigError(err) => err.fmt(f),
}
}
}
@@ -25,6 +27,12 @@ impl From<lettre::transport::smtp::Error> for Error {
}
}
impl From<config::Error> for Error {
fn from(err: config::Error) -> Error {
Error::ConfigError(err)
}
}
// Result wrapper
type Result<T> = result::Result<T, Error>;
@@ -35,7 +43,7 @@ pub fn send(account: &Account, msg: &lettre::Message) -> Result<()> {
use lettre::Transport;
lettre::transport::smtp::SmtpTransport::relay(&account.smtp_host)?
.credentials(account.smtp_creds())
.credentials(account.smtp_creds()?)
.build()
.send(msg)
.map(|_| Ok(()))?