NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
DOXYGEN
postpone.c
Go to the documentation of this file.
1 
30 #include "config.h"
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include "mutt/lib.h"
37 #include "address/lib.h"
38 #include "config/lib.h"
39 #include "email/lib.h"
40 #include "core/lib.h"
41 #include "mutt.h"
42 #include "lib.h"
43 #include "ncrypt/lib.h"
44 #include "send/lib.h"
45 #include "handler.h"
46 #include "mutt_logging.h"
47 #include "mutt_thread.h"
48 #include "muttlib.h"
49 #include "mview.h"
50 #include "mx.h"
51 #include "options.h"
52 #include "protos.h"
53 #include "rfc3676.h"
54 #ifdef USE_IMAP
55 #include "imap/lib.h"
56 #endif
57 
58 short PostCount = 0;
59 static bool UpdateNumPostponed = false;
60 
69 int mutt_num_postponed(struct Mailbox *m, bool force)
70 {
71  struct stat st = { 0 };
72 
73  static time_t LastModify = 0;
74  static char *OldPostponed = NULL;
75 
77  {
78  UpdateNumPostponed = false;
79  force = true;
80  }
81 
82  const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
83  if (!mutt_str_equal(c_postponed, OldPostponed))
84  {
85  FREE(&OldPostponed);
86  OldPostponed = mutt_str_dup(c_postponed);
87  LastModify = 0;
88  force = true;
89  }
90 
91  if (!c_postponed)
92  return 0;
93 
94  // We currently are in the `$postponed` mailbox so just pick the current status
95  if (m && mutt_str_equal(c_postponed, m->realpath))
96  {
98  return PostCount;
99  }
100 
101 #ifdef USE_IMAP
102  /* LastModify is useless for IMAP */
103  if (imap_path_probe(c_postponed, NULL) == MUTT_IMAP)
104  {
105  if (force)
106  {
107  short newpc;
108 
109  newpc = imap_path_status(c_postponed, false);
110  if (newpc >= 0)
111  {
112  PostCount = newpc;
113  mutt_debug(LL_DEBUG3, "%d postponed IMAP messages found\n", PostCount);
114  }
115  else
116  mutt_debug(LL_DEBUG3, "using old IMAP postponed count\n");
117  }
118  return PostCount;
119  }
120 #endif
121 
122  if (stat(c_postponed, &st) == -1)
123  {
124  PostCount = 0;
125  LastModify = 0;
126  return 0;
127  }
128 
129  if (S_ISDIR(st.st_mode))
130  {
131  /* if we have a maildir mailbox, we need to stat the "new" dir */
132  struct Buffer *buf = mutt_buffer_pool_get();
133 
134  mutt_buffer_printf(buf, "%s/new", c_postponed);
135  if ((access(mutt_buffer_string(buf), F_OK) == 0) &&
136  (stat(mutt_buffer_string(buf), &st) == -1))
137  {
138  PostCount = 0;
139  LastModify = 0;
141  return 0;
142  }
144  }
145 
146  if (LastModify < st.st_mtime)
147  {
148 #ifdef USE_NNTP
149  int optnews = OptNews;
150 #endif
151  LastModify = st.st_mtime;
152 
153  if (access(c_postponed, R_OK | F_OK) != 0)
154  return PostCount = 0;
155 #ifdef USE_NNTP
156  if (optnews)
157  OptNews = false;
158 #endif
159  struct Mailbox *m_post = mx_path_resolve(c_postponed);
160  if (mx_mbox_open(m_post, MUTT_NOSORT | MUTT_QUIET))
161  {
162  PostCount = m_post->msg_count;
163  mx_fastclose_mailbox(m_post, false);
164  }
165  else
166  {
167  PostCount = 0;
168  }
169  mailbox_free(&m_post);
170 
171 #ifdef USE_NNTP
172  if (optnews)
173  OptNews = true;
174 #endif
175  }
176 
177  return PostCount;
178 }
179 
184 {
185  UpdateNumPostponed = true;
186 }
187 
192 static void hardclose(struct Mailbox *m)
193 {
194  /* messages might have been marked for deletion.
195  * try once more on reopen before giving up. */
196  enum MxStatus rc = mx_mbox_close(m);
197  if (rc != MX_STATUS_ERROR && rc != MX_STATUS_OK)
198  rc = mx_mbox_close(m);
199  if (rc != MX_STATUS_OK)
200  mx_fastclose_mailbox(m, false);
201 }
202 
210 SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
211 {
212  char smime_cryptalg[1024] = { 0 };
213  char sign_as[1024] = { 0 };
214  char *q = NULL;
215  SecurityFlags flags = SEC_NO_FLAGS;
216 
217  if (!WithCrypto)
218  return SEC_NO_FLAGS;
219 
221  for (; p[0] != '\0'; p++)
222  {
223  switch (p[0])
224  {
225  case 'c':
226  case 'C':
227  q = smime_cryptalg;
228 
229  if (p[1] == '<')
230  {
231  for (p += 2; (p[0] != '\0') && (p[0] != '>') &&
232  (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
233  *q++ = *p++)
234  {
235  }
236 
237  if (p[0] != '>')
238  {
239  mutt_error(_("Illegal S/MIME header"));
240  return SEC_NO_FLAGS;
241  }
242  }
243 
244  *q = '\0';
245  break;
246 
247  case 'e':
248  case 'E':
249  flags |= SEC_ENCRYPT;
250  break;
251 
252  case 'i':
253  case 'I':
254  flags |= SEC_INLINE;
255  break;
256 
257  /* This used to be the micalg parameter.
258  *
259  * It's no longer needed, so we just skip the parameter in order
260  * to be able to recall old messages. */
261  case 'm':
262  case 'M':
263  if (p[1] != '<')
264  break;
265 
266  for (p += 2; (p[0] != '\0') && (p[0] != '>'); p++)
267  ; // do nothing
268 
269  if (p[0] != '>')
270  {
271  mutt_error(_("Illegal crypto header"));
272  return SEC_NO_FLAGS;
273  }
274  break;
275 
276  case 'o':
277  case 'O':
278  flags |= SEC_OPPENCRYPT;
279  break;
280 
281  case 'a':
282  case 'A':
283 #ifdef USE_AUTOCRYPT
284  flags |= SEC_AUTOCRYPT;
285 #endif
286  break;
287 
288  case 'z':
289  case 'Z':
290 #ifdef USE_AUTOCRYPT
291  flags |= SEC_AUTOCRYPT_OVERRIDE;
292 #endif
293  break;
294 
295  case 's':
296  case 'S':
297  flags |= SEC_SIGN;
298  q = sign_as;
299 
300  if (p[1] == '<')
301  {
302  for (p += 2;
303  (p[0] != '\0') && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
304  *q++ = *p++)
305  {
306  }
307 
308  if (p[0] != '>')
309  {
310  mutt_error(_("Illegal crypto header"));
311  return SEC_NO_FLAGS;
312  }
313  }
314 
315  q[0] = '\0';
316  break;
317 
318  default:
319  mutt_error(_("Illegal crypto header"));
320  return SEC_NO_FLAGS;
321  }
322  }
323 
324  /* the cryptalg field must not be empty */
325  if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
326  {
327  struct Buffer errmsg = mutt_buffer_make(0);
328  int rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
329  smime_cryptalg, &errmsg);
330 
331  if ((CSR_RESULT(rc) != CSR_SUCCESS) && !mutt_buffer_is_empty(&errmsg))
332  mutt_error("%s", mutt_buffer_string(&errmsg));
333 
334  mutt_buffer_dealloc(&errmsg);
335  }
336 
337  /* Set {Smime,Pgp}SignAs, if desired. */
338 
339  if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
340  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
341  {
342  cs_subset_str_string_set(NeoMutt->sub, "pgp_sign_as", sign_as, NULL);
343  }
344 
345  if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
346  (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
347  {
348  cs_subset_str_string_set(NeoMutt->sub, "smime_sign_as", sign_as, NULL);
349  }
350 
351  return flags;
352 }
353 
364 static int create_tmp_files_for_attachments(FILE *fp_body, struct Buffer *file,
365  struct Email *e_new, struct Body *body,
366  struct Envelope *protected_headers)
367 {
368  struct Body *b = NULL;
369  struct State s = { 0 };
370  SecurityFlags sec_type;
371 
372  s.fp_in = fp_body;
373 
374  for (b = body; b; b = b->next)
375  {
376  if (b->type == TYPE_MULTIPART)
377  {
378  if (create_tmp_files_for_attachments(fp_body, file, e_new, b->parts, protected_headers) < 0)
379  {
380  return -1;
381  }
382  }
383  else
384  {
385  mutt_buffer_reset(file);
386  if (b->filename)
387  {
388  mutt_buffer_strcpy(file, b->filename);
390  }
391  else
392  {
393  /* avoid Content-Disposition: header with temporary filename */
394  b->use_disp = false;
395  }
396 
397  /* set up state flags */
398 
399  s.flags = 0;
400 
401  if (b->type == TYPE_TEXT)
402  {
403  if (mutt_istr_equal("yes", mutt_param_get(&b->parameter, "x-mutt-noconv")))
404  {
405  b->noconv = true;
406  }
407  else
408  {
409  s.flags |= MUTT_CHARCONV;
410  b->noconv = false;
411  }
412 
413  mutt_param_delete(&b->parameter, "x-mutt-noconv");
414  }
415 
416  mutt_adv_mktemp(file);
417  s.fp_out = mutt_file_fopen(mutt_buffer_string(file), "w");
418  if (!s.fp_out)
419  return -1;
420 
421  if (((WithCrypto & APPLICATION_PGP) != 0) &&
422  ((sec_type = mutt_is_application_pgp(b)) & (SEC_ENCRYPT | SEC_SIGN)))
423  {
424  if (sec_type & SEC_ENCRYPT)
425  {
427  return -1;
428  mutt_message(_("Decrypting message..."));
429  }
430 
431  if (mutt_body_handler(b, &s) < 0)
432  {
433  mutt_error(_("Decryption failed"));
434  return -1;
435  }
436 
437  if ((b == body) && !protected_headers)
438  {
439  protected_headers = b->mime_headers;
440  b->mime_headers = NULL;
441  }
442 
443  e_new->security |= sec_type;
444  b->type = TYPE_TEXT;
445  mutt_str_replace(&b->subtype, "plain");
446  mutt_param_delete(&b->parameter, "x-action");
447  }
448  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
449  ((sec_type = mutt_is_application_smime(b)) & (SEC_ENCRYPT | SEC_SIGN)))
450  {
451  if (sec_type & SEC_ENCRYPT)
452  {
454  return -1;
455  crypt_smime_getkeys(e_new->env);
456  mutt_message(_("Decrypting message..."));
457  }
458 
459  if (mutt_body_handler(b, &s) < 0)
460  {
461  mutt_error(_("Decryption failed"));
462  return -1;
463  }
464 
465  e_new->security |= sec_type;
466  b->type = TYPE_TEXT;
467  mutt_str_replace(&b->subtype, "plain");
468  }
469  else
470  {
471  mutt_decode_attachment(b, &s);
472  }
473 
474  if (mutt_file_fclose(&s.fp_out) != 0)
475  return -1;
476 
478  b->unlink = true;
479 
481 
482  mutt_body_free(&b->parts);
483  if (b->email)
484  b->email->body = NULL; /* avoid dangling pointer */
485  }
486  }
487 
488  return 0;
489 }
490 
503 int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new,
504  struct Email *e, bool resend)
505 {
506  struct Message *msg = NULL;
507  struct Body *b = NULL;
508  FILE *fp_body = NULL;
509  int rc = -1;
510  SecurityFlags sec_type;
511  struct Envelope *protected_headers = NULL;
512  struct Buffer *file = NULL;
513 
514  if (!fp && !(msg = mx_msg_open(m, e->msgno)))
515  return -1;
516 
517  if (!fp)
518  fp = msg->fp;
519 
520  fp_body = fp;
521 
522  /* parse the message header and MIME structure */
523 
524  if (!mutt_file_seek(fp, e->offset, SEEK_SET))
525  {
526  return -1;
527  }
528  e_new->offset = e->offset;
529  /* enable header weeding for resent messages */
530  e_new->env = mutt_rfc822_read_header(fp, e_new, true, resend);
531  e_new->body->length = e->body->length;
532  mutt_parse_part(fp, e_new->body);
533 
534  /* If resending a message, don't keep message_id or mail_followup_to.
535  * Otherwise, we are resuming a postponed message, and want to keep those
536  * headers if they exist. */
537  if (resend)
538  {
539  FREE(&e_new->env->message_id);
541  }
542 
543  /* decrypt pgp/mime encoded messages */
544 
545  if (((WithCrypto & APPLICATION_PGP) != 0) &&
546  (sec_type = mutt_is_multipart_encrypted(e_new->body)))
547  {
548  e_new->security |= sec_type;
549  if (!crypt_valid_passphrase(sec_type))
550  goto bail;
551 
552  mutt_message(_("Decrypting message..."));
553  if ((crypt_pgp_decrypt_mime(fp, &fp_body, e_new->body, &b) == -1) || !b)
554  {
555  mutt_error(_("Could not decrypt PGP message"));
556  goto bail;
557  }
558 
559  mutt_body_free(&e_new->body);
560  e_new->body = b;
561 
562  if (b->mime_headers)
563  {
564  protected_headers = b->mime_headers;
565  b->mime_headers = NULL;
566  }
567 
569  }
570 
571  /* remove a potential multipart/signed layer - useful when
572  * resending messages */
573  if ((WithCrypto != 0) && mutt_is_multipart_signed(e_new->body))
574  {
575  e_new->security |= SEC_SIGN;
576  if (((WithCrypto & APPLICATION_PGP) != 0) &&
577  mutt_istr_equal(mutt_param_get(&e_new->body->parameter, "protocol"), "application/pgp-signature"))
578  {
579  e_new->security |= APPLICATION_PGP;
580  }
581  else if (WithCrypto & APPLICATION_SMIME)
582  e_new->security |= APPLICATION_SMIME;
583 
584  /* destroy the signature */
585  mutt_body_free(&e_new->body->parts->next);
586  e_new->body = mutt_remove_multipart(e_new->body);
587 
588  if (e_new->body->mime_headers)
589  {
590  mutt_env_free(&protected_headers);
591  protected_headers = e_new->body->mime_headers;
592  e_new->body->mime_headers = NULL;
593  }
594  }
595 
596  /* We don't need no primary multipart/mixed. */
597  if ((e_new->body->type == TYPE_MULTIPART) && mutt_istr_equal(e_new->body->subtype, "mixed"))
598  e_new->body = mutt_remove_multipart(e_new->body);
599 
600  file = mutt_buffer_pool_get();
601 
602  /* create temporary files for all attachments */
603  if (create_tmp_files_for_attachments(fp_body, file, e_new, e_new->body, protected_headers) < 0)
604  {
605  goto bail;
606  }
607 
608  const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
609  if (c_crypt_protected_headers_read && protected_headers && protected_headers->subject &&
610  !mutt_str_equal(e_new->env->subject, protected_headers->subject))
611  {
612  mutt_str_replace(&e_new->env->subject, protected_headers->subject);
613  }
614  mutt_env_free(&protected_headers);
615 
616  /* Fix encryption flags. */
617 
618  /* No inline if multipart. */
619  if ((WithCrypto != 0) && (e_new->security & SEC_INLINE) && e_new->body->next)
620  e_new->security &= ~SEC_INLINE;
621 
622  /* Do we even support multiple mechanisms? */
624 
625  /* Theoretically, both could be set. Take the one the user wants to set by default. */
626  if ((e_new->security & APPLICATION_PGP) && (e_new->security & APPLICATION_SMIME))
627  {
628  const bool c_smime_is_default = cs_subset_bool(NeoMutt->sub, "smime_is_default");
629  if (c_smime_is_default)
630  e_new->security &= ~APPLICATION_PGP;
631  else
632  e_new->security &= ~APPLICATION_SMIME;
633  }
634 
636 
637  rc = 0;
638 
639 bail:
640 
641  /* that's it. */
643  if (fp_body != fp)
644  mutt_file_fclose(&fp_body);
645  if (msg)
646  mx_msg_close(m, &msg);
647 
648  if (rc == -1)
649  {
650  mutt_env_free(&e_new->env);
651  mutt_body_free(&e_new->body);
652  }
653 
654  return rc;
655 }
656 
667 int mutt_get_postponed(struct Mailbox *m_cur, struct Email *hdr,
668  struct Email **cur, struct Buffer *fcc)
669 {
670  const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
671  if (!c_postponed)
672  return -1;
673 
674  struct Email *e = NULL;
675  int rc = SEND_POSTPONED;
676  const char *p = NULL;
677 
678  struct Mailbox *m = mx_path_resolve(c_postponed);
679  if (m_cur != m)
680  {
681  if (!mx_mbox_open(m, MUTT_NOSORT))
682  {
683  PostCount = 0;
684  mutt_error(_("No postponed messages"));
685  mailbox_free(&m);
686  return -1;
687  }
688  }
689 
690  mx_mbox_check(m);
691 
692  if (m->msg_count == 0)
693  {
694  PostCount = 0;
695  mutt_error(_("No postponed messages"));
696  if (m_cur != m)
697  {
698  mx_fastclose_mailbox(m, false);
699  mailbox_free(&m);
700  }
701  return -1;
702  }
703 
704  /* avoid the "purge deleted messages" prompt */
705  const enum QuadOption c_delete = cs_subset_quad(NeoMutt->sub, "delete");
706  cs_subset_str_native_set(NeoMutt->sub, "delete", MUTT_YES, NULL);
707 
708  struct MailboxView *mv = (m_cur != m) ? mview_new(m) : NULL;
709  if (m->msg_count == 1)
710  {
711  /* only one message, so just use that one. */
712  e = m->emails[0];
713  }
714  else if (!(e = dlg_select_postponed_email(m)))
715  {
716  rc = -1;
717  goto cleanup;
718  }
719 
720  if (mutt_prepare_template(NULL, m, hdr, e, false) < 0)
721  {
722  rc = -1;
723  goto cleanup;
724  }
725 
726  /* finished with this message, so delete it. */
727  mutt_set_flag(m, e, MUTT_DELETE, true);
728  mutt_set_flag(m, e, MUTT_PURGE, true);
729 
730  /* update the count for the status display */
731  PostCount = m->msg_count - m->msg_deleted;
732 
733  struct ListNode *np = NULL, *tmp = NULL;
734  STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
735  {
736  size_t plen = mutt_istr_startswith(np->data, "X-Mutt-References:");
737  if (plen)
738  {
739  /* if a mailbox is currently open, look to see if the original message
740  * the user attempted to reply to is in this mailbox */
741  p = mutt_str_skip_email_wsp(np->data + plen);
742  if (!m_cur->id_hash)
743  m_cur->id_hash = mutt_make_id_hash(m_cur);
744  *cur = mutt_hash_find(m_cur->id_hash, p);
745 
746  if (*cur)
747  rc |= SEND_REPLY;
748  }
749  else if ((plen = mutt_istr_startswith(np->data, "X-Mutt-Fcc:")))
750  {
751  p = mutt_str_skip_email_wsp(np->data + plen);
752  mutt_buffer_strcpy(fcc, p);
754 
755  /* note that x-mutt-fcc was present. we do this because we want to add a
756  * default fcc if the header was missing, but preserve the request of the
757  * user to not make a copy if the header field is present, but empty.
758  * see http://dev.mutt.org/trac/ticket/3653 */
759  rc |= SEND_POSTPONED_FCC;
760  }
761  else if (((WithCrypto & APPLICATION_PGP) != 0) &&
762  /* this is generated by old neomutt versions */
763  (mutt_str_startswith(np->data, "Pgp:") ||
764  /* this is the new way */
765  mutt_str_startswith(np->data, "X-Mutt-PGP:")))
766  {
767  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_PGP);
768  hdr->security |= APPLICATION_PGP;
769  }
770  else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
771  mutt_str_startswith(np->data, "X-Mutt-SMIME:"))
772  {
773  hdr->security = mutt_parse_crypt_hdr(strchr(np->data, ':') + 1, true, APPLICATION_SMIME);
774  hdr->security |= APPLICATION_SMIME;
775  }
776 #ifdef MIXMASTER
777  else if (mutt_str_startswith(np->data, "X-Mutt-Mix:"))
778  {
779  mutt_list_free(&hdr->chain);
780 
781  char *t = strtok(np->data + 11, " \t\n");
782  while (t)
783  {
785  t = strtok(NULL, " \t\n");
786  }
787  }
788 #endif
789  else
790  {
791  // skip header removal
792  continue;
793  }
794 
795  // remove the header
796  STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
797  FREE(&np->data);
798  FREE(&np);
799  }
800 
801  const bool c_crypt_opportunistic_encrypt = cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
802  if (c_crypt_opportunistic_encrypt)
804 
805 cleanup:
806  if (m_cur != m)
807  {
808  hardclose(m);
809  mview_free(&mv);
810  mailbox_free(&m);
811  }
812 
813  cs_subset_str_native_set(NeoMutt->sub, "delete", c_delete, NULL);
814  return rc;
815 }
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
Email Address Handling.
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:63
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:250
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:292
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:158
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:81
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:544
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition: crypt.c:1025
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:402
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:601
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition: crypt.c:439
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition: cryptglue.c:455
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:211
struct Email * dlg_select_postponed_email(struct Mailbox *m)
Create a Menu to select a postponed message.
Definition: dlg_postpone.c:166
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
Structs that make up an email.
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#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:2400
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email's attachment.
Definition: handler.c:1867
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
Decide how to display email content.
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:362
IMAP network mailbox.
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition: imap.c:1238
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
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
#define FREE(x)
Definition: memory.h:43
@ 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
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:796
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:784
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:656
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:239
Many unsorted constants and some structs.
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:97
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:95
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
NeoMutt Logging.
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for message-ids.
Definition: mutt_thread.c:1651
Create/manipulate threading in emails.
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:599
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:84
Some miscellaneous functions.
void mview_free(struct MailboxView **ptr)
Free a MailboxView.
Definition: mview.c:49
struct MailboxView * mview_new(struct Mailbox *m)
Create a new MailboxView.
Definition: mview.c:77
The "currently-open" mailbox.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1193
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition: mx.c:430
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1147
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1677
enum MxStatus mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition: mx.c:1126
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:615
API for mailboxes.
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:65
#define MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition: mxapi.h:62
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:84
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:85
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:86
API for encryption/signing of emails.
#define SEC_INLINE
Email has an inline signature.
Definition: lib.h:85
#define SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition: lib.h:87
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:74
#define SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition: lib.h:86
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:77
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
#define WithCrypto
Definition: lib.h:116
#define SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition: lib.h:88
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
Handling of global boolean variables.
bool OptNews
(pseudo) used to change reader mode
Definition: options.h:50
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:1737
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
Definition: parse.c:1158
static size_t plen
Length of cached packet.
Definition: pgppacket.c:39
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
SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
Parse a crypto header string.
Definition: postpone.c:210
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition: postpone.c:69
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition: postpone.c:183
short PostCount
Definition: postpone.c:58
static bool UpdateNumPostponed
Definition: postpone.c:59
int mutt_get_postponed(struct Mailbox *m_cur, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
Recall a postponed message.
Definition: postpone.c:667
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:503
static void hardclose(struct Mailbox *m)
Try hard to close a mailbox.
Definition: postpone.c:192
static int create_tmp_files_for_attachments(FILE *fp_body, struct Buffer *file, struct Email *e_new, struct Body *body, struct Envelope *protected_headers)
Create temporary files for all attachments.
Definition: postpone.c:364
Prototypes for many functions.
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:64
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
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition: rfc3676.c:494
RFC3676 Format Flowed routines.
Convenience wrapper for the send headers.
#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
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:401
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
Key value store.
The body of an email.
Definition: body.h:36
char * d_filename
filename to be used for the content-disposition header If NULL, filename is used instead.
Definition: body.h:56
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
bool noconv
Don't do character set conversion.
Definition: body.h:46
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:67
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:75
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
bool use_disp
Content-Disposition uses filename= ?
Definition: body.h:47
struct Email * email
header information for message/rfc822
Definition: body.h:73
struct Body * next
next attachment in the list
Definition: body.h:71
char * subtype
content-type subtype
Definition: body.h:60
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:34
The envelope/body of an email.
Definition: email.h:37
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
struct ListHead chain
Mixmaster chain.
Definition: email.h:90
int msgno
Number displayed to the user.
Definition: email.h:111
The header of an Email.
Definition: envelope.h:57
struct ListHead userhdrs
user defined headers
Definition: envelope.h:87
char * message_id
Message ID.
Definition: envelope.h:73
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition: envelope.h:65
char * subject
Email's subject.
Definition: envelope.h:70
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
The "current" mailbox.
Definition: mview.h:38
A mailbox.
Definition: mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
int msg_count
Total number of messages.
Definition: mailbox.h:88
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:124
int msg_deleted
Number of deleted messages.
Definition: mailbox.h:93
A local copy of an email.
Definition: mxapi.h:43
FILE * fp
pointer to the message data
Definition: mxapi.h:44
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Keep track when processing files.
Definition: state.h:46
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
FILE * fp_out
File to write to.
Definition: state.h:48
FILE * fp_in
File to read from.
Definition: state.h:47
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
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