summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-09-23 09:30:23 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-09-23 09:30:23 +0300
commit26e4d50b402213c07c7d492ace8d6cd2e88a816d (patch)
treedb617824fc0244b72bc2a3abd2e729a17fdfa53d
parented248be03179f0d188d0fff7f7fc7ea5647262e4 (diff)
Try to save sent messages elsewhere if Sent folder fails
If Sent folder wasn't correctly configured, the sent message would be lost. With this change it tries these folders in this order: 1. Sent 2. Inbox 3. Any other normal folder The check is done by looking at the special usage metadata on each folder. If everything fails, the message is saved in a file in the tmpfs.
-rw-r--r--ui/src/components/mail/compose.rs89
-rw-r--r--ui/src/components/mail/view.rs1
-rw-r--r--ui/src/components/mail/view/envelope.rs1
-rw-r--r--ui/src/components/mail/view/html.rs2
-rw-r--r--ui/src/conf/accounts.rs13
-rw-r--r--ui/src/types/helpers.rs21
6 files changed, 85 insertions, 42 deletions
diff --git a/ui/src/components/mail/compose.rs b/ui/src/components/mail/compose.rs
index 699b0b90..41522690 100644
--- a/ui/src/components/mail/compose.rs
+++ b/ui/src/components/mail/compose.rs
@@ -616,6 +616,7 @@ impl Component for Composer {
self.draft.to_string().unwrap().as_str().as_bytes(),
None,
None,
+ true,
);
// TODO: check exit status
@@ -773,47 +774,63 @@ pub fn send_draft(context: &mut Context, account_cursor: usize, draft: Draft) ->
stdin
.write_all(draft.as_bytes())
.expect("Failed to write to stdin");
- if let Err(e) = context.accounts[account_cursor].save(
- draft.as_bytes(),
- &context.accounts[account_cursor].sent_folder(),
- Some(Flag::SEEN),
- ) {
- debug!("{:?} could not save sent msg", e);
+ for folder in &[
+ &context.accounts[account_cursor].special_use_folder(SpecialUseMailbox::Sent),
+ &context.accounts[account_cursor].special_use_folder(SpecialUseMailbox::Inbox),
+ &context.accounts[account_cursor].special_use_folder(SpecialUseMailbox::Normal),
+ ] {
+ if let Err(e) =
+ context.accounts[account_cursor].save(draft.as_bytes(), folder, Some(Flag::SEEN))
+ {
+ debug!("{:?} could not save sent msg", e);
+ context.replies.push_back(UIEvent::Notification(
+ Some(format!("Could not save in '{}' folder.", folder)),
+ e.into(),
+ Some(NotificationType::ERROR),
+ ));
+ } else {
+ failure = false;
+ break;
+ }
+ }
+
+ if failure {
+ let file = create_temp_file(draft.as_bytes(), None, None, false);
+ debug!("message saved in {}", file.path.display());
context.replies.push_back(UIEvent::Notification(
- Some("Could not save in 'Sent' folder.".into()),
- e.into(),
- Some(NotificationType::ERROR),
+ Some("Could not save in any folder".into()),
+ format!(
+ "Message was stored in {} so that you can restore it manually.",
+ file.path.display()
+ ),
+ Some(NotificationType::INFO),
));
- } else {
- failure = false;
}
}
- if !failure {
- let output = msmtp.wait().expect("Failed to wait on mailer");
- if output.success() {
- context.replies.push_back(UIEvent::Notification(
- Some("Sent.".into()),
- String::new(),
- None,
- ));
+ let output = msmtp.wait().expect("Failed to wait on mailer");
+ if output.success() {
+ context.replies.push_back(UIEvent::Notification(
+ Some("Sent.".into()),
+ String::new(),
+ None,
+ ));
+ } else {
+ if let Some(exit_code) = output.code() {
+ log(
+ format!(
+ "Could not send e-mail using `{}`: Process exited with {}",
+ cmd, exit_code
+ ),
+ ERROR,
+ );
} else {
- if let Some(exit_code) = output.code() {
- log(
- format!(
- "Could not send e-mail using `{}`: Process exited with {}",
- cmd, exit_code
- ),
- ERROR,
- );
- } else {
- log(
- format!(
- "Could not send e-mail using `{}`: Process was killed by signal",
- cmd
- ),
- ERROR,
- );
- }
+ log(
+ format!(
+ "Could not send e-mail using `{}`: Process was killed by signal",
+ cmd
+ ),
+ ERROR,
+ );
}
}
!failure
diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs
index 2767acd6..3bf69b2e 100644
--- a/ui/src/components/mail/view.rs
+++ b/ui/src/components/mail/view.rs
@@ -785,6 +785,7 @@ impl Component for MailView {
&decode(u, None),
name.as_ref().map(|n| n.clone()),
None,
+ true,
);
Command::new(&binary)
.arg(p.path())
diff --git a/ui/src/components/mail/view/envelope.rs b/ui/src/components/mail/view/envelope.rs
index a614a21c..a9cfd626 100644
--- a/ui/src/components/mail/view/envelope.rs
+++ b/ui/src/components/mail/view/envelope.rs
@@ -448,6 +448,7 @@ impl Component for EnvelopeView {
&decode(u, None),
name.as_ref().map(|n| n.clone()),
None,
+ true,
);
Command::new(&binary)
.arg(p.path())
diff --git a/ui/src/components/mail/view/html.rs b/ui/src/components/mail/view/html.rs
index 97ee5aba..26666e78 100644
--- a/ui/src/components/mail/view/html.rs
+++ b/ui/src/components/mail/view/html.rs
@@ -134,7 +134,7 @@ impl Component for HtmlView {
// scripts)
let binary = query_default_app("text/html");
if let Ok(binary) = binary {
- let p = create_temp_file(&self.bytes, None, None);
+ let p = create_temp_file(&self.bytes, None, None, true);
Command::new(&binary)
.arg(p.path())
.stdin(Stdio::piped())
diff --git a/ui/src/conf/accounts.rs b/ui/src/conf/accounts.rs
index 1308a800..1a479565 100644
--- a/ui/src/conf/accounts.rs
+++ b/ui/src/conf/accounts.rs
@@ -771,6 +771,19 @@ impl Account {
""
}
}
+
+ pub fn special_use_folder(&self, special_use: SpecialUseMailbox) -> &str {
+ let ret = self
+ .settings
+ .folder_confs
+ .iter()
+ .find(|(_, f)| f.usage == Some(special_use));
+ if let Some(ret) = ret.as_ref() {
+ ret.0
+ } else {
+ ""
+ }
+ }
}
impl Index<FolderHash> for Account {
diff --git a/ui/src/types/helpers.rs b/ui/src/types/helpers.rs
index fa82c10c..86aea577 100644
--- a/ui/src/types/helpers.rs
+++ b/ui/src/types/helpers.rs
@@ -29,12 +29,15 @@ use uuid::Uuid;
#[derive(Debug)]
pub struct File {
- path: PathBuf,
+ pub path: PathBuf,
+ delete_on_drop: bool,
}
impl Drop for File {
fn drop(&mut self) {
- std::fs::remove_file(self.path()).unwrap_or_else(|_| {});
+ if self.delete_on_drop {
+ std::fs::remove_file(self.path()).unwrap_or_else(|_| {});
+ }
}
}
@@ -61,9 +64,14 @@ impl File {
}
}
-/// Returned `File` will be deleted when dropped, so make sure to add it on `context.temp_files`
+/// Returned `File` will be deleted when dropped if delete_on_drop is set, so make sure to add it on `context.temp_files`
/// to reap it later.
-pub fn create_temp_file(bytes: &[u8], filename: Option<String>, path: Option<&PathBuf>) -> File {
+pub fn create_temp_file(
+ bytes: &[u8],
+ filename: Option<String>,
+ path: Option<&PathBuf>,
+ delete_on_drop: bool,
+) -> File {
let mut dir = std::env::temp_dir();
let path = if let Some(p) = path {
@@ -87,5 +95,8 @@ pub fn create_temp_file(bytes: &[u8], filename: Option<String>, path: Option<&Pa
f.write_all(bytes).unwrap();
f.flush().unwrap();
- File { path: path.clone() }
+ File {
+ path: path.clone(),
+ delete_on_drop,
+ }
}