improve list msgs perf, remove flags column

This commit is contained in:
Clément DOUIN
2021-01-18 11:57:53 +01:00
parent d392d71129
commit 5e948b5cc1
8 changed files with 82 additions and 76 deletions
+1 -1
View File
@@ -167,7 +167,7 @@ impl Config {
Ok(toml::from_slice(&content)?)
}
pub fn get_account(&self, name: Option<&str>) -> Result<&Account> {
pub fn find_account_by_name(&self, name: Option<&str>) -> Result<&Account> {
match name {
Some(name) => self
.accounts
+4 -5
View File
@@ -88,8 +88,8 @@ impl<'a> ImapConnector<'a> {
Ok(Self { account, sess })
}
pub fn close(&mut self) {
match self.sess.close() {
pub fn logout(&mut self) {
match self.sess.logout() {
_ => (),
}
}
@@ -113,7 +113,7 @@ impl<'a> ImapConnector<'a> {
let msgs = self
.sess
.fetch(range, "(UID BODY.PEEK[])")?
.fetch(range, "(UID ENVELOPE INTERNALDATE)")?
.iter()
.rev()
.map(Msg::from)
@@ -143,9 +143,8 @@ impl<'a> ImapConnector<'a> {
let msgs = self
.sess
.fetch(range, "(UID BODY.PEEK[])")?
.fetch(range, "(UID ENVELOPE INTERNALDATE)")?
.iter()
.rev()
.map(Msg::from)
.collect::<Vec<_>>();
+17 -16
View File
@@ -221,19 +221,20 @@ fn run() -> Result<()> {
if let Some(_) = matches.subcommand_matches("mailboxes") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
let mut imap_conn = ImapConnector::new(&account)?;
let mboxes = imap_conn.list_mboxes()?;
print(&output_type, mboxes)?;
imap_conn.close();
imap_conn.logout();
}
if let Some(matches) = matches.subcommand_matches("list") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
let mut imap_conn = ImapConnector::new(&account)?;
let mbox = matches.value_of("mailbox").unwrap();
let page_size: u32 = matches
.value_of("size")
@@ -249,12 +250,12 @@ fn run() -> Result<()> {
let msgs = imap_conn.list_msgs(&mbox, &page_size, &page)?;
print(&output_type, msgs)?;
imap_conn.close();
imap_conn.logout();
}
if let Some(matches) = matches.subcommand_matches("search") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
let mut imap_conn = ImapConnector::new(&account)?;
let mbox = matches.value_of("mailbox").unwrap();
let page_size: usize = matches
@@ -295,12 +296,12 @@ fn run() -> Result<()> {
let msgs = imap_conn.search_msgs(&mbox, &query, &page_size, &page)?;
print(&output_type, msgs)?;
imap_conn.close();
imap_conn.logout();
}
if let Some(matches) = matches.subcommand_matches("read") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
let mut imap_conn = ImapConnector::new(&account)?;
let mbox = matches.value_of("mailbox").unwrap();
let uid = matches.value_of("uid").unwrap();
@@ -310,12 +311,12 @@ fn run() -> Result<()> {
let text_bodies = msg.text_bodies(&mime)?;
println!("{}", text_bodies);
imap_conn.close();
imap_conn.logout();
}
if let Some(matches) = matches.subcommand_matches("attachments") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
let mut imap_conn = ImapConnector::new(&account)?;
let mbox = matches.value_of("mailbox").unwrap();
let uid = matches.value_of("uid").unwrap();
@@ -334,12 +335,12 @@ fn run() -> Result<()> {
println!("Done!");
}
imap_conn.close();
imap_conn.logout();
}
if let Some(_) = matches.subcommand_matches("write") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
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())?;
@@ -352,12 +353,12 @@ fn run() -> Result<()> {
imap_conn.append_msg("Sent", &msg.to_vec()?)?;
println!("Done!");
imap_conn.close();
imap_conn.logout();
}
if let Some(matches) = matches.subcommand_matches("reply") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
let mut imap_conn = ImapConnector::new(&account)?;
let mbox = matches.value_of("mailbox").unwrap();
@@ -380,12 +381,12 @@ fn run() -> Result<()> {
imap_conn.append_msg("Sent", &msg.to_vec()?)?;
println!("Done!");
imap_conn.close();
imap_conn.logout();
}
if let Some(matches) = matches.subcommand_matches("forward") {
let config = Config::new_from_file()?;
let account = config.get_account(account_name)?;
let account = config.find_account_by_name(account_name)?;
let mut imap_conn = ImapConnector::new(&account)?;
let mbox = matches.value_of("mailbox").unwrap();
@@ -403,7 +404,7 @@ fn run() -> Result<()> {
imap_conn.append_msg("Sent", &msg.to_vec()?)?;
println!("Done!");
imap_conn.close();
imap_conn.logout();
}
Ok(())
+40 -46
View File
@@ -1,5 +1,6 @@
use lettre;
use mailparse::{self, MailHeaderMap};
use rfc2047_decoder;
use serde::Serialize;
use std::{fmt, result};
@@ -45,38 +46,54 @@ type Result<T> = result::Result<T, Error>;
#[derive(Debug, Serialize)]
pub struct Msg {
pub uid: u32,
pub flags: Vec<String>,
pub subject: String,
pub sender: String,
pub date: String,
#[serde(skip_serializing)]
raw: Vec<u8>,
}
impl From<String> for Msg {
fn from(item: String) -> Self {
impl From<Vec<u8>> for Msg {
fn from(raw: Vec<u8>) -> Self {
Self {
uid: 0,
flags: vec![],
raw: item.as_bytes().to_vec(),
subject: String::from(""),
sender: String::from(""),
date: String::from(""),
raw,
}
}
}
impl From<Vec<u8>> for Msg {
fn from(item: Vec<u8>) -> Self {
Self {
uid: 0,
flags: vec![],
raw: item,
}
impl From<String> for Msg {
fn from(raw: String) -> Self {
Self::from(raw.as_bytes().to_vec())
}
}
impl From<&imap::types::Fetch> for Msg {
fn from(fetch: &imap::types::Fetch) -> Self {
Self {
uid: fetch.uid.unwrap_or_default(),
flags: vec![],
raw: fetch.body().unwrap_or_default().to_vec(),
match fetch.envelope() {
None => Self::from(fetch.body().unwrap_or_default().to_vec()),
Some(envelope) => Self {
uid: fetch.uid.unwrap_or_default(),
subject: envelope
.subject
.and_then(|subj| rfc2047_decoder::decode(subj).ok())
.unwrap_or_default(),
sender: envelope
.from
.as_ref()
.and_then(|addrs| addrs.first()?.name)
.and_then(|name| rfc2047_decoder::decode(name).ok())
.unwrap_or_default(),
date: fetch
.internal_date()
.map(|date| date.naive_local().to_string())
.unwrap_or_default(),
raw: fetch.body().unwrap_or_default().to_vec(),
},
}
}
}
@@ -376,36 +393,14 @@ impl<'a> Msg {
impl DisplayRow for Msg {
fn to_row(&self) -> Vec<table::Cell> {
match self.parse() {
Err(_) => vec![],
Ok(parsed) => {
let headers = parsed.get_headers();
use crate::table::*;
let uid = &self.uid.to_string();
let flags = match self.extract_attachments().map(|vec| vec.is_empty()) {
Ok(false) => "",
_ => " ",
};
let sender = headers
.get_first_value("reply-to")
.or(headers.get_first_value("from"))
.unwrap_or_default();
let subject = headers.get_first_value("subject").unwrap_or_default();
let date = headers.get_first_value("date").unwrap_or_default();
{
use crate::table::*;
vec![
Cell::new(&[RED], &uid),
Cell::new(&[WHITE], &flags),
Cell::new(&[BLUE], &sender),
FlexCell::new(&[GREEN], &subject),
Cell::new(&[YELLOW], &date),
]
}
}
}
vec![
Cell::new(&[RED], &self.uid.to_string()),
Cell::new(&[BLUE], &self.sender),
FlexCell::new(&[GREEN], &self.subject),
Cell::new(&[YELLOW], &self.date),
]
}
}
@@ -420,7 +415,6 @@ impl<'a> DisplayTable<'a, Msg> for Msgs {
vec![
Cell::new(&[BOLD, UNDERLINE, WHITE], "UID"),
Cell::new(&[BOLD, UNDERLINE, WHITE], "FLAGS"),
Cell::new(&[BOLD, UNDERLINE, WHITE], "SENDER"),
FlexCell::new(&[BOLD, UNDERLINE, WHITE], "SUBJECT"),
Cell::new(&[BOLD, UNDERLINE, WHITE], "DATE"),
+3
View File
@@ -42,6 +42,9 @@ type Result<T> = result::Result<T, Error>;
pub fn send(account: &Account, msg: &lettre::Message) -> Result<()> {
use lettre::Transport;
// TODO
// lettre::transport::smtp::SmtpTransport::starttls_relay
lettre::transport::smtp::SmtpTransport::relay(&account.smtp_host)?
.credentials(account.smtp_creds()?)
.build()
+4 -8
View File
@@ -60,15 +60,11 @@ impl Cell {
let style_end = "\x1b[0m";
if col_size > 0 && self.printable_value_len() > col_size {
let col_size = self
.value
.char_indices()
.map(|(i, _)| i)
.nth(col_size)
.unwrap()
- 2;
let value: String = self.value.chars().collect::<Vec<_>>()[0..=col_size - 2]
.into_iter()
.collect();
String::from(style_begin + &self.value[0..=col_size] + "" + style_end)
String::from(style_begin + &value + "" + style_end)
} else {
let padding = if col_size == 0 {
"".to_string()