NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
pop.c
Go to the documentation of this file.
1 
31 #include "config.h"
32 #include <errno.h>
33 #include <limits.h>
34 #include <stdbool.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include "private.h"
40 #include "mutt/lib.h"
41 #include "config/lib.h"
42 #include "email/lib.h"
43 #include "core/lib.h"
44 #include "conn/lib.h"
45 #include "gui/lib.h"
46 #include "lib.h"
47 #include "context.h"
48 #include "hook.h"
49 #include "mutt_account.h"
50 #include "mutt_globals.h"
51 #include "mutt_header.h"
52 #include "mutt_logging.h"
53 #include "mutt_socket.h"
54 #include "muttlib.h"
55 #include "mx.h"
56 #include "progress.h"
57 #include "bcache/lib.h"
58 #include "ncrypt/lib.h"
59 #ifdef ENABLE_NLS
60 #include <libintl.h>
61 #endif
62 #ifdef USE_HCACHE
63 #include "hcache/lib.h"
64 #endif
65 
66 struct BodyCache;
67 struct stat;
68 
69 #define HC_FNAME "neomutt" /* filename for hcache as POP lacks paths */
70 #define HC_FEXT "hcache" /* extension for hcache as POP lacks paths */
71 
81 static const char *cache_id(const char *id)
82 {
83  static char clean[128];
84  mutt_str_copy(clean, id, sizeof(clean));
85  mutt_file_sanitize_filename(clean, true);
86  return clean;
87 }
88 
97 static void pop_adata_free(void **ptr)
98 {
99  if (!ptr || !*ptr)
100  return;
101 
102  struct PopAccountData *adata = *ptr;
103  FREE(&adata->auth_list.data);
104  FREE(ptr);
105 }
106 
111 static struct PopAccountData *pop_adata_new(void)
112 {
113  return mutt_mem_calloc(1, sizeof(struct PopAccountData));
114 }
115 
123 static void pop_edata_free(void **ptr)
124 {
125  if (!ptr || !*ptr)
126  return;
127 
128  struct PopEmailData *edata = *ptr;
129  FREE(&edata->uid);
130  FREE(ptr);
131 }
132 
138 static struct PopEmailData *pop_edata_new(const char *uid)
139 {
140  struct PopEmailData *edata = mutt_mem_calloc(1, sizeof(struct PopEmailData));
141  edata->uid = mutt_str_dup(uid);
142  return edata;
143 }
144 
152 static int fetch_message(const char *line, void *data)
153 {
154  FILE *fp = data;
155 
156  fputs(line, fp);
157  if (fputc('\n', fp) == EOF)
158  return -1;
159 
160  return 0;
161 }
162 
172 static int pop_read_header(struct PopAccountData *adata, struct Email *e)
173 {
174  FILE *fp = mutt_file_mkstemp();
175  if (!fp)
176  {
177  mutt_perror(_("Can't create temporary file"));
178  return -3;
179  }
180 
181  int index = 0;
182  size_t length = 0;
183  char buf[1024];
184 
185  struct PopEmailData *edata = pop_edata_get(e);
186 
187  snprintf(buf, sizeof(buf), "LIST %d\r\n", edata->refno);
188  int rc = pop_query(adata, buf, sizeof(buf));
189  if (rc == 0)
190  {
191  sscanf(buf, "+OK %d %zu", &index, &length);
192 
193  snprintf(buf, sizeof(buf), "TOP %d 0\r\n", edata->refno);
194  rc = pop_fetch_data(adata, buf, NULL, fetch_message, fp);
195 
196  if (adata->cmd_top == 2)
197  {
198  if (rc == 0)
199  {
200  adata->cmd_top = 1;
201 
202  mutt_debug(LL_DEBUG1, "set TOP capability\n");
203  }
204 
205  if (rc == -2)
206  {
207  adata->cmd_top = 0;
208 
209  mutt_debug(LL_DEBUG1, "unset TOP capability\n");
210  snprintf(adata->err_msg, sizeof(adata->err_msg), "%s",
211  _("Command TOP is not supported by server"));
212  }
213  }
214  }
215 
216  switch (rc)
217  {
218  case 0:
219  {
220  rewind(fp);
221  e->env = mutt_rfc822_read_header(fp, e, false, false);
222  e->content->length = length - e->content->offset + 1;
223  rewind(fp);
224  while (!feof(fp))
225  {
226  e->content->length--;
227  fgets(buf, sizeof(buf), fp);
228  }
229  break;
230  }
231  case -2:
232  {
233  mutt_error("%s", adata->err_msg);
234  break;
235  }
236  case -3:
237  {
238  mutt_error(_("Can't write header to temporary file"));
239  break;
240  }
241  }
242 
243  mutt_file_fclose(&fp);
244  return rc;
245 }
246 
254 static int fetch_uidl(const char *line, void *data)
255 {
256  struct Mailbox *m = data;
257  struct PopAccountData *adata = pop_adata_get(m);
258  char *endp = NULL;
259 
260  errno = 0;
261  int index = strtol(line, &endp, 10);
262  if (errno)
263  return -1;
264  while (*endp == ' ')
265  endp++;
266  line = endp;
267 
268  /* uid must be at least be 1 byte */
269  if (strlen(line) == 0)
270  return -1;
271 
272  int i;
273  for (i = 0; i < m->msg_count; i++)
274  {
275  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
276  if (mutt_str_equal(line, edata->uid))
277  break;
278  }
279 
280  if (i == m->msg_count)
281  {
282  mutt_debug(LL_DEBUG1, "new header %d %s\n", index, line);
283 
284  if (i >= m->email_max)
285  mx_alloc_memory(m);
286 
287  m->msg_count++;
288  m->emails[i] = email_new();
289 
290  m->emails[i]->edata = pop_edata_new(line);
292  }
293  else if (m->emails[i]->index != index - 1)
294  adata->clear_cache = true;
295 
296  m->emails[i]->index = index - 1;
297 
298  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
299  edata->refno = index;
300 
301  return 0;
302 }
303 
307 static int msg_cache_check(const char *id, struct BodyCache *bcache, void *data)
308 {
309  struct Mailbox *m = data;
310  if (!m)
311  return -1;
312 
313  struct PopAccountData *adata = pop_adata_get(m);
314  if (!adata)
315  return -1;
316 
317 #ifdef USE_HCACHE
318  /* keep hcache file if hcache == bcache */
319  if (strcmp(HC_FNAME "." HC_FEXT, id) == 0)
320  return 0;
321 #endif
322 
323  for (int i = 0; i < m->msg_count; i++)
324  {
325  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
326  /* if the id we get is known for a header: done (i.e. keep in cache) */
327  if (edata->uid && mutt_str_equal(edata->uid, id))
328  return 0;
329  }
330 
331  /* message not found in context -> remove it from cache
332  * return the result of bcache, so we stop upon its first error */
333  return mutt_bcache_del(bcache, cache_id(id));
334 }
335 
336 #ifdef USE_HCACHE
337 
340 static void pop_hcache_namer(const char *path, struct Buffer *dest)
341 {
342  mutt_buffer_printf(dest, "%s." HC_FEXT, path);
343 }
344 
351 static header_cache_t *pop_hcache_open(struct PopAccountData *adata, const char *path)
352 {
353  if (!adata || !adata->conn)
354  return mutt_hcache_open(C_HeaderCache, path, NULL);
355 
356  struct Url url = { 0 };
357  char p[1024];
358 
359  mutt_account_tourl(&adata->conn->account, &url);
360  url.path = HC_FNAME;
361  url_tostring(&url, p, sizeof(p), U_PATH);
363 }
364 #endif
365 
374 static int pop_fetch_headers(struct Mailbox *m)
375 {
376  if (!m)
377  return -1;
378 
379  struct PopAccountData *adata = pop_adata_get(m);
380  struct Progress progress;
381 
382 #ifdef USE_HCACHE
384 #endif
385 
386  adata->check_time = mutt_date_epoch();
387  adata->clear_cache = false;
388 
389  for (int i = 0; i < m->msg_count; i++)
390  {
391  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
392  edata->refno = -1;
393  }
394 
395  const int old_count = m->msg_count;
396  int rc = pop_fetch_data(adata, "UIDL\r\n", NULL, fetch_uidl, m);
397  const int new_count = m->msg_count;
398  m->msg_count = old_count;
399 
400  if (adata->cmd_uidl == 2)
401  {
402  if (rc == 0)
403  {
404  adata->cmd_uidl = 1;
405 
406  mutt_debug(LL_DEBUG1, "set UIDL capability\n");
407  }
408 
409  if ((rc == -2) && (adata->cmd_uidl == 2))
410  {
411  adata->cmd_uidl = 0;
412 
413  mutt_debug(LL_DEBUG1, "unset UIDL capability\n");
414  snprintf(adata->err_msg, sizeof(adata->err_msg), "%s",
415  _("Command UIDL is not supported by server"));
416  }
417  }
418 
419  if (m->verbose)
420  {
421  mutt_progress_init(&progress, _("Fetching message headers..."),
422  MUTT_PROGRESS_READ, new_count - old_count);
423  }
424 
425  if (rc == 0)
426  {
427  int i, deleted;
428  for (i = 0, deleted = 0; i < old_count; i++)
429  {
430  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
431  if (edata->refno == -1)
432  {
433  m->emails[i]->deleted = true;
434  deleted++;
435  }
436  }
437  if (deleted > 0)
438  {
439  mutt_error(
440  ngettext("%d message has been lost. Try reopening the mailbox.",
441  "%d messages have been lost. Try reopening the mailbox.", deleted),
442  deleted);
443  }
444 
445  bool hcached = false;
446  for (i = old_count; i < new_count; i++)
447  {
448  if (m->verbose)
449  mutt_progress_update(&progress, i + 1 - old_count, -1);
450  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
451 #ifdef USE_HCACHE
452  struct HCacheEntry hce = mutt_hcache_fetch(hc, edata->uid, strlen(edata->uid), 0);
453  if (hce.email)
454  {
455  /* Detach the private data */
456  m->emails[i]->edata = NULL;
457 
458  int index = m->emails[i]->index;
459  /* - POP dynamically numbers headers and relies on e->refno
460  * to map messages; so restore header and overwrite restored
461  * refno with current refno, same for index
462  * - e->data needs to a separate pointer as it's driver-specific
463  * data freed separately elsewhere
464  * (the old e->data should point inside a malloc'd block from
465  * hcache so there shouldn't be a memleak here) */
466  email_free(&m->emails[i]);
467  m->emails[i] = hce.email;
468  m->emails[i]->index = index;
469 
470  /* Reattach the private data */
471  m->emails[i]->edata = edata;
473  rc = 0;
474  hcached = true;
475  }
476  else
477 #endif
478  if ((rc = pop_read_header(adata, m->emails[i])) < 0)
479  break;
480 #ifdef USE_HCACHE
481  else
482  {
483  mutt_hcache_store(hc, edata->uid, strlen(edata->uid), m->emails[i], 0);
484  }
485 #endif
486 
487  /* faked support for flags works like this:
488  * - if 'hcached' is true, we have the message in our hcache:
489  * - if we also have a body: read
490  * - if we don't have a body: old
491  * (if $mark_old is set which is maybe wrong as
492  * $mark_old should be considered for syncing the
493  * folder and not when opening it XXX)
494  * - if 'hcached' is false, we don't have the message in our hcache:
495  * - if we also have a body: read
496  * - if we don't have a body: new */
497  const bool bcached =
498  (mutt_bcache_exists(adata->bcache, cache_id(edata->uid)) == 0);
499  m->emails[i]->old = false;
500  m->emails[i]->read = false;
501  if (hcached)
502  {
503  if (bcached)
504  m->emails[i]->read = true;
505  else if (C_MarkOld)
506  m->emails[i]->old = true;
507  }
508  else
509  {
510  if (bcached)
511  m->emails[i]->read = true;
512  }
513 
514  m->msg_count++;
515  }
516  }
517 
518 #ifdef USE_HCACHE
519  mutt_hcache_close(hc);
520 #endif
521 
522  if (rc < 0)
523  {
524  for (int i = m->msg_count; i < new_count; i++)
525  email_free(&m->emails[i]);
526  return rc;
527  }
528 
529  /* after putting the result into our structures,
530  * clean up cache, i.e. wipe messages deleted outside
531  * the availability of our cache */
534 
536  return new_count - old_count;
537 }
538 
543 static void pop_clear_cache(struct PopAccountData *adata)
544 {
545  if (!adata->clear_cache)
546  return;
547 
548  mutt_debug(LL_DEBUG1, "delete cached messages\n");
549 
550  for (int i = 0; i < POP_CACHE_LEN; i++)
551  {
552  if (adata->cache[i].path)
553  {
554  unlink(adata->cache[i].path);
555  FREE(&adata->cache[i].path);
556  }
557  }
558 }
559 
563 void pop_fetch_mail(void)
564 {
565  if (!C_PopHost)
566  {
567  mutt_error(_("POP host is not defined"));
568  return;
569  }
570 
571  char buf[1024];
572  char msgbuf[128];
573  int last = 0, msgs, bytes, rset = 0, ret;
574  struct ConnAccount cac = { { 0 } };
575 
576  char *p = mutt_mem_calloc(strlen(C_PopHost) + 7, sizeof(char));
577  char *url = p;
579  {
580  strcpy(url, "pop://");
581  p = strchr(url, '\0');
582  }
583  strcpy(p, C_PopHost);
584 
585  ret = pop_parse_path(url, &cac);
586  FREE(&url);
587  if (ret)
588  {
589  mutt_error(_("%s is an invalid POP path"), C_PopHost);
590  return;
591  }
592 
593  struct Connection *conn = mutt_conn_find(&cac);
594  if (!conn)
595  return;
596 
597  struct PopAccountData *adata = pop_adata_new();
598  adata->conn = conn;
599 
600  if (pop_open_connection(adata) < 0)
601  {
602  //XXX mutt_socket_free(adata->conn);
603  pop_adata_free((void **) &adata);
604  return;
605  }
606 
607  mutt_message(_("Checking for new messages..."));
608 
609  /* find out how many messages are in the mailbox. */
610  mutt_str_copy(buf, "STAT\r\n", sizeof(buf));
611  ret = pop_query(adata, buf, sizeof(buf));
612  if (ret == -1)
613  goto fail;
614  if (ret == -2)
615  {
616  mutt_error("%s", adata->err_msg);
617  goto finish;
618  }
619 
620  sscanf(buf, "+OK %d %d", &msgs, &bytes);
621 
622  /* only get unread messages */
623  if ((msgs > 0) && C_PopLast)
624  {
625  mutt_str_copy(buf, "LAST\r\n", sizeof(buf));
626  ret = pop_query(adata, buf, sizeof(buf));
627  if (ret == -1)
628  goto fail;
629  if (ret == 0)
630  sscanf(buf, "+OK %d", &last);
631  }
632 
633  if (msgs <= last)
634  {
635  mutt_message(_("No new mail in POP mailbox"));
636  goto finish;
637  }
638 
639  struct Mailbox *m_spool = mx_path_resolve(C_Spoolfile);
640  struct Context *ctx = mx_mbox_open(m_spool, MUTT_OPEN_NO_FLAGS);
641  if (!ctx)
642  {
643  mailbox_free(&m_spool);
644  goto finish;
645  }
646 
647  bool old_append = m_spool->append;
648  m_spool->append = true;
649 
650  enum QuadOption delanswer =
651  query_quadoption(C_PopDelete, _("Delete messages from server?"));
652 
653  snprintf(msgbuf, sizeof(msgbuf),
654  ngettext("Reading new messages (%d byte)...",
655  "Reading new messages (%d bytes)...", bytes),
656  bytes);
657  mutt_message("%s", msgbuf);
658 
659  for (int i = last + 1; i <= msgs; i++)
660  {
661  struct Message *msg = mx_msg_open_new(ctx->mailbox, NULL, MUTT_ADD_FROM);
662  if (msg)
663  {
664  snprintf(buf, sizeof(buf), "RETR %d\r\n", i);
665  ret = pop_fetch_data(adata, buf, NULL, fetch_message, msg->fp);
666  if (ret == -3)
667  rset = 1;
668 
669  if ((ret == 0) && (mx_msg_commit(ctx->mailbox, msg) != 0))
670  {
671  rset = 1;
672  ret = -3;
673  }
674 
675  mx_msg_close(ctx->mailbox, &msg);
676  }
677  else
678  {
679  ret = -3;
680  }
681 
682  if ((ret == 0) && (delanswer == MUTT_YES))
683  {
684  /* delete the message on the server */
685  snprintf(buf, sizeof(buf), "DELE %d\r\n", i);
686  ret = pop_query(adata, buf, sizeof(buf));
687  }
688 
689  if (ret == -1)
690  {
691  m_spool->append = old_append;
692  mx_mbox_close(&ctx);
693  goto fail;
694  }
695  if (ret == -2)
696  {
697  mutt_error("%s", adata->err_msg);
698  break;
699  }
700  if (ret == -3)
701  {
702  mutt_error(_("Error while writing mailbox"));
703  break;
704  }
705 
706  /* L10N: The plural is picked by the second numerical argument, i.e.
707  the %d right before 'messages', i.e. the total number of messages. */
708  mutt_message(ngettext("%s [%d of %d message read]",
709  "%s [%d of %d messages read]", msgs - last),
710  msgbuf, i - last, msgs - last);
711  }
712 
713  m_spool->append = old_append;
714  mx_mbox_close(&ctx);
715 
716  if (rset)
717  {
718  /* make sure no messages get deleted */
719  mutt_str_copy(buf, "RSET\r\n", sizeof(buf));
720  if (pop_query(adata, buf, sizeof(buf)) == -1)
721  goto fail;
722  }
723 
724 finish:
725  /* exit gracefully */
726  mutt_str_copy(buf, "QUIT\r\n", sizeof(buf));
727  if (pop_query(adata, buf, sizeof(buf)) == -1)
728  goto fail;
729  mutt_socket_close(conn);
730  FREE(&conn);
731  pop_adata_free((void **) &adata);
732  return;
733 
734 fail:
735  mutt_error(_("Server closed connection"));
736  mutt_socket_close(conn);
737  pop_adata_free((void **) &adata);
738 }
739 
743 static struct Account *pop_ac_find(struct Account *a, const char *path)
744 {
745  if (!a || (a->type != MUTT_POP) || !path)
746  return NULL;
747 
748  struct Url *url = url_parse(path);
749  if (!url)
750  return NULL;
751 
752  struct PopAccountData *adata = a->adata;
753  struct ConnAccount *cac = &adata->conn->account;
754 
755  if (!mutt_istr_equal(url->host, cac->host) || !mutt_istr_equal(url->user, cac->user))
756  {
757  a = NULL;
758  }
759 
760  url_free(&url);
761  return a;
762 }
763 
767 static int pop_ac_add(struct Account *a, struct Mailbox *m)
768 {
769  if (!a || !m || (m->type != MUTT_POP))
770  return -1;
771 
772  if (a->adata)
773  return 0;
774 
775  struct ConnAccount cac = { { 0 } };
776  struct PopAccountData *adata = pop_adata_new();
777  a->adata = adata;
779 
780  if (pop_parse_path(mailbox_path(m), &cac))
781  {
782  mutt_error(_("%s is an invalid POP path"), mailbox_path(m));
783  return -1;
784  }
785 
786  adata->conn = mutt_conn_new(&cac);
787  if (!adata->conn)
788  {
789  pop_adata_free((void **) &adata);
790  return -1;
791  }
792 
793  return 0;
794 }
795 
801 static int pop_mbox_open(struct Mailbox *m)
802 {
803  if (!m || !m->account)
804  return -1;
805 
806  char buf[PATH_MAX];
807  struct ConnAccount cac = { { 0 } };
808  struct Url url = { 0 };
809 
810  if (pop_parse_path(mailbox_path(m), &cac))
811  {
812  mutt_error(_("%s is an invalid POP path"), mailbox_path(m));
813  return -1;
814  }
815 
816  mutt_account_tourl(&cac, &url);
817  url.path = NULL;
818  url_tostring(&url, buf, sizeof(buf), 0);
819 
820  mutt_buffer_strcpy(&m->pathbuf, buf);
822 
823  struct PopAccountData *adata = m->account->adata;
824  if (!adata)
825  {
826  adata = pop_adata_new();
827  m->account->adata = adata;
829  }
830 
831  struct Connection *conn = adata->conn;
832  if (!conn)
833  {
834  adata->conn = mutt_conn_new(&cac);
835  conn = adata->conn;
836  if (!conn)
837  return -1;
838  }
839 
840  if (conn->fd < 0)
842 
843  if (pop_open_connection(adata) < 0)
844  return -1;
845 
846  adata->bcache = mutt_bcache_open(&cac, NULL);
847 
848  /* init (hard-coded) ACL rights */
850 #ifdef USE_HCACHE
851  /* flags are managed using header cache, so it only makes sense to
852  * enable them in that case */
853  m->rights |= MUTT_ACL_WRITE;
854 #endif
855 
856  while (true)
857  {
858  if (pop_reconnect(m) < 0)
859  return -1;
860 
861  m->size = adata->size;
862 
863  mutt_message(_("Fetching list of messages..."));
864 
865  const int rc = pop_fetch_headers(m);
866 
867  if (rc >= 0)
868  return 0;
869 
870  if (rc < -1)
871  return -1;
872  }
873 }
874 
878 static int pop_mbox_check(struct Mailbox *m)
879 {
880  if (!m)
881  return -1;
882 
883  struct PopAccountData *adata = pop_adata_get(m);
884 
885  if ((adata->check_time + C_PopCheckinterval) > mutt_date_epoch())
886  return 0;
887 
888  pop_logout(m);
889 
890  mutt_socket_close(adata->conn);
891 
892  if (pop_open_connection(adata) < 0)
893  return -1;
894 
895  m->size = adata->size;
896 
897  mutt_message(_("Checking for new messages..."));
898 
899  int old_msg_count = m->msg_count;
900  int rc = pop_fetch_headers(m);
901  pop_clear_cache(adata);
902  if (m->msg_count > old_msg_count)
904 
905  if (rc < 0)
906  return -1;
907 
908  if (rc > 0)
909  return MUTT_NEW_MAIL;
910 
911  return 0;
912 }
913 
919 static int pop_mbox_sync(struct Mailbox *m)
920 {
921  if (!m)
922  return -1;
923 
924  int i, j, rc = 0;
925  char buf[1024];
926  struct PopAccountData *adata = pop_adata_get(m);
927  struct Progress progress;
928 #ifdef USE_HCACHE
929  header_cache_t *hc = NULL;
930 #endif
931 
932  adata->check_time = 0;
933 
934  int num_deleted = 0;
935  for (i = 0; i < m->msg_count; i++)
936  {
937  if (m->emails[i]->deleted)
938  num_deleted++;
939  }
940 
941  while (true)
942  {
943  if (pop_reconnect(m) < 0)
944  return -1;
945 
946  mutt_progress_init(&progress, _("Marking messages deleted..."),
947  MUTT_PROGRESS_WRITE, num_deleted);
948 
949 #ifdef USE_HCACHE
950  hc = pop_hcache_open(adata, mailbox_path(m));
951 #endif
952 
953  for (i = 0, j = 0, rc = 0; (rc == 0) && (i < m->msg_count); i++)
954  {
955  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
956  if (m->emails[i]->deleted && (edata->refno != -1))
957  {
958  j++;
959  if (m->verbose)
960  mutt_progress_update(&progress, j, -1);
961  snprintf(buf, sizeof(buf), "DELE %d\r\n", edata->refno);
962  rc = pop_query(adata, buf, sizeof(buf));
963  if (rc == 0)
964  {
965  mutt_bcache_del(adata->bcache, cache_id(edata->uid));
966 #ifdef USE_HCACHE
967  mutt_hcache_delete_header(hc, edata->uid, strlen(edata->uid));
968 #endif
969  }
970  }
971 
972 #ifdef USE_HCACHE
973  if (m->emails[i]->changed)
974  {
975  mutt_hcache_store(hc, edata->uid, strlen(edata->uid), m->emails[i], 0);
976  }
977 #endif
978  }
979 
980 #ifdef USE_HCACHE
981  mutt_hcache_close(hc);
982 #endif
983 
984  if (rc == 0)
985  {
986  mutt_str_copy(buf, "QUIT\r\n", sizeof(buf));
987  rc = pop_query(adata, buf, sizeof(buf));
988  }
989 
990  if (rc == 0)
991  {
992  adata->clear_cache = true;
993  pop_clear_cache(adata);
994  adata->status = POP_DISCONNECTED;
995  return 0;
996  }
997 
998  if (rc == -2)
999  {
1000  mutt_error("%s", adata->err_msg);
1001  return -1;
1002  }
1003  }
1004 }
1005 
1009 static int pop_mbox_close(struct Mailbox *m)
1010 {
1011  if (!m)
1012  return -1;
1013 
1014  struct PopAccountData *adata = pop_adata_get(m);
1015  if (!adata)
1016  return 0;
1017 
1018  pop_logout(m);
1019 
1020  if (adata->status != POP_NONE)
1021  {
1022  mutt_socket_close(adata->conn);
1023  // FREE(&adata->conn);
1024  }
1025 
1026  adata->status = POP_NONE;
1027 
1028  adata->clear_cache = true;
1029  pop_clear_cache(adata);
1030 
1031  mutt_bcache_close(&adata->bcache);
1032 
1033  return 0;
1034 }
1035 
1039 static int pop_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
1040 {
1041  if (!m)
1042  return -1;
1043 
1044  char buf[1024];
1045  struct Progress progress;
1046  struct PopAccountData *adata = pop_adata_get(m);
1047  struct Email *e = m->emails[msgno];
1048  struct PopEmailData *edata = pop_edata_get(e);
1049  bool bcache = true;
1050  int rc = -1;
1051  struct Buffer *path = NULL;
1052 
1053  /* see if we already have the message in body cache */
1054  msg->fp = mutt_bcache_get(adata->bcache, cache_id(edata->uid));
1055  if (msg->fp)
1056  return 0;
1057 
1058  /* see if we already have the message in our cache in
1059  * case $message_cachedir is unset */
1060  struct PopCache *cache = &adata->cache[e->index % POP_CACHE_LEN];
1061 
1062  if (cache->path)
1063  {
1064  if (cache->index == e->index)
1065  {
1066  /* yes, so just return a pointer to the message */
1067  msg->fp = fopen(cache->path, "r");
1068  if (msg->fp)
1069  return 0;
1070 
1071  mutt_perror(cache->path);
1072  return -1;
1073  }
1074  else
1075  {
1076  /* clear the previous entry */
1077  unlink(cache->path);
1078  FREE(&cache->path);
1079  }
1080  }
1081 
1082  path = mutt_buffer_pool_get();
1083 
1084  while (true)
1085  {
1086  if (pop_reconnect(m) < 0)
1087  goto cleanup;
1088 
1089  /* verify that massage index is correct */
1090  if (edata->refno < 0)
1091  {
1092  mutt_error(
1093  _("The message index is incorrect. Try reopening the mailbox."));
1094  goto cleanup;
1095  }
1096 
1097  mutt_progress_init(&progress, _("Fetching message..."), MUTT_PROGRESS_NET,
1098  e->content->length + e->content->offset - 1);
1099 
1100  /* see if we can put in body cache; use our cache as fallback */
1101  msg->fp = mutt_bcache_put(adata->bcache, cache_id(edata->uid));
1102  if (!msg->fp)
1103  {
1104  /* no */
1105  bcache = false;
1106  mutt_buffer_mktemp(path);
1107  msg->fp = mutt_file_fopen(mutt_b2s(path), "w+");
1108  if (!msg->fp)
1109  {
1110  mutt_perror(mutt_b2s(path));
1111  goto cleanup;
1112  }
1113  }
1114 
1115  snprintf(buf, sizeof(buf), "RETR %d\r\n", edata->refno);
1116 
1117  const int ret = pop_fetch_data(adata, buf, &progress, fetch_message, msg->fp);
1118  if (ret == 0)
1119  break;
1120 
1121  mutt_file_fclose(&msg->fp);
1122 
1123  /* if RETR failed (e.g. connection closed), be sure to remove either
1124  * the file in bcache or from POP's own cache since the next iteration
1125  * of the loop will re-attempt to put() the message */
1126  if (!bcache)
1127  unlink(mutt_b2s(path));
1128 
1129  if (ret == -2)
1130  {
1131  mutt_error("%s", adata->err_msg);
1132  goto cleanup;
1133  }
1134 
1135  if (ret == -3)
1136  {
1137  mutt_error(_("Can't write message to temporary file"));
1138  goto cleanup;
1139  }
1140  }
1141 
1142  /* Update the header information. Previously, we only downloaded a
1143  * portion of the headers, those required for the main display. */
1144  if (bcache)
1145  mutt_bcache_commit(adata->bcache, cache_id(edata->uid));
1146  else
1147  {
1148  cache->index = e->index;
1149  cache->path = mutt_buffer_strdup(path);
1150  }
1151  rewind(msg->fp);
1152 
1153  /* Detach the private data */
1154  e->edata = NULL;
1155 
1156  /* we replace envelope, key in subj_hash has to be updated as well */
1157  if (m->subj_hash && e->env->real_subj)
1159  mutt_label_hash_remove(m, e);
1160  mutt_env_free(&e->env);
1161  e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
1162  if (m->subj_hash && e->env->real_subj)
1164  mutt_label_hash_add(m, e);
1165 
1166  /* Reattach the private data */
1167  e->edata = edata;
1169 
1170  e->lines = 0;
1171  fgets(buf, sizeof(buf), msg->fp);
1172  while (!feof(msg->fp))
1173  {
1174  m->emails[msgno]->lines++;
1175  fgets(buf, sizeof(buf), msg->fp);
1176  }
1177 
1178  e->content->length = ftello(msg->fp) - e->content->offset;
1179 
1180  /* This needs to be done in case this is a multipart message */
1181  if (!WithCrypto)
1182  e->security = crypt_query(e->content);
1183 
1184  mutt_clear_error();
1185  rewind(msg->fp);
1186 
1187  rc = 0;
1188 
1189 cleanup:
1190  mutt_buffer_pool_release(&path);
1191  return rc;
1192 }
1193 
1199 static int pop_msg_close(struct Mailbox *m, struct Message *msg)
1200 {
1201  return mutt_file_fclose(&msg->fp);
1202 }
1203 
1207 static int pop_msg_save_hcache(struct Mailbox *m, struct Email *e)
1208 {
1209  int rc = 0;
1210 #ifdef USE_HCACHE
1211  struct PopAccountData *adata = pop_adata_get(m);
1212  struct PopEmailData *edata = e->edata;
1213  header_cache_t *hc = pop_hcache_open(adata, mailbox_path(m));
1214  rc = mutt_hcache_store(hc, edata->uid, strlen(edata->uid), e, 0);
1215  mutt_hcache_close(hc);
1216 #endif
1217 
1218  return rc;
1219 }
1220 
1224 enum MailboxType pop_path_probe(const char *path, const struct stat *st)
1225 {
1226  if (!path)
1227  return MUTT_UNKNOWN;
1228 
1229  if (mutt_istr_startswith(path, "pop://"))
1230  return MUTT_POP;
1231 
1232  if (mutt_istr_startswith(path, "pops://"))
1233  return MUTT_POP;
1234 
1235  return MUTT_UNKNOWN;
1236 }
1237 
1241 static int pop_path_canon(char *buf, size_t buflen)
1242 {
1243  if (!buf)
1244  return -1;
1245 
1246  return 0;
1247 }
1248 
1252 static int pop_path_pretty(char *buf, size_t buflen, const char *folder)
1253 {
1254  /* Succeed, but don't do anything, for now */
1255  return 0;
1256 }
1257 
1261 static int pop_path_parent(char *buf, size_t buflen)
1262 {
1263  /* Succeed, but don't do anything, for now */
1264  return 0;
1265 }
1266 
1267 // clang-format off
1271 struct MxOps MxPopOps = {
1272  .type = MUTT_POP,
1273  .name = "pop",
1274  .is_local = false,
1275  .ac_find = pop_ac_find,
1276  .ac_add = pop_ac_add,
1277  .mbox_open = pop_mbox_open,
1278  .mbox_open_append = NULL,
1279  .mbox_check = pop_mbox_check,
1280  .mbox_check_stats = NULL,
1281  .mbox_sync = pop_mbox_sync,
1282  .mbox_close = pop_mbox_close,
1283  .msg_open = pop_msg_open,
1284  .msg_open_new = NULL,
1285  .msg_commit = NULL,
1286  .msg_close = pop_msg_close,
1287  .msg_padding_size = NULL,
1288  .msg_save_hcache = pop_msg_save_hcache,
1289  .tags_edit = NULL,
1290  .tags_commit = NULL,
1291  .path_probe = pop_path_probe,
1292  .path_canon = pop_path_canon,
1293  .path_pretty = pop_path_pretty,
1294  .path_parent = pop_path_parent,
1295 };
1296 // clang-format on
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
Definition: url.c:221
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:876
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
Convenience wrapper for the gui headers.
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mx.h:52
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
The "current" mailbox.
Definition: context.h:37
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:196
Progress tracks bytes, according to C_NetInc.
Definition: progress.h:44
#define pop_query(adata, buf, buflen)
Definition: private.h:153
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:327
char * path
Definition: private.h:72
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
int lines
How many lines in the body of this message?
Definition: email.h:84
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
int msg_count
Total number of messages.
Definition: mailbox.h:91
char err_msg[POP_CMD_RESPONSE]
Definition: private.h:98
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
Representation of the email&#39;s header.
#define WithCrypto
Definition: lib.h:118
static int pop_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty()
Definition: pop.c:1252
bool C_MarkOld
Config: Mark new emails as old when leaving the mailbox.
Definition: globals.c:36
The envelope/body of an email.
Definition: email.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
size_t size
Definition: private.h:92
#define mutt_perror(...)
Definition: logging.h:85
bool C_MessageCacheClean
Config: (imap/pop) Clean out obsolete entries from the message cache.
Definition: bcache.c:44
int pop_parse_path(const char *path, struct ConnAccount *cac)
Parse a POP mailbox name.
Definition: lib.c:79
Wrapper for Email retrieved from the header cache.
Definition: lib.h:98
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:36
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:604
Structs that make up an email.
The "currently-open" mailbox.
#define HC_FNAME
Definition: pop.c:69
struct BodyCache * mutt_bcache_open(struct ConnAccount *account, const char *mailbox)
Open an Email-Body Cache.
Definition: bcache.c:136
int pop_open_connection(struct PopAccountData *adata)
Open connection and authenticate.
Definition: lib.c:318
#define mutt_message(...)
Definition: logging.h:83
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:66
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
struct PopCache cache[POP_CACHE_LEN]
Definition: private.h:99
Progress tracks elements, according to C_WriteInc.
Definition: progress.h:43
char * C_HeaderCache
Config: (hcache) Directory/file for the header cache database.
Definition: config.c:37
int mutt_bcache_commit(struct BodyCache *bcache, const char *id)
Move a temporary file into the Body Cache.
Definition: bcache.c:239
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:84
NeoMutt Logging.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Body * content
List of MIME parts.
Definition: email.h:90
struct BodyCache * bcache
body cache
Definition: private.h:97
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
A group of associated Mailboxes.
Definition: account.h:36
struct HCacheEntry mutt_hcache_fetch(header_cache_t *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:437
An open network connection (socket)
Definition: connection.h:34
String manipulation buffer.
Definition: buffer.h:33
struct PopEmailData * pop_edata_get(struct Email *e)
Get the private data for this Email.
Definition: lib.c:269
char user[128]
Username.
Definition: connaccount.h:55
static int pop_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox - Implements MxOps::msg_open()
Definition: pop.c:1039
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1206
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:375
Url wasn&#39;t recognised.
Definition: url.h:34
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
Mailbox wasn&#39;t recognised.
Definition: mailbox.h:47
struct Connection * conn
Definition: private.h:80
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
bool changed
Email has been edited.
Definition: email.h:48
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:267
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message&#39;s labels to the Hash Table.
Definition: mutt_header.c:372
static struct PopEmailData * pop_edata_new(const char *uid)
Create a new PopEmailData for an email.
Definition: pop.c:138
static int pop_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent()
Definition: pop.c:1261
void pop_fetch_mail(void)
Fetch messages and save them in $spoolfile.
Definition: pop.c:563
static const char * cache_id(const char *id)
Make a message-cache-compatible id.
Definition: pop.c:81
Email list was changed.
Definition: mailbox.h:166
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message&#39;s labels from the Hash Table.
Definition: mutt_header.c:385
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
int refno
Message number on server.
Definition: private.h:108
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static struct Account * pop_ac_find(struct Account *a, const char *path)
Find an Account that matches a Mailbox path - Implements MxOps::ac_find()
Definition: pop.c:743
Disconnected from server.
Definition: private.h:52
A progress bar.
Definition: progress.h:50
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
static int pop_fetch_headers(struct Mailbox *m)
Read headers.
Definition: pop.c:374
static int msg_cache_check(const char *id, struct BodyCache *bcache, void *data)
Check the Body Cache for an ID - Implements bcache_list_t.
Definition: pop.c:307
static void pop_clear_cache(struct PopAccountData *adata)
delete all cached messages
Definition: pop.c:543
Convenience wrapper for the config headers.
void mutt_account_tourl(struct ConnAccount *cac, struct Url *url)
Fill URL with info from account.
Definition: mutt_account.c:79
int mutt_bcache_list(struct BodyCache *bcache, bcache_list_t want_id, void *data)
Find matching entries in the Body Cache.
Definition: bcache.c:321
void mutt_hcache_close(header_cache_t *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:418
short C_PopCheckinterval
Config: (pop) Interval between checks for new mail.
Definition: config.c:38
struct Buffer auth_list
list of auth mechanisms
Definition: private.h:95
char * C_PopHost
Config: (pop) Url of the POP server.
Definition: config.c:40
char host[128]
Server to login to.
Definition: connaccount.h:53
Some miscellaneous functions.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1180
bool read
Email is read.
Definition: email.h:51
void mutt_progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:212
int mutt_hcache_store(header_cache_t *hc, const char *key, size_t keylen, struct Email *e, uint32_t uidvalidity)
Multiplexor for StoreOps::store.
Definition: hcache.c:525
Header cache multiplexor.
struct Mailbox * mailbox
Definition: context.h:50
Parse and execute user-defined hooks.
FILE * mutt_bcache_get(struct BodyCache *bcache, const char *id)
Open a file in the Body Cache.
Definition: bcache.c:172
API for mailboxes.
bool old
Email is seen, but unread.
Definition: email.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:60
#define POP_CACHE_LEN
Definition: private.h:40
const char * uid
Definition: private.h:107
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
static int pop_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close()
Definition: pop.c:1009
struct Envelope * env
Envelope information.
Definition: email.h:89
Convenience wrapper for the core headers.
Progress tracks elements, according to C_ReadInc.
Definition: progress.h:42
int mutt_bcache_exists(struct BodyCache *bcache, const char *id)
Check if a file exists in the Body Cache.
Definition: bcache.c:279
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:113
struct Message * mx_msg_open_new(struct Mailbox *m, struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1046
Progress bar.
void(* adata_free)(void **ptr)
Callback function to free private data.
Definition: account.h:44
No connected to server.
Definition: private.h:50
struct Connection * mutt_conn_find(const struct ConnAccount *cac)
Find a connection from a list.
Definition: mutt_socket.c:86
header_cache_t * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:321
#define MUTT_ACL_WRITE
Write to a message (for flagging or linking threads)
Definition: mailbox.h:74
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mx.h:107
Body Caching - local copies of email bodies.
int pop_fetch_data(struct PopAccountData *adata, const char *query, struct Progress *progress, pop_fetch_t callback, void *data)
Read Headers with callback function.
Definition: lib.c:511
FILE * mutt_bcache_put(struct BodyCache *bcache, const char *id)
Create a file in the Body Cache.
Definition: bcache.c:199
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:888
time_t check_time
Definition: private.h:93
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:618
#define mutt_b2s(buf)
Definition: buffer.h:41
struct Connection * mutt_conn_new(const struct ConnAccount *cac)
Create a new Connection.
Definition: mutt_socket.c:46
int mutt_hcache_delete_header(header_cache_t *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_header.
Definition: hcache.c:602
ConnAccount object used by POP and IMAP.
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
A local copy of an email.
Definition: mx.h:83
int email_max
Number of pointers in emails.
Definition: mailbox.h:100
void mutt_account_hook(const char *url)
Perform an account hook.
Definition: hook.c:754
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
static int fetch_uidl(const char *line, void *data)
parse UIDL - Implements pop_fetch_t
Definition: pop.c:254
int pop_reconnect(struct Mailbox *m)
reconnect and verify indexes if connection was lost
Definition: lib.c:609
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:44
char * user
Username.
Definition: url.h:69
int fd
Socket file descriptor.
Definition: connection.h:40
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
bool clear_cache
Definition: private.h:91
unsigned int cmd_uidl
optional command UIDL
Definition: private.h:87
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
char * data
Pointer to data.
Definition: buffer.h:35
void(* edata_free)(void **ptr)
Driver-specific data free function.
Definition: email.h:107
static int pop_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open()
Definition: pop.c:801
static int pop_read_header(struct PopAccountData *adata, struct Email *e)
Read header.
Definition: pop.c:172
#define mutt_file_mkstemp()
Definition: file.h:106
API for encryption/signing of emails.
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
bool verbose
Display status messages?
Definition: mailbox.h:118
char * host
Host.
Definition: url.h:71
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
Definition: bcache.c:256
static struct PopAccountData * pop_adata_new(void)
Create a new PopAccountData object.
Definition: pop.c:111
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
unsigned char C_PopDelete
Config: (pop) After downloading POP messages, delete them on the server.
Definition: config.c:39
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
void mutt_progress_init(struct Progress *progress, const char *msg, enum ProgressType type, size_t size)
Set up a progress bar.
Definition: progress.c:153
Login details for a remote server.
Definition: connaccount.h:51
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
static int pop_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync()
Definition: pop.c:919
unsigned int cmd_top
optional command TOP
Definition: private.h:88
unsigned int status
Definition: private.h:81
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:96
POP-specific Email data -.
Definition: private.h:105
bool C_PopLast
Config: (pop) Use the &#39;LAST&#39; command to fetch new mail.
Definition: config.c:41
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * path
Path.
Definition: url.h:73
static void pop_hcache_namer(const char *path, struct Buffer *dest)
Create a header cache filename for a POP mailbox - Implements hcache_namer_t.
Definition: pop.c:340
static header_cache_t * pop_hcache_open(struct PopAccountData *adata, const char *path)
Open the header cache.
Definition: pop.c:351
Local cache of email bodies.
Definition: bcache.c:53
static void pop_edata_free(void **ptr)
Free data attached to an Email.
Definition: pop.c:123
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: curs_lib.c:515
static int pop_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon()
Definition: pop.c:1241
#define HC_FEXT
Definition: pop.c:70
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
WHERE char * C_Spoolfile
Config: Inbox.
Definition: mutt_globals.h:111
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:721
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:451
static void pop_adata_free(void **ptr)
Free data attached to the Mailbox.
Definition: pop.c:97
bool deleted
Email is deleted.
Definition: email.h:45
void * edata
Driver-specific data.
Definition: email.h:106
#define mutt_error(...)
Definition: logging.h:84
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe()
Definition: pop.c:1224
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1159
unsigned int index
Definition: private.h:71
Connection Library.
char * path
Path of Email (for local Mailboxes)
Definition: email.h:91
FILE * fp
pointer to the message data
Definition: mx.h:85
int index
The absolute (unsorted) message number.
Definition: email.h:85
static int pop_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close()
Definition: pop.c:1199
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1670
int url_tostring(struct Url *url, char *dest, size_t len, int flags)
Output the URL string for a given Url object.
Definition: url.c:418
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
static int pop_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check()
Definition: pop.c:878
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
static int pop_msg_save_hcache(struct Mailbox *m, struct Email *e)
Save message to the header cache - Implements MxOps::msg_save_hcache()
Definition: pop.c:1207
struct Email * email_new(void)
Create a new Email.
Definition: email.c:68
POP-specific email cache.
Definition: private.h:69
static int pop_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add()
Definition: pop.c:767
Hundreds of global variables to back the user variables.
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct PopAccountData * pop_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: lib.c:659
New mail received in Mailbox.
Definition: mx.h:74
struct Email * email
Retrieved email.
Definition: lib.h:102
POP-specific Account data -.
Definition: private.h:78
NeoMutt connections.
int const char int line
Definition: acutest.h:617
header cache structure
Definition: lib.h:85
struct Buffer pathbuf
Definition: mailbox.h:83
Convenience wrapper for the library headers.
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:66
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:41
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1106
SecurityFlags crypt_query(struct Body *m)
Check out the type of encryption used.
Definition: crypt.c:683
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:174
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:157
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
void pop_logout(struct Mailbox *m)
logout from a POP server
Definition: lib.c:425
#define U_PATH
Definition: url.h:48
The Mailbox API.
Definition: mx.h:105
int msgno
Number displayed to the user.
Definition: email.h:86
static int fetch_message(const char *line, void *data)
write line to file - Implements pop_fetch_t
Definition: pop.c:152
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
POP network mailbox.