NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
pop.c
Go to the documentation of this file.
1 
33 #include "config.h"
34 #include <errno.h>
35 #include <limits.h>
36 #include <stdbool.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include "private.h"
42 #include "mutt/lib.h"
43 #include "config/lib.h"
44 #include "email/lib.h"
45 #include "core/lib.h"
46 #include "conn/lib.h"
47 #include "lib.h"
48 #include "bcache/lib.h"
49 #include "ncrypt/lib.h"
50 #include "progress/lib.h"
51 #include "question/lib.h"
52 #include "adata.h"
53 #include "edata.h"
54 #include "hook.h"
55 #include "mutt_account.h"
56 #include "mutt_header.h"
57 #include "mutt_logging.h"
58 #include "mutt_socket.h"
59 #include "muttlib.h"
60 #include "mx.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  const char *const c_header_cache =
300  cs_subset_path(NeoMutt->sub, "header_cache");
301  if (!adata || !adata->conn)
302  return mutt_hcache_open(c_header_cache, path, NULL);
303 
304  struct Url url = { 0 };
305  char p[1024];
306 
307  mutt_account_tourl(&adata->conn->account, &url);
308  url.path = HC_FNAME;
309  url_tostring(&url, p, sizeof(p), U_PATH);
310  return mutt_hcache_open(c_header_cache, p, pop_hcache_namer);
311 }
312 #endif
313 
322 static int pop_fetch_headers(struct Mailbox *m)
323 {
324  if (!m)
325  return -1;
326 
327  struct PopAccountData *adata = pop_adata_get(m);
328  struct Progress *progress = NULL;
329 
330 #ifdef USE_HCACHE
331  struct HeaderCache *hc = pop_hcache_open(adata, mailbox_path(m));
332 #endif
333 
334  adata->check_time = mutt_date_epoch();
335  adata->clear_cache = false;
336 
337  for (int i = 0; i < m->msg_count; i++)
338  {
339  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
340  edata->refno = -1;
341  }
342 
343  const int old_count = m->msg_count;
344  int rc = pop_fetch_data(adata, "UIDL\r\n", NULL, fetch_uidl, m);
345  const int new_count = m->msg_count;
346  m->msg_count = old_count;
347 
348  if (adata->cmd_uidl == 2)
349  {
350  if (rc == 0)
351  {
352  adata->cmd_uidl = 1;
353 
354  mutt_debug(LL_DEBUG1, "set UIDL capability\n");
355  }
356 
357  if ((rc == -2) && (adata->cmd_uidl == 2))
358  {
359  adata->cmd_uidl = 0;
360 
361  mutt_debug(LL_DEBUG1, "unset UIDL capability\n");
362  snprintf(adata->err_msg, sizeof(adata->err_msg), "%s",
363  _("Command UIDL is not supported by server"));
364  }
365  }
366 
367  if (m->verbose)
368  {
369  progress = progress_new(_("Fetching message headers..."),
370  MUTT_PROGRESS_READ, new_count - old_count);
371  }
372 
373  if (rc == 0)
374  {
375  int i, deleted;
376  for (i = 0, deleted = 0; i < old_count; i++)
377  {
378  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
379  if (edata->refno == -1)
380  {
381  m->emails[i]->deleted = true;
382  deleted++;
383  }
384  }
385  if (deleted > 0)
386  {
387  mutt_error(
388  ngettext("%d message has been lost. Try reopening the mailbox.",
389  "%d messages have been lost. Try reopening the mailbox.", deleted),
390  deleted);
391  }
392 
393  bool hcached = false;
394  for (i = old_count; i < new_count; i++)
395  {
396  if (m->verbose)
397  progress_update(progress, i + 1 - old_count, -1);
398  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
399 #ifdef USE_HCACHE
400  struct HCacheEntry hce = mutt_hcache_fetch(hc, edata->uid, strlen(edata->uid), 0);
401  if (hce.email)
402  {
403  /* Detach the private data */
404  m->emails[i]->edata = NULL;
405 
406  int index = m->emails[i]->index;
407  /* - POP dynamically numbers headers and relies on e->refno
408  * to map messages; so restore header and overwrite restored
409  * refno with current refno, same for index
410  * - e->data needs to a separate pointer as it's driver-specific
411  * data freed separately elsewhere
412  * (the old e->data should point inside a malloc'd block from
413  * hcache so there shouldn't be a memleak here) */
414  email_free(&m->emails[i]);
415  m->emails[i] = hce.email;
416  m->emails[i]->index = index;
417 
418  /* Reattach the private data */
419  m->emails[i]->edata = edata;
421  rc = 0;
422  hcached = true;
423  }
424  else
425 #endif
426  if ((rc = pop_read_header(adata, m->emails[i])) < 0)
427  break;
428 #ifdef USE_HCACHE
429  else
430  {
431  mutt_hcache_store(hc, edata->uid, strlen(edata->uid), m->emails[i], 0);
432  }
433 #endif
434 
435  /* faked support for flags works like this:
436  * - if 'hcached' is true, we have the message in our hcache:
437  * - if we also have a body: read
438  * - if we don't have a body: old
439  * (if $mark_old is set which is maybe wrong as
440  * $mark_old should be considered for syncing the
441  * folder and not when opening it XXX)
442  * - if 'hcached' is false, we don't have the message in our hcache:
443  * - if we also have a body: read
444  * - if we don't have a body: new */
445  const bool bcached =
446  (mutt_bcache_exists(adata->bcache, cache_id(edata->uid)) == 0);
447  m->emails[i]->old = false;
448  m->emails[i]->read = false;
449  if (hcached)
450  {
451  const bool c_mark_old = cs_subset_bool(NeoMutt->sub, "mark_old");
452  if (bcached)
453  m->emails[i]->read = true;
454  else if (c_mark_old)
455  m->emails[i]->old = true;
456  }
457  else
458  {
459  if (bcached)
460  m->emails[i]->read = true;
461  }
462 
463  m->msg_count++;
464  }
465  }
466  progress_free(&progress);
467 
468 #ifdef USE_HCACHE
469  mutt_hcache_close(hc);
470 #endif
471 
472  if (rc < 0)
473  {
474  for (int i = m->msg_count; i < new_count; i++)
475  email_free(&m->emails[i]);
476  return rc;
477  }
478 
479  /* after putting the result into our structures,
480  * clean up cache, i.e. wipe messages deleted outside
481  * the availability of our cache */
482  const bool c_message_cache_clean =
483  cs_subset_bool(NeoMutt->sub, "message_cache_clean");
484  if (c_message_cache_clean)
486 
488  return new_count - old_count;
489 }
490 
495 static void pop_clear_cache(struct PopAccountData *adata)
496 {
497  if (!adata->clear_cache)
498  return;
499 
500  mutt_debug(LL_DEBUG1, "delete cached messages\n");
501 
502  for (int i = 0; i < POP_CACHE_LEN; i++)
503  {
504  if (adata->cache[i].path)
505  {
506  unlink(adata->cache[i].path);
507  FREE(&adata->cache[i].path);
508  }
509  }
510 }
511 
515 void pop_fetch_mail(void)
516 {
517  const char *const c_pop_host = cs_subset_string(NeoMutt->sub, "pop_host");
518  if (!c_pop_host)
519  {
520  mutt_error(_("POP host is not defined"));
521  return;
522  }
523 
524  char buf[1024];
525  char msgbuf[128];
526  int last = 0, msgs, bytes, rset = 0, ret;
527  struct ConnAccount cac = { { 0 } };
528 
529  char *p = mutt_mem_calloc(strlen(c_pop_host) + 7, sizeof(char));
530  char *url = p;
531  if (url_check_scheme(c_pop_host) == U_UNKNOWN)
532  {
533  strcpy(url, "pop://");
534  p = strchr(url, '\0');
535  }
536  strcpy(p, c_pop_host);
537 
538  ret = pop_parse_path(url, &cac);
539  FREE(&url);
540  if (ret)
541  {
542  mutt_error(_("%s is an invalid POP path"), c_pop_host);
543  return;
544  }
545 
546  struct Connection *conn = mutt_conn_find(&cac);
547  if (!conn)
548  return;
549 
550  struct PopAccountData *adata = pop_adata_new();
551  adata->conn = conn;
552 
553  if (pop_open_connection(adata) < 0)
554  {
555  //XXX mutt_socket_free(adata->conn);
556  pop_adata_free((void **) &adata);
557  return;
558  }
559 
560  mutt_message(_("Checking for new messages..."));
561 
562  /* find out how many messages are in the mailbox. */
563  mutt_str_copy(buf, "STAT\r\n", sizeof(buf));
564  ret = pop_query(adata, buf, sizeof(buf));
565  if (ret == -1)
566  goto fail;
567  if (ret == -2)
568  {
569  mutt_error("%s", adata->err_msg);
570  goto finish;
571  }
572 
573  sscanf(buf, "+OK %d %d", &msgs, &bytes);
574 
575  /* only get unread messages */
576  const bool c_pop_last = cs_subset_bool(NeoMutt->sub, "pop_last");
577  if ((msgs > 0) && c_pop_last)
578  {
579  mutt_str_copy(buf, "LAST\r\n", sizeof(buf));
580  ret = pop_query(adata, buf, sizeof(buf));
581  if (ret == -1)
582  goto fail;
583  if (ret == 0)
584  sscanf(buf, "+OK %d", &last);
585  }
586 
587  if (msgs <= last)
588  {
589  mutt_message(_("No new mail in POP mailbox"));
590  goto finish;
591  }
592 
593  const char *const c_spool_file = cs_subset_string(NeoMutt->sub, "spool_file");
594  struct Mailbox *m_spool = mx_path_resolve(c_spool_file);
595 
596  if (!mx_mbox_open(m_spool, MUTT_OPEN_NO_FLAGS))
597  {
598  mailbox_free(&m_spool);
599  goto finish;
600  }
601  bool old_append = m_spool->append;
602  m_spool->append = true;
603 
604  const enum QuadOption c_pop_delete =
605  cs_subset_quad(NeoMutt->sub, "pop_delete");
606  enum QuadOption delanswer =
607  query_quadoption(c_pop_delete, _("Delete messages from server?"));
608 
609  snprintf(msgbuf, sizeof(msgbuf),
610  ngettext("Reading new messages (%d byte)...",
611  "Reading new messages (%d bytes)...", bytes),
612  bytes);
613  mutt_message("%s", msgbuf);
614 
615  for (int i = last + 1; i <= msgs; i++)
616  {
617  struct Message *msg = mx_msg_open_new(m_spool, NULL, MUTT_ADD_FROM);
618  if (msg)
619  {
620  snprintf(buf, sizeof(buf), "RETR %d\r\n", i);
621  ret = pop_fetch_data(adata, buf, NULL, fetch_message, msg->fp);
622  if (ret == -3)
623  rset = 1;
624 
625  if ((ret == 0) && (mx_msg_commit(m_spool, msg) != 0))
626  {
627  rset = 1;
628  ret = -3;
629  }
630 
631  mx_msg_close(m_spool, &msg);
632  }
633  else
634  {
635  ret = -3;
636  }
637 
638  if ((ret == 0) && (delanswer == MUTT_YES))
639  {
640  /* delete the message on the server */
641  snprintf(buf, sizeof(buf), "DELE %d\r\n", i);
642  ret = pop_query(adata, buf, sizeof(buf));
643  }
644 
645  if (ret == -1)
646  {
647  m_spool->append = old_append;
648  mx_mbox_close(m_spool);
649  goto fail;
650  }
651  if (ret == -2)
652  {
653  mutt_error("%s", adata->err_msg);
654  break;
655  }
656  if (ret == -3)
657  {
658  mutt_error(_("Error while writing mailbox"));
659  break;
660  }
661 
662  /* L10N: The plural is picked by the second numerical argument, i.e.
663  the %d right before 'messages', i.e. the total number of messages. */
664  mutt_message(ngettext("%s [%d of %d message read]",
665  "%s [%d of %d messages read]", msgs - last),
666  msgbuf, i - last, msgs - last);
667  }
668 
669  m_spool->append = old_append;
670  mx_mbox_close(m_spool);
671 
672  if (rset)
673  {
674  /* make sure no messages get deleted */
675  mutt_str_copy(buf, "RSET\r\n", sizeof(buf));
676  if (pop_query(adata, buf, sizeof(buf)) == -1)
677  goto fail;
678  }
679 
680 finish:
681  /* exit gracefully */
682  mutt_str_copy(buf, "QUIT\r\n", sizeof(buf));
683  if (pop_query(adata, buf, sizeof(buf)) == -1)
684  goto fail;
685  mutt_socket_close(conn);
686  FREE(&conn);
687  pop_adata_free((void **) &adata);
688  return;
689 
690 fail:
691  mutt_error(_("Server closed connection"));
692  mutt_socket_close(conn);
693  pop_adata_free((void **) &adata);
694 }
695 
699 static bool pop_ac_owns_path(struct Account *a, const char *path)
700 {
701  struct Url *url = url_parse(path);
702  if (!url)
703  return false;
704 
705  struct PopAccountData *adata = a->adata;
706  struct ConnAccount *cac = &adata->conn->account;
707 
708  const bool ret = mutt_istr_equal(url->host, cac->host) &&
709  mutt_istr_equal(url->user, cac->user);
710  url_free(&url);
711  return ret;
712 }
713 
717 static bool pop_ac_add(struct Account *a, struct Mailbox *m)
718 {
719  if (a->adata)
720  return true;
721 
722  struct ConnAccount cac = { { 0 } };
723  struct PopAccountData *adata = pop_adata_new();
724  a->adata = adata;
726 
727  if (pop_parse_path(mailbox_path(m), &cac))
728  {
729  mutt_error(_("%s is an invalid POP path"), mailbox_path(m));
730  return false;
731  }
732 
733  adata->conn = mutt_conn_new(&cac);
734  if (!adata->conn)
735  {
736  pop_adata_free((void **) &adata);
737  return false;
738  }
739 
740  return true;
741 }
742 
748 static enum MxOpenReturns pop_mbox_open(struct Mailbox *m)
749 {
750  if (!m->account)
751  return MX_OPEN_ERROR;
752 
753  char buf[PATH_MAX];
754  struct ConnAccount cac = { { 0 } };
755  struct Url url = { 0 };
756 
757  if (pop_parse_path(mailbox_path(m), &cac))
758  {
759  mutt_error(_("%s is an invalid POP path"), mailbox_path(m));
760  return MX_OPEN_ERROR;
761  }
762 
763  mutt_account_tourl(&cac, &url);
764  url.path = NULL;
765  url_tostring(&url, buf, sizeof(buf), U_NO_FLAGS);
766 
767  mutt_buffer_strcpy(&m->pathbuf, buf);
769 
770  struct PopAccountData *adata = m->account->adata;
771  if (!adata)
772  {
773  adata = pop_adata_new();
774  m->account->adata = adata;
776  }
777 
778  struct Connection *conn = adata->conn;
779  if (!conn)
780  {
781  adata->conn = mutt_conn_new(&cac);
782  conn = adata->conn;
783  if (!conn)
784  return MX_OPEN_ERROR;
785  }
786 
787  if (conn->fd < 0)
789 
790  if (pop_open_connection(adata) < 0)
791  return MX_OPEN_ERROR;
792 
793  adata->bcache = mutt_bcache_open(&cac, NULL);
794 
795  /* init (hard-coded) ACL rights */
797 #ifdef USE_HCACHE
798  /* flags are managed using header cache, so it only makes sense to
799  * enable them in that case */
800  m->rights |= MUTT_ACL_WRITE;
801 #endif
802 
803  while (true)
804  {
805  if (pop_reconnect(m) < 0)
806  return MX_OPEN_ERROR;
807 
808  m->size = adata->size;
809 
810  mutt_message(_("Fetching list of messages..."));
811 
812  const int rc = pop_fetch_headers(m);
813 
814  if (rc >= 0)
815  return MX_OPEN_OK;
816 
817  if (rc < -1)
818  return MX_OPEN_ERROR;
819  }
820 }
821 
825 static enum MxStatus pop_mbox_check(struct Mailbox *m)
826 {
827  struct PopAccountData *adata = pop_adata_get(m);
828 
829  const short c_pop_check_interval =
830  cs_subset_number(NeoMutt->sub, "pop_check_interval");
831  if ((adata->check_time + c_pop_check_interval) > mutt_date_epoch())
832  return MX_STATUS_OK;
833 
834  pop_logout(m);
835 
836  mutt_socket_close(adata->conn);
837 
838  if (pop_open_connection(adata) < 0)
839  return MX_STATUS_ERROR;
840 
841  m->size = adata->size;
842 
843  mutt_message(_("Checking for new messages..."));
844 
845  int old_msg_count = m->msg_count;
846  int rc = pop_fetch_headers(m);
847  pop_clear_cache(adata);
848  if (m->msg_count > old_msg_count)
850 
851  if (rc < 0)
852  return MX_STATUS_ERROR;
853 
854  if (rc > 0)
855  return MX_STATUS_NEW_MAIL;
856 
857  return MX_STATUS_OK;
858 }
859 
865 static enum MxStatus pop_mbox_sync(struct Mailbox *m)
866 {
867  int i, j, rc = 0;
868  char buf[1024];
869  struct PopAccountData *adata = pop_adata_get(m);
870 #ifdef USE_HCACHE
871  struct HeaderCache *hc = NULL;
872 #endif
873 
874  adata->check_time = 0;
875 
876  int num_deleted = 0;
877  for (i = 0; i < m->msg_count; i++)
878  {
879  if (m->emails[i]->deleted)
880  num_deleted++;
881  }
882 
883  while (true)
884  {
885  if (pop_reconnect(m) < 0)
886  return MX_STATUS_ERROR;
887 
888 #ifdef USE_HCACHE
889  hc = pop_hcache_open(adata, mailbox_path(m));
890 #endif
891 
892  struct Progress *progress = NULL;
893  if (m->verbose)
894  {
895  progress = progress_new(_("Marking messages deleted..."),
896  MUTT_PROGRESS_WRITE, num_deleted);
897  }
898 
899  for (i = 0, j = 0, rc = 0; (rc == 0) && (i < m->msg_count); i++)
900  {
901  struct PopEmailData *edata = pop_edata_get(m->emails[i]);
902  if (m->emails[i]->deleted && (edata->refno != -1))
903  {
904  j++;
905  if (m->verbose)
906  progress_update(progress, j, -1);
907  snprintf(buf, sizeof(buf), "DELE %d\r\n", edata->refno);
908  rc = pop_query(adata, buf, sizeof(buf));
909  if (rc == 0)
910  {
911  mutt_bcache_del(adata->bcache, cache_id(edata->uid));
912 #ifdef USE_HCACHE
913  mutt_hcache_delete_record(hc, edata->uid, strlen(edata->uid));
914 #endif
915  }
916  }
917 
918 #ifdef USE_HCACHE
919  if (m->emails[i]->changed)
920  {
921  mutt_hcache_store(hc, edata->uid, strlen(edata->uid), m->emails[i], 0);
922  }
923 #endif
924  }
925  progress_free(&progress);
926 
927 #ifdef USE_HCACHE
928  mutt_hcache_close(hc);
929 #endif
930 
931  if (rc == 0)
932  {
933  mutt_str_copy(buf, "QUIT\r\n", sizeof(buf));
934  rc = pop_query(adata, buf, sizeof(buf));
935  }
936 
937  if (rc == 0)
938  {
939  adata->clear_cache = true;
940  pop_clear_cache(adata);
941  adata->status = POP_DISCONNECTED;
942  return MX_STATUS_OK;
943  }
944 
945  if (rc == -2)
946  {
947  mutt_error("%s", adata->err_msg);
948  return MX_STATUS_ERROR;
949  }
950  }
951 }
952 
956 static enum MxStatus pop_mbox_close(struct Mailbox *m)
957 {
958  struct PopAccountData *adata = pop_adata_get(m);
959  if (!adata)
960  return MX_STATUS_OK;
961 
962  pop_logout(m);
963 
964  if (adata->status != POP_NONE)
965  {
966  mutt_socket_close(adata->conn);
967  // FREE(&adata->conn);
968  }
969 
970  adata->status = POP_NONE;
971 
972  adata->clear_cache = true;
973  pop_clear_cache(adata);
974 
975  mutt_bcache_close(&adata->bcache);
976 
977  return MX_STATUS_OK;
978 }
979 
983 static bool pop_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
984 {
985  char buf[1024];
986  struct PopAccountData *adata = pop_adata_get(m);
987  struct Email *e = m->emails[msgno];
988  struct PopEmailData *edata = pop_edata_get(e);
989  bool bcache = true;
990  bool success = false;
991  struct Buffer *path = NULL;
992 
993  /* see if we already have the message in body cache */
994  msg->fp = mutt_bcache_get(adata->bcache, cache_id(edata->uid));
995  if (msg->fp)
996  return true;
997 
998  /* see if we already have the message in our cache in
999  * case $message_cachedir is unset */
1000  struct PopCache *cache = &adata->cache[e->index % POP_CACHE_LEN];
1001 
1002  if (cache->path)
1003  {
1004  if (cache->index == e->index)
1005  {
1006  /* yes, so just return a pointer to the message */
1007  msg->fp = fopen(cache->path, "r");
1008  if (msg->fp)
1009  return true;
1010 
1011  mutt_perror(cache->path);
1012  return false;
1013  }
1014  else
1015  {
1016  /* clear the previous entry */
1017  unlink(cache->path);
1018  FREE(&cache->path);
1019  }
1020  }
1021 
1022  path = mutt_buffer_pool_get();
1023 
1024  while (true)
1025  {
1026  if (pop_reconnect(m) < 0)
1027  goto cleanup;
1028 
1029  /* verify that massage index is correct */
1030  if (edata->refno < 0)
1031  {
1032  mutt_error(
1033  _("The message index is incorrect. Try reopening the mailbox."));
1034  goto cleanup;
1035  }
1036 
1037  /* see if we can put in body cache; use our cache as fallback */
1038  msg->fp = mutt_bcache_put(adata->bcache, cache_id(edata->uid));
1039  if (!msg->fp)
1040  {
1041  /* no */
1042  bcache = false;
1043  mutt_buffer_mktemp(path);
1044  msg->fp = mutt_file_fopen(mutt_buffer_string(path), "w+");
1045  if (!msg->fp)
1046  {
1048  goto cleanup;
1049  }
1050  }
1051 
1052  snprintf(buf, sizeof(buf), "RETR %d\r\n", edata->refno);
1053 
1054  struct Progress *progress = progress_new(_("Fetching message..."), MUTT_PROGRESS_NET,
1055  e->body->length + e->body->offset - 1);
1056  const int ret = pop_fetch_data(adata, buf, progress, fetch_message, msg->fp);
1057  progress_free(&progress);
1058 
1059  if (ret == 0)
1060  break;
1061 
1062  mutt_file_fclose(&msg->fp);
1063 
1064  /* if RETR failed (e.g. connection closed), be sure to remove either
1065  * the file in bcache or from POP's own cache since the next iteration
1066  * of the loop will re-attempt to put() the message */
1067  if (!bcache)
1068  unlink(mutt_buffer_string(path));
1069 
1070  if (ret == -2)
1071  {
1072  mutt_error("%s", adata->err_msg);
1073  goto cleanup;
1074  }
1075 
1076  if (ret == -3)
1077  {
1078  mutt_error(_("Can't write message to temporary file"));
1079  goto cleanup;
1080  }
1081  }
1082 
1083  /* Update the header information. Previously, we only downloaded a
1084  * portion of the headers, those required for the main display. */
1085  if (bcache)
1086  mutt_bcache_commit(adata->bcache, cache_id(edata->uid));
1087  else
1088  {
1089  cache->index = e->index;
1090  cache->path = mutt_buffer_strdup(path);
1091  }
1092  rewind(msg->fp);
1093 
1094  /* Detach the private data */
1095  e->edata = NULL;
1096 
1097  /* we replace envelope, key in subj_hash has to be updated as well */
1098  if (m->subj_hash && e->env->real_subj)
1100  mutt_label_hash_remove(m, e);
1101  mutt_env_free(&e->env);
1102  e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
1103  if (m->subj_hash && e->env->real_subj)
1105  mutt_label_hash_add(m, e);
1106 
1107  /* Reattach the private data */
1108  e->edata = edata;
1110 
1111  e->lines = 0;
1112  fgets(buf, sizeof(buf), msg->fp);
1113  while (!feof(msg->fp))
1114  {
1115  m->emails[msgno]->lines++;
1116  fgets(buf, sizeof(buf), msg->fp);
1117  }
1118 
1119  e->body->length = ftello(msg->fp) - e->body->offset;
1120 
1121  /* This needs to be done in case this is a multipart message */
1122  if (!WithCrypto)
1123  e->security = crypt_query(e->body);
1124 
1125  mutt_clear_error();
1126  rewind(msg->fp);
1127 
1128  success = true;
1129 
1130 cleanup:
1131  mutt_buffer_pool_release(&path);
1132  return success;
1133 }
1134 
1140 static int pop_msg_close(struct Mailbox *m, struct Message *msg)
1141 {
1142  return mutt_file_fclose(&msg->fp);
1143 }
1144 
1148 static int pop_msg_save_hcache(struct Mailbox *m, struct Email *e)
1149 {
1150  int rc = 0;
1151 #ifdef USE_HCACHE
1152  struct PopAccountData *adata = pop_adata_get(m);
1153  struct PopEmailData *edata = e->edata;
1154  struct HeaderCache *hc = pop_hcache_open(adata, mailbox_path(m));
1155  rc = mutt_hcache_store(hc, edata->uid, strlen(edata->uid), e, 0);
1156  mutt_hcache_close(hc);
1157 #endif
1158 
1159  return rc;
1160 }
1161 
1165 enum MailboxType pop_path_probe(const char *path, const struct stat *st)
1166 {
1167  if (mutt_istr_startswith(path, "pop://"))
1168  return MUTT_POP;
1169 
1170  if (mutt_istr_startswith(path, "pops://"))
1171  return MUTT_POP;
1172 
1173  return MUTT_UNKNOWN;
1174 }
1175 
1179 static int pop_path_canon(char *buf, size_t buflen)
1180 {
1181  return 0;
1182 }
1183 
1187 static int pop_path_pretty(char *buf, size_t buflen, const char *folder)
1188 {
1189  /* Succeed, but don't do anything, for now */
1190  return 0;
1191 }
1192 
1196 static int pop_path_parent(char *buf, size_t buflen)
1197 {
1198  /* Succeed, but don't do anything, for now */
1199  return 0;
1200 }
1201 
1202 // clang-format off
1206 struct MxOps MxPopOps = {
1207  .type = MUTT_POP,
1208  .name = "pop",
1209  .is_local = false,
1210  .ac_owns_path = pop_ac_owns_path,
1211  .ac_add = pop_ac_add,
1212  .mbox_open = pop_mbox_open,
1213  .mbox_open_append = NULL,
1214  .mbox_check = pop_mbox_check,
1215  .mbox_check_stats = NULL,
1216  .mbox_sync = pop_mbox_sync,
1217  .mbox_close = pop_mbox_close,
1218  .msg_open = pop_msg_open,
1219  .msg_open_new = NULL,
1220  .msg_commit = NULL,
1221  .msg_close = pop_msg_close,
1222  .msg_padding_size = NULL,
1223  .msg_save_hcache = pop_msg_save_hcache,
1224  .tags_edit = NULL,
1225  .tags_commit = NULL,
1226  .path_probe = pop_path_probe,
1227  .path_canon = pop_path_canon,
1228  .path_pretty = pop_path_pretty,
1229  .path_parent = pop_path_parent,
1230  .path_is_empty = NULL,
1231 };
1232 // 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:904
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
void pop_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:41
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
#define pop_query(adata, buf, buflen)
Definition: private.h:106
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:71
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
int lines
How many lines in the body of this message?
Definition: email.h:85
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: adata.h:56
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Representation of the email&#39;s header.
#define WithCrypto
Definition: lib.h:113
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:96
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: adata.h:50
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
int pop_parse_path(const char *path, struct ConnAccount *cac)
Parse a POP mailbox name.
Definition: lib.c:83
Wrapper for Email retrieved from the header cache.
Definition: lib.h:95
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:40
struct Body * body
List of MIME parts.
Definition: email.h:91
Structs that make up an email.
#define mutt_error(...)
Definition: logging.h:88
#define HC_FNAME
Definition: pop.c:71
struct BodyCache * mutt_bcache_open(struct ConnAccount *account, const char *mailbox)
Open an Email-Body Cache.
Definition: bcache.c:143
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
int pop_open_connection(struct PopAccountData *adata)
Open connection and authenticate.
Definition: lib.c:310
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:68
enum MailboxType pop_path_probe(const char *path, const struct stat *st)
Is this a POP Mailbox? - Implements MxOps::path_probe() -.
Definition: pop.c:1165
struct PopCache cache[POP_CACHE_LEN]
Definition: adata.h:57
Pop-specific Account data.
int mutt_bcache_commit(struct BodyCache *bcache, const char *id)
Move a temporary file into the Body Cache.
Definition: bcache.c:247
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 BodyCache * bcache
body cache
Definition: adata.h:55
A group of associated Mailboxes.
Definition: account.h:36
header cache structure
Definition: lib.h:84
String manipulation buffer.
Definition: buffer.h:33
New mail received in Mailbox.
Definition: mxapi.h:79
char user[128]
Username.
Definition: connaccount.h:55
void mx_alloc_memory(struct Mailbox *m)
Create storage for the emails.
Definition: mx.c:1212
Url wasn&#39;t recognised.
Definition: url.h:35
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: adata.h:38
Progress tracks elements, according to $read_inc
Definition: lib.h:46
static enum MxOpenReturns pop_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -Fetch only headers.
Definition: pop.c:748
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
bool changed
Email has been edited.
Definition: email.h:48
#define U_NO_FLAGS
Definition: url.h:49
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:380
void pop_fetch_mail(void)
Fetch messages and save them in $spool_file.
Definition: pop.c:515
static const char * cache_id(const char *id)
Make a message-cache-compatible id.
Definition: pop.c:83
Email list was changed.
Definition: mailbox.h:180
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:393
MxOpenReturns
Return values for mbox_open()
Definition: mxapi.h:88
int refno
Message number on server.
Definition: edata.h:34
struct PopEmailData * pop_edata_new(const char *uid)
Create a new PopEmailData for an email.
Definition: edata.c:53
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:610
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
struct HeaderCache * mutt_hcache_open(const char *path, const char *folder, hcache_namer_t namer)
Multiplexor for StoreOps::open.
Definition: hcache.c:332
static int pop_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty() -.
Definition: pop.c:1187
Disconnected from server.
Definition: private.h:51
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
struct PopAccountData * pop_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:64
#define mutt_perror(...)
Definition: logging.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:36
A Progress Bar.
Definition: progress.c:47
static int pop_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: pop.c:1179
#define MUTT_ACL_DELETE
Delete a message.
Definition: mailbox.h:66
Open succeeded.
Definition: mxapi.h:90
static int pop_fetch_headers(struct Mailbox *m)
Read headers.
Definition: pop.c:322
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
static void pop_clear_cache(struct PopAccountData *adata)
delete all cached messages
Definition: pop.c:495
QuadOption
Possible values for a quad-option.
Definition: quad.h:35
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:329
static struct HeaderCache * pop_hcache_open(struct PopAccountData *adata, const char *path)
Open the header cache.
Definition: pop.c:297
struct Email * email_new(void)
Create a new Email.
Definition: email.c:78
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
char host[128]
Server to login to.
Definition: connaccount.h:53
Some miscellaneous functions.
Progress bar.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1186
bool read
Email is read.
Definition: email.h:51
Header cache multiplexor.
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1054
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:179
API for mailboxes.
struct PopAccountData * pop_adata_new(void)
Create a new PopAccountData object.
Definition: adata.c:54
bool old
Email is seen, but unread.
Definition: email.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
#define POP_CACHE_LEN
Definition: private.h:39
static enum MxStatus pop_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
Definition: pop.c:825
const char * uid
Definition: edata.h:33
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
struct Envelope * env
Envelope information.
Definition: email.h:90
Convenience wrapper for the core headers.
int mutt_bcache_exists(struct BodyCache *bcache, const char *id)
Check if a file exists in the Body Cache.
Definition: bcache.c:287
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:347
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
void(* adata_free)(void **ptr)
Free the private data attached to the Account.
Definition: account.h:53
No connected to server.
Definition: private.h:49
struct Connection * mutt_conn_find(const struct ConnAccount *cac)
Find a connection from a list.
Definition: mutt_socket.c:89
static int pop_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
Definition: pop.c:1140
#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: mxapi.h:105
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:506
FILE * mutt_bcache_put(struct BodyCache *bcache, const char *id)
Create a file in the Body Cache.
Definition: bcache.c:207
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
time_t check_time
Definition: adata.h:51
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:618
struct Connection * mutt_conn_new(const struct ConnAccount *cac)
Create a new Connection.
Definition: mutt_socket.c:48
ConnAccount object used by POP and IMAP.
&#39;POP3&#39; Mailbox type
Definition: mailbox.h:55
A local copy of an email.
Definition: mxapi.h:41
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:782
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:200
int pop_reconnect(struct Mailbox *m)
reconnect and verify indexes if connection was lost
Definition: lib.c:604
A mailbox.
Definition: mailbox.h:81
#define PATH_MAX
Definition: mutt.h:40
char * user
Username.
Definition: url.h:71
int fd
Socket file descriptor.
Definition: connection.h:44
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
bool clear_cache
Definition: adata.h:49
unsigned int cmd_uidl
optional command UIDL
Definition: adata.h:45
No changes.
Definition: mxapi.h:78
Pop-specific Email data.
void(* edata_free)(void **ptr)
Free the private data attached to the Email.
Definition: email.h:121
int mutt_hcache_delete_record(struct HeaderCache *hc, const char *key, size_t keylen)
Multiplexor for StoreOps::delete_record.
Definition: hcache.c:637
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
static int pop_read_header(struct PopAccountData *adata, struct Email *e)
Read header.
Definition: pop.c:118
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
#define mutt_file_mkstemp()
Definition: file.h:108
API for encryption/signing of emails.
char msg[1024]
Message to display.
Definition: progress.c:50
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:113
bool verbose
Display status messages?
Definition: mailbox.h:118
Ask the user a question.
char * host
Host.
Definition: url.h:73
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:556
void pop_adata_free(void **ptr)
Free the private Account data - Implements Account::adata_free()
Definition: adata.c:40
int mutt_bcache_del(struct BodyCache *bcache, const char *id)
Delete a file from the Body Cache.
Definition: bcache.c:264
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
AclFlags rights
ACL bits, see AclFlags.
Definition: mailbox.h:121
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:194
Progress tracks bytes, according to $net_inc
Definition: lib.h:48
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
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
unsigned int cmd_top
optional command TOP
Definition: adata.h:46
unsigned int status
Definition: adata.h:39
int mutt_socket_close(struct Connection *conn)
Close a socket.
Definition: socket.c:97
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:228
POP-specific Email data -.
Definition: edata.h:31
void progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:175
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:75
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
void mutt_hcache_close(struct HeaderCache *hc)
Multiplexor for StoreOps::close.
Definition: hcache.c:435
Local cache of email bodies.
Definition: bcache.c:50
struct PopEmailData * pop_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:65
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:983
#define HC_FEXT
Definition: pop.c:72
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:131
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:749
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
Progress tracks elements, according to $write_inc
Definition: lib.h:47
static int pop_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent() -.
Definition: pop.c:1196
bool deleted
Email is deleted.
Definition: email.h:45
void * edata
Driver-specific data.
Definition: email.h:111
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:246
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1165
unsigned int index
Definition: private.h:70
Connection Library.
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
FILE * fp
pointer to the message data
Definition: mxapi.h:43
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:698
int index
The absolute (unsorted) message number.
Definition: email.h:86
#define mutt_message(...)
Definition: logging.h:87
#define FREE(x)
Definition: memory.h:40
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1668
char * folder
Definition: lib.h:86
#define MUTT_OPEN_NO_FLAGS
No flags are set.
Definition: mxapi.h:60
#define MUTT_ACL_SEEN
Change the &#39;seen&#39; status of a message.
Definition: mailbox.h:73
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
struct HCacheEntry mutt_hcache_fetch(struct HeaderCache *hc, const char *key, size_t keylen, uint32_t uidvalidity)
Multiplexor for StoreOps::fetch.
Definition: hcache.c:461
POP-specific email cache.
Definition: private.h:68
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
struct Email * email
Retrieved email.
Definition: lib.h:99
POP-specific Account data -.
Definition: adata.h:36
static bool pop_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add() -.
Definition: pop.c:717
NeoMutt connections.
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:699
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:589
Open failed with an error.
Definition: mxapi.h:91
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:42
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1124
static enum MxStatus pop_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -Update POP mailbox, delete messages from...
Definition: pop.c:865
void mailbox_changed(struct Mailbox *m, enum NotifyMailbox action)
Notify observers of a change to a Mailbox.
Definition: mailbox.c:208
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close() ...
Definition: mxapi.h:75
void mutt_bcache_close(struct BodyCache **bcache)
Close an Email-Body Cache.
Definition: bcache.c:164
static enum MxStatus pop_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close() -.
Definition: pop.c:956
void pop_logout(struct Mailbox *m)
logout from a POP server
Definition: lib.c:420
char * path
path to temp file
Definition: mxapi.h:44
#define U_PATH
Definition: url.h:50
Definition: mxapi.h:103
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:1148
int msgno
Number displayed to the user.
Definition: email.h:87
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:39
static int fetch_message(const char *line, void *data)
write line to file - Implements pop_fetch_t
Definition: pop.c:98
An error occurred.
Definition: mxapi.h:77
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:234
POP network mailbox.