NeoMutt  2018-07-16 +952-a2da0a
Teaching an old dog new tricks
DOXYGEN
postpone.c File Reference

Save/restore and GUI list postponed emails. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "context.h"
#include "format_flags.h"
#include "globals.h"
#include "handler.h"
#include "hdrline.h"
#include "keymap.h"
#include "mailbox.h"
#include "menu.h"
#include "mutt_logging.h"
#include "mutt_thread.h"
#include "muttlib.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "protos.h"
#include "send.h"
#include "sendlib.h"
#include "sort.h"
#include "state.h"
#include "imap/imap.h"
+ Include dependency graph for postpone.c:

Go to the source code of this file.

Functions

int mutt_num_postponed (struct Mailbox *m, bool force)
 Return the number of postponed messages. More...
 
void mutt_update_num_postponed (void)
 Force the update of the number of postponed messages. More...
 
static void post_make_entry (char *buf, size_t buflen, struct Menu *menu, int line)
 Format a menu item for the email list - Implements Menu::menu_make_entry() More...
 
static struct Emailselect_msg (void)
 Create a Menu to select a postponed message. More...
 
int mutt_get_postponed (struct Context *ctx, struct Email *hdr, struct Email **cur, char *fcc, size_t fcclen)
 Recall a postponed message. More...
 
int mutt_parse_crypt_hdr (const char *p, int set_empty_signas, int crypt_app)
 Parse a crypto header string. More...
 
int mutt_prepare_template (FILE *fp, struct Mailbox *m, struct Email *newhdr, struct Email *e, bool resend)
 Prepare a message template. More...
 

Variables

static const struct Mapping PostponeHelp []
 
static short PostCount = 0
 
static struct ContextPostContext = NULL
 
static short UpdateNumPostponed = 0
 

Detailed Description

Save/restore and GUI list postponed emails.

Authors
  • Michael R. Elkins
  • Thomas Roessler

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 postpone.c.

Function Documentation

int mutt_num_postponed ( struct Mailbox m,
bool  force 
)

Return the number of postponed messages.

Parameters
mcurrently selected mailbox
force
  • false Use a cached value if costly to get a fresh count (IMAP)
  • true Force check
Return values
numPostponed messages

Definition at line 86 of file postpone.c.

87 {
88  struct stat st;
89 
90  static time_t LastModify = 0;
91  static char *OldPostponed = NULL;
92 
94  {
96  force = true;
97  }
98 
99  if (mutt_str_strcmp(Postponed, OldPostponed) != 0)
100  {
101  FREE(&OldPostponed);
102  OldPostponed = mutt_str_strdup(Postponed);
103  LastModify = 0;
104  force = true;
105  }
106 
107  if (!Postponed)
108  return 0;
109 
110  // We currently are in the Postponed mailbox so just pick the current status
111  if (m && mutt_str_strcmp(Postponed, m->realpath) == 0)
112  {
113  PostCount = m->msg_count - m->msg_deleted;
114  return PostCount;
115  }
116 
117 #ifdef USE_IMAP
118  /* LastModify is useless for IMAP */
119  if (imap_path_probe(Postponed, NULL) == MUTT_IMAP)
120  {
121  if (force)
122  {
123  short newpc;
124 
125  newpc = imap_path_status(Postponed, false);
126  if (newpc >= 0)
127  {
128  PostCount = newpc;
129  mutt_debug(3, "%d postponed IMAP messages found.\n", PostCount);
130  }
131  else
132  mutt_debug(3, "using old IMAP postponed count.\n");
133  }
134  return PostCount;
135  }
136 #endif
137 
138  if (stat(Postponed, &st) == -1)
139  {
140  PostCount = 0;
141  LastModify = 0;
142  return 0;
143  }
144 
145  if (S_ISDIR(st.st_mode))
146  {
147  /* if we have a maildir mailbox, we need to stat the "new" dir */
148 
149  char buf[PATH_MAX];
150 
151  snprintf(buf, sizeof(buf), "%s/new", Postponed);
152  if (access(buf, F_OK) == 0 && stat(buf, &st) == -1)
153  {
154  PostCount = 0;
155  LastModify = 0;
156  return 0;
157  }
158  }
159 
160  if (LastModify < st.st_mtime)
161  {
162 #ifdef USE_NNTP
163  int optnews = OptNews;
164 #endif
165  LastModify = st.st_mtime;
166 
167  if (access(Postponed, R_OK | F_OK) != 0)
168  return PostCount = 0;
169 #ifdef USE_NNTP
170  if (optnews)
171  OptNews = false;
172 #endif
173  struct Context *ctx = mx_mbox_open(NULL, Postponed, MUTT_NOSORT | MUTT_QUIET);
174  if (!ctx)
175  PostCount = 0;
176  else
177  PostCount = ctx->mailbox->msg_count;
179  mutt_context_free(&ctx);
180 #ifdef USE_NNTP
181  if (optnews)
182  OptNews = true;
183 #endif
184  }
185 
186  return PostCount;
187 }
The "current" mailbox.
Definition: context.h:36
int msg_count
total number of messages
Definition: mailbox.h:86
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1318
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP mailbox? - Implements MxOps::path_probe()
Definition: imap.c:2479
int msg_deleted
number of deleted messages
Definition: mailbox.h:90
WHERE char * Postponed
Config: Folder to store postponed messages.
Definition: globals.h:137
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
struct Context * mx_mbox_open(struct Mailbox *m, const char *path, int flags)
Open a mailbox and parse it.
Definition: mx.c:254
struct Mailbox * mailbox
Definition: context.h:50
#define PATH_MAX
Definition: mutt.h:46
#define MUTT_NOSORT
do not sort the mailbox after opening it
Definition: mx.h:49
void mx_fastclose_mailbox(struct Context *ctx)
free up memory associated with the mailbox context
Definition: mx.c:404
static short PostCount
Definition: postpone.c:74
#define MUTT_QUIET
do not print any messages
Definition: mx.h:52
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
static short UpdateNumPostponed
Definition: postpone.c:76
#define FREE(x)
Definition: memory.h:46
char realpath[PATH_MAX]
used for duplicate detection, context comparison, and the sidebar
Definition: mailbox.h:79
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
WHERE bool OptNews
(pseudo) used to change reader mode
Definition: options.h:42
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612
void mutt_context_free(struct Context **ctx)
Free a Context.
Definition: mailbox.c:730

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void mutt_update_num_postponed ( void  )

Force the update of the number of postponed messages.

Definition at line 192 of file postpone.c.

193 {
194  UpdateNumPostponed = 1;
195 }
static short UpdateNumPostponed
Definition: postpone.c:76

+ Here is the caller graph for this function:

static void post_make_entry ( char *  buf,
size_t  buflen,
struct Menu menu,
int  line 
)
static

Format a menu item for the email list - Implements Menu::menu_make_entry()

Definition at line 200 of file postpone.c.

201 {
202  struct Context *ctx = menu->data;
203 
204  mutt_make_string_flags(buf, buflen, NONULL(IndexFormat), ctx,
206 }
The "current" mailbox.
Definition: context.h:36
#define NONULL(x)
Definition: string2.h:39
WHERE char * IndexFormat
Config: printf-like format string for the index menu (emails)
Definition: globals.h:112
struct Email ** hdrs
Definition: mailbox.h:93
struct Mailbox * mailbox
Definition: context.h:50
const char * line
Definition: common.c:35
reserve space for arrow_cursor
Definition: format_flags.h:38
void mutt_make_string_flags(char *buf, size_t buflen, const char *s, struct Context *ctx, struct Email *e, enum FormatFlag flags)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1454
void * data
extra data for the current menu
Definition: menu.h:60

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static struct Email* select_msg ( void  )
static

Create a Menu to select a postponed message.

Return values
ptrEmail Header

Definition at line 212 of file postpone.c.

213 {
214  int r = -1;
215  bool done = false;
216  char helpstr[LONG_STRING];
217 
218  struct Menu *menu = mutt_menu_new(MENU_POST);
220  menu->max = PostContext->mailbox->msg_count;
221  menu->title = _("Postponed Messages");
222  menu->data = PostContext;
223  menu->help = mutt_compile_help(helpstr, sizeof(helpstr), MENU_POST, PostponeHelp);
225 
226  /* The postponed mailbox is setup to have sorting disabled, but the global
227  * Sort variable may indicate something different. Sorting has to be
228  * disabled while the postpone menu is being displayed. */
229  const short orig_sort = Sort;
230  Sort = SORT_ORDER;
231 
232  while (!done)
233  {
234  const int i = mutt_menu_loop(menu);
235  switch (i)
236  {
237  case OP_DELETE:
238  case OP_UNDELETE:
239  /* should deleted draft messages be saved in the trash folder? */
241  MUTT_DELETE, (i == OP_DELETE) ? 1 : 0);
243  if (Resolve && menu->current < menu->max - 1)
244  {
245  menu->oldcurrent = menu->current;
246  menu->current++;
247  if (menu->current >= menu->top + menu->pagelen)
248  {
249  menu->top = menu->current;
250  menu->redraw |= REDRAW_INDEX | REDRAW_STATUS;
251  }
252  else
253  menu->redraw |= REDRAW_MOTION_RESYNCH;
254  }
255  else
256  menu->redraw |= REDRAW_CURRENT;
257  break;
258 
259  case OP_GENERIC_SELECT_ENTRY:
260  r = menu->current;
261  done = true;
262  break;
263 
264  case OP_EXIT:
265  done = true;
266  break;
267  }
268  }
269 
270  Sort = orig_sort;
271  mutt_menu_pop_current(menu);
272  mutt_menu_destroy(&menu);
273  return r > -1 ? PostContext->mailbox->hdrs[r] : NULL;
274 }
static const struct Mapping PostponeHelp[]
Definition: postpone.c:66
int msg_count
total number of messages
Definition: mailbox.h:86
int redraw
when to redraw the screen
Definition: menu.h:63
GUI selectable list of items.
Definition: menu.h:56
int msg_deleted
number of deleted messages
Definition: mailbox.h:90
int oldcurrent
for driver use only
Definition: menu.h:85
Messages to be deleted.
Definition: mutt.h:118
#define _(a)
Definition: message.h:28
int menu
menu definition for keymap entries.
Definition: menu.h:64
#define LONG_STRING
Definition: string2.h:36
void(* menu_make_entry)(char *buf, size_t buflen, struct Menu *menu, int line)
Format a item for a menu.
Definition: menu.h:96
struct Email ** hdrs
Definition: mailbox.h:93
char * mutt_compile_help(char *buf, size_t buflen, int menu, const struct Mapping *items)
Create the text for the help menu.
Definition: help.c:115
static void post_make_entry(char *buf, size_t buflen, struct Menu *menu, int line)
Format a menu item for the email list - Implements Menu::menu_make_entry()
Definition: postpone.c:200
struct Mailbox * mailbox
Definition: context.h:50
WHERE bool Resolve
Config: Move to the next email whenever a command modifies an email.
Definition: globals.h:248
static struct Context * PostContext
Definition: postpone.c:75
int top
entry that is the top of the current page
Definition: menu.h:84
static short PostCount
Definition: postpone.c:74
#define mutt_set_flag(a, b, c, d)
Definition: protos.h:54
int pagelen
number of entries per screen
Definition: menu.h:66
Select a postponed email.
Definition: keymap.h:75
int max
the number of entries in the menu
Definition: menu.h:62
char * title
the title of this menu
Definition: menu.h:58
WHERE short Sort
Config: Sort method for the index.
Definition: sort.h:58
void * data
extra data for the current menu
Definition: menu.h:60
int current
current entry
Definition: menu.h:61
char * help
quickref for the current menu
Definition: menu.h:59
#define SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort.h:50

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_get_postponed ( struct Context ctx,
struct Email hdr,
struct Email **  cur,
char *  fcc,
size_t  fcclen 
)

Recall a postponed message.

Parameters
ctxContext info, used when recalling a message to which we reply
hdrenvelope/attachment info for recalled message
curif message was a reply, `cur' is set to the message which `hdr' is in reply to
fccfcc for the recalled message
fcclenmax length of fcc
Return values
-1Error/no messages
0Normal exit
SEND_REPLYRecalled message is a reply

Definition at line 287 of file postpone.c.

289 {
290  struct Email *e = NULL;
291  int code = SEND_POSTPONED;
292  const char *p = NULL;
293  int opt_delete;
294 
295  if (!Postponed)
296  return -1;
297 
298  struct Mailbox *m = mx_mbox_find2(Postponed);
299  if (ctx->mailbox == m)
300  PostContext = ctx;
301  else
303 
304  if (!PostContext)
305  {
306  PostCount = 0;
307  mutt_error(_("No postponed messages"));
308  return -1;
309  }
310 
312  {
313  PostCount = 0;
314  if (PostContext == ctx)
315  PostContext = NULL;
316  else
317  mx_mbox_close(&PostContext, NULL);
318  mutt_error(_("No postponed messages"));
319  return -1;
320  }
321 
322  if (PostContext->mailbox->msg_count == 1)
323  {
324  /* only one message, so just use that one. */
325  e = PostContext->mailbox->hdrs[0];
326  }
327  else if (!(e = select_msg()))
328  {
329  if (PostContext == ctx)
330  PostContext = NULL;
331  else
332  mx_mbox_close(&PostContext, NULL);
333  return -1;
334  }
335 
336  if (mutt_prepare_template(NULL, PostContext->mailbox, hdr, e, false) < 0)
337  {
338  if (PostContext != ctx)
339  {
341  FREE(&PostContext);
342  }
343  return -1;
344  }
345 
346  /* finished with this message, so delete it. */
349 
350  /* update the count for the status display */
352 
353  /* avoid the "purge deleted messages" prompt */
354  opt_delete = Delete;
355  Delete = MUTT_YES;
356  if (PostContext == ctx)
357  PostContext = NULL;
358  else
359  mx_mbox_close(&PostContext, NULL);
360  Delete = opt_delete;
361 
362  struct ListNode *np, *tmp;
363  STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
364  {
365  size_t plen = mutt_str_startswith(np->data, "X-Mutt-References:", CASE_IGNORE);
366  if (plen)
367  {
368  if (ctx)
369  {
370  /* if a mailbox is currently open, look to see if the original message
371  the user attempted to reply to is in this mailbox */
372  p = mutt_str_skip_email_wsp(np->data + plen);
373  if (!ctx->mailbox->id_hash)
375  *cur = mutt_hash_find(ctx->mailbox->id_hash, p);
376  }
377  if (*cur)
378  code |= SEND_REPLY;
379  }
380  else if ((plen = mutt_str_startswith(np->data, "X-Mutt-Fcc:", CASE_IGNORE)))
381  {
382  p = mutt_str_skip_email_wsp(np->data + plen);
383  mutt_str_strfcpy(fcc, p, fcclen);
384  mutt_pretty_mailbox(fcc, fcclen);
385 
386  /* note that x-mutt-fcc was present. we do this because we want to add a
387  * default fcc if the header was missing, but preserve the request of the
388  * user to not make a copy if the header field is present, but empty.
389  * see http://dev.mutt.org/trac/ticket/3653
390  */
391  code |= SEND_POSTPONED_FCC;
392  }
393  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
394  /* this is generated by old neomutt versions */
395  (mutt_str_startswith(np->data, "Pgp:", CASE_MATCH) ||
396  /* this is the new way */
397  mutt_str_startswith(np->data, "X-Mutt-PGP:", CASE_MATCH)))
398  {
399  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, 1, APPLICATION_PGP);
400  hdr->security |= APPLICATION_PGP;
401  }
402  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
403  mutt_str_startswith(np->data, "X-Mutt-SMIME:", CASE_MATCH))
404  {
405  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, 1, APPLICATION_SMIME);
406  hdr->security |= APPLICATION_SMIME;
407  }
408 
409 #ifdef MIXMASTER
410  else if (mutt_str_startswith(np->data, "X-Mutt-Mix:", CASE_MATCH))
411  {
412  mutt_list_free(&hdr->chain);
413 
414  char *t = strtok(np->data + 11, " \t\n");
415  while (t)
416  {
417  mutt_list_insert_tail(&hdr->chain, mutt_str_strdup(t));
418  t = strtok(NULL, " \t\n");
419  }
420  }
421 #endif
422 
423  else
424  {
425  // skip header removal
426  continue;
427  }
428 
429  // remove the header
430  STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
431  FREE(&np->data);
432  FREE(&np);
433  }
434 
437 
438  return code;
439 }
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:400
int msg_count
total number of messages
Definition: mailbox.h:86
#define SEND_POSTPONED_FCC
used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present ...
Definition: send.h:91
The envelope/body of an email.
Definition: email.h:35
int msg_deleted
number of deleted messages
Definition: mailbox.h:90
void mutt_pretty_mailbox(char *s, size_t buflen)
Shorten a mailbox path using &#39;~&#39; or &#39;=&#39;.
Definition: muttlib.c:606
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
Messages to be deleted.
Definition: mutt.h:118
static size_t plen
Length of cached packet.
Definition: pgppacket.c:38
void * mutt_hash_find(const struct Hash *table, const char *strkey)
Find the HashElem data in a Hash table element using a key.
Definition: hash.c:374
WHERE char * Postponed
Config: Folder to store postponed messages.
Definition: globals.h:137
struct ListHead userhdrs
user defined headers
Definition: envelope.h:61
#define _(a)
Definition: message.h:28
Match case when comparing strings.
Definition: string2.h:69
struct Mailbox * mx_mbox_find2(const char *path)
XXX.
Definition: mx.c:1714
#define SEND_POSTPONED
Definition: send.h:86
struct Email ** hdrs
Definition: mailbox.h:93
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:105
struct Context * mx_mbox_open(struct Mailbox *m, const char *path, int flags)
Open a mailbox and parse it.
Definition: mx.c:254
struct Mailbox * mailbox
Definition: context.h:50
static struct Email * select_msg(void)
Create a Menu to select a postponed message.
Definition: postpone.c:212
struct Envelope * env
envelope information
Definition: email.h:91
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:360
static struct Context * PostContext
Definition: postpone.c:75
int mx_mbox_close(struct Context **pctx, int *index_hint)
Save changes and close mailbox.
Definition: mx.c:568
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:58
void crypt_opportunistic_encrypt(struct Email *msg)
Can all recipients be determined.
Definition: crypt.c:1021
A mailbox.
Definition: mailbox.h:76
#define MUTT_NOSORT
do not sort the mailbox after opening it
Definition: mx.h:49
void mx_fastclose_mailbox(struct Context *ctx)
free up memory associated with the mailbox context
Definition: mx.c:404
Messages to be purged (bypass trash)
Definition: mutt.h:120
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *newhdr, struct Email *e, bool resend)
Prepare a message template.
Definition: postpone.c:580
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
static short PostCount
Definition: postpone.c:74
#define mutt_set_flag(a, b, c, d)
Definition: protos.h:54
Ignore case when comparing strings.
Definition: string2.h:70
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:768
#define SEND_REPLY
Definition: send.h:82
struct Hash * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1439
#define APPLICATION_PGP
Definition: ncrypt.h:129
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:166
WHERE unsigned char Delete
Config: Really delete messages, when the mailbox is closed.
Definition: globals.h:187
char * data
Definition: list.h:35
WHERE bool CryptOpportunisticEncrypt
Config: Enable encryption when the recipient&#39;s key is available.
Definition: globals.h:271
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
int mutt_parse_crypt_hdr(const char *p, int set_empty_signas, int crypt_app)
Parse a crypto header string.
Definition: postpone.c:448
#define mutt_error(...)
Definition: logging.h:88
#define FREE(x)
Definition: memory.h:46
A List node for strings.
Definition: list.h:33
#define WithCrypto
Definition: ncrypt.h:154
struct Hash * id_hash
hash table by msg id
Definition: mailbox.h:121
#define APPLICATION_SMIME
Definition: ncrypt.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_parse_crypt_hdr ( const char *  p,
int  set_empty_signas,
int  crypt_app 
)

Parse a crypto header string.

Parameters
pHeader string to parse
set_empty_signasAllow an empty "Sign as"
crypt_appApp, e.g. APPLICATION_PGP
Return values
numFlags, e.g. ENCRYPT

Definition at line 448 of file postpone.c.

449 {
450  char smime_cryptalg[LONG_STRING] = "\0";
451  char sign_as[LONG_STRING] = "\0", *q = NULL;
452  int flags = 0;
453 
454  if (!WithCrypto)
455  return 0;
456 
458  for (; *p; p++)
459  {
460  switch (*p)
461  {
462  case 'c':
463  case 'C':
464  q = smime_cryptalg;
465 
466  if (*(p + 1) == '<')
467  {
468  for (p += 2; *p && (*p != '>') &&
469  (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
470  *q++ = *p++)
471  {
472  }
473 
474  if (*p != '>')
475  {
476  mutt_error(_("Illegal S/MIME header"));
477  return 0;
478  }
479  }
480 
481  *q = '\0';
482  break;
483 
484  case 'e':
485  case 'E':
486  flags |= ENCRYPT;
487  break;
488 
489  case 'i':
490  case 'I':
491  flags |= INLINE;
492  break;
493 
494  /* This used to be the micalg parameter.
495  *
496  * It's no longer needed, so we just skip the parameter in order
497  * to be able to recall old messages.
498  */
499  case 'm':
500  case 'M':
501  if (*(p + 1) == '<')
502  {
503  for (p += 2; *p && (*p != '>'); p++)
504  ;
505  if (*p != '>')
506  {
507  mutt_error(_("Illegal crypto header"));
508  return 0;
509  }
510  }
511 
512  break;
513 
514  case 'o':
515  case 'O':
516  flags |= OPPENCRYPT;
517  break;
518 
519  case 's':
520  case 'S':
521  flags |= SIGN;
522  q = sign_as;
523 
524  if (*(p + 1) == '<')
525  {
526  for (p += 2; *p && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
527  *q++ = *p++)
528  {
529  }
530 
531  if (*p != '>')
532  {
533  mutt_error(_("Illegal crypto header"));
534  return 0;
535  }
536  }
537 
538  *q = '\0';
539  break;
540 
541  default:
542  mutt_error(_("Illegal crypto header"));
543  return 0;
544  }
545  }
546 
547  /* the cryptalg field must not be empty */
548  if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
549  mutt_str_replace(&SmimeEncryptWith, smime_cryptalg);
550 
551  /* Set {Smime,Pgp}SignAs, if desired. */
552 
553  if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
554  (flags & SIGN) && (set_empty_signas || *sign_as))
555  {
556  mutt_str_replace(&PgpSignAs, sign_as);
557  }
558 
559  if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
560  (flags & SIGN) && (set_empty_signas || *sign_as))
561  {
562  mutt_str_replace(&SmimeSignAs, sign_as);
563  }
564 
565  return flags;
566 }
#define SIGN
Definition: ncrypt.h:120
#define _(a)
Definition: message.h:28
#define LONG_STRING
Definition: string2.h:36
#define INLINE
Definition: ncrypt.h:126
WHERE char * SmimeEncryptWith
Config: Algorithm for encryption.
Definition: globals.h:173
#define OPPENCRYPT
Definition: ncrypt.h:127
WHERE char * PgpSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:168
WHERE char * SmimeSignAs
Config: Use this alternative key for signing messages.
Definition: globals.h:172
#define ENCRYPT
Definition: ncrypt.h:119
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:768
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
#define APPLICATION_PGP
Definition: ncrypt.h:129
#define mutt_error(...)
Definition: logging.h:88
#define WithCrypto
Definition: ncrypt.h:154
#define APPLICATION_SMIME
Definition: ncrypt.h:130

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_prepare_template ( FILE *  fp,
struct Mailbox m,
struct Email newhdr,
struct Email e,
bool  resend 
)

Prepare a message template.

Parameters
fpIf not NULL, file containing the template
mIf fp is NULL, the Mailbox containing the header with the template
newhdrThe template is read into this Header
eEmail to recall/resend
resendSet if resending (as opposed to recalling a postponed msg) Resent messages enable header weeding, and also discard any existing Message-ID and Mail-Followup-To
Return values
0Success
-1Error

Definition at line 580 of file postpone.c.

582 {
583  struct Message *msg = NULL;
584  char file[PATH_MAX];
585  struct Body *b = NULL;
586  FILE *bfp = NULL;
587  int rc = -1;
588  struct State s = { 0 };
589  int sec_type;
590 
591  if (!fp && !(msg = mx_msg_open(m, e->msgno)))
592  return -1;
593 
594  if (!fp)
595  fp = msg->fp;
596 
597  bfp = fp;
598 
599  /* parse the message header and MIME structure */
600 
601  fseeko(fp, e->offset, SEEK_SET);
602  newhdr->offset = e->offset;
603  /* enable header weeding for resent messages */
604  newhdr->env = mutt_rfc822_read_header(fp, newhdr, true, resend);
605  newhdr->content->length = e->content->length;
606  mutt_parse_part(fp, newhdr->content);
607 
608  /* If resending a message, don't keep message_id or mail_followup_to.
609  * Otherwise, we are resuming a postponed message, and want to keep those
610  * headers if they exist.
611  */
612  if (resend)
613  {
614  FREE(&newhdr->env->message_id);
615  FREE(&newhdr->env->mail_followup_to);
616  }
617 
618  /* decrypt pgp/mime encoded messages */
619 
620  if (((WithCrypto & APPLICATION_PGP) != 0) &&
621  (sec_type = mutt_is_multipart_encrypted(newhdr->content)))
622  {
623  newhdr->security |= sec_type;
624  if (!crypt_valid_passphrase(sec_type))
625  goto bail;
626 
627  mutt_message(_("Decrypting message..."));
628  if ((crypt_pgp_decrypt_mime(fp, &bfp, newhdr->content, &b) == -1) || !b)
629  {
630  goto bail;
631  }
632 
633  mutt_body_free(&newhdr->content);
634  newhdr->content = b;
635 
637  }
638 
639  /* remove a potential multipart/signed layer - useful when
640  * resending messages
641  */
642  if ((WithCrypto != 0) && mutt_is_multipart_signed(newhdr->content))
643  {
644  newhdr->security |= SIGN;
645  if (((WithCrypto & APPLICATION_PGP) != 0) &&
647  mutt_param_get(&newhdr->content->parameter, "protocol"),
648  "application/pgp-signature") == 0))
649  {
650  newhdr->security |= APPLICATION_PGP;
651  }
652  else if (WithCrypto & APPLICATION_SMIME)
653  newhdr->security |= APPLICATION_SMIME;
654 
655  /* destroy the signature */
656  mutt_body_free(&newhdr->content->parts->next);
657  newhdr->content = mutt_remove_multipart(newhdr->content);
658  }
659 
660  /* We don't need no primary multipart.
661  * Note: We _do_ preserve messages!
662  *
663  * XXX - we don't handle multipart/alternative in any
664  * smart way when sending messages. However, one may
665  * consider this a feature.
666  */
667  if (newhdr->content->type == TYPE_MULTIPART)
668  newhdr->content = mutt_remove_multipart(newhdr->content);
669 
670  s.fpin = bfp;
671 
672  /* create temporary files for all attachments */
673  for (b = newhdr->content; b; b = b->next)
674  {
675  /* what follows is roughly a receive-mode variant of
676  * mutt_get_tmp_attachment () from muttlib.c
677  */
678 
679  file[0] = '\0';
680  if (b->filename)
681  {
682  mutt_str_strfcpy(file, b->filename, sizeof(file));
684  }
685  else
686  {
687  /* avoid Content-Disposition: header with temporary filename */
688  b->use_disp = false;
689  }
690 
691  /* set up state flags */
692 
693  s.flags = 0;
694 
695  if (b->type == TYPE_TEXT)
696  {
697  if (mutt_str_strcasecmp("yes",
698  mutt_param_get(&b->parameter, "x-mutt-noconv")) == 0)
699  {
700  b->noconv = true;
701  }
702  else
703  {
704  s.flags |= MUTT_CHARCONV;
705  b->noconv = false;
706  }
707 
708  mutt_param_delete(&b->parameter, "x-mutt-noconv");
709  }
710 
711  mutt_adv_mktemp(file, sizeof(file));
712  s.fpout = mutt_file_fopen(file, "w");
713  if (!s.fpout)
714  goto bail;
715 
716  if (((WithCrypto & APPLICATION_PGP) != 0) &&
717  ((sec_type = mutt_is_application_pgp(b)) & (ENCRYPT | SIGN)))
718  {
719  if (sec_type & ENCRYPT)
720  {
721  if (!crypt_valid_passphrase(APPLICATION_PGP))
722  goto bail;
723  mutt_message(_("Decrypting message..."));
724  }
725 
726  if (mutt_body_handler(b, &s) < 0)
727  {
728  mutt_error(_("Decryption failed"));
729  goto bail;
730  }
731 
732  newhdr->security |= sec_type;
733 
734  b->type = TYPE_TEXT;
735  mutt_str_replace(&b->subtype, "plain");
736  mutt_param_delete(&b->parameter, "x-action");
737  }
738  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
739  ((sec_type = mutt_is_application_smime(b)) & (ENCRYPT | SIGN)))
740  {
741  if (sec_type & ENCRYPT)
742  {
743  if (!crypt_valid_passphrase(APPLICATION_SMIME))
744  goto bail;
745  crypt_smime_getkeys(newhdr->env);
746  mutt_message(_("Decrypting message..."));
747  }
748 
749  if (mutt_body_handler(b, &s) < 0)
750  {
751  mutt_error(_("Decryption failed"));
752  goto bail;
753  }
754 
755  newhdr->security |= sec_type;
756  b->type = TYPE_TEXT;
757  mutt_str_replace(&b->subtype, "plain");
758  }
759  else
760  mutt_decode_attachment(b, &s);
761 
762  if (mutt_file_fclose(&s.fpout) != 0)
763  goto bail;
764 
765  mutt_str_replace(&b->filename, file);
766  b->unlink = true;
767 
769 
770  mutt_body_free(&b->parts);
771  if (b->email)
772  b->email->content = NULL; /* avoid dangling pointer */
773  }
774 
775  /* Fix encryption flags. */
776 
777  /* No inline if multipart. */
778  if ((WithCrypto != 0) && (newhdr->security & INLINE) && newhdr->content->next)
779  newhdr->security &= ~INLINE;
780 
781  /* Do we even support multiple mechanisms? */
782  newhdr->security &= WithCrypto | ~(APPLICATION_PGP | APPLICATION_SMIME);
783 
784  /* Theoretically, both could be set. Take the one the user wants to set by default. */
785  if ((newhdr->security & APPLICATION_PGP) && (newhdr->security & APPLICATION_SMIME))
786  {
787  if (SmimeIsDefault)
788  newhdr->security &= ~APPLICATION_PGP;
789  else
790  newhdr->security &= ~APPLICATION_SMIME;
791  }
792 
793  rc = 0;
794 
795 bail:
796 
797  /* that's it. */
798  if (bfp != fp)
799  mutt_file_fclose(&bfp);
800  if (msg)
801  mx_msg_close(m, &msg);
802 
803  if (rc == -1)
804  {
805  mutt_env_free(&newhdr->env);
806  mutt_body_free(&newhdr->content);
807  }
808 
809  return rc;
810 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1728
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:1391
#define SIGN
Definition: ncrypt.h:120
int mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:403
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:47
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: sendlib.c:1715
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:44
#define mutt_message(...)
Definition: logging.h:87
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
struct Body * content
list of MIME parts
Definition: email.h:92
bool noconv
don&#39;t do character set conversion
Definition: body.h:77
#define _(a)
Definition: message.h:28
struct Body * next
next attachment in the list
Definition: body.h:57
int crypt_pgp_decrypt_mime(FILE *a, FILE **b, struct Body *c, struct Body **d)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition: cryptglue.c:192
int mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:360
The body of an email.
Definition: body.h:33
FILE * fpout
Definition: state.h:34
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1187
int flags
Definition: state.h:36
char * message_id
Definition: envelope.h:47
struct Address * mail_followup_to
Definition: envelope.h:41
#define INLINE
Definition: ncrypt.h:126
struct Envelope * env
envelope information
Definition: email.h:91
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
WHERE bool SmimeIsDefault
Config: Use SMIME rather than PGP by default.
Definition: globals.h:272
char * subtype
content-type subtype
Definition: body.h:36
#define ENCRYPT
Definition: ncrypt.h:119
A local copy of an email.
Definition: mx.h:81
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
#define PATH_MAX
Definition: mutt.h:46
Type: &#39;text/*&#39;.
Definition: mime.h:38
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition: cryptglue.c:406
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
FILE * fpin
Definition: state.h:33
int mutt_is_application_pgp(struct Body *m)
Does the message use PGP?
Definition: crypt.c:510
void mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:460
unsigned int type
content-type primary type
Definition: body.h:67
LOFF_T offset
where in the stream does this message begin?
Definition: email.h:85
#define APPLICATION_PGP
Definition: ncrypt.h:129
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1229
char * mutt_param_get(const struct ParameterList *p, const char *s)
Find a matching Parameter.
Definition: parameter.c:81
void mutt_body_free(struct Body **p)
Free a Body.
Definition: body.c:56
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:70
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
#define mutt_error(...)
Definition: logging.h:88
bool unlink
flag to indicate the file named by "filename" should be unlink()ed before free()ing this structure ...
Definition: body.h:71
void mutt_env_free(struct Envelope **p)
Free an Envelope.
Definition: envelope.c:53
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625
FILE * fp
pointer to the message data
Definition: mx.h:83
#define FREE(x)
Definition: memory.h:46
int crypt_valid_passphrase(int flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:144
Keep track when processing files.
Definition: state.h:31
struct Envelope * mutt_rfc822_read_header(FILE *f, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:971
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1502
char * d_filename
filename to be used for the content-disposition header.
Definition: body.h:49
int mutt_is_application_smime(struct Body *m)
Does the message use S/MIME?
Definition: crypt.c:569
void mutt_param_delete(struct ParameterList *p, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:139
struct ParameterList parameter
parameters of the content-type
Definition: body.h:38
struct Email * email
header information for message/rfc822
Definition: body.h:59
#define WithCrypto
Definition: ncrypt.h:154
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1139
int msgno
number displayed to the user
Definition: email.h:88
#define APPLICATION_SMIME
Definition: ncrypt.h:130
void mutt_adv_mktemp(char *buf, size_t buflen)
Advanced mktemp(3)
Definition: muttlib.c:123

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

const struct Mapping PostponeHelp[]
static
Initial value:
= {
{ N_("Exit"), OP_EXIT },
{ N_("Del"), OP_DELETE },
{ N_("Undel"), OP_UNDELETE },
{ N_("Help"), OP_HELP },
{ NULL, 0 },
}
#define N_(a)
Definition: message.h:32

Definition at line 66 of file postpone.c.

short PostCount = 0
static

Definition at line 74 of file postpone.c.

struct Context* PostContext = NULL
static

Definition at line 75 of file postpone.c.

short UpdateNumPostponed = 0
static

Definition at line 76 of file postpone.c.