Show messages in rev chrono order
This commit is contained in:
parent
f2a6149294
commit
49ae811259
|
@ -151,9 +151,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "buzz"
|
name = "buzz"
|
||||||
version = "1.1.3"
|
version = "1.1.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama_escape 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"askama_escape 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"imap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"imap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mailparse 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mailparse 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "buzz"
|
name = "buzz"
|
||||||
version = "1.1.3"
|
version = "1.1.4"
|
||||||
|
|
||||||
description = "A simple system tray application for notifying about unseen e-mail"
|
description = "A simple system tray application for notifying about unseen e-mail"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -31,3 +31,4 @@ xdg = "2.1.0"
|
||||||
notify-rust = "3.4.0"
|
notify-rust = "3.4.0"
|
||||||
rayon = "1.0.0"
|
rayon = "1.0.0"
|
||||||
askama_escape = "0.1"
|
askama_escape = "0.1"
|
||||||
|
chrono = "0.4"
|
||||||
|
|
51
src/main.rs
51
src/main.rs
|
@ -1,4 +1,5 @@
|
||||||
extern crate askama_escape;
|
extern crate askama_escape;
|
||||||
|
extern crate chrono;
|
||||||
extern crate imap;
|
extern crate imap;
|
||||||
extern crate mailparse;
|
extern crate mailparse;
|
||||||
extern crate native_tls;
|
extern crate native_tls;
|
||||||
|
@ -11,6 +12,8 @@ extern crate xdg;
|
||||||
use native_tls::{TlsConnector, TlsStream};
|
use native_tls::{TlsConnector, TlsStream};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
@ -105,7 +108,7 @@ impl<T: Read + Write + imap::extensions::idle::SetReadTimeout> Connection<T> {
|
||||||
}
|
}
|
||||||
let uids: Vec<_> = uids.into_iter().map(|v: u32| format!("{}", v)).collect();
|
let uids: Vec<_> = uids.into_iter().map(|v: u32| format!("{}", v)).collect();
|
||||||
|
|
||||||
let mut subjects = Vec::new();
|
let mut subjects = BTreeMap::new();
|
||||||
if !uids.is_empty() {
|
if !uids.is_empty() {
|
||||||
for msg in self
|
for msg in self
|
||||||
.socket
|
.socket
|
||||||
|
@ -120,17 +123,34 @@ impl<T: Read + Write + imap::extensions::idle::SetReadTimeout> Connection<T> {
|
||||||
match mailparse::parse_headers(msg.unwrap()) {
|
match mailparse::parse_headers(msg.unwrap()) {
|
||||||
Ok((headers, _)) => {
|
Ok((headers, _)) => {
|
||||||
use mailparse::MailHeaderMap;
|
use mailparse::MailHeaderMap;
|
||||||
match headers.get_first_value("Subject") {
|
|
||||||
Ok(Some(subject)) => {
|
let subject = match headers.get_first_value("Subject") {
|
||||||
subjects.push(subject);
|
Ok(Some(subject)) => Cow::from(subject),
|
||||||
}
|
Ok(None) => Cow::from("<no subject>"),
|
||||||
Ok(None) => {
|
|
||||||
subjects.push(String::from("<no subject>"));
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("failed to get message subject: {:?}", e);
|
println!("failed to get message subject: {:?}", e);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let date = match headers.get_first_value("Date") {
|
||||||
|
Ok(Some(date)) => {
|
||||||
|
match chrono::DateTime::parse_from_rfc2822(&date) {
|
||||||
|
Ok(date) => date.with_timezone(&chrono::Local),
|
||||||
|
Err(e) => {
|
||||||
|
println!("failed to parse message date: {:?}", e);
|
||||||
|
chrono::Local::now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None) => chrono::Local::now(),
|
||||||
|
Err(e) => {
|
||||||
|
println!("failed to get message date: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
subjects.insert(date, subject);
|
||||||
}
|
}
|
||||||
Err(e) => println!("failed to parse headers of message: {:?}", e),
|
Err(e) => println!("failed to parse headers of message: {:?}", e),
|
||||||
}
|
}
|
||||||
|
@ -143,12 +163,21 @@ impl<T: Read + Write + imap::extensions::idle::SetReadTimeout> Connection<T> {
|
||||||
"@{} has new mail ({} unseen)",
|
"@{} has new mail ({} unseen)",
|
||||||
self.account.name, num_unseen
|
self.account.name, num_unseen
|
||||||
);
|
);
|
||||||
let notification = format!("> {}", subjects.join("\n> "));
|
|
||||||
|
// we want the n newest e-mail in reverse chronological order
|
||||||
|
let mut notification = String::new();
|
||||||
|
for subject in subjects.values().rev() {
|
||||||
|
notification.push_str("> ");
|
||||||
|
notification.push_str(subject);
|
||||||
|
notification.push_str("\n");
|
||||||
|
}
|
||||||
|
let notification = notification.trim_end();
|
||||||
|
|
||||||
println!("! {}", title);
|
println!("! {}", title);
|
||||||
println!("{}", notification);
|
println!("{}", notification);
|
||||||
Notification::new()
|
Notification::new()
|
||||||
.summary(&title)
|
.summary(&title)
|
||||||
.body(&format!("{}", askama_escape::escape(¬ification)))
|
.body(&format!("{}", askama_escape::escape(notification)))
|
||||||
.icon("notification-message-email")
|
.icon("notification-message-email")
|
||||||
.hint(NotificationHint::Category("email".to_owned()))
|
.hint(NotificationHint::Category("email".to_owned()))
|
||||||
.timeout(-1)
|
.timeout(-1)
|
||||||
|
|
Loading…
Reference in New Issue