NeoMutt  2025-12-11-276-g10b23b
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
external.h File Reference

Manage where the email is piped to external commands. More...

#include <stdbool.h>
#include <stdio.h>
+ Include dependency graph for external.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  MessageTransformOpt { TRANSFORM_NONE = 0 , TRANSFORM_DECRYPT , TRANSFORM_DECODE }
 Message transformation option. More...
 
enum  MessageSaveOpt { SAVE_COPY = 0 , SAVE_MOVE }
 Message save option. More...
 

Functions

void index_bounce_message (struct Mailbox *m, struct EmailArray *ea)
 Bounce an email.
 
bool mutt_check_traditional_pgp (struct Mailbox *m, struct EmailArray *ea)
 Check if a message has inline PGP content.
 
void external_cleanup (void)
 Clean up commands globals.
 
void mutt_display_address (struct Envelope *env)
 Display the address of a message.
 
bool mutt_edit_content_type (struct Email *e, struct Body *b, FILE *fp)
 Edit the content type of an attachment.
 
void mutt_enter_command (struct MuttWindow *win)
 Enter a neomutt command.
 
void mutt_pipe_message (struct Mailbox *m, struct EmailArray *ea)
 Pipe a message.
 
void mutt_print_message (struct Mailbox *m, struct EmailArray *ea)
 Print a message.
 
int mutt_save_message (struct Mailbox *m, struct EmailArray *ea, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
 Save an email.
 
int mutt_save_message_mbox (struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
 Save a message to a given mailbox.
 
bool mutt_select_sort (bool reverse)
 Ask the user for a sort method.
 
bool mutt_shell_escape (void)
 Invoke a command in a subshell.
 

Detailed Description

Manage where the email is piped to external commands.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Ihor Antonov

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file external.h.

Enumeration Type Documentation

◆ MessageTransformOpt

Message transformation option.

Enumerator
TRANSFORM_NONE 

No transformation.

TRANSFORM_DECRYPT 

Decrypt message.

TRANSFORM_DECODE 

Decode message.

Definition at line 41 of file external.h.

42{
43 TRANSFORM_NONE = 0,
46};
@ TRANSFORM_NONE
No transformation.
Definition external.h:43
@ TRANSFORM_DECODE
Decode message.
Definition external.h:45
@ TRANSFORM_DECRYPT
Decrypt message.
Definition external.h:44

◆ MessageSaveOpt

Message save option.

Enumerator
SAVE_COPY 

Copy message, making a duplicate in another mailbox.

SAVE_MOVE 

Move message to another mailbox, removing the original.

Definition at line 51 of file external.h.

52{
53 SAVE_COPY = 0,
54 SAVE_MOVE,
55};
@ SAVE_MOVE
Move message to another mailbox, removing the original.
Definition external.h:54
@ SAVE_COPY
Copy message, making a duplicate in another mailbox.
Definition external.h:53

Function Documentation

◆ index_bounce_message()

void index_bounce_message ( struct Mailbox * m,
struct EmailArray * ea )

Bounce an email.

Parameters
mMailbox
eaArray of Emails to bounce

Definition at line 87 of file external.c.

88{
89 if (!m || !ea || ARRAY_EMPTY(ea))
90 return;
91
92 struct Buffer *buf = buf_pool_get();
93 struct Buffer *prompt = buf_pool_get();
94 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
95 char *err = NULL;
96 int rc;
97 int msg_count = 0;
98
99 struct Email **ep = NULL;
100 ARRAY_FOREACH(ep, ea)
101 {
102 struct Email *e = *ep;
103 /* RFC5322 mandates a From: header,
104 * so warn before bouncing messages without one */
105 if (TAILQ_EMPTY(&e->env->from))
106 mutt_error(_("Warning: message contains no From: header"));
107
108 msg_count++;
109 }
110
111 if (msg_count == 1)
112 buf_strcpy(prompt, _("Bounce message to: "));
113 else
114 buf_strcpy(prompt, _("Bounce tagged messages to: "));
115
117 &CompleteAliasOps, NULL);
118 if ((rc != 0) || buf_is_empty(buf))
119 goto done;
120
122 if (TAILQ_EMPTY(&al))
123 {
124 mutt_error(_("Error parsing address"));
125 goto done;
126 }
127
129
130 if (mutt_addrlist_to_intl(&al, &err) < 0)
131 {
132 mutt_error(_("Bad IDN: '%s'"), err);
133 FREE(&err);
134 goto done;
135 }
136
137 buf_reset(buf);
138 mutt_addrlist_write(&al, buf, true);
139
140 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", msg_count),
141 buf_string(buf));
142
143 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
144 {
145 msgwin_clear_text(NULL);
146 mutt_message(ngettext("Message not bounced", "Messages not bounced", msg_count));
147 goto done;
148 }
149
150 msgwin_clear_text(NULL);
151
152 struct Message *msg = NULL;
153 ARRAY_FOREACH(ep, ea)
154 {
155 struct Email *e = *ep;
156 msg = mx_msg_open(m, e);
157 if (!msg)
158 {
159 rc = -1;
160 break;
161 }
162
163 rc = mutt_bounce_message(msg->fp, m, e, &al, NeoMutt->sub);
164 mx_msg_close(m, &msg);
165
166 if (rc < 0)
167 break;
168 }
169
170 /* If no error, or background, display message. */
171 if ((rc == 0) || (rc == S_BKG))
172 mutt_message(ngettext("Message bounced", "Messages bounced", msg_count));
173
174done:
176 buf_pool_release(&buf);
177 buf_pool_release(&prompt);
178}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1460
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1206
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:644
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1293
const struct CompleteOps CompleteAliasOps
Auto-Completion of Aliases.
Definition complete.c:108
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition alias.c:296
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition wdata.h:42
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:271
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
@ HC_ALIAS
Aliases.
Definition lib.h:56
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition msgwin.c:518
#define _(a)
Definition message.h:28
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1182
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1136
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition question.c:378
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
int mutt_bounce_message(FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
Bounce an email message.
Definition sendlib.c:876
#define S_BKG
Definition string2.h:48
String manipulation buffer.
Definition buffer.h:36
The envelope/body of an email.
Definition email.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
struct AddressList from
Email's 'From' list.
Definition envelope.h:59
A local copy of an email.
Definition message.h:34
FILE * fp
pointer to the message data
Definition message.h:35
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_check_traditional_pgp()

bool mutt_check_traditional_pgp ( struct Mailbox * m,
struct EmailArray * ea )

Check if a message has inline PGP content.

Parameters
mMailbox
eaArray of Emails to check
Return values
trueMessage contains inline PGP content

Definition at line 1213 of file external.c.

1214{
1215 bool rc = false;
1216
1217 struct Email **ep = NULL;
1218 ARRAY_FOREACH(ep, ea)
1219 {
1220 struct Email *e = *ep;
1222 rc = check_traditional_pgp(m, e) || rc;
1223 }
1224
1225 return rc;
1226}
static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
Check for an inline PGP content.
Definition external.c:1185
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition lib.h:100
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ external_cleanup()

void external_cleanup ( void )

Clean up commands globals.

Definition at line 77 of file external.c.

78{
80}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition buffer.c:377
static struct Buffer LastSaveFolder
The folder the user last saved to. Used by ci_save_message()
Definition external.c:72
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_display_address()

void mutt_display_address ( struct Envelope * env)

Display the address of a message.

Parameters
envEnvelope containing address

Definition at line 663 of file external.c.

664{
665 const char *pfx = NULL;
666
667 struct AddressList *al = mutt_get_address(env, &pfx);
668 if (!al)
669 return;
670
671 /* Note: We don't convert IDNA to local representation this time.
672 * That is intentional, so the user has an opportunity to copy &
673 * paste the on-the-wire form of the address to other, IDN-unable
674 * software. */
675 struct Buffer *buf = buf_pool_get();
676 mutt_addrlist_write(al, buf, false);
677 mutt_message("%s: %s", pfx, buf_string(buf));
678 buf_pool_release(&buf);
679}
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition alias.c:328
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_edit_content_type()

bool mutt_edit_content_type ( struct Email * e,
struct Body * b,
FILE * fp )

Edit the content type of an attachment.

Parameters
eEmail
bAttachment
fpFile handle to the attachment
Return values
trueA Any change is made

recvattach requires the return code to know when to regenerate the actx.

Definition at line 1072 of file external.c.

1073{
1074 struct Buffer *buf = buf_pool_get();
1075 struct Buffer *charset = buf_pool_get();
1076 struct Buffer *obuf = buf_pool_get();
1077 struct Buffer *tmp = buf_pool_get();
1078
1079 bool rc = false;
1080 bool charset_changed = false;
1081 bool type_changed = false;
1082 bool structure_changed = false;
1083
1084 char *cp = mutt_param_get(&b->parameter, "charset");
1085 buf_strcpy(charset, cp);
1086
1087 buf_printf(buf, "%s/%s", BODY_TYPE(b), b->subtype);
1088 buf_copy(obuf, buf);
1089 if (!TAILQ_EMPTY(&b->parameter))
1090 {
1091 struct Parameter *np = NULL;
1092 TAILQ_FOREACH(np, &b->parameter, entries)
1093 {
1094 mutt_addr_cat(tmp->data, tmp->dsize, np->value, MimeSpecials);
1095 buf_add_printf(buf, "; %s=%s", np->attribute, buf_string(tmp));
1096 }
1097 }
1098
1099 if ((mw_get_field("Content-Type: ", buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
1100 buf_is_empty(buf))
1101 {
1102 goto done;
1103 }
1104
1105 /* clean up previous junk */
1107 FREE(&b->subtype);
1108
1110
1111 buf_printf(tmp, "%s/%s", BODY_TYPE(b), NONULL(b->subtype));
1112 type_changed = !mutt_istr_equal(buf_string(tmp), buf_string(obuf));
1113 charset_changed = !mutt_istr_equal(buf_string(charset),
1114 mutt_param_get(&b->parameter, "charset"));
1115
1116 /* if in send mode, check for conversion - current setting is default. */
1117
1118 if (!e && (b->type == TYPE_TEXT) && charset_changed)
1119 {
1120 buf_printf(tmp, _("Convert to %s upon sending?"),
1121 mutt_param_get(&b->parameter, "charset"));
1122 enum QuadOption ans = query_yesorno(buf_string(tmp), b->noconv ? MUTT_NO : MUTT_YES);
1123 if (ans != MUTT_ABORT)
1124 b->noconv = (ans == MUTT_NO);
1125 }
1126
1127 /* inform the user */
1128
1129 buf_printf(tmp, "%s/%s", BODY_TYPE(b), NONULL(b->subtype));
1130 if (type_changed)
1131 mutt_message(_("Content-Type changed to %s"), buf_string(tmp));
1132 if ((b->type == TYPE_TEXT) && charset_changed)
1133 {
1134 if (type_changed)
1135 mutt_sleep(1);
1136 mutt_message(b->noconv ? _("Character set changed to %s; not converting") :
1137 _("Character set changed to %s; converting"),
1138 mutt_param_get(&b->parameter, "charset"));
1139 }
1140
1141 b->force_charset |= charset_changed;
1142
1143 if (!is_multipart(b) && b->parts)
1144 {
1145 structure_changed = true;
1146 mutt_body_free(&b->parts);
1147 }
1148 if (!mutt_is_message_type(b->type, b->subtype) && b->email)
1149 {
1150 structure_changed = true;
1151 b->email->body = NULL;
1152 email_free(&b->email);
1153 }
1154
1155 if (fp && !b->parts && (is_multipart(b) || mutt_is_message_type(b->type, b->subtype)))
1156 {
1157 structure_changed = true;
1158 mutt_parse_part(fp, b);
1159 }
1160
1161 if ((WithCrypto != 0) && e)
1162 {
1163 if (e->body == b)
1165
1166 e->security |= crypt_query(b);
1167 }
1168
1169 rc = structure_changed | type_changed;
1170
1171done:
1172 buf_pool_release(&buf);
1173 buf_pool_release(&charset);
1174 buf_pool_release(&obuf);
1175 buf_pool_release(&tmp);
1176 return rc;
1177}
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition address.c:708
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:601
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition crypt.c:687
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
void email_free(struct Email **ptr)
Free an Email.
Definition email.c:46
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition parse.c:1833
void mutt_parse_content_type(const char *s, struct Body *b)
Parse a content type.
Definition parse.c:468
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition parse.c:1506
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:60
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition mime.c:67
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
#define BODY_TYPE(body)
Get the type name of a body part.
Definition mime.h:93
#define is_multipart(body)
Check if a body part is multipart or a message container.
Definition mime.h:85
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:674
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:786
#define SEC_NO_FLAGS
No flags are set.
Definition lib.h:85
#define WithCrypto
Definition lib.h:124
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition parameter.c:85
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition parameter.c:62
QuadOption
Possible values for a quad-option.
Definition quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition quad.h:38
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:326
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define NONULL(x)
Definition string2.h:44
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
bool noconv
Don't do character set conversion.
Definition body.h:46
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
struct Email * email
header information for message/rfc822
Definition body.h:74
bool force_charset
Send mode: don't adjust the character set when in send-mode.
Definition body.h:44
char * subtype
content-type subtype
Definition body.h:61
unsigned int type
content-type primary type, ContentType
Definition body.h:40
size_t dsize
Length of data.
Definition buffer.h:39
char * data
Pointer to data.
Definition buffer.h:37
struct Body * body
List of MIME parts.
Definition email.h:69
Attribute associated with a MIME part.
Definition parameter.h:33
char * attribute
Parameter name.
Definition parameter.h:34
char * value
Parameter value.
Definition parameter.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_command()

void mutt_enter_command ( struct MuttWindow * win)

Enter a neomutt command.

Parameters
winFocused Window

Definition at line 619 of file external.c.

620{
621 struct Buffer *buf = buf_pool_get();
622 struct ParseContext *pc = parse_context_new();
623 struct ParseError *pe = parse_error_new();
624
625 window_redraw(NULL);
626
627 /* if enter is pressed after : with no command, just return */
628 struct FileCompletionData cdata = { false, NULL, NULL, NULL, win };
630 &CompleteCommandOps, &cdata) != 0) ||
631 buf_is_empty(buf))
632 {
633 goto done;
634 }
635
636 enum CommandResult rc = parse_rc_line(buf, pc, pe);
637 if (!buf_is_empty(pe->message))
638 {
639 if (rc == MUTT_CMD_SUCCESS) /* command succeeded with message */
640 mutt_message("%s", buf_string(pe->message));
641 else if (rc == MUTT_CMD_ERROR)
642 mutt_error("%s", buf_string(pe->message));
643 else if (rc == MUTT_CMD_WARNING)
644 mutt_warning("%s", buf_string(pe->message));
645 }
646
647 if (NeoMutt)
648 {
649 // Running commands could cause anything to change, so let others know
651 }
652
653done:
654 buf_pool_release(&buf);
656 parse_error_free(&pe);
657}
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:40
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:39
const struct CompleteOps CompleteCommandOps
Auto-Completion of Commands.
Definition helpers.c:532
#define mutt_warning(...)
Definition logging2.h:92
@ HC_NEO_COMMAND
NeoMutt commands.
Definition lib.h:57
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition neomutt.h:72
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition notify_type.h:46
void parse_context_free(struct ParseContext **pptr)
Free a ParseContext.
Definition pcontext.c:48
struct ParseContext * parse_context_new(void)
Create a new ParseContext.
Definition pcontext.c:37
void parse_error_free(struct ParseError **pptr)
Free a ParseError.
Definition perror.c:50
struct ParseError * parse_error_new(void)
Create a new ParseError.
Definition perror.c:37
enum CommandResult parse_rc_line(struct Buffer *line, struct ParseContext *pc, struct ParseError *pe)
Parse a line of user config.
Definition rc.c:45
Input for the file completion function.
Definition curs_lib.h:39
struct MuttWindow * win
Current Focused Window.
Definition curs_lib.h:44
struct Notify * notify
Notifications handler.
Definition neomutt.h:45
Context for config parsing (history/backtrace)
Definition pcontext.h:34
Detailed error information from config parsing.
Definition perror.h:34
struct Buffer * message
Error message.
Definition perror.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pipe_message()

void mutt_pipe_message ( struct Mailbox * m,
struct EmailArray * ea )

Pipe a message.

Parameters
mMailbox
eaArray of Emails to pipe

Definition at line 404 of file external.c.

405{
406 if (!m || !ea)
407 return;
408
409 struct Buffer *buf = buf_pool_get();
410
411 if (mw_get_field(_("Pipe to command: "), buf, MUTT_COMP_NO_FLAGS,
412 HC_EXT_COMMAND, &CompleteFileOps, NULL) != 0)
413 {
414 goto cleanup;
415 }
416
417 if (buf_is_empty(buf))
418 goto cleanup;
419
420 expand_path(buf, false);
421 const bool c_pipe_decode = cs_subset_bool(NeoMutt->sub, "pipe_decode");
422 const bool c_pipe_split = cs_subset_bool(NeoMutt->sub, "pipe_split");
423 const char *const c_pipe_sep = cs_subset_string(NeoMutt->sub, "pipe_sep");
424 pipe_message(m, ea, buf_string(buf), c_pipe_decode, false, c_pipe_split, c_pipe_sep);
425
426cleanup:
427 buf_pool_release(&buf);
428}
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
static int pipe_message(struct Mailbox *m, struct EmailArray *ea, const char *cmd, bool decode, bool print, bool split, const char *sep)
Pipe message to a command.
Definition external.c:275
@ HC_EXT_COMMAND
External commands.
Definition lib.h:55
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:121
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_print_message()

void mutt_print_message ( struct Mailbox * m,
struct EmailArray * ea )

Print a message.

Parameters
mMailbox
eaArray of Emails to print

Definition at line 435 of file external.c.

436{
437 if (!m || !ea)
438 return;
439
440 const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
441 const char *const c_print_command = cs_subset_string(NeoMutt->sub, "print_command");
442 if (c_print && !c_print_command)
443 {
444 mutt_message(_("No printing command has been defined"));
445 return;
446 }
447
448 int msg_count = ARRAY_SIZE(ea);
449 const char *msg = ngettext("Print message?", "Print tagged messages?", msg_count);
450 if (query_quadoption(msg, NeoMutt->sub, "print") != MUTT_YES)
451 {
452 return;
453 }
454
455 const bool c_print_decode = cs_subset_bool(NeoMutt->sub, "print_decode");
456 const bool c_print_split = cs_subset_bool(NeoMutt->sub, "print_split");
457 if (pipe_message(m, ea, c_print_command, c_print_decode, true, c_print_split, "\f") == 0)
458 {
459 mutt_message(ngettext("Message printed", "Messages printed", msg_count));
460 }
461 else
462 {
463 mutt_message(ngettext("Message could not be printed",
464 "Messages could not be printed", msg_count));
465 }
466}
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition helpers.c:192
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_message()

int mutt_save_message ( struct Mailbox * m,
struct EmailArray * ea,
enum MessageSaveOpt save_opt,
enum MessageTransformOpt transform_opt )

Save an email.

Parameters
mMailbox
eaArray of Emails to save
save_optCopy or move, e.g. SAVE_MOVE
transform_optTransformation, e.g. TRANSFORM_DECRYPT
Return values
0Copy/save was successful
-1Error/abort

Definition at line 780 of file external.c.

782{
783 if (!ea || ARRAY_EMPTY(ea))
784 return -1;
785
786 int rc = -1;
787 int tagged_progress_count = 0;
788 unsigned int msg_count = ARRAY_SIZE(ea);
789 struct Mailbox *m_save = NULL;
790
791 struct Buffer *buf = buf_pool_get();
792 struct stat st = { 0 };
793 struct Email *e_cur = *ARRAY_GET(ea, 0);
794
795 const SecurityFlags security_flags = WithCrypto ? e_cur->security : SEC_NO_FLAGS;
796 const bool is_passphrase_needed = security_flags & SEC_ENCRYPT;
797
798 const char *prompt = NULL;
799 const char *progress_msg = NULL;
800
801 // Set prompt and progress_msg
802 switch (save_opt)
803 {
804 case SAVE_COPY:
805 // L10N: Progress meter message when copying tagged messages
806 progress_msg = (msg_count > 1) ? _("Copying tagged messages...") : NULL;
807 switch (transform_opt)
808 {
809 case TRANSFORM_NONE:
810 prompt = (msg_count > 1) ? _("Copy tagged to mailbox") : _("Copy to mailbox");
811 break;
813 prompt = (msg_count > 1) ? _("Decrypt-copy tagged to mailbox") :
814 _("Decrypt-copy to mailbox");
815 break;
816 case TRANSFORM_DECODE:
817 prompt = (msg_count > 1) ? _("Decode-copy tagged to mailbox") :
818 _("Decode-copy to mailbox");
819 break;
820 }
821 break;
822
823 case SAVE_MOVE:
824 // L10N: Progress meter message when saving tagged messages
825 progress_msg = (msg_count > 1) ? _("Saving tagged messages...") : NULL;
826 switch (transform_opt)
827 {
828 case TRANSFORM_NONE:
829 prompt = (msg_count > 1) ? _("Save tagged to mailbox") : _("Save to mailbox");
830 break;
832 prompt = (msg_count > 1) ? _("Decrypt-save tagged to mailbox") :
833 _("Decrypt-save to mailbox");
834 break;
835 case TRANSFORM_DECODE:
836 prompt = (msg_count > 1) ? _("Decode-save tagged to mailbox") :
837 _("Decode-save to mailbox");
838 break;
839 }
840 break;
841 }
842
844 mutt_default_save(buf, e_cur);
845 pretty_mailbox(buf);
846
847 if (mw_enter_fname(prompt, buf, false, NULL, false, NULL, NULL, MUTT_SEL_NO_FLAGS) == -1)
848 {
849 goto cleanup;
850 }
851
852 size_t pathlen = buf_len(buf);
853 if (pathlen == 0)
854 goto cleanup;
855
856 mutt_path_tidy(buf, true);
857
858 /* This is an undocumented feature of ELM pointed out to me by Felix von
859 * Leitner <leitner@prz.fu-berlin.de> */
862 if (mutt_str_equal(buf_string(buf), "."))
864 else
866
867 expand_path(buf, false);
868
869 /* check to make sure that this file is really the one the user wants */
870 if (mutt_save_confirm(buf_string(buf), &st) != 0)
871 goto cleanup;
872
873 if (is_passphrase_needed && (transform_opt != TRANSFORM_NONE) &&
874 !crypt_valid_passphrase(security_flags))
875 {
876 rc = -1;
877 goto errcleanup;
878 }
879
880 mutt_message(_("Copying to %s..."), buf_string(buf));
881
882 enum MailboxType mailbox_type = imap_path_probe(buf_string(buf), NULL);
883 if ((m->type == MUTT_IMAP) && (transform_opt == TRANSFORM_NONE) && (mailbox_type == MUTT_IMAP))
884 {
885 rc = imap_copy_messages(m, ea, buf_string(buf), save_opt);
886 switch (rc)
887 {
888 /* success */
889 case 0:
891 rc = 0;
892 if (save_opt == SAVE_MOVE)
893 {
894 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
895 if (c_delete_untag)
896 {
897 struct Email **ep = NULL;
898 ARRAY_FOREACH(ep, ea)
899 {
900 mutt_set_flag(m, *ep, MUTT_TAG, false, true);
901 }
902 }
903 }
904 goto cleanup;
905 /* non-fatal error: continue to fetch/append */
906 case 1:
907 break;
908 /* fatal error, abort */
909 case -1:
910 goto errcleanup;
911 }
912 }
913
915 m_save = mx_path_resolve(buf_string(buf));
916 bool old_append = m_save->append;
917 OpenMailboxFlags mbox_flags = MUTT_APPEND;
918 /* Display a tagged message progress counter, rather than (for
919 * IMAP) a per-message progress counter */
920 if (msg_count > 1)
921 mbox_flags |= MUTT_QUIET;
922 if (!mx_mbox_open(m_save, mbox_flags))
923 {
924 rc = -1;
925 mailbox_free(&m_save);
926 goto errcleanup;
927 }
928 m_save->append = true;
929
930 /* If we're saving to a compressed mailbox, the stats won't be updated
931 * until the next open. Until then, improvise. */
932 struct Mailbox *m_comp = NULL;
933 if (m_save->compress_info)
934 {
935 m_comp = mailbox_find(m_save->realpath);
936 }
937 /* We probably haven't been opened yet */
938 if (m_comp && (m_comp->msg_count == 0))
939 m_comp = NULL;
940
941 if (msg_count == 1)
942 {
943 rc = mutt_save_message_mbox(m, e_cur, save_opt, transform_opt, m_save);
944 if (rc != 0)
945 {
946 mx_mbox_close(m_save);
947 m_save->append = old_append;
948 goto errcleanup;
949 }
950
951 if (m_comp)
952 {
953 m_comp->msg_count++;
954 if (!e_cur->read)
955 {
956 m_comp->msg_unread++;
957 if (!e_cur->old)
958 m_comp->msg_new++;
959 }
960 if (e_cur->flagged)
961 m_comp->msg_flagged++;
962 }
963 }
964 else
965 {
966 rc = 0;
967
968#ifdef USE_NOTMUCH
969 if (m->type == MUTT_NOTMUCH)
970 nm_db_longrun_init(m, true);
971#endif
972 struct Progress *progress = progress_new(MUTT_PROGRESS_WRITE, msg_count);
973 progress_set_message(progress, "%s", progress_msg);
974 struct Email **ep = NULL;
975 ARRAY_FOREACH(ep, ea)
976 {
977 struct Email *e = *ep;
978 progress_update(progress, ++tagged_progress_count, -1);
980 rc = mutt_save_message_mbox(m, e, save_opt, transform_opt, m_save);
981 if (rc != 0)
982 break;
983
984 if (m_comp)
985 {
986 struct Email *e2 = e;
987 m_comp->msg_count++;
988 if (!e2->read)
989 {
990 m_comp->msg_unread++;
991 if (!e2->old)
992 m_comp->msg_new++;
993 }
994 if (e2->flagged)
995 m_comp->msg_flagged++;
996 }
997 }
998 progress_free(&progress);
999
1000#ifdef USE_NOTMUCH
1001 if (m->type == MUTT_NOTMUCH)
1003#endif
1004 if (rc != 0)
1005 {
1006 mx_mbox_close(m_save);
1007 m_save->append = old_append;
1008 goto errcleanup;
1009 }
1010 }
1011
1012 const bool need_mailbox_cleanup = ((m_save->type == MUTT_MBOX) ||
1013 (m_save->type == MUTT_MMDF));
1014
1015 mx_mbox_close(m_save);
1016 m_save->append = old_append;
1017
1018 if (need_mailbox_cleanup)
1020
1022 rc = 0;
1023
1024errcleanup:
1025 if (rc != 0)
1026 {
1027 switch (save_opt)
1028 {
1029 case SAVE_MOVE:
1030 if (msg_count > 1)
1031 {
1032 // L10N: Message when an index tagged save operation fails for some reason
1033 mutt_error(_("Error saving tagged messages"));
1034 }
1035 else
1036 {
1037 // L10N: Message when an index/pager save operation fails for some reason
1038 mutt_error(_("Error saving message"));
1039 }
1040 break;
1041 case SAVE_COPY:
1042 if (msg_count > 1)
1043 {
1044 // L10N: Message when an index tagged copy operation fails for some reason
1045 mutt_error(_("Error copying tagged messages"));
1046 }
1047 else
1048 {
1049 // L10N: Message when an index/pager copy operation fails for some reason
1050 mutt_error(_("Error copying message"));
1051 }
1052 break;
1053 }
1054 }
1055
1056 mailbox_free(&m_save);
1057
1058cleanup:
1059 buf_pool_release(&buf);
1060 return rc;
1061}
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition lib.h:58
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition buffer.c:491
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:337
@ CMD_MESSAGE_HOOK
:message-hook
Definition command.h:94
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:90
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition mailbox.c:151
MailboxType
Supported mailbox formats.
Definition mailbox.h:40
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:50
@ MUTT_MMDF
'mmdf' Mailbox type
Definition mailbox.h:45
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
@ MUTT_MBOX
'mbox' Mailbox type
Definition mailbox.h:44
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition crypt.c:131
int mutt_save_message_mbox(struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
Save a message to a given mailbox.
Definition external.c:739
void mutt_file_resolve_symlink(struct Buffer *buf)
Resolve a symlink in place.
Definition file.c:1549
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:54
int mw_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox, struct Mailbox *m, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file -.
Definition curs_lib.c:236
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2543
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition exec.c:214
void exec_message_hook(struct Mailbox *m, struct Email *e, enum CommandId id)
Perform a message hook.
Definition exec.c:135
int imap_copy_messages(struct Mailbox *m, struct EmailArray *ea, const char *dest, enum MessageSaveOpt save_opt)
Server COPY messages to another folder.
Definition message.c:1703
bool mutt_path_tidy(struct Buffer *path, bool is_dir)
Remove unnecessary parts of a path.
Definition path.c:169
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:662
@ MUTT_TAG
Tagged messages.
Definition mutt.h:98
#define PATH_MAX
Definition mutt.h:48
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
void mailbox_restore_timestamp(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:427
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition muttlib.c:689
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:285
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1647
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition mx.c:595
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition mxapi.h:38
#define MUTT_APPEND
Open mailbox for appending messages.
Definition mxapi.h:41
#define MUTT_QUIET
Do not print any messages.
Definition mxapi.h:43
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition lib.h:84
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:86
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition db.c:379
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition db.c:364
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
Definition lib.h:85
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition progress.c:80
bool read
Email is read.
Definition email.h:50
bool old
Email is seen, but unread.
Definition email.h:49
bool flagged
Marked important?
Definition email.h:47
A mailbox.
Definition mailbox.h:78
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:80
bool append
Mailbox is opened in append mode.
Definition mailbox.h:108
int msg_new
Number of new messages.
Definition mailbox.h:91
int msg_count
Total number of messages.
Definition mailbox.h:87
enum MailboxType type
Mailbox type.
Definition mailbox.h:101
int msg_flagged
Number of flagged messages.
Definition mailbox.h:89
void * compress_info
Compressed mbox module private data.
Definition mailbox.h:120
int msg_unread
Number of unread messages.
Definition mailbox.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_message_mbox()

int mutt_save_message_mbox ( struct Mailbox * m_src,
struct Email * e,
enum MessageSaveOpt save_opt,
enum MessageTransformOpt transform_opt,
struct Mailbox * m_dst )

Save a message to a given mailbox.

Parameters
m_srcMailbox to copy from
eEmail
save_optCopy or move, e.g. SAVE_MOVE
transform_optTransformation, e.g. TRANSFORM_DECRYPT
m_dstMailbox to save to
Return values
0Success
-1Error

Definition at line 739 of file external.c.

741{
744 int rc;
745
746 set_copy_flags(e, transform_opt, &cmflags, &chflags);
747
748 struct Message *msg = mx_msg_open(m_src, e);
749 if (msg && transform_opt != TRANSFORM_NONE)
750 {
752 }
753
754 rc = mutt_append_message(m_dst, m_src, e, msg, cmflags, chflags);
755 mx_msg_close(m_src, &msg);
756 if (rc != 0)
757 return rc;
758
759 if (save_opt == SAVE_MOVE)
760 {
761 mutt_set_flag(m_src, e, MUTT_DELETE, true, true);
762 mutt_set_flag(m_src, e, MUTT_PURGE, true, true);
763 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
764 if (c_delete_untag)
765 mutt_set_flag(m_src, e, MUTT_TAG, false, true);
766 }
767
768 return 0;
769}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition commands.c:622
int mutt_append_message(struct Mailbox *m_dst, struct Mailbox *m_src, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Append a message.
Definition copy_email.c:992
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition copy_email.h:54
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition copy_email.h:37
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition copy_email.h:36
#define CH_NO_FLAGS
No flags are set.
Definition copy_email.h:55
static void set_copy_flags(struct Email *e, enum MessageTransformOpt transform_opt, CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
Set the flags for a message copy.
Definition external.c:688
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition mutt.h:95
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:93
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_select_sort()

bool mutt_select_sort ( bool reverse)

Ask the user for a sort method.

Parameters
reverseIf true make it a reverse sort
Return values
trueThe sort type changed

Definition at line 473 of file external.c.

474{
475 enum EmailSortType sort = EMAIL_SORT_DATE;
476
477 switch (mw_multi_choice(reverse ?
478 /* L10N: The highlighted letters must match the "Sort" options */
479 _("Rev-Sort (d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)nsort,si(z)e,s(c)ore,s(p)am,(l)abel?") :
480 /* L10N: The highlighted letters must match the "Rev-Sort" options */
481 _("Sort (d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)nsort,si(z)e,s(c)ore,s(p)am,(l)abel?"),
482 /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
483 _("dfrsotuzcpl")))
484 {
485 case -1: /* abort - don't resort */
486 return false;
487
488 case 1: /* (d)ate */
489 sort = EMAIL_SORT_DATE;
490 break;
491
492 case 2: /* (f)rm */
493 sort = EMAIL_SORT_FROM;
494 break;
495
496 case 3: /* (r)ecv */
498 break;
499
500 case 4: /* (s)ubj */
501 sort = EMAIL_SORT_SUBJECT;
502 break;
503
504 case 5: /* t(o) */
505 sort = EMAIL_SORT_TO;
506 break;
507
508 case 6: /* (t)hread */
509 sort = EMAIL_SORT_THREADS;
510 break;
511
512 case 7: /* (u)nsort */
513 sort = EMAIL_SORT_UNSORTED;
514 break;
515
516 case 8: /* si(z)e */
517 sort = EMAIL_SORT_SIZE;
518 break;
519
520 case 9: /* s(c)ore */
521 sort = EMAIL_SORT_SCORE;
522 break;
523
524 case 10: /* s(p)am */
525 sort = EMAIL_SORT_SPAM;
526 break;
527
528 case 11: /* (l)abel */
529 sort = EMAIL_SORT_LABEL;
530 break;
531 }
532
533 const unsigned char c_use_threads = cs_subset_enum(NeoMutt->sub, "use_threads");
534 const enum EmailSortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
535 int rc = CSR_ERR_CODE;
536 if ((sort != EMAIL_SORT_THREADS) || (c_use_threads == UT_UNSET))
537 {
538 if ((sort != EMAIL_SORT_THREADS) && (c_sort & SORT_LAST))
539 sort |= SORT_LAST;
540 if (reverse)
541 sort |= SORT_REVERSE;
542
543 rc = cs_subset_str_native_set(NeoMutt->sub, "sort", sort, NULL);
544 }
545 else
546 {
547 ASSERT((c_sort & SORT_MASK) != EMAIL_SORT_THREADS); /* See index_config_observer() */
548 /* Preserve the value of $sort, and toggle whether we are threaded. */
549 switch (c_use_threads)
550 {
551 case UT_FLAT:
552 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
553 reverse ? UT_REVERSE : UT_THREADS, NULL);
554 break;
555 case UT_THREADS:
556 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
557 reverse ? UT_REVERSE : UT_FLAT, NULL);
558 break;
559 case UT_REVERSE:
560 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
561 reverse ? UT_FLAT : UT_THREADS, NULL);
562 break;
563 default:
564 ASSERT(false);
565 }
566 }
567
568 return ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE));
569}
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition helpers.c:71
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition helpers.c:266
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition set.h:42
#define CSR_ERR_CODE
Problem with the code.
Definition set.h:34
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
#define SORT_MASK
Mask for the sort id.
Definition sort.h:39
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition sort.h:41
#define SORT_REVERSE
Reverse the order of the sort.
Definition sort.h:40
EmailSortType
Methods for sorting Emails.
Definition sort.h:53
@ EMAIL_SORT_LABEL
Sort by the emails label.
Definition sort.h:57
@ EMAIL_SORT_DATE_RECEIVED
Sort by when the message was delivered locally.
Definition sort.h:55
@ EMAIL_SORT_SPAM
Sort by the email's spam score.
Definition sort.h:60
@ EMAIL_SORT_SCORE
Sort by the email's score.
Definition sort.h:58
@ EMAIL_SORT_DATE
Sort by the date the email was sent.
Definition sort.h:54
@ EMAIL_SORT_THREADS
Sort by email threads.
Definition sort.h:62
@ EMAIL_SORT_SUBJECT
Sort by the email's subject.
Definition sort.h:61
@ EMAIL_SORT_FROM
Sort by the email's From field.
Definition sort.h:56
@ EMAIL_SORT_UNSORTED
Sort by the order the messages appear in the mailbox.
Definition sort.h:64
@ EMAIL_SORT_SIZE
Sort by the size of the email.
Definition sort.h:59
@ EMAIL_SORT_TO
Sort by the email's To field.
Definition sort.h:63
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition question.c:62
@ UT_FLAT
Unthreaded.
Definition thread.h:98
@ UT_UNSET
Not yet set by user, stick to legacy semantics.
Definition thread.h:97
@ UT_THREADS
Normal threading (root above subthreads)
Definition thread.h:99
@ UT_REVERSE
Reverse threading (subthreads above root)
Definition thread.h:100
#define ASSERT(COND)
Definition signal2.h:59
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_shell_escape()

bool mutt_shell_escape ( void )

Invoke a command in a subshell.

Return values
trueA command was invoked (no matter what its result)
falseNo command was invoked

Definition at line 576 of file external.c.

577{
578 bool rc = false;
579 struct Buffer *buf = buf_pool_get();
580
581 if (mw_get_field(_("Shell command: "), buf, MUTT_COMP_NO_FLAGS,
582 HC_EXT_COMMAND, &CompleteFileOps, NULL) != 0)
583 {
584 goto done;
585 }
586
587 if (buf_is_empty(buf))
588 {
589 const char *const c_shell = cs_subset_string(NeoMutt->sub, "shell");
590 buf_strcpy(buf, c_shell);
591 }
592
593 if (buf_is_empty(buf))
594 {
595 goto done;
596 }
597
598 msgwin_clear_text(NULL);
599 mutt_endwin();
600 fflush(stdout);
601 int rc2 = mutt_system(buf_string(buf));
602 if (rc2 == -1)
603 mutt_debug(LL_DEBUG1, "Error running \"%s\"\n", buf_string(buf));
604
605 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
606 if ((rc2 != 0) || c_wait_key)
608
609 rc = true;
610done:
611 buf_pool_release(&buf);
612 return rc;
613}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition curs_lib.c:173
void mutt_endwin(void)
Shutdown curses.
Definition curs_lib.c:151
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
int mutt_system(const char *cmd)
Run an external command.
Definition system.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function: