Browse Source

Add export-mail command

jmap-eventsource
Manos Pitsidianakis 1 year ago
parent
commit
0c68807814
Signed by: epilys GPG Key ID: 73627C2F690DF710
  1. 15
      src/command.rs
  2. 1
      src/command/actions.rs
  3. 120
      src/components/mail/view.rs

15
src/command.rs

@ -701,6 +701,19 @@ Alternatives(&[to_stream!(One(Literal("add-attachment")), One(Filepath)), to_str
}
)
},
{ tags: ["export-mail "],
desc: "export-mail PATH",
tokens: &[One(Literal("export-mail")), One(Filepath)],
parser:(
fn export_mail(input: &[u8]) -> IResult<&[u8], Action> {
let (input, _) = tag("export-mail")(input.trim())?;
let (input, _) = is_a(" ")(input)?;
let (input, path) = quoted_argument(input.trim())?;
let (input, _) = eof(input)?;
Ok((input, View(ExportMail(path.to_string()))))
}
)
},
{ tags: ["tag", "tag add", "tag remove"],
desc: "tag [add/remove], edits message's tags.",
tokens: &[One(Literal("tag")), One(Alternatives(&[to_stream!(One(Literal("add"))), to_stream!(One(Literal("remove")))]))],
@ -836,7 +849,7 @@ fn account_action(input: &[u8]) -> IResult<&[u8], Action> {
}
fn view(input: &[u8]) -> IResult<&[u8], Action> {
alt((pipe, save_attachment))(input)
alt((pipe, save_attachment, export_mail))(input)
}
pub fn parse_command(input: &[u8]) -> Result<Action, MeliError> {

1
src/command/actions.rs

@ -75,6 +75,7 @@ pub enum MailingListAction {
pub enum ViewAction {
Pipe(String, Vec<String>),
SaveAttachment(usize, String),
ExportMail(String),
}
#[derive(Debug)]

120
src/components/mail/view.rs

@ -751,9 +751,6 @@ impl MailView {
lidx: usize,
context: &mut Context,
) -> Option<&'_ melib::Attachment> {
if lidx == 0 {
return None;
}
let display = if let MailViewState::Loaded { ref display, .. } = self.state {
display
} else {
@ -821,7 +818,18 @@ impl MailView {
None
}
return find_attachment(root_attachment, &path[1..]);
let ret = find_attachment(root_attachment, &path[1..]);
if lidx == 0 {
return ret.and_then(|a| {
if a.content_disposition.kind.is_attachment() {
Some(a)
} else {
None
}
});
} else {
return ret;
}
}
context
.replies
@ -1941,7 +1949,8 @@ impl Component for MailView {
UIEvent::EnvelopeRename(old_hash, new_hash) if self.coordinates.2 == old_hash => {
self.coordinates.2 = new_hash;
}
UIEvent::Action(View(ViewAction::SaveAttachment(a_i, ref path))) => {
UIEvent::Action(View(ViewAction::ExportMail(ref path))) => {
// Save entire message as eml
let account = &context.accounts[&self.coordinates.0];
if !account.contains_key(self.coordinates.2) {
/* The envelope has been renamed or removed, so wait for the appropriate event to
@ -1967,13 +1976,78 @@ impl Component for MailView {
};
let mut path = std::path::Path::new(path).to_path_buf();
if a_i == 0 {
// Save entire message as eml
if path.is_dir() {
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
path.push(format!("{}.eml", envelope.message_id_raw()));
}
match save_attachment(&path, bytes) {
Err(err) => {
context.replies.push_back(UIEvent::Notification(
Some(format!("Failed to create file at {}", path.display())),
err.to_string(),
Some(NotificationType::Error(melib::ErrorKind::External)),
));
log(
format!(
"Failed to create file at {}: {}",
path.display(),
err.to_string()
),
ERROR,
);
return true;
}
Ok(()) => {
context.replies.push_back(UIEvent::Notification(
None,
format!("Saved at {}", &path.display()),
Some(NotificationType::Info),
));
}
}
return true;
}
UIEvent::Action(View(ViewAction::SaveAttachment(a_i, ref path))) => {
{
let account = &context.accounts[&self.coordinates.0];
if !account.contains_key(self.coordinates.2) {
/* The envelope has been renamed or removed, so wait for the appropriate event to
* arrive */
return true;
}
}
let bytes = if let MailViewState::Loaded { ref bytes, .. } = self.state {
bytes
} else if let MailViewState::Error { ref err } = self.state {
context.replies.push_back(UIEvent::Notification(
Some("Failed to open e-mail".to_string()),
err.to_string(),
Some(NotificationType::Error(err.kind)),
));
log(
format!("Failed to open envelope: {}", err.to_string()),
ERROR,
);
self.init_futures(context);
return true;
} else {
return true;
};
let mut path = std::path::Path::new(path).to_path_buf();
if let Some(u) = self.open_attachment(a_i, context) {
if path.is_dir() {
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
path.push(format!("{}.eml", envelope.message_id_display()));
if let Some(filename) = u.filename() {
path.push(filename);
} else {
let u = Uuid::new_v4();
path.push(u.to_hyphenated().to_string());
}
}
match save_attachment(&path, bytes) {
match save_attachment(&path, &decode(u, None)) {
Err(err) => {
context.replies.push_back(UIEvent::Notification(
Some(format!("Failed to create file at {}", path.display())),
@ -1988,30 +2062,23 @@ impl Component for MailView {
),
ERROR,
);
return true;
}
Ok(()) => {
context.replies.push_back(UIEvent::Notification(
None,
format!("Saved at {}", &path.display()),
format!("Saved at {}", path.display()),
Some(NotificationType::Info),
));
}
}
return true;
}
if let Some(u) = self.open_attachment(a_i, context) {
} else if a_i == 0 {
let account = &context.accounts[&self.coordinates.0];
// Save entire message as eml
if path.is_dir() {
if let Some(filename) = u.filename() {
path.push(filename);
} else {
let u = Uuid::new_v4();
path.push(u.to_hyphenated().to_string());
}
let envelope: EnvelopeRef = account.collection.get_env(self.coordinates.2);
path.push(format!("{}.eml", envelope.message_id_raw()));
}
match save_attachment(&path, &decode(u, None)) {
match save_attachment(&path, bytes) {
Err(err) => {
context.replies.push_back(UIEvent::Notification(
Some(format!("Failed to create file at {}", path.display())),
@ -2026,15 +2093,18 @@ impl Component for MailView {
),
ERROR,
);
return true;
}
Ok(()) => {
context.replies.push_back(UIEvent::Notification(
None,
format!("Saved at {}", path.display()),
format!("Saved at {}", &path.display()),
Some(NotificationType::Info),
));
}
}
return true;
} else {
context
.replies

Loading…
Cancel
Save