NeoMutt  2021-10-22-8-g9cb437
Teaching an old dog new tricks
DOXYGEN
postpone.c File Reference

Postponed Email Selection Dialog. More...

#include "config.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "ncrypt/lib.h"
#include "send/lib.h"
#include "context.h"
#include "handler.h"
#include "mutt_logging.h"
#include "mutt_thread.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "protos.h"
#include "rfc3676.h"
#include "imap/lib.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 hardclose (struct Mailbox *m)
 Try hard to close a mailbox. More...
 
SecurityFlags mutt_parse_crypt_hdr (const char *p, bool set_empty_signas, SecurityFlags crypt_app)
 Parse a crypto header string. More...
 
int mutt_prepare_template (FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
 Prepare a message template. More...
 
int mutt_get_postponed (struct Mailbox *m_cur, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
 Recall a postponed message. More...
 

Variables

short PostCount = 0
 
static bool UpdateNumPostponed = false
 

Detailed Description

Postponed Email Selection Dialog.

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

◆ mutt_num_postponed()

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 68 of file postpone.c.

69 {
70  struct stat st = { 0 };
71 
72  static time_t LastModify = 0;
73  static char *OldPostponed = NULL;
74 
76  {
77  UpdateNumPostponed = false;
78  force = true;
79  }
80 
81  const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
82  if (!mutt_str_equal(c_postponed, OldPostponed))
83  {
84  FREE(&OldPostponed);
85  OldPostponed = mutt_str_dup(c_postponed);
86  LastModify = 0;
87  force = true;
88  }
89 
90  if (!c_postponed)
91  return 0;
92 
93  // We currently are in the `$postponed` mailbox so just pick the current status
94  if (m && mutt_str_equal(c_postponed, m->realpath))
95  {
97  return PostCount;
98  }
99 
100 #ifdef USE_IMAP
101  /* LastModify is useless for IMAP */
102  if (imap_path_probe(c_postponed, NULL) == MUTT_IMAP)
103  {
104  if (force)
105  {
106  short newpc;
107 
108  newpc = imap_path_status(c_postponed, false);
109  if (newpc >= 0)
110  {
111  PostCount = newpc;
112  mutt_debug(LL_DEBUG3, "%d postponed IMAP messages found\n", PostCount);
113  }
114  else
115  mutt_debug(LL_DEBUG3, "using old IMAP postponed count\n");
116  }
117  return PostCount;
118  }
119 #endif
120 
121  if (stat(c_postponed, &st) == -1)
122  {
123  PostCount = 0;
124  LastModify = 0;
125  return 0;
126  }
127 
128  if (S_ISDIR(st.st_mode))
129  {
130  /* if we have a maildir mailbox, we need to stat the "new" dir */
131  struct Buffer *buf = mutt_buffer_pool_get();
132 
133  mutt_buffer_printf(buf, "%s/new", c_postponed);
134  if ((access(mutt_buffer_string(buf), F_OK) == 0) &&
135  (stat(mutt_buffer_string(buf), &st) == -1))
136  {
137  PostCount = 0;
138  LastModify = 0;
140  return 0;
141  }
143  }
144 
145  if (LastModify < st.st_mtime)
146  {
147 #ifdef USE_NNTP
148  int optnews = OptNews;
149 #endif
150  LastModify = st.st_mtime;
151 
152  if (access(c_postponed, R_OK | F_OK) != 0)
153  return PostCount = 0;
154 #ifdef USE_NNTP
155  if (optnews)
156  OptNews = false;
157 #endif
158  struct Mailbox *m_post = mx_path_resolve(c_postponed);
159  if (mx_mbox_open(m_post, MUTT_NOSORT | MUTT_QUIET))
160  {
161  PostCount = m_post->msg_count;
162  mx_fastclose_mailbox(m_post);
163  if (m_post->flags == MB_HIDDEN)
164  mailbox_free(&m_post);
165  }
166  else
167  {
168  mailbox_free(&m_post);
169  PostCount = 0;
170  }
171 
172 #ifdef USE_NNTP
173  if (optnews)
174  OptNews = true;
175 #endif
176  }
177 
178  return PostCount;
179 }
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2402
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1235
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
#define MB_HIDDEN
Definition: mailbox.h:38
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
#define FREE(x)
Definition: memory.h:40
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1671
void mx_fastclose_mailbox(struct Mailbox *m)
Free up memory associated with the Mailbox.
Definition: mx.c:429
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:64
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mxapi.h:61
bool OptNews
(pseudo) used to change reader mode
Definition: options.h:50
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
short PostCount
Definition: postpone.c:57
static bool UpdateNumPostponed
Definition: postpone.c:58
String manipulation buffer.
Definition: buffer.h:34
A mailbox.
Definition: mailbox.h:82
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
int msg_count
Total number of messages.
Definition: mailbox.h:91
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:96
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_update_num_postponed()

void mutt_update_num_postponed ( void  )

Force the update of the number of postponed messages.

Definition at line 184 of file postpone.c.

185 {
186  UpdateNumPostponed = true;
187 }
+ Here is the caller graph for this function:

◆ hardclose()

static void hardclose ( struct Mailbox m)
static

Try hard to close a mailbox.

Parameters
mMailbox to close

Definition at line 193 of file postpone.c.

194 {
195  /* messages might have been marked for deletion.
196  * try once more on reopen before giving up. */
197  enum MxStatus rc = mx_mbox_close(m);
198  if (rc != MX_STATUS_ERROR && rc != MX_STATUS_OK)
199  rc = mx_mbox_close(m);
200  if (rc != MX_STATUS_OK)
202 }
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:613
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:76
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:77
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_crypt_hdr()

SecurityFlags mutt_parse_crypt_hdr ( const char *  p,
bool  set_empty_signas,
SecurityFlags  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
numSecurityFlags, see SecurityFlags

Definition at line 211 of file postpone.c.

212 {
213  char smime_cryptalg[1024] = { 0 };
214  char sign_as[1024] = { 0 };
215  char *q = NULL;
216  SecurityFlags flags = SEC_NO_FLAGS;
217 
218  if (!WithCrypto)
219  return SEC_NO_FLAGS;
220 
222  for (; p[0] != '\0'; p++)
223  {
224  switch (p[0])
225  {
226  case 'c':
227  case 'C':
228  q = smime_cryptalg;
229 
230  if (p[1] == '<')
231  {
232  for (p += 2; (p[0] != '\0') && (p[0] != '>') &&
233  (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
234  *q++ = *p++)
235  {
236  }
237 
238  if (p[0] != '>')
239  {
240  mutt_error(_("Illegal S/MIME header"));
241  return SEC_NO_FLAGS;
242  }
243  }
244 
245  *q = '\0';
246  break;
247 
248  case 'e':
249  case 'E':
250  flags |= SEC_ENCRYPT;
251  break;
252 
253  case 'i':
254  case 'I':
255  flags |= SEC_INLINE;
256  break;
257 
258  /* This used to be the micalg parameter.
259  *
260  * It's no longer needed, so we just skip the parameter in order
261  * to be able to recall old messages. */
262  case 'm':
263  case 'M':
264  if (p[1] != '<')
265  break;
266 
267  for (p += 2; (p[0] != '\0') && (p[0] != '>'); p++)
268  ; // do nothing
269 
270  if (p[0] != '>')
271  {
272  mutt_error(_("Illegal crypto header"));
273  return SEC_NO_FLAGS;
274  }
275  break;
276 
277  case 'o':
278  case 'O':
279  flags |= SEC_OPPENCRYPT;
280  break;
281 
282  case 'a':
283  case 'A':
284 #ifdef USE_AUTOCRYPT
285  flags |= SEC_AUTOCRYPT;
286 #endif
287  break;
288 
289  case 'z':
290  case 'Z':
291 #ifdef USE_AUTOCRYPT
292  flags |= SEC_AUTOCRYPT_OVERRIDE;
293 #endif
294  break;
295 
296  case 's':
297  case 'S':
298  flags |= SEC_SIGN;
299  q = sign_as;
300 
301  if (p[1] == '<')
302  {
303  for (p += 2;
304  (p[0] != '\0') && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
305  *q++ = *p++)
306  {
307  }
308 
309  if (p[0] != '>')
310  {
311  mutt_error(_("Illegal crypto header"));
312  return SEC_NO_FLAGS;
313  }
314  }
315 
316  q[0] = '\0';
317  break;
318 
319  default:
320  mutt_error(_("Illegal crypto header"));
321  return SEC_NO_FLAGS;
322  }
323  }
324 
325  /* the cryptalg field must not be empty */
326  if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
327  {
328  struct Buffer errmsg = mutt_buffer_make(0);
329  int rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
330  smime_cryptalg, &errmsg);
331 
332  if ((CSR_RESULT(rc) != CSR_SUCCESS) && !mutt_buffer_is_empty(&errmsg))
333  mutt_error("%s", mutt_buffer_string(&errmsg));
334 
335  mutt_buffer_dealloc(&errmsg);
336  }
337 
338  /* Set {Smime,Pgp}SignAs, if desired. */
339 
340  if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
341  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
342  {
343  cs_subset_str_string_set(NeoMutt->sub, "pgp_sign_as", sign_as, NULL);
344  }
345 
346  if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
347  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
348  {
349  cs_subset_str_string_set(NeoMutt->sub, "smime_sign_as", sign_as, NULL);
350  }
351 
352  return flags;
353 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
#define mutt_error(...)
Definition: logging.h:87
#define _(a)
Definition: message.h:28
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:82
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:84
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:71
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:83
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:74
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:75
#define WithCrypto
Definition: lib.h:113
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:85
#define SEC_SIGN
Email is signed.
Definition: lib.h:76
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
int cs_subset_str_string_set(const struct ConfigSubset *sub, const char *name, const char *value, struct Buffer *err)
Set a config item by string.
Definition: subset.c:408
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_prepare_template()

int mutt_prepare_template ( FILE *  fp,
struct Mailbox m,
struct Email e_new,
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
e_newThe 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 367 of file postpone.c.

369 {
370  struct Message *msg = NULL;
371  struct Body *b = NULL;
372  FILE *fp_body = NULL;
373  int rc = -1;
374  struct State s = { 0 };
375  SecurityFlags sec_type;
376  struct Envelope *protected_headers = NULL;
377  struct Buffer *file = NULL;
378 
379  if (!fp && !(msg = mx_msg_open(m, e->msgno)))
380  return -1;
381 
382  if (!fp)
383  fp = msg->fp;
384 
385  fp_body = fp;
386 
387  /* parse the message header and MIME structure */
388 
389  if (fseeko(fp, e->offset, SEEK_SET) != 0)
390  {
391  mutt_perror("fseeko");
392  return -1;
393  }
394  e_new->offset = e->offset;
395  /* enable header weeding for resent messages */
396  e_new->env = mutt_rfc822_read_header(fp, e_new, true, resend);
397  e_new->body->length = e->body->length;
398  mutt_parse_part(fp, e_new->body);
399 
400  /* If resending a message, don't keep message_id or mail_followup_to.
401  * Otherwise, we are resuming a postponed message, and want to keep those
402  * headers if they exist. */
403  if (resend)
404  {
405  FREE(&e_new->env->message_id);
407  }
408 
409  /* decrypt pgp/mime encoded messages */
410 
411  if (((WithCrypto & APPLICATION_PGP) != 0) &&
412  (sec_type = mutt_is_multipart_encrypted(e_new->body)))
413  {
414  e_new->security |= sec_type;
415  if (!crypt_valid_passphrase(sec_type))
416  goto bail;
417 
418  mutt_message(_("Decrypting message..."));
419  if ((crypt_pgp_decrypt_mime(fp, &fp_body, e_new->body, &b) == -1) || !b)
420  {
421  mutt_error(_("Could not decrypt PGP message"));
422  goto bail;
423  }
424 
425  mutt_body_free(&e_new->body);
426  e_new->body = b;
427 
428  if (b->mime_headers)
429  {
430  protected_headers = b->mime_headers;
431  b->mime_headers = NULL;
432  }
433 
435  }
436 
437  /* remove a potential multipart/signed layer - useful when
438  * resending messages */
439  if ((WithCrypto != 0) && mutt_is_multipart_signed(e_new->body))
440  {
441  e_new->security |= SEC_SIGN;
442  if (((WithCrypto & APPLICATION_PGP) != 0) &&
443  mutt_istr_equal(mutt_param_get(&e_new->body->parameter, "protocol"),
444  "application/pgp-signature"))
445  {
446  e_new->security |= APPLICATION_PGP;
447  }
448  else if (WithCrypto & APPLICATION_SMIME)
449  e_new->security |= APPLICATION_SMIME;
450 
451  /* destroy the signature */
452  mutt_body_free(&e_new->body->parts->next);
453  e_new->body = mutt_remove_multipart(e_new->body);
454 
455  if (e_new->body->mime_headers)
456  {
457  mutt_env_free(&protected_headers);
458  protected_headers = e_new->body->mime_headers;
459  e_new->body->mime_headers = NULL;
460  }
461  }
462 
463  /* We don't need no primary multipart.
464  * Note: We _do_ preserve messages!
465  *
466  * XXX - we don't handle multipart/alternative in any
467  * smart way when sending messages. However, one may
468  * consider this a feature. */
469  if (e_new->body->type == TYPE_MULTIPART)
470  e_new->body = mutt_remove_multipart(e_new->body);
471 
472  s.fp_in = fp_body;
473 
474  file = mutt_buffer_pool_get();
475 
476  /* create temporary files for all attachments */
477  for (b = e_new->body; b; b = b->next)
478  {
479  /* what follows is roughly a receive-mode variant of
480  * mutt_get_tmp_attachment () from muttlib.c */
481 
482  mutt_buffer_reset(file);
483  if (b->filename)
484  {
485  mutt_buffer_strcpy(file, b->filename);
487  }
488  else
489  {
490  /* avoid Content-Disposition: header with temporary filename */
491  b->use_disp = false;
492  }
493 
494  /* set up state flags */
495 
496  s.flags = 0;
497 
498  if (b->type == TYPE_TEXT)
499  {
500  if (mutt_istr_equal("yes",
501  mutt_param_get(&b->parameter, "x-mutt-noconv")))
502  {
503  b->noconv = true;
504  }
505  else
506  {
507  s.flags |= MUTT_CHARCONV;
508  b->noconv = false;
509  }
510 
511  mutt_param_delete(&b->parameter, "x-mutt-noconv");
512  }
513 
514  mutt_adv_mktemp(file);
515  s.fp_out = mutt_file_fopen(mutt_buffer_string(file), "w");
516  if (!s.fp_out)
517  goto bail;
518 
519  if (((WithCrypto & APPLICATION_PGP) != 0) &&
520  ((sec_type = mutt_is_application_pgp(b)) & (SEC_ENCRYPT | SEC_SIGN)))
521  {
522  if (sec_type & SEC_ENCRYPT)
523  {
525  goto bail;
526  mutt_message(_("Decrypting message..."));
527  }
528 
529  if (mutt_body_handler(b, &s) < 0)
530  {
531  mutt_error(_("Decryption failed"));
532  goto bail;
533  }
534 
535  if ((b == e_new->body) && !protected_headers)
536  {
537  protected_headers = b->mime_headers;
538  b->mime_headers = NULL;
539  }
540 
541  e_new->security |= sec_type;
542  b->type = TYPE_TEXT;
543  mutt_str_replace(&b->subtype, "plain");
544  mutt_param_delete(&b->parameter, "x-action");
545  }
546  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
547  ((sec_type = mutt_is_application_smime(b)) & (SEC_ENCRYPT | SEC_SIGN)))
548  {
549  if (sec_type & SEC_ENCRYPT)
550  {
552  goto bail;
553  crypt_smime_getkeys(e_new->env);
554  mutt_message(_("Decrypting message..."));
555  }
556 
557  if (mutt_body_handler(b, &s) < 0)
558  {
559  mutt_error(_("Decryption failed"));
560  goto bail;
561  }
562 
563  e_new->security |= sec_type;
564  b->type = TYPE_TEXT;
565  mutt_str_replace(&b->subtype, "plain");
566  }
567  else
568  mutt_decode_attachment(b, &s);
569 
570  if (mutt_file_fclose(&s.fp_out) != 0)
571  goto bail;
572 
574  b->unlink = true;
575 
577 
578  mutt_body_free(&b->parts);
579  if (b->email)
580  b->email->body = NULL; /* avoid dangling pointer */
581  }
582 
583  const bool c_crypt_protected_headers_read =
584  cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
585  if (c_crypt_protected_headers_read && protected_headers && protected_headers->subject &&
586  !mutt_str_equal(e_new->env->subject, protected_headers->subject))
587  {
588  mutt_str_replace(&e_new->env->subject, protected_headers->subject);
589  }
590  mutt_env_free(&protected_headers);
591 
592  /* Fix encryption flags. */
593 
594  /* No inline if multipart. */
595  if ((WithCrypto != 0) && (e_new->security & SEC_INLINE) && e_new->body->next)
596  e_new->security &= ~SEC_INLINE;
597 
598  /* Do we even support multiple mechanisms? */
600 
601  /* Theoretically, both could be set. Take the one the user wants to set by default. */
602  if ((e_new->security & APPLICATION_PGP) && (e_new->security & APPLICATION_SMIME))
603  {
604  const bool c_smime_is_default =
605  cs_subset_bool(NeoMutt->sub, "smime_is_default");
606  if (c_smime_is_default)
607  e_new->security &= ~APPLICATION_PGP;
608  else
609  e_new->security &= ~APPLICATION_SMIME;
610  }
611 
613 
614  rc = 0;
615 
616 bail:
617 
618  /* that's it. */
620  if (fp_body != fp)
621  mutt_file_fclose(&fp_body);
622  if (msg)
623  mx_msg_close(m, &msg);
624 
625  if (rc == -1)
626  {
627  mutt_env_free(&e_new->env);
628  mutt_body_free(&e_new->body);
629  }
630 
631  return rc;
632 }
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:559
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:414
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:617
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:454
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition: cryptglue.c:456
int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **cur)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition: cryptglue.c:212
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:593
#define mutt_message(...)
Definition: logging.h:86
#define mutt_perror(...)
Definition: logging.h:88
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email's attachment.
Definition: handler.c:1854
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition: multipart.c:126
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:83
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1189
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1143
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition: parameter.c:142
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1721
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
Definition: parse.c:1168
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition: rfc3676.c:496
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:896
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
The body of an email.
Definition: body.h:35
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:55
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:71
bool noconv
Don't do character set conversion.
Definition: body.h:45
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:66
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:74
LOFF_T length
length (in bytes) of attachment
Definition: body.h:52
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:61
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:46
struct Email * email
header information for message/rfc822
Definition: body.h:72
struct Body * next
next attachment in the list
Definition: body.h:70
char * subtype
content-type subtype
Definition: body.h:59
unsigned int type
content-type primary type, ContentType
Definition: body.h:39
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:57
struct Envelope * env
Envelope information.
Definition: email.h:66
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
struct Body * body
List of MIME parts.
Definition: email.h:67
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:69
int msgno
Number displayed to the user.
Definition: email.h:111
The header of an Email.
Definition: envelope.h:55
char * message_id
Message ID.
Definition: envelope.h:71
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition: envelope.h:63
char * subject
Email's subject.
Definition: envelope.h:68
A local copy of an email.
Definition: mxapi.h:42
FILE * fp
pointer to the message data
Definition: mxapi.h:43
Keep track when processing files.
Definition: state.h:45
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_get_postponed()

int mutt_get_postponed ( struct Mailbox m_cur,
struct Email hdr,
struct Email **  cur,
struct Buffer fcc 
)

Recall a postponed message.

Parameters
[in]m_curCurrent mailbox
[in]hdrenvelope/attachment info for recalled message
[out]curif message was a reply, 'cur' is set to the message which 'hdr' is in reply to
[in]fccfcc for the recalled message
Return values
-1Error/no messages
0Normal exit
SEND_REPLYRecalled message is a reply

Definition at line 644 of file postpone.c.

646 {
647  const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
648  if (!c_postponed)
649  return -1;
650 
651  struct Email *e = NULL;
652  int rc = SEND_POSTPONED;
653  const char *p = NULL;
654 
655  struct Mailbox *m = mx_path_resolve(c_postponed);
656  if (m_cur != m)
657  {
658  if (!mx_mbox_open(m, MUTT_NOSORT))
659  {
660  PostCount = 0;
661  mutt_error(_("No postponed messages"));
662  mailbox_free(&m);
663  return -1;
664  }
665  }
666 
667  mx_mbox_check(m);
668 
669  if (m->msg_count == 0)
670  {
671  PostCount = 0;
672  mutt_error(_("No postponed messages"));
673  if (m_cur != m)
674  {
676  }
677  return -1;
678  }
679 
680  /* avoid the "purge deleted messages" prompt */
681  const enum QuadOption c_delete = cs_subset_quad(NeoMutt->sub, "delete");
682  cs_subset_str_native_set(NeoMutt->sub, "delete", MUTT_YES, NULL);
683 
684  struct Context *ctx = (m_cur != m) ? ctx_new(m) : NULL;
685  if (m->msg_count == 1)
686  {
687  /* only one message, so just use that one. */
688  e = m->emails[0];
689  }
690  else if (!(e = dlg_select_postponed_email(m)))
691  {
692  rc = -1;
693  goto cleanup;
694  }
695 
696  if (mutt_prepare_template(NULL, m, hdr, e, false) < 0)
697  {
698  rc = -1;
699  goto cleanup;
700  }
701 
702  /* finished with this message, so delete it. */
703  mutt_set_flag(m, e, MUTT_DELETE, true);
704  mutt_set_flag(m, e, MUTT_PURGE, true);
705 
706  /* update the count for the status display */
707  PostCount = m->msg_count - m->msg_deleted;
708 
709  struct ListNode *np = NULL, *tmp = NULL;
710  STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
711  {
712  size_t plen = mutt_istr_startswith(np->data, "X-Mutt-References:");
713  if (plen)
714  {
715  /* if a mailbox is currently open, look to see if the original message
716  * the user attempted to reply to is in this mailbox */
717  p = mutt_str_skip_email_wsp(np->data + plen);
718  if (!m_cur->id_hash)
719  m_cur->id_hash = mutt_make_id_hash(m_cur);
720  *cur = mutt_hash_find(m_cur->id_hash, p);
721 
722  if (*cur)
723  rc |= SEND_REPLY;
724  }
725  else if ((plen = mutt_istr_startswith(np->data, "X-Mutt-Fcc:")))
726  {
727  p = mutt_str_skip_email_wsp(np->data + plen);
728  mutt_buffer_strcpy(fcc, p);
730 
731  /* note that x-mutt-fcc was present. we do this because we want to add a
732  * default fcc if the header was missing, but preserve the request of the
733  * user to not make a copy if the header field is present, but empty.
734  * see http://dev.mutt.org/trac/ticket/3653 */
735  rc |= SEND_POSTPONED_FCC;
736  }
737  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
738  /* this is generated by old neomutt versions */
739  (mutt_str_startswith(np->data, "Pgp:") ||
740  /* this is the new way */
741  mutt_str_startswith(np->data, "X-Mutt-PGP:")))
742  {
743  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_PGP);
744  hdr->security |= APPLICATION_PGP;
745  }
746  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
747  mutt_str_startswith(np->data, "X-Mutt-SMIME:"))
748  {
749  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_SMIME);
750  hdr->security |= APPLICATION_SMIME;
751  }
752 #ifdef MIXMASTER
753  else if (mutt_str_startswith(np->data, "X-Mutt-Mix:"))
754  {
755  mutt_list_free(&hdr->chain);
756 
757  char *t = strtok(np->data + 11, " \t\n");
758  while (t)
759  {
761  t = strtok(NULL, " \t\n");
762  }
763  }
764 #endif
765  else
766  {
767  // skip header removal
768  continue;
769  }
770 
771  // remove the header
772  STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
773  FREE(&np->data);
774  FREE(&np);
775  }
776 
777  const bool c_crypt_opportunistic_encrypt =
778  cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
779  if (c_crypt_opportunistic_encrypt)
781 
782 cleanup:
783  if (m_cur != m)
784  {
785  hardclose(m);
786  ctx_free(&ctx);
787  }
788 
789  cs_subset_str_native_set(NeoMutt->sub, "delete", c_delete, NULL);
790  return rc;
791 }
struct Context * ctx_new(struct Mailbox *m)
Create a new Context.
Definition: context.c:77
void ctx_free(struct Context **ptr)
Free a Context.
Definition: context.c:49
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1050
struct Email * dlg_select_postponed_email(struct Mailbox *m)
Create a Menu to select a postponed message.
Definition: dlg_postpone.c:167
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:172
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:96
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:94
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1658
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:603
enum MxStatus mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1122
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
Parse a crypto header string.
Definition: postpone.c:211
int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new, struct Email *e, bool resend)
Prepare a message template.
Definition: postpone.c:367
static void hardclose(struct Mailbox *m)
Try hard to close a mailbox.
Definition: postpone.c:193
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
#define SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the x-mutt-fcc header field was present.
Definition: send.h:48
#define SEND_POSTPONED
Recall a postponed email.
Definition: send.h:44
#define SEND_REPLY
Reply to sender.
Definition: send.h:40
The "current" mailbox.
Definition: context.h:38
The envelope/body of an email.
Definition: email.h:37
struct ListHead chain
Mixmaster chain.
Definition: email.h:90
struct ListHead userhdrs
user defined headers
Definition: envelope.h:85
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
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:305
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ PostCount

short PostCount = 0

Definition at line 57 of file postpone.c.

◆ UpdateNumPostponed

bool UpdateNumPostponed = false
static

Definition at line 58 of file postpone.c.