mirror of
https://github.com/soywod/himalaya.git
synced 2024-07-05 09:05:13 +00:00
improve signature and template management (#114)
* Added signature seperator option plus some refactoring * Have add_content make newline seperation to headers * Remove signature separator as a separate argument
This commit is contained in:
parent
28812eab06
commit
6284b0c5a6
|
@ -39,7 +39,10 @@ methods.*
|
||||||
|
|
||||||
name = "Your full name"
|
name = "Your full name"
|
||||||
downloads-dir = "/abs/path/to/downloads"
|
downloads-dir = "/abs/path/to/downloads"
|
||||||
signature = "Regards,"
|
signature = """
|
||||||
|
--
|
||||||
|
Regards,
|
||||||
|
"""
|
||||||
|
|
||||||
[gmail]
|
[gmail]
|
||||||
default = true
|
default = true
|
||||||
|
|
226
src/msg/model.rs
226
src/msg/model.rs
|
@ -363,105 +363,47 @@ impl<'m> Msg<'m> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_new_tpl(config: &Config, account: &Account) -> Result<Tpl> {
|
pub fn build_new_tpl(config: &Config, account: &Account) -> Result<Tpl> {
|
||||||
let mut tpl = vec![];
|
let msg_spec = MsgSpec{
|
||||||
|
in_reply_to: None,
|
||||||
// "Content" headers
|
to: None,
|
||||||
tpl.push("Content-Type: text/plain; charset=utf-8".to_string());
|
cc: None,
|
||||||
tpl.push("Content-Transfer-Encoding: 8bit".to_string());
|
subject: None,
|
||||||
|
default_content: None,
|
||||||
// "From" header
|
};
|
||||||
tpl.push(format!("From: {}", config.address(account)));
|
Msg::build_tpl(config, account, msg_spec)
|
||||||
|
|
||||||
// "To" header
|
|
||||||
tpl.push("To: ".to_string());
|
|
||||||
|
|
||||||
// "Subject" header
|
|
||||||
tpl.push("Subject: ".to_string());
|
|
||||||
|
|
||||||
// Separator between headers and body
|
|
||||||
tpl.push(String::new());
|
|
||||||
|
|
||||||
// Signature
|
|
||||||
if let Some(sig) = config.signature(&account) {
|
|
||||||
tpl.push(String::new());
|
|
||||||
tpl.push("--".to_string());
|
|
||||||
for line in sig.split("\n") {
|
|
||||||
tpl.push(line.to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Tpl(tpl.join("\r\n")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_reply_tpl(&self, config: &Config, account: &Account) -> Result<Tpl> {
|
pub fn build_reply_tpl(&self, config: &Config, account: &Account) -> Result<Tpl> {
|
||||||
let msg = &self.parse()?;
|
let msg = &self.parse()?;
|
||||||
let headers = msg.get_headers();
|
let headers = msg.get_headers();
|
||||||
let mut tpl = vec![];
|
|
||||||
|
|
||||||
// "Content" headers
|
|
||||||
tpl.push("Content-Type: text/plain; charset=utf-8".to_string());
|
|
||||||
tpl.push("Content-Transfer-Encoding: 8bit".to_string());
|
|
||||||
|
|
||||||
// "From" header
|
|
||||||
tpl.push(format!("From: {}", config.address(account)));
|
|
||||||
|
|
||||||
// "In-Reply-To" header
|
|
||||||
if let Some(msg_id) = headers.get_first_value("message-id") {
|
|
||||||
tpl.push(format!("In-Reply-To: {}", msg_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// "To" header
|
|
||||||
let to = headers
|
let to = headers
|
||||||
.get_first_value("reply-to")
|
.get_first_value("reply-to")
|
||||||
.or(headers.get_first_value("from"))
|
.or(headers.get_first_value("from"));
|
||||||
.unwrap_or(String::new());
|
let to = match to {
|
||||||
tpl.push(format!("To: {}", to));
|
Some(t) => {Some(vec![t])},
|
||||||
|
None => {None},
|
||||||
|
};
|
||||||
|
|
||||||
// "Subject" header
|
let thread = self // Original msg prepend with ">"
|
||||||
let subject = headers.get_first_value("subject").unwrap_or(String::new());
|
|
||||||
tpl.push(format!("Subject: Re: {}", subject));
|
|
||||||
|
|
||||||
// Separator between headers and body
|
|
||||||
tpl.push(String::new());
|
|
||||||
|
|
||||||
// Original msg prepend with ">"
|
|
||||||
let thread = self
|
|
||||||
.text_bodies("text/plain")?
|
.text_bodies("text/plain")?
|
||||||
.replace("\r", "")
|
.replace("\r", "")
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.map(|line| format!(">{}", line))
|
.map(|line| format!(">{}", line))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>();
|
||||||
.join("\r\n");
|
|
||||||
tpl.push(thread);
|
|
||||||
|
|
||||||
// Signature
|
let msg_spec = MsgSpec{
|
||||||
if let Some(sig) = config.signature(&account) {
|
in_reply_to: headers.get_first_value("message-id"),
|
||||||
tpl.push(String::new());
|
to,
|
||||||
tpl.push("--".to_string());
|
cc: None,
|
||||||
for line in sig.split("\n") {
|
subject: headers.get_first_value("subject"),
|
||||||
tpl.push(line.to_string());
|
default_content: Some(thread),
|
||||||
}
|
};
|
||||||
}
|
Msg::build_tpl(config, account, msg_spec)
|
||||||
|
|
||||||
Ok(Tpl(tpl.join("\r\n")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_reply_all_tpl(&self, config: &Config, account: &Account) -> Result<Tpl> {
|
pub fn build_reply_all_tpl(&self, config: &Config, account: &Account) -> Result<Tpl> {
|
||||||
let msg = &self.parse()?;
|
let msg = &self.parse()?;
|
||||||
let headers = msg.get_headers();
|
let headers = msg.get_headers();
|
||||||
let mut tpl = vec![];
|
|
||||||
|
|
||||||
// "Content" headers
|
|
||||||
tpl.push("Content-Type: text/plain; charset=utf-8".to_string());
|
|
||||||
tpl.push("Content-Transfer-Encoding: 8bit".to_string());
|
|
||||||
|
|
||||||
// "From" header
|
|
||||||
tpl.push(format!("From: {}", config.address(account)));
|
|
||||||
|
|
||||||
// "In-Reply-To" header
|
|
||||||
if let Some(msg_id) = headers.get_first_value("message-id") {
|
|
||||||
tpl.push(format!("In-Reply-To: {}", msg_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// "To" header
|
// "To" header
|
||||||
// All addresses coming from original "To" …
|
// All addresses coming from original "To" …
|
||||||
|
@ -499,86 +441,122 @@ impl<'m> Msg<'m> {
|
||||||
} else {
|
} else {
|
||||||
reply_to
|
reply_to
|
||||||
};
|
};
|
||||||
tpl.push(format!("To: {}", vec![reply_to, to].concat().join(", ")));
|
|
||||||
|
|
||||||
// "Cc" header
|
// "Cc" header
|
||||||
let cc = headers
|
let cc = Some(headers
|
||||||
.get_all_values("cc")
|
.get_all_values("cc")
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|addrs| addrs.split(","))
|
.flat_map(|addrs| addrs.split(","))
|
||||||
.map(|addr| addr.trim().to_string())
|
.map(|addr| addr.trim().to_string())
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>());
|
||||||
if !cc.is_empty() {
|
|
||||||
tpl.push(format!("Cc: {}", cc.join(", ")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Subject" header
|
|
||||||
let subject = headers.get_first_value("subject").unwrap_or(String::new());
|
|
||||||
tpl.push(format!("Subject: Re: {}", subject));
|
|
||||||
|
|
||||||
// Separator between headers and body
|
|
||||||
tpl.push(String::new());
|
|
||||||
|
|
||||||
// Original msg prepend with ">"
|
// Original msg prepend with ">"
|
||||||
let thread = self
|
let thread = self
|
||||||
.text_bodies("text/plain")?
|
.text_bodies("text/plain")?
|
||||||
.split("\r\n")
|
.split("\r\n")
|
||||||
.map(|line| format!(">{}", line))
|
.map(|line| format!(">{}", line))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>();
|
||||||
.join("\r\n");
|
|
||||||
tpl.push(thread);
|
|
||||||
|
|
||||||
// Signature
|
let msg_spec = MsgSpec{
|
||||||
if let Some(sig) = config.signature(&account) {
|
in_reply_to: headers.get_first_value("message-id"),
|
||||||
tpl.push(String::new());
|
cc,
|
||||||
tpl.push("--".to_string());
|
to: Some(vec![reply_to, to].concat()),
|
||||||
for line in sig.split("\n") {
|
subject: headers.get_first_value("subject"),
|
||||||
tpl.push(line.to_string());
|
default_content: Some(thread),
|
||||||
}
|
};
|
||||||
}
|
Msg::build_tpl(config, account, msg_spec)
|
||||||
|
|
||||||
Ok(Tpl(tpl.join("\r\n")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_forward_tpl(&self, config: &Config, account: &Account) -> Result<Tpl> {
|
pub fn build_forward_tpl(&self, config: &Config, account: &Account) -> Result<Tpl> {
|
||||||
let msg = &self.parse()?;
|
let msg = &self.parse()?;
|
||||||
let headers = msg.get_headers();
|
let headers = msg.get_headers();
|
||||||
let mut tpl = vec![];
|
|
||||||
|
|
||||||
// "Content" headers
|
let subject = format!("Fwd: {}", headers.get_first_value("subject").unwrap_or_else(String::new));
|
||||||
|
let original_msg = vec![
|
||||||
|
"-------- Forwarded Message --------".to_string(),
|
||||||
|
self.text_bodies("text/plain")?,
|
||||||
|
];
|
||||||
|
|
||||||
|
let msg_spec = MsgSpec{
|
||||||
|
in_reply_to: None,
|
||||||
|
cc: None,
|
||||||
|
to: None,
|
||||||
|
subject: Some(subject),
|
||||||
|
default_content: Some(original_msg),
|
||||||
|
};
|
||||||
|
Msg::build_tpl(config, account, msg_spec)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_content_headers(tpl: &mut Vec<String>) {
|
||||||
tpl.push("Content-Type: text/plain; charset=utf-8".to_string());
|
tpl.push("Content-Type: text/plain; charset=utf-8".to_string());
|
||||||
tpl.push("Content-Transfer-Encoding: 8bit".to_string());
|
tpl.push("Content-Transfer-Encoding: 8bit".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
// "From" header
|
fn add_from_header(tpl: &mut Vec<String>, from: Option<String>) {
|
||||||
tpl.push(format!("From: {}", config.address(account)));
|
tpl.push(format!("From: {}", from.unwrap_or_else(String::new)));
|
||||||
|
}
|
||||||
|
|
||||||
// "To" header
|
fn add_in_reply_to_header(tpl: &mut Vec<String>, in_reply_to: Option<String>) {
|
||||||
tpl.push("To: ".to_string());
|
if let Some(r) = in_reply_to {
|
||||||
|
tpl.push(format!("In-Reply-To: {}", r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// "Subject" header
|
fn add_cc_header(tpl: &mut Vec<String>, cc: Option<Vec<String>>) {
|
||||||
let subject = headers.get_first_value("subject").unwrap_or(String::new());
|
if let Some(c) = cc {
|
||||||
tpl.push(format!("Subject: Fwd: {}", subject));
|
tpl.push(format!("Cc: {}", c.join(", ")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Separator between headers and body
|
fn add_to_header(tpl: &mut Vec<String>, to: Option<Vec<String>>) {
|
||||||
tpl.push(String::new());
|
tpl.push(format!("To: {}", match to {
|
||||||
|
Some(t) => {t.join(", ")}
|
||||||
|
None => {String::new()}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// Original msg
|
fn add_subject_header(tpl: &mut Vec<String>, subject: Option<String>) {
|
||||||
tpl.push("-------- Forwarded Message --------".to_string());
|
tpl.push(format!("Subject: {}", subject.unwrap_or_else(String::new)));
|
||||||
tpl.push(self.text_bodies("text/plain")?);
|
}
|
||||||
|
|
||||||
// Signature
|
fn add_content(tpl: &mut Vec<String>, content: Option<Vec<String>>) {
|
||||||
|
if let Some(c) = content {
|
||||||
|
tpl.push(String::new()); // Separator between headers and body
|
||||||
|
tpl.extend(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_signature(tpl: &mut Vec<String>, config: &Config, account: &Account) {
|
||||||
if let Some(sig) = config.signature(&account) {
|
if let Some(sig) = config.signature(&account) {
|
||||||
tpl.push(String::new());
|
tpl.push(String::new());
|
||||||
tpl.push("--".to_string());
|
|
||||||
for line in sig.split("\n") {
|
for line in sig.split("\n") {
|
||||||
tpl.push(line.to_string());
|
tpl.push(line.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_tpl(config: &Config, account: &Account, msg_spec: MsgSpec) -> Result<Tpl> {
|
||||||
|
let mut tpl = vec![];
|
||||||
|
Msg::add_content_headers(&mut tpl);
|
||||||
|
Msg::add_from_header(&mut tpl, Some(config.address(account)));
|
||||||
|
Msg::add_in_reply_to_header(&mut tpl, msg_spec.in_reply_to);
|
||||||
|
Msg::add_cc_header(&mut tpl, msg_spec.cc);
|
||||||
|
Msg::add_to_header(&mut tpl, msg_spec.to);
|
||||||
|
Msg::add_subject_header(&mut tpl, msg_spec.subject);
|
||||||
|
Msg::add_content(&mut tpl, msg_spec.default_content);
|
||||||
|
Msg::add_signature(&mut tpl, config, account);
|
||||||
Ok(Tpl(tpl.join("\r\n")))
|
Ok(Tpl(tpl.join("\r\n")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MsgSpec {
|
||||||
|
in_reply_to: Option<String>,
|
||||||
|
to: Option<Vec<String>>,
|
||||||
|
cc: Option<Vec<String>>,
|
||||||
|
subject: Option<String>,
|
||||||
|
default_content: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'m> DisplayRow for Msg<'m> {
|
impl<'m> DisplayRow for Msg<'m> {
|
||||||
fn to_row(&self) -> Vec<table::Cell> {
|
fn to_row(&self) -> Vec<table::Cell> {
|
||||||
use crate::table::*;
|
use crate::table::*;
|
||||||
|
|
Loading…
Reference in a new issue