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