/**
* mutt_save_message - Save an email
- * @param e Email
+ * @param m Mailbox
+ * @param el List of Emails to save
* @param delete If true, delete the original (save)
* @param decode If true, decode the message
* @param decrypt If true, decrypt the message
* @retval 0 Copy/save was successful
* @retval -1 Error/abort
*/
-int mutt_save_message(struct Email *e, bool delete, bool decode, bool decrypt)
+int mutt_save_message(struct Mailbox *m, struct EmailList *el, bool delete, bool decode, bool decrypt)
{
+ if (!el || STAILQ_EMPTY(el))
+ return -1;
+
bool need_passphrase = false;
int app = 0;
char buf[PATH_MAX];
const char *prompt = NULL;
struct Context *savectx = NULL;
struct stat st;
+ struct EmailNode *en = STAILQ_FIRST(el);
+ bool single = !STAILQ_NEXT(en, entries);
if (delete)
{
if (decode)
- prompt = e ? _("Decode-save to mailbox") : _("Decode-save tagged to mailbox");
+ prompt = single ? _("Decode-save to mailbox") : _("Decode-save tagged to mailbox");
else if (decrypt)
- prompt = e ? _("Decrypt-save to mailbox") : _("Decrypt-save tagged to mailbox");
+ prompt = single ? _("Decrypt-save to mailbox") : _("Decrypt-save tagged to mailbox");
else
- prompt = e ? _("Save to mailbox") : _("Save tagged to mailbox");
+ prompt = single ? _("Save to mailbox") : _("Save tagged to mailbox");
}
else
{
if (decode)
- prompt = e ? _("Decode-copy to mailbox") : _("Decode-copy tagged to mailbox");
+ prompt = single ? _("Decode-copy to mailbox") : _("Decode-copy tagged to mailbox");
else if (decrypt)
- prompt = e ? _("Decrypt-copy to mailbox") : _("Decrypt-copy tagged to mailbox");
+ prompt = single ? _("Decrypt-copy to mailbox") : _("Decrypt-copy tagged to mailbox");
else
- prompt = e ? _("Copy to mailbox") : _("Copy tagged to mailbox");
+ prompt = single ? _("Copy to mailbox") : _("Copy tagged to mailbox");
}
- if (e)
- {
- if (WithCrypto)
- {
- need_passphrase = (e->security & ENCRYPT);
- app = e->security;
- }
- mutt_message_hook(Context->mailbox, e, MUTT_MESSAGE_HOOK);
- mutt_default_save(buf, sizeof(buf), e);
- }
- else
+ if (WithCrypto)
{
- /* look for the first tagged message */
- for (int i = 0; i < Context->mailbox->msg_count; i++)
- {
- if (message_is_tagged(Context, i))
- {
- e = Context->mailbox->emails[i];
- break;
- }
- }
-
- if (e)
- {
- mutt_message_hook(Context->mailbox, e, MUTT_MESSAGE_HOOK);
- mutt_default_save(buf, sizeof(buf), e);
- if (WithCrypto)
- {
- need_passphrase = (e->security & ENCRYPT);
- app = e->security;
- }
- e = NULL;
- }
+ need_passphrase = (en->email->security & ENCRYPT);
+ app = en->email->security;
}
+ mutt_message_hook(m, en->email, MUTT_MESSAGE_HOOK);
+ mutt_default_save(buf, sizeof(buf), en->email);
mutt_pretty_mailbox(buf, sizeof(buf));
if (mutt_enter_fname(prompt, buf, sizeof(buf), 0) == -1)
mutt_message(_("Copying to %s..."), buf);
#ifdef USE_IMAP
- if ((Context->mailbox->magic == MUTT_IMAP) && !(decode || decrypt) &&
+ if ((m->magic == MUTT_IMAP) && !(decode || decrypt) &&
(imap_path_probe(buf, NULL) == MUTT_IMAP))
{
- switch (imap_copy_messages(Context->mailbox, e, buf, delete))
+ switch (imap_copy_messages(m, el, buf, delete))
{
/* success */
case 0:
#endif
savectx = mx_mbox_open(NULL, buf, MUTT_APPEND);
- if (savectx)
- {
+ if (!savectx)
+ return -1;
+
#ifdef USE_COMPRESSED
- /* If we're saving to a compressed mailbox, the stats won't be updated
- * until the next open. Until then, improvise. */
- struct Mailbox *cm = NULL;
- if (savectx->mailbox->compress_info)
+ /* If we're saving to a compressed mailbox, the stats won't be updated
+ * until the next open. Until then, improvise. */
+ struct Mailbox *cm = NULL;
+ if (savectx->mailbox->compress_info)
+ {
+ cm = mutt_find_mailbox(savectx->mailbox->realpath);
+ }
+ /* We probably haven't been opened yet */
+ if (cm && (cm->msg_count == 0))
+ cm = NULL;
+#endif
+ if (single)
+ {
+ if (mutt_save_message_ctx(en->email, delete, decode, decrypt, savectx->mailbox) != 0)
{
- cm = mutt_find_mailbox(savectx->mailbox->realpath);
+ mx_mbox_close(&savectx);
+ return -1;
}
- /* We probably haven't been opened yet */
- if (cm && (cm->msg_count == 0))
- cm = NULL;
-#endif
- if (e)
+#ifdef USE_COMPRESSED
+ if (cm)
{
- if (mutt_save_message_ctx(e, delete, decode, decrypt, savectx->mailbox) != 0)
+ cm->msg_count++;
+ if (!en->email->read)
{
- mx_mbox_close(&savectx);
- return -1;
+ cm->msg_unread++;
+ if (!en->email->old)
+ cm->msg_new++;
}
+ if (en->email->flagged)
+ cm->msg_flagged++;
+ }
+#endif
+ }
+ else
+ {
+ int rc = 0;
+
+#ifdef USE_NOTMUCH
+ if (m->magic == MUTT_NOTMUCH)
+ nm_db_longrun_init(m, true);
+#endif
+ STAILQ_FOREACH(en, el, entries)
+ {
+ mutt_message_hook(m, en->email, MUTT_MESSAGE_HOOK);
+ rc = mutt_save_message_ctx(en->email, delete, decode,
+ decrypt, savectx->mailbox);
+ if (rc != 0)
+ break;
#ifdef USE_COMPRESSED
if (cm)
{
+ struct Email *e2 = en->email;
cm->msg_count++;
- if (!e->read)
+ if (!e2->read)
{
cm->msg_unread++;
- if (!e->old)
+ if (!e2->old)
cm->msg_new++;
}
- if (e->flagged)
+ if (e2->flagged)
cm->msg_flagged++;
}
#endif
}
- else
- {
- int rc = 0;
-
-#ifdef USE_NOTMUCH
- if (Context->mailbox->magic == MUTT_NOTMUCH)
- nm_db_longrun_init(Context->mailbox, true);
-#endif
- for (int i = 0; i < Context->mailbox->msg_count; i++)
- {
- if (!message_is_tagged(Context, i))
- continue;
-
- mutt_message_hook(Context->mailbox, Context->mailbox->emails[i], MUTT_MESSAGE_HOOK);
- rc = mutt_save_message_ctx(Context->mailbox->emails[i], delete, decode,
- decrypt, savectx->mailbox);
- if (rc != 0)
- break;
-#ifdef USE_COMPRESSED
- if (cm)
- {
- struct Email *e2 = Context->mailbox->emails[i];
- cm->msg_count++;
- if (!e2->read)
- {
- cm->msg_unread++;
- if (!e2->old)
- cm->msg_new++;
- }
- if (e2->flagged)
- cm->msg_flagged++;
- }
-#endif
- }
#ifdef USE_NOTMUCH
- if (Context->mailbox->magic == MUTT_NOTMUCH)
- nm_db_longrun_done(Context->mailbox);
+ if (m->magic == MUTT_NOTMUCH)
+ nm_db_longrun_done(m);
#endif
- if (rc != 0)
- {
- mx_mbox_close(&savectx);
- return -1;
- }
+ if (rc != 0)
+ {
+ mx_mbox_close(&savectx);
+ return -1;
}
+ }
- const bool need_mailbox_cleanup = ((savectx->mailbox->magic == MUTT_MBOX) ||
- (savectx->mailbox->magic == MUTT_MMDF));
-
- mx_mbox_close(&savectx);
+ const bool need_mailbox_cleanup = ((savectx->mailbox->magic == MUTT_MBOX) ||
+ (savectx->mailbox->magic == MUTT_MMDF));
- if (need_mailbox_cleanup)
- mutt_mailbox_cleanup(buf, &st);
+ mx_mbox_close(&savectx);
- mutt_clear_error();
- return 0;
- }
+ if (need_mailbox_cleanup)
+ mutt_mailbox_cleanup(buf, &st);
- return -1;
+ mutt_clear_error();
+ return 0;
}
/**
void mutt_pipe_message(struct Email *e);
void mutt_print_message(struct Email *e);
int mutt_save_message_ctx(struct Email *e, bool delete, bool decode, bool decrypt, struct Mailbox *m);
-int mutt_save_message(struct Email *e, bool delete, bool decode, bool decrypt);
+int mutt_save_message(struct Mailbox *m, struct EmailList *el, bool delete, bool decode, bool decrypt);
int mutt_select_sort(int reverse);
void mutt_shell_escape(void);
struct BrowserState;
struct Email;
+struct EmailList;
struct Pattern;
/* These Config Variables are only used in imap/auth.c */
int imap_mailbox_rename(const char *path);
/* message.c */
-int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool delete);
+int imap_copy_messages(struct Mailbox *m, struct EmailList *el, char *dest, bool delete);
/* socket.c */
void imap_logout_all(void);
/**
* imap_copy_messages - Server COPY messages to another folder
* @param m Mailbox
- * @param e Email
+ * @param el List of Emails to copy
* @param dest Destination folder
* @param delete Delete the original?
* @retval -1 Error
* @retval 0 Success
* @retval 1 Non-fatal error - try fetch/append
*/
-int imap_copy_messages(struct Mailbox *m, struct Email *e, char *dest, bool delete)
+int imap_copy_messages(struct Mailbox *m, struct EmailList *el, char *dest, bool delete)
{
- if (!m || !dest)
+ if (!m || !el || !dest)
return -1;
struct Buffer cmd, sync_cmd;
struct ConnAccount conn_account;
int err_continue = MUTT_NO;
int triedcreate = 0;
+ struct EmailNode *en = STAILQ_FIRST(el);
+ bool single = !STAILQ_NEXT(en, entries);
+ struct ImapAccountData *adata = imap_adata_get(m);
- if (e && e->attach_del)
+ if (single && en->email->attach_del)
{
mutt_debug(3, "#1 Message contains attachments to be deleted\n");
return 1;
}
- struct ImapAccountData *adata = imap_adata_get(m);
-
if (imap_parse_path(dest, &conn_account, buf, sizeof(buf)))
{
mutt_debug(1, "bad destination %s\n", dest);
mutt_buffer_init(&cmd);
/* Null Header* means copy tagged messages */
- if (!e)
+ if (!single)
{
/* if any messages have attachments to delete, fall through to FETCH
* and APPEND. TODO: Copy what we can with COPY, fall through for the
* remainder. */
- for (int i = 0; i < m->msg_count; i++)
+ STAILQ_FOREACH(en, el, entries)
{
- if (!m->emails[i]->tagged)
- continue;
-
- if (m->emails[i]->attach_del)
+ if (en->email->attach_del)
{
mutt_debug(3, "#2 Message contains attachments to be deleted\n");
return 1;
}
- if (m->emails[i]->active && m->emails[i]->changed)
+ if (en->email->active && en->email->changed)
{
- rc = imap_sync_message_for_copy(m, m->emails[i], &sync_cmd, &err_continue);
+ rc = imap_sync_message_for_copy(m, en->email, &sync_cmd, &err_continue);
if (rc < 0)
{
mutt_debug(1, "#1 could not sync\n");
}
else
{
- mutt_message(_("Copying message %d to %s..."), e->index + 1, mbox);
- mutt_buffer_add_printf(&cmd, "UID COPY %u %s", imap_edata_get(e)->uid, mmbox);
+ mutt_message(_("Copying message %d to %s..."), en->email->index + 1, mbox);
+ mutt_buffer_add_printf(&cmd, "UID COPY %u %s", imap_edata_get(en->email)->uid, mmbox);
- if (e->active && e->changed)
+ if (en->email->active && en->email->changed)
{
- rc = imap_sync_message_for_copy(m, e, &sync_cmd, &err_continue);
+ rc = imap_sync_message_for_copy(m, en->email, &sync_cmd, &err_continue);
if (rc < 0)
{
mutt_debug(1, "#2 could not sync\n");
/* cleanup */
if (delete)
{
- if (!e)
- {
- for (int i = 0; i < m->msg_count; i++)
- {
- if (!m->emails[i]->tagged)
- continue;
-
- mutt_set_flag(m, m->emails[i], MUTT_DELETE, 1);
- mutt_set_flag(m, m->emails[i], MUTT_PURGE, 1);
- if (DeleteUntag)
- mutt_set_flag(m, m->emails[i], MUTT_TAG, 0);
- }
- }
- else
+ STAILQ_FOREACH(en, el, entries)
{
- mutt_set_flag(m, e, MUTT_DELETE, 1);
- mutt_set_flag(m, e, MUTT_PURGE, 1);
+ mutt_set_flag(m, en->email, MUTT_DELETE, 1);
+ mutt_set_flag(m, en->email, MUTT_PURGE, 1);
if (DeleteUntag)
- mutt_set_flag(m, e, MUTT_TAG, 0);
+ mutt_set_flag(m, en->email, MUTT_TAG, 0);
}
}
case OP_SAVE:
case OP_DECODE_COPY:
case OP_DECODE_SAVE:
+ {
CHECK_MSGCOUNT;
CHECK_VISIBLE;
- if ((mutt_save_message(tag ? NULL : CUR_EMAIL,
+ struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
+ el_add_tagged(&el, Context, CUR_EMAIL, tag);
+ if ((mutt_save_message(Context->mailbox, &el,
(op == OP_DECRYPT_SAVE) || (op == OP_SAVE) || (op == OP_DECODE_SAVE),
(op == OP_DECODE_SAVE) || (op == OP_DECODE_COPY),
(op == OP_DECRYPT_SAVE) || (op == OP_DECRYPT_COPY)) == 0) &&
else
menu->redraw |= REDRAW_CURRENT;
}
+ el_free(&el);
break;
+ }
case OP_MAIN_NEXT_NEW:
case OP_MAIN_NEXT_UNREAD:
case OP_DECODE_SAVE:
case OP_DECODE_COPY:
case OP_DECRYPT_COPY:
+ {
if (!(WithCrypto != 0) && ch == OP_DECRYPT_COPY)
{
ch = -1;
break;
}
CHECK_MODE(IsEmail(extra));
- if ((mutt_save_message(
- extra->email, (ch == OP_DECRYPT_SAVE) || (ch == OP_SAVE) || (ch == OP_DECODE_SAVE),
- (ch == OP_DECODE_SAVE) || (ch == OP_DECODE_COPY),
- (ch == OP_DECRYPT_SAVE) || (ch == OP_DECRYPT_COPY)) == 0) &&
+ struct EmailList el = STAILQ_HEAD_INITIALIZER(el);
+ el_add_email(&el, extra->email);
+ if ((mutt_save_message(Context->mailbox, &el,
+ (ch == OP_DECRYPT_SAVE) || (ch == OP_SAVE) || (ch == OP_DECODE_SAVE),
+ (ch == OP_DECODE_SAVE) || (ch == OP_DECODE_COPY),
+ (ch == OP_DECRYPT_SAVE) || (ch == OP_DECRYPT_COPY)) == 0) &&
((ch == OP_SAVE) || (ch == OP_DECODE_SAVE) || (ch == OP_DECRYPT_SAVE)))
{
if (Resolve)
else
pager_menu->redraw |= REDRAW_STATUS | REDRAW_INDEX;
}
+ el_free(&el);
break;
+ }
case OP_SHELL_ESCAPE:
mutt_shell_escape();