mirror of
https://github.com/soywod/himalaya.git
synced 2024-07-08 18:45:13 +00:00
introduce read_headers in account config (#338)
This commit is contained in:
parent
d3968461e2
commit
f9bed5f3c2
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
|
||||
- SMTP pre-send hook [#178]
|
||||
- Customize headers to show at the top of a read message [#338]
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -503,3 +504,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
[#329]: https://github.com/soywod/himalaya/issues/329
|
||||
[#331]: https://github.com/soywod/himalaya/issues/331
|
||||
[#335]: https://github.com/soywod/himalaya/issues/335
|
||||
[#338]: https://github.com/soywod/himalaya/issues/338
|
||||
|
|
|
@ -32,6 +32,9 @@ pub struct AccountConfig {
|
|||
/// Represents the text/plain format as defined in the
|
||||
/// [RFC2646](https://www.ietf.org/rfc/rfc2646.txt)
|
||||
pub format: Format,
|
||||
/// Overrides the default headers displayed at the top of
|
||||
/// the read message.
|
||||
pub read_headers: Vec<String>,
|
||||
|
||||
/// Represents mailbox aliases.
|
||||
pub mailboxes: HashMap<String, String>,
|
||||
|
@ -157,6 +160,7 @@ impl<'a> AccountConfig {
|
|||
.unwrap_or(&vec![])
|
||||
.to_owned(),
|
||||
format: base_account.format.unwrap_or_default(),
|
||||
read_headers: base_account.read_headers,
|
||||
mailboxes: base_account.mailboxes.clone(),
|
||||
hooks: base_account.hooks.unwrap_or_default(),
|
||||
default: base_account.default.unwrap_or_default(),
|
||||
|
|
|
@ -56,6 +56,10 @@ macro_rules! make_account_config {
|
|||
/// Represents the text/plain format as defined in the
|
||||
/// [RFC2646](https://www.ietf.org/rfc/rfc2646.txt)
|
||||
pub format: Option<Format>,
|
||||
/// Overrides the default headers displayed at the top of
|
||||
/// the read message.
|
||||
#[serde(default)]
|
||||
pub read_headers: Vec<String>,
|
||||
|
||||
/// Makes this account the default one.
|
||||
pub default: Option<bool>,
|
||||
|
@ -102,6 +106,7 @@ macro_rules! make_account_config {
|
|||
notify_query: self.notify_query.clone(),
|
||||
watch_cmds: self.watch_cmds.clone(),
|
||||
format: self.format.clone(),
|
||||
read_headers: self.read_headers.clone(),
|
||||
|
||||
default: self.default.clone(),
|
||||
email: self.email.clone(),
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -222,7 +222,16 @@ fn main() -> Result<()> {
|
|||
return msg_handlers::move_(seq, mbox, mbox_dst, &mut printer, backend);
|
||||
}
|
||||
Some(msg_args::Cmd::Read(seq, text_mime, raw, headers)) => {
|
||||
return msg_handlers::read(seq, text_mime, raw, headers, mbox, &mut printer, backend);
|
||||
return msg_handlers::read(
|
||||
seq,
|
||||
text_mime,
|
||||
raw,
|
||||
headers,
|
||||
mbox,
|
||||
&account_config,
|
||||
&mut printer,
|
||||
backend,
|
||||
);
|
||||
}
|
||||
Some(msg_args::Cmd::Reply(seq, all, attachment_paths, encrypt)) => {
|
||||
return msg_handlers::reply(
|
||||
|
|
|
@ -729,11 +729,29 @@ impl Msg {
|
|||
/// message is like a template, except that:
|
||||
/// - headers part is customizable (can be omitted if empty filter given in argument)
|
||||
/// - body type is customizable (plain or html)
|
||||
pub fn to_readable_string(&self, text_mime: &str, headers: Vec<&str>) -> Result<String> {
|
||||
let mut readable_msg = String::new();
|
||||
pub fn to_readable_string(
|
||||
&self,
|
||||
text_mime: &str,
|
||||
headers: Vec<&str>,
|
||||
config: &AccountConfig,
|
||||
) -> Result<String> {
|
||||
let mut all_headers = vec![];
|
||||
for h in config.read_headers.iter() {
|
||||
let h = h.to_lowercase();
|
||||
if !all_headers.contains(&h) {
|
||||
all_headers.push(h)
|
||||
}
|
||||
}
|
||||
for h in headers.iter() {
|
||||
let h = h.to_lowercase();
|
||||
if !all_headers.contains(&h) {
|
||||
all_headers.push(h)
|
||||
}
|
||||
}
|
||||
|
||||
for h in headers {
|
||||
match h.to_lowercase().as_str() {
|
||||
let mut readable_msg = String::new();
|
||||
for h in all_headers {
|
||||
match h.as_str() {
|
||||
"message-id" => match self.message_id {
|
||||
Some(ref message_id) if !message_id.is_empty() => {
|
||||
readable_msg.push_str(&format!("Message-Id: {}\n", message_id));
|
||||
|
@ -833,9 +851,8 @@ impl TryInto<lettre::address::Envelope> for &Msg {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use mailparse::SingleInfo;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use crate::msg::Addr;
|
||||
|
||||
|
@ -982,6 +999,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_to_readable() {
|
||||
let config = AccountConfig::default();
|
||||
let msg = Msg {
|
||||
parts: Parts(vec![Part::TextPlain(TextPlainPart {
|
||||
content: String::from("hello, world!"),
|
||||
|
@ -989,21 +1007,22 @@ mod tests {
|
|||
..Msg::default()
|
||||
};
|
||||
|
||||
// empty msg, empty headers
|
||||
// empty msg headers, empty headers, empty config
|
||||
assert_eq!(
|
||||
"hello, world!",
|
||||
msg.to_readable_string("plain", vec![]).unwrap()
|
||||
msg.to_readable_string("plain", vec![], &config).unwrap()
|
||||
);
|
||||
// empty msg, basic headers
|
||||
// empty msg headers, basic headers
|
||||
assert_eq!(
|
||||
"hello, world!",
|
||||
msg.to_readable_string("plain", vec!["from", "date", "custom-header"])
|
||||
msg.to_readable_string("plain", vec!["From", "DATE", "custom-hEader"], &config)
|
||||
.unwrap()
|
||||
);
|
||||
// empty msg, subject header
|
||||
// empty msg headers, multiple subject headers
|
||||
assert_eq!(
|
||||
"Subject: \n\nhello, world!",
|
||||
msg.to_readable_string("plain", vec!["subject"]).unwrap()
|
||||
msg.to_readable_string("plain", vec!["subject", "Subject", "SUBJECT"], &config)
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
let msg = Msg {
|
||||
|
@ -1023,26 +1042,39 @@ mod tests {
|
|||
..Msg::default()
|
||||
};
|
||||
|
||||
// header present in msg headers
|
||||
// header present in msg headers, empty config
|
||||
assert_eq!(
|
||||
"From: \"Test\" <test@local>\n\nhello, world!",
|
||||
msg.to_readable_string("plain", vec!["from"]).unwrap()
|
||||
);
|
||||
// header present but empty in msg headers
|
||||
assert_eq!(
|
||||
"hello, world!",
|
||||
msg.to_readable_string("plain", vec!["cc"]).unwrap()
|
||||
);
|
||||
// custom header present in msg headers
|
||||
assert_eq!(
|
||||
"Custom-Header: custom value\n\nhello, world!",
|
||||
msg.to_readable_string("plain", vec!["custom-header"])
|
||||
msg.to_readable_string("plain", vec!["from"], &config)
|
||||
.unwrap()
|
||||
);
|
||||
// custom header present in msg headers (case insensitivity)
|
||||
// header present but empty in msg headers, empty config
|
||||
assert_eq!(
|
||||
"hello, world!",
|
||||
msg.to_readable_string("plain", vec!["cc"], &config)
|
||||
.unwrap()
|
||||
);
|
||||
// multiple same custom headers present in msg headers, empty
|
||||
// config
|
||||
assert_eq!(
|
||||
"Custom-Header: custom value\n\nhello, world!",
|
||||
msg.to_readable_string("plain", vec!["CUSTOM-hEaDer"])
|
||||
msg.to_readable_string("plain", vec!["custom-header", "cuSTom-HeaDer"], &config)
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
let config = AccountConfig {
|
||||
read_headers: vec![
|
||||
"CusTOM-heaDER".into(),
|
||||
"Subject".into(),
|
||||
"from".into(),
|
||||
"cc".into(),
|
||||
],
|
||||
..AccountConfig::default()
|
||||
};
|
||||
// header present but empty in msg headers, empty config
|
||||
assert_eq!(
|
||||
"Custom-Header: custom value\nSubject: \nFrom: \"Test\" <test@local>\nMessage-Id: <message-id>\n\nhello, world!",
|
||||
msg.to_readable_string("plain", vec!["cc", "message-ID"], &config)
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -209,6 +209,7 @@ pub fn read<'a, P: PrinterService, B: Backend<'a> + ?Sized>(
|
|||
raw: bool,
|
||||
headers: Vec<&str>,
|
||||
mbox: &str,
|
||||
config: &AccountConfig,
|
||||
printer: &mut P,
|
||||
backend: Box<&'a mut B>,
|
||||
) -> Result<()> {
|
||||
|
@ -218,7 +219,7 @@ pub fn read<'a, P: PrinterService, B: Backend<'a> + ?Sized>(
|
|||
// Emails don't always have valid utf8. Using "lossy" to display what we can.
|
||||
String::from_utf8_lossy(&msg.raw).into_owned()
|
||||
} else {
|
||||
msg.to_readable_string(text_mime, headers)?
|
||||
msg.to_readable_string(text_mime, headers, config)?
|
||||
})
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue