NeoMutt  2025-12-11-911-gd8d604
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
postpone.c
Go to the documentation of this file.
1
25
31
32#include "config.h"
33#include <stdbool.h>
34#include <stdio.h>
35#include <sys/stat.h>
36#include <time.h>
37#include <unistd.h>
38#include "mutt/lib.h"
39#include "address/lib.h"
40#include "config/lib.h"
41#include "email/lib.h"
42#include "core/lib.h"
43#include "gui/lib.h"
44#include "mutt.h"
45#include "lib.h"
46#include "imap/lib.h"
47#include "ncrypt/lib.h"
48#include "send/lib.h"
49#include "globals.h"
50#include "module_data.h"
51#include "mutt_logging.h"
52#include "muttlib.h"
53#include "mx.h"
54
63int mutt_num_postponed(struct Mailbox *m, bool force)
64{
65 struct stat st = { 0 };
67
68 static time_t LastModify = 0;
69 static char *OldPostponed = NULL;
70
71 if (mod_data->update_num_postponed)
72 {
73 mod_data->update_num_postponed = false;
74 force = true;
75 }
76
77 const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
78 if (!mutt_str_equal(c_postponed, OldPostponed))
79 {
80 FREE(&OldPostponed);
81 OldPostponed = mutt_str_dup(c_postponed);
82 LastModify = 0;
83 force = true;
84 }
85
86 if (!c_postponed)
87 return 0;
88
89 // We currently are in the `$postponed` mailbox so just pick the current status
90 if (m && mutt_str_equal(c_postponed, m->realpath))
91 {
92 mod_data->post_count = m->msg_count - m->msg_deleted;
93 return mod_data->post_count;
94 }
95
96 /* LastModify is useless for IMAP */
97 if (imap_path_probe(c_postponed, NULL) == MUTT_IMAP)
98 {
99 if (force)
100 {
101 short newpc;
102
103 newpc = imap_path_status(c_postponed, false);
104 if (newpc >= 0)
105 {
106 mod_data->post_count = newpc;
107 mutt_debug(LL_DEBUG3, "%d postponed IMAP messages found\n", mod_data->post_count);
108 }
109 else
110 {
111 mutt_debug(LL_DEBUG3, "using old IMAP postponed count\n");
112 }
113 }
114 return mod_data->post_count;
115 }
116
117 if (stat(c_postponed, &st) == -1)
118 {
119 mod_data->post_count = 0;
120 LastModify = 0;
121 return 0;
122 }
123
124 if (S_ISDIR(st.st_mode))
125 {
126 /* if we have a maildir mailbox, we need to stat the "new" dir */
127 struct Buffer *buf = buf_pool_get();
128
129 buf_printf(buf, "%s/new", c_postponed);
130 if ((access(buf_string(buf), F_OK) == 0) && (stat(buf_string(buf), &st) == -1))
131 {
132 mod_data->post_count = 0;
133 LastModify = 0;
134 buf_pool_release(&buf);
135 return 0;
136 }
137 buf_pool_release(&buf);
138 }
139
140 if (LastModify < st.st_mtime)
141 {
142 int optnews = OptNews;
143 LastModify = st.st_mtime;
144
145 if (access(c_postponed, R_OK | F_OK) != 0)
146 return mod_data->post_count = 0;
147 if (optnews)
148 OptNews = false;
149 struct Mailbox *m_post = mx_path_resolve(c_postponed);
150 if (mx_mbox_open(m_post, MUTT_NOSORT | MUTT_QUIET))
151 {
152 mod_data->post_count = m_post->msg_count;
153 mx_fastclose_mailbox(m_post, false);
154 }
155 else
156 {
157 mod_data->post_count = 0;
158 }
159 mailbox_free(&m_post);
160
161 if (optnews)
162 OptNews = true;
163 }
164
165 return mod_data->post_count;
166}
167
176
181static void hardclose(struct Mailbox *m)
182{
183 /* messages might have been marked for deletion.
184 * try once more on reopen before giving up. */
185 enum MxStatus rc = mx_mbox_close(m);
186 if (rc != MX_STATUS_ERROR && rc != MX_STATUS_OK)
187 rc = mx_mbox_close(m);
188 if (rc != MX_STATUS_OK)
189 mx_fastclose_mailbox(m, false);
190}
191
199SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
200{
201 char smime_cryptalg[1024] = { 0 };
202 char sign_as[1024] = { 0 };
203 char *q = NULL;
204 SecurityFlags flags = SEC_NONE;
205
206 if (!WithCrypto)
207 return SEC_NONE;
208
210 for (; p[0] != '\0'; p++)
211 {
212 switch (p[0])
213 {
214 case 'c':
215 case 'C':
216 q = smime_cryptalg;
217
218 if (p[1] == '<')
219 {
220 for (p += 2; (p[0] != '\0') && (p[0] != '>') &&
221 (q < (smime_cryptalg + sizeof(smime_cryptalg) - 1));
222 *q++ = *p++)
223 {
224 }
225
226 if (p[0] != '>')
227 {
228 mutt_error(_("Illegal S/MIME header"));
229 return SEC_NONE;
230 }
231 }
232
233 *q = '\0';
234 break;
235
236 case 'e':
237 case 'E':
238 flags |= SEC_ENCRYPT;
239 break;
240
241 case 'i':
242 case 'I':
243 flags |= SEC_INLINE;
244 break;
245
246 /* This used to be the micalg parameter.
247 *
248 * It's no longer needed, so we just skip the parameter in order
249 * to be able to recall old messages. */
250 case 'm':
251 case 'M':
252 if (p[1] != '<')
253 break;
254
255 for (p += 2; (p[0] != '\0') && (p[0] != '>'); p++)
256 ; // do nothing
257
258 if (p[0] != '>')
259 {
260 mutt_error(_("Illegal crypto header"));
261 return SEC_NONE;
262 }
263 break;
264
265 case 'o':
266 case 'O':
267 flags |= SEC_OPPENCRYPT;
268 break;
269
270 case 'a':
271 case 'A':
272#ifdef USE_AUTOCRYPT
273 flags |= SEC_AUTOCRYPT;
274#endif
275 break;
276
277 case 'z':
278 case 'Z':
279#ifdef USE_AUTOCRYPT
280 flags |= SEC_AUTOCRYPT_OVERRIDE;
281#endif
282 break;
283
284 case 's':
285 case 'S':
286 flags |= SEC_SIGN;
287 q = sign_as;
288
289 if (p[1] == '<')
290 {
291 for (p += 2;
292 (p[0] != '\0') && (*p != '>') && (q < (sign_as + sizeof(sign_as) - 1));
293 *q++ = *p++)
294 {
295 }
296
297 if (p[0] != '>')
298 {
299 mutt_error(_("Illegal crypto header"));
300 return SEC_NONE;
301 }
302 }
303
304 q[0] = '\0';
305 break;
306
307 default:
308 mutt_error(_("Illegal crypto header"));
309 return SEC_NONE;
310 }
311 }
312
313 /* the cryptalg field must not be empty */
314 if (((WithCrypto & APPLICATION_SMIME) != 0) && *smime_cryptalg)
315 {
316 struct Buffer *errmsg = buf_pool_get();
317 int rc = cs_subset_str_string_set(NeoMutt->sub, "smime_encrypt_with",
318 smime_cryptalg, errmsg);
319
320 if ((CSR_RESULT(rc) != CSR_SUCCESS) && !buf_is_empty(errmsg))
321 mutt_error("%s", buf_string(errmsg));
322
323 buf_pool_release(&errmsg);
324 }
325
326 /* Set {Smime,Pgp}SignAs, if desired. */
327
328 if (((WithCrypto & APPLICATION_PGP) != 0) && (crypt_app == APPLICATION_PGP) &&
329 (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
330 {
331 cs_subset_str_string_set(NeoMutt->sub, "pgp_sign_as", sign_as, NULL);
332 }
333
334 if (((WithCrypto & APPLICATION_SMIME) != 0) && (crypt_app == APPLICATION_SMIME) &&
335 (flags & SEC_SIGN) && (set_empty_signas || *sign_as))
336 {
337 cs_subset_str_string_set(NeoMutt->sub, "smime_sign_as", sign_as, NULL);
338 }
339
340 return flags;
341}
342
354static int create_tmp_files_for_attachments(FILE *fp_body, struct Buffer *file,
355 struct Email *e_new, struct Body *body,
356 struct Envelope *protected_headers, int depth)
357{
358 if (depth > 50)
359 {
360 mutt_debug(LL_DEBUG1, "stripping too deep MIME tree\n");
361 return -1;
362 }
363
364 struct Body *b = NULL;
365 struct State state = { 0 };
366
367 state.fp_in = fp_body;
368
369 for (b = body; b; b = b->next)
370 {
371 if (b->type == TYPE_MULTIPART)
372 {
373 if (create_tmp_files_for_attachments(fp_body, file, e_new, b->parts,
374 protected_headers, depth + 1) < 0)
375 {
376 return -1;
377 }
378 }
379 else
380 {
381 buf_reset(file);
382 if (b->filename)
383 {
384 buf_strcpy(file, b->filename);
386 }
387 else
388 {
389 /* avoid Content-Disposition: header with temporary filename */
390 b->use_disp = false;
391 }
392
393 /* set up state flags */
394
395 state.flags = 0;
396
397 if (b->type == TYPE_TEXT)
398 {
399 if (mutt_istr_equal("yes", mutt_param_get(&b->parameter, "x-mutt-noconv")))
400 {
401 b->noconv = true;
402 }
403 else
404 {
405 state.flags |= STATE_CHARCONV;
406 b->noconv = false;
407 }
408
409 mutt_param_delete(&b->parameter, "x-mutt-noconv");
410 }
411
413 state.fp_out = mutt_file_fopen(buf_string(file), "w");
414 if (!state.fp_out)
415 return -1;
416
417 SecurityFlags sec_type = SEC_NONE;
418 if (((WithCrypto & APPLICATION_PGP) != 0) && sec_type == SEC_NONE)
419 sec_type = mutt_is_application_pgp(b);
420 if (((WithCrypto & APPLICATION_SMIME) != 0) && sec_type == SEC_NONE)
421 sec_type = mutt_is_application_smime(b);
422 if (sec_type & (SEC_ENCRYPT | SEC_SIGN))
423 {
424 if (sec_type & SEC_ENCRYPT)
425 {
426 if (!crypt_valid_passphrase(sec_type))
427 {
428 mutt_file_fclose(&state.fp_out);
429 return -1;
430 }
431 if (sec_type & APPLICATION_SMIME)
432 crypt_smime_getkeys(e_new->env);
433 mutt_message(_("Decrypting message..."));
434 }
435
436 if (mutt_body_handler(b, &state) < 0)
437 {
438 mutt_error(_("Decryption failed"));
439 mutt_file_fclose(&state.fp_out);
440 return -1;
441 }
442
443 /* Is this the first body part? Then save the headers. */
444 if ((b == body) && !protected_headers)
445 {
446 protected_headers = b->mime_headers;
447 b->mime_headers = NULL;
448 }
449
450 e_new->security |= sec_type;
451 b->type = TYPE_TEXT;
452 mutt_str_replace(&b->subtype, "plain");
453 if (sec_type & APPLICATION_PGP)
454 mutt_param_delete(&b->parameter, "x-action");
455 }
456 else
457 {
458 mutt_decode_attachment(b, &state);
459 }
460
461 if (mutt_file_fclose(&state.fp_out) != 0)
462 return -1;
463
465 b->unlink = true;
466
468
470 if (b->email)
471 b->email->body = NULL; /* avoid dangling pointer */
472 }
473 }
474
475 return 0;
476}
477
490int mutt_prepare_template(FILE *fp, struct Mailbox *m, struct Email *e_new,
491 struct Email *e, bool resend)
492{
493 struct Message *msg = NULL;
494 struct Body *b = NULL;
495 FILE *fp_body = NULL;
496 int rc = -1;
497 struct Envelope *protected_headers = NULL;
498 struct Buffer *file = NULL;
499
500 if (!fp && !(msg = mx_msg_open(m, e)))
501 return -1;
502
503 if (!fp)
504 fp = msg->fp;
505
506 fp_body = fp;
507
508 /* parse the message header and MIME structure */
509
510 if (!mutt_file_seek(fp, e->offset, SEEK_SET))
511 {
512 goto bail;
513 }
514 e_new->offset = e->offset;
515 /* enable header weeding for resent messages */
516 e_new->env = mutt_rfc822_read_header(fp, e_new, true, resend);
517 e_new->body->length = e->body->length;
518 mutt_parse_part(fp, e_new->body);
519
520 /* If resending a message, don't keep message_id or mail_followup_to.
521 * Otherwise, we are resuming a postponed message, and want to keep those
522 * headers if they exist. */
523 if (resend)
524 {
525 FREE(&e_new->env->message_id);
527 }
528
529 SecurityFlags sec_type = SEC_NONE;
530 if (((WithCrypto & APPLICATION_PGP) != 0) && sec_type == SEC_NONE)
531 sec_type = mutt_is_multipart_encrypted(e_new->body);
532 if (((WithCrypto & APPLICATION_SMIME) != 0) && sec_type == SEC_NONE)
533 sec_type = mutt_is_application_smime(e_new->body);
534 if (sec_type != SEC_NONE)
535 {
536 e_new->security |= sec_type;
537 if (!crypt_valid_passphrase(sec_type))
538 goto bail;
539
540 mutt_message(_("Decrypting message..."));
541 int ret = -1;
542 if (sec_type & APPLICATION_PGP)
543 ret = crypt_pgp_decrypt_mime(fp, &fp_body, e_new->body, &b);
544 else if (sec_type & APPLICATION_SMIME)
545 ret = crypt_smime_decrypt_mime(fp, &fp_body, e_new->body, &b);
546 if ((ret == -1) || !b)
547 {
548 mutt_error(_("Could not decrypt postponed message"));
549 goto bail;
550 }
551
552 /* throw away the outer layer and keep only the (now decrypted) inner part
553 * with its headers. */
554 mutt_body_free(&e_new->body);
555 e_new->body = b;
556
557 if (b->mime_headers)
558 {
559 protected_headers = b->mime_headers;
560 b->mime_headers = NULL;
561 }
562
564 }
565
566 /* remove a potential multipart/signed layer - useful when
567 * resending messages */
568 if ((WithCrypto != 0) && mutt_is_multipart_signed(e_new->body) && e_new->body->parts)
569 {
570 e_new->security |= SEC_SIGN;
571 if (((WithCrypto & APPLICATION_PGP) != 0) &&
572 mutt_istr_equal(mutt_param_get(&e_new->body->parameter, "protocol"), "application/pgp-signature"))
573 {
574 e_new->security |= APPLICATION_PGP;
575 }
576 else if (WithCrypto & APPLICATION_SMIME)
577 {
578 e_new->security |= APPLICATION_SMIME;
579 }
580
581 /* destroy the signature */
582 mutt_body_free(&e_new->body->parts->next);
583 e_new->body = mutt_remove_multipart(e_new->body);
584
585 if (e_new->body->mime_headers)
586 {
587 mutt_env_free(&protected_headers);
588 protected_headers = e_new->body->mime_headers;
589 e_new->body->mime_headers = NULL;
590 }
591 }
592
593 /* We don't need no primary multipart/mixed. */
594 if ((e_new->body->type == TYPE_MULTIPART) && mutt_istr_equal(e_new->body->subtype, "mixed"))
595 e_new->body = mutt_remove_multipart(e_new->body);
596
597 file = buf_pool_get();
598
599 /* create temporary files for all attachments */
600 if (create_tmp_files_for_attachments(fp_body, file, e_new, e_new->body,
601 protected_headers, 0) < 0)
602 {
603 goto bail;
604 }
605
606 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
607 if (c_crypt_protected_headers_read && protected_headers && protected_headers->subject &&
608 !mutt_str_equal(e_new->env->subject, protected_headers->subject))
609 {
610 mutt_env_set_subject(e_new->env, protected_headers->subject);
611 }
612 mutt_env_free(&protected_headers);
613
614 /* Fix encryption flags. */
615
616 /* No inline if multipart. */
617 if ((WithCrypto != 0) && (e_new->security & SEC_INLINE) && e_new->body->next)
618 e_new->security &= ~SEC_INLINE;
619
620 /* Do we even support multiple mechanisms? */
622
623 /* Theoretically, both could be set. Take the one the user wants to set by default. */
624 if ((e_new->security & APPLICATION_PGP) && (e_new->security & APPLICATION_SMIME))
625 {
626 const bool c_smime_is_default = cs_subset_bool(NeoMutt->sub, "smime_is_default");
627 if (c_smime_is_default)
628 e_new->security &= ~APPLICATION_PGP;
629 else
631 }
632
634
635 rc = 0;
636
637bail:
638
639 /* that's it. */
640 buf_pool_release(&file);
641 if (fp_body != fp)
642 mutt_file_fclose(&fp_body);
643 if (msg)
644 mx_msg_close(m, &msg);
645
646 if (rc == -1)
647 {
648 mutt_env_free(&e_new->env);
649 mutt_body_free(&e_new->body);
650 }
651
652 return rc;
653}
654
665int mutt_get_postponed(struct Mailbox *m_cur, struct Email *hdr,
666 struct Email **cur, struct Buffer *fcc)
667{
669 const char *const c_postponed = cs_subset_string(NeoMutt->sub, "postponed");
670 if (!c_postponed)
671 return -1;
672
673 struct Email *e = NULL;
674 int rc = SEND_POSTPONED;
675 const char *p = NULL;
676
677 struct Mailbox *m = mx_path_resolve(c_postponed);
678 if (m_cur != m)
679 {
680 if (!mx_mbox_open(m, MUTT_NOSORT))
681 {
682 mod_data->post_count = 0;
683 mutt_error(_("No postponed messages"));
684 mailbox_free(&m);
685 return -1;
686 }
687 }
688
689 mx_mbox_check(m);
690
691 if (m->msg_count == 0)
692 {
693 mod_data->post_count = 0;
694 mutt_error(_("No postponed messages"));
695 if (m_cur != m)
696 {
697 mx_fastclose_mailbox(m, false);
698 mailbox_free(&m);
699 }
700 return -1;
701 }
702
703 /* avoid the "purge deleted messages" prompt */
704 const enum QuadOption c_delete = cs_subset_quad(NeoMutt->sub, "delete");
705 cs_subset_str_native_set(NeoMutt->sub, "delete", MUTT_YES, NULL);
706
707 if (m->msg_count == 1)
708 {
709 /* only one message, so just use that one. */
710 e = m->emails[0];
711 }
712 else if (!(e = dlg_postpone(m)))
713 {
714 rc = -1;
715 goto cleanup;
716 }
717
718 if (mutt_prepare_template(NULL, m, hdr, e, false) < 0)
719 {
720 rc = -1;
721 goto cleanup;
722 }
723
724 /* finished with this message, so delete it. */
725 mutt_set_flag(m, e, MUTT_DELETE, true, true);
726 mutt_set_flag(m, e, MUTT_PURGE, true, true);
727
728 /* update the count for the status display */
729 mod_data->post_count = m->msg_count - m->msg_deleted;
730
731 struct ListNode *np = NULL, *tmp = NULL;
732 STAILQ_FOREACH_SAFE(np, &hdr->env->userhdrs, entries, tmp)
733 {
734 size_t plen = 0;
735 // Check for header names: most specific first
736 if ((plen = mutt_istr_startswith(np->data, "X-Mutt-References:")) ||
737 (plen = mutt_istr_startswith(np->data, "Mutt-References:")))
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 if (m_cur)
742 {
743 p = mutt_str_skip_email_wsp(np->data + plen);
744 if (!m_cur->id_hash)
745 m_cur->id_hash = mutt_make_id_hash(m_cur);
746 *cur = mutt_hash_find(m_cur->id_hash, p);
747
748 if (*cur)
749 rc |= SEND_REPLY;
750 }
751 }
752 // Check for header names: most specific first
753 else if ((plen = mutt_istr_startswith(np->data, "X-Mutt-Fcc:")) ||
754 (plen = mutt_istr_startswith(np->data, "Mutt-Fcc:")))
755 {
756 p = mutt_str_skip_email_wsp(np->data + plen);
757 buf_strcpy(fcc, p);
758 pretty_mailbox(fcc);
759
760 /* note that mutt-fcc was present. we do this because we want to add a
761 * default fcc if the header was missing, but preserve the request of the
762 * user to not make a copy if the header field is present, but empty. */
763 rc |= SEND_POSTPONED_FCC;
764 }
765 // Check for header names: most specific first
766 else if (((WithCrypto & APPLICATION_PGP) != 0) &&
767 ((plen = mutt_istr_startswith(np->data, "X-Mutt-PGP:")) ||
768 (plen = mutt_istr_startswith(np->data, "Mutt-PGP:")) ||
769 (plen = mutt_istr_startswith(np->data, "Pgp:"))))
770 {
771 hdr->security = mutt_parse_crypt_hdr(np->data + plen, true, APPLICATION_PGP);
773 }
774 // Check for header names: most specific first
775 else if (((WithCrypto & APPLICATION_SMIME) != 0) &&
776 ((plen = mutt_istr_startswith(np->data, "X-Mutt-SMIME:")) ||
777 (plen = mutt_istr_startswith(np->data, "Mutt-SMIME:"))))
778 {
779 hdr->security = mutt_parse_crypt_hdr(np->data + plen, true, APPLICATION_SMIME);
781 }
782 else
783 {
784 // skip header removal
785 continue;
786 }
787
788 // remove the header
789 STAILQ_REMOVE(&hdr->env->userhdrs, np, ListNode, entries);
790 FREE(&np->data);
791 FREE(&np);
792 }
793
794 const bool c_crypt_opportunistic_encrypt = cs_subset_bool(NeoMutt->sub, "crypt_opportunistic_encrypt");
795 if (c_crypt_opportunistic_encrypt)
797
798cleanup:
799 if (m_cur != m)
800 {
801 hardclose(m);
802 mailbox_free(&m);
803 }
804
805 cs_subset_str_native_set(NeoMutt->sub, "delete", c_delete, NULL);
806 return rc;
807}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1469
Email Address Handling.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition helpers.c:192
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
#define CSR_RESULT(x)
Extract the result code from CSR_* flags.
Definition set.h:53
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
Convenience wrapper for the core headers.
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:90
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:49
void crypt_opportunistic_encrypt(struct Email *e)
Can all recipients be determined.
Definition crypt.c:1050
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition crypt.c:408
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition crypt.c:609
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition crypt.c:131
SecurityFlags mutt_is_multipart_encrypted(struct Body *b)
Does the message have encrypted parts?
Definition crypt.c:443
SecurityFlags mutt_is_application_pgp(const struct Body *b)
Does the message use PGP?
Definition crypt.c:548
int crypt_pgp_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition cryptglue.c:237
void crypt_smime_getkeys(struct Envelope *env)
Wrapper for CryptModuleSpecs::smime_getkeys()
Definition cryptglue.c:538
int crypt_smime_decrypt_mime(FILE *fp_in, FILE **fp_out, struct Body *b, struct Body **b_dec)
Wrapper for CryptModuleSpecs::decrypt_mime()
Definition cryptglue.c:510
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition body.c:58
Structs that make up an email.
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition parse.c:1883
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
Definition parse.c:1261
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
void mutt_env_set_subject(struct Envelope *env, const char *subj)
Set both subject and real_subj to subj.
Definition envelope.c:68
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:54
bool OptNews
(pseudo) used to change reader mode
Definition globals.c:53
Global variables.
struct Email * dlg_postpone(struct Mailbox *m)
Create a Menu to select a postponed message -.
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2681
Convenience wrapper for the gui headers.
struct HashTable * mutt_make_id_hash(struct Mailbox *m)
Create a Hash Table for Message-IDs.
Definition thread.c:1790
int mutt_body_handler(struct Body *b, struct State *state)
Handler for the Body of an email.
Definition handler.c:1664
void mutt_decode_attachment(const struct Body *b, struct State *state)
Decode an email's attachment.
Definition handler.c:1938
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:364
IMAP network mailbox.
int imap_path_status(const char *path, bool queue)
Refresh the number of total and new messages.
Definition imap.c:1362
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition mime.h:37
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
@ MODULE_ID_POSTPONE
ModulePostpone, Postponed Emails
Definition module_api.h:87
struct Body * mutt_remove_multipart(struct Body *b)
Extract the multipart body if it exists.
Definition multipart.c:133
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
@ STATE_CHARCONV
Do character set conversions.
Definition state.h:41
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:677
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition string.c:613
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition string.c:246
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
Many unsorted constants and some structs.
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition mutt.h:96
@ MUTT_DELETE
Messages to be deleted.
Definition mutt.h:94
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
NeoMutt Logging.
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:428
Some miscellaneous functions.
#define mutt_adv_mktemp_draft(buf)
Definition muttlib.h:40
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition mx.c:1182
void mx_fastclose_mailbox(struct Mailbox *m, bool keep_account)
Free up memory associated with the Mailbox.
Definition mx.c:411
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:285
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1136
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1647
enum MxStatus mx_mbox_check(struct Mailbox *m)
Check for new mail - Wrapper for MxOps::mbox_check()
Definition mx.c:1107
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition mx.c:595
API for mailboxes.
@ MUTT_QUIET
Do not print any messages.
Definition mxapi.h:46
@ MUTT_NOSORT
Do not sort the mailbox after opening it.
Definition mxapi.h:43
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_sync(), and mbox_close()
Definition mxapi.h:70
@ MX_STATUS_ERROR
An error occurred.
Definition mxapi.h:71
@ MX_STATUS_OK
No changes.
Definition mxapi.h:72
API for encryption/signing of emails.
uint16_t SecurityFlags
Definition lib.h:104
@ SEC_NONE
No flags are set.
Definition lib.h:91
@ SEC_OPPENCRYPT
Opportunistic encrypt mode.
Definition lib.h:100
@ SEC_SIGN
Email is signed.
Definition lib.h:93
@ SEC_INLINE
Email has an inline signature.
Definition lib.h:99
@ SEC_ENCRYPT
Email is encrypted.
Definition lib.h:92
@ SEC_AUTOCRYPT
(Autocrypt) Message will be, or was Autocrypt encrypt+signed
Definition lib.h:101
@ SEC_AUTOCRYPT_OVERRIDE
(Autocrypt) Indicates manual set/unset of encryption
Definition lib.h:102
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition lib.h:106
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition lib.h:107
#define WithCrypto
Definition lib.h:132
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:663
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition parameter.c:85
void mutt_param_delete(struct ParameterList *pl, const char *attribute)
Delete a matching Parameter.
Definition parameter.c:143
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
Postponed Emails.
Postpone private Module data.
SecurityFlags mutt_parse_crypt_hdr(const char *p, bool set_empty_signas, SecurityFlags crypt_app)
Parse a crypto header string.
Definition postpone.c:199
int mutt_num_postponed(struct Mailbox *m, bool force)
Return the number of postponed messages.
Definition postpone.c:63
static int create_tmp_files_for_attachments(FILE *fp_body, struct Buffer *file, struct Email *e_new, struct Body *body, struct Envelope *protected_headers, int depth)
Create temporary files for all attachments.
Definition postpone.c:354
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition postpone.c:171
int mutt_get_postponed(struct Mailbox *m_cur, struct Email *hdr, struct Email **cur, struct Buffer *fcc)
Recall a postponed message.
Definition postpone.c:665
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:490
static void hardclose(struct Mailbox *m)
Try hard to close a mailbox.
Definition postpone.c:181
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:441
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:400
void mutt_rfc3676_space_unstuff(struct Email *e)
Remove RFC3676 space stuffing.
Definition rfc3676.c:503
Convenience wrapper for the send headers.
@ SEND_REPLY
Reply to sender.
Definition send.h:46
@ SEND_POSTPONED_FCC
Used by mutt_get_postponed() to signal that the Mutt-Fcc header field was present.
Definition send.h:54
@ SEND_POSTPONED
Recall a postponed email.
Definition send.h:50
void mutt_stamp_attachment(struct Body *b)
Timestamp an Attachment.
Definition sendlib.c:409
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:73
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:68
struct Envelope * mime_headers
Memory hole protected headers.
Definition body.h:76
LOFF_T length
length (in bytes) of attachment
Definition body.h:53
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
bool use_disp
Content-Disposition uses filename= ?
Definition body.h:47
struct Email * email
header information for message/rfc822
Definition body.h:74
struct Body * next
next attachment in the list
Definition body.h:72
char * subtype
content-type subtype
Definition body.h:61
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:59
String manipulation buffer.
Definition buffer.h:36
The envelope/body of an email.
Definition email.h:39
struct Envelope * env
Envelope information.
Definition email.h:68
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
struct Body * body
List of MIME parts.
Definition email.h:69
LOFF_T offset
Where in the stream does this message begin?
Definition email.h:71
The header of an Email.
Definition envelope.h:57
struct ListHead userhdrs
user defined headers
Definition envelope.h:85
char *const subject
Email's subject.
Definition envelope.h:70
char * message_id
Message ID.
Definition envelope.h:73
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition envelope.h:65
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
A mailbox.
Definition mailbox.h:81
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:83
int msg_count
Total number of messages.
Definition mailbox.h:90
struct Email ** emails
Array of Emails.
Definition mailbox.h:98
struct HashTable * id_hash
Hash Table: "Message-ID" -> Email.
Definition mailbox.h:125
int msg_deleted
Number of deleted messages.
Definition mailbox.h:95
A local copy of an email.
Definition message.h:34
FILE * fp
pointer to the message data
Definition message.h:35
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Postpone private Module data.
Definition module_data.h:32
short post_count
Number of postponed (draft) emails.
Definition module_data.h:35
bool update_num_postponed
When true, force recount of drafts.
Definition module_data.h:36
Keep track when processing files.
Definition state.h:54
StateFlags flags
Flags, e.g. STATE_DISPLAY.
Definition state.h:58
FILE * fp_out
File to write to.
Definition state.h:56
FILE * fp_in
File to read from.
Definition state.h:55
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition subset.c:303
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:392