review forward command

This commit is contained in:
Clément DOUIN 2021-09-19 16:35:52 +02:00
parent 65664d5405
commit e609fc296c
No known key found for this signature in database
GPG key ID: 69C9B9CFFDEE2DEF
3 changed files with 90 additions and 87 deletions

View file

@ -43,14 +43,14 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
if let Some(m) = m.subcommand_matches("attachments") {
debug!("attachments command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", &uid);
debug!("uid: {}", uid);
return Ok(Some(Command::Attachments(uid)));
}
if let Some(m) = m.subcommand_matches("copy") {
debug!("copy command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", &uid);
debug!("uid: {}", uid);
let target = m.value_of("target");
debug!("target mailbox: `{:?}`", target);
return Ok(Some(Command::Copy(uid, target)));
@ -59,7 +59,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
if let Some(m) = m.subcommand_matches("delete") {
debug!("copy command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", &uid);
debug!("uid: {}", uid);
return Ok(Some(Command::Delete(uid)));
}
@ -68,7 +68,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
let uid = m.value_of("uid").unwrap();
let paths: Vec<&str> = m.values_of("attachments").unwrap_or_default().collect();
debug!("attachments paths: {:?}", paths);
debug!("uid: {}", &uid);
debug!("uid: {}", uid);
return Ok(Some(Command::Forward(uid, paths)));
}
@ -90,7 +90,7 @@ pub fn matches<'a>(m: &'a ArgMatches) -> Result<Option<Command<'a>>> {
if let Some(m) = m.subcommand_matches("move") {
debug!("move command matched");
let uid = m.value_of("uid").unwrap();
debug!("uid: {}", &uid);
debug!("uid: {}", uid);
let target = m.value_of("target");
debug!("target mailbox: `{:?}`", target);
return Ok(Some(Command::Move(uid, target)));
@ -283,7 +283,7 @@ pub fn subcmds<'a>() -> Vec<App<'a, 'a>> {
.arg(reply_all_arg())
.arg(msg::attachment::arg::path_arg()),
SubCommand::with_name("forward")
.aliases(&["fwd"])
.aliases(&["fwd", "f"])
.about("Forwards a message")
.arg(uid_arg())
.arg(msg::attachment::arg::path_arg()),

View file

@ -325,28 +325,39 @@ impl Msg {
/// ```
pub fn change_to_forwarding(&mut self, account: &Account) {
// -- Header --
let old_subject = self.headers.subject.clone().unwrap_or(String::new());
let subject = self
.headers
.subject
.as_ref()
.map(|sub| {
if sub.starts_with("Fwd:") {
sub.to_owned()
} else {
format!("Fwd: {}", sub)
}
})
.unwrap_or_default();
self.headers = Headers {
subject: Some(format!("Fwd: {}", old_subject)),
sender: Some(account.address()),
subject: Some(subject),
sender: None,
reply_to: None,
message_id: None,
from: vec![account.address()],
to: vec![],
// and use the rest of the headers
..self.headers.clone()
};
let mut body = String::new();
// -- Body --
// apply a line which should indicate where the forwarded message begins
body.push_str(&format!(
"\n---------- Forwarded Message ----------\n{}",
// TODO: add Subject, Date, From and To headers after "Forwarded Message"
self.body = Body::new_with_text(format!(
"\n\n---------- Forwarded Message ----------\n{}",
self.body
.plain
.clone()
.to_owned()
.unwrap_or_default()
.replace("\r", ""),
));
self.body = Body::new_with_text(body);
self.sig = account.signature.to_owned();
}

View file

@ -6,7 +6,7 @@ use anyhow::{Context, Result};
use atty::Stream;
use imap::types::Flag;
use lettre::message::header::ContentTransferEncoding;
use log::{debug, error, trace};
use log::{debug, trace};
use std::{
borrow::Cow,
convert::TryFrom,
@ -30,7 +30,10 @@ use crate::{
smtp::service::SmtpServiceInterface,
},
output::service::{OutputService, OutputServiceInterface},
ui::choice::{self, PostEditChoice},
ui::{
choice::{self, PostEditChoice},
editor,
},
};
// TODO: move this function to the right folder
@ -44,76 +47,66 @@ fn msg_interaction<ImapService: ImapServiceInterface, SmtpService: SmtpServiceIn
msg.edit_body()?;
loop {
match choice::post_edit() {
Ok(choice) => match choice {
PostEditChoice::Send => {
debug!("sending message…");
match choice::post_edit()? {
PostEditChoice::Send => {
debug!("sending message…");
// prepare the msg to be send
let sendable = match msg.to_sendable_msg() {
Ok(sendable) => sendable,
// In general if an error occured, then this is normally
// due to a missing value of a header. So let's give the
// user another try and give him/her the chance to fix
// that :)
Err(err) => {
println!("{}", err);
println!("Please reedit your msg to make it to a sendable message!");
continue;
}
};
smtp.send(&sendable)?;
// TODO: Gmail sent mailboxes are called `[Gmail]/Sent`
// which creates a conflict, fix this!
// let the server know, that the user sent a msg
msg.flags.insert(Flag::Seen);
let mbox = Mbox::from("Sent");
imap.append_msg(&mbox, msg)?;
// remove the draft, since we sent it
msg::utils::remove_draft()?;
output.print("Message successfully sent")?;
break;
}
// edit the body of the msg
PostEditChoice::Edit => {
// Did something goes wrong when the user changed the
// content?
if let Err(err) = msg.edit_body() {
println!("[ERROR] {}", err);
println!(concat!(
"Please try to fix the problem by editing",
"the msg again."
));
// prepare the msg to be send
let sendable = match msg.to_sendable_msg() {
Ok(sendable) => sendable,
// In general if an error occured, then this is normally
// due to a missing value of a header. So let's give the
// user another try and give him/her the chance to fix
// that :)
Err(err) => {
println!("{}", err);
println!("Please reedit your msg to make it to a sendable message!");
continue;
}
}
PostEditChoice::LocalDraft => break,
PostEditChoice::RemoteDraft => {
debug!("saving to draft…");
};
smtp.send(&sendable)?;
msg.flags.insert(Flag::Seen);
// TODO: Gmail sent mailboxes are called `[Gmail]/Sent`
// which creates a conflict, fix this!
let mbox = Mbox::from("Drafts");
match imap.append_msg(&mbox, msg) {
Ok(_) => {
msg::utils::remove_draft()?;
output.print("Message successfully saved to Drafts")?;
}
Err(err) => {
output.print("Cannot save draft to the server")?;
return Err(err.into());
}
};
break;
}
PostEditChoice::Discard => {
msg::utils::remove_draft()?;
break;
}
},
Err(err) => error!("{}", err),
// let the server know, that the user sent a msg
msg.flags.insert(Flag::Seen);
let mbox = Mbox::from("Sent");
imap.append_msg(&mbox, msg)?;
// remove the draft, since we sent it
msg::utils::remove_draft()?;
output.print("Message successfully sent")?;
break;
}
// edit the body of the msg
PostEditChoice::Edit => {
Msg::parse_from_str(msg, &editor::open_editor_with_draft()?)?;
continue;
}
PostEditChoice::LocalDraft => break,
PostEditChoice::RemoteDraft => {
debug!("saving to draft…");
msg.flags.insert(Flag::Seen);
let mbox = Mbox::from("Drafts");
match imap.append_msg(&mbox, msg) {
Ok(_) => {
msg::utils::remove_draft()?;
output.print("Message successfully saved to Drafts")?;
}
Err(err) => {
output.print("Cannot save draft to the server")?;
return Err(err.into());
}
};
break;
}
PostEditChoice::Discard => {
msg::utils::remove_draft()?;
break;
}
}
}
@ -186,6 +179,7 @@ pub fn delete<OutputService: OutputServiceInterface, ImapService: ImapServiceInt
Ok(())
}
/// Forward the given message UID from the selected mailbox.
pub fn forward<ImapService: ImapServiceInterface, SmtpService: SmtpServiceInterface>(
uid: &str,
attachments_paths: Vec<&str>,
@ -195,14 +189,12 @@ pub fn forward<ImapService: ImapServiceInterface, SmtpService: SmtpServiceInterf
smtp: &mut SmtpService,
) -> Result<()> {
let mut msg = imap.get_msg(&uid)?;
// prepare to forward it
msg.change_to_forwarding(&account);
attachments_paths
.iter()
.for_each(|path| msg.add_attachment(path));
debug!("found {} attachments", attachments_paths.len());
trace!("attachments: {:?}", attachments_paths);
// apply changes
msg_interaction(output, &mut msg, imap, smtp)?;
imap.logout()?;
Ok(())