NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
msg_open()

Open an email message in a Mailbox. More...

+ Collaboration diagram for msg_open():

Functions

static bool comp_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
bool imap_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static bool maildir_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static bool mh_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static bool mbox_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static bool nntp_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static bool nm_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 
static bool pop_msg_open (struct Mailbox *m, struct Message *msg, int msgno)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -. More...
 

Detailed Description

Open an email message in a Mailbox.

Parameters
mMailbox
msgMessage to open
msgnoIndex of message to open
Return values
trueSuccess
falseError

Contract

Function Documentation

◆ comp_msg_open()

static bool comp_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 734 of file compress.c.

735 {
736  if (!m->compress_info)
737  return false;
738 
739  struct CompressInfo *ci = m->compress_info;
740 
741  const struct MxOps *ops = ci->child_ops;
742  if (!ops)
743  return false;
744 
745  /* Delegate */
746  return ops->msg_open(m, msg, msgno);
747 }
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Definition: mxapi.h:238
Private data for compress.
Definition: lib.h:46
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:124
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:52
Definition: mxapi.h:103

◆ imap_msg_open()

bool imap_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 1927 of file message.c.

1928 {
1929  struct Envelope *newenv = NULL;
1930  char buf[1024];
1931  char *pc = NULL;
1932  unsigned int bytes;
1933  struct Progress *progress = NULL;
1934  unsigned int uid;
1935  bool retried = false;
1936  bool read;
1937  int rc;
1938 
1939  /* Sam's weird courier server returns an OK response even when FETCH
1940  * fails. Thanks Sam. */
1941  bool fetched = false;
1942 
1943  struct ImapAccountData *adata = imap_adata_get(m);
1944 
1945  if (!adata || (adata->mailbox != m))
1946  return false;
1947 
1948  struct Email *e = m->emails[msgno];
1949  if (!e)
1950  return false;
1951 
1952  msg->fp = msg_cache_get(m, e);
1953  if (msg->fp)
1954  {
1955  if (imap_edata_get(e)->parsed)
1956  return true;
1957  goto parsemsg;
1958  }
1959 
1960  /* This function is called in a few places after endwin()
1961  * e.g. mutt_pipe_message(). */
1962  bool output_progress = !isendwin() && m->verbose;
1963  if (output_progress)
1964  mutt_message(_("Fetching message..."));
1965 
1966  msg->fp = msg_cache_put(m, e);
1967  if (!msg->fp)
1968  {
1969  struct Buffer *path = mutt_buffer_pool_get();
1970  mutt_buffer_mktemp(path);
1971  msg->fp = mutt_file_fopen(mutt_buffer_string(path), "w+");
1972  unlink(mutt_buffer_string(path));
1973  mutt_buffer_pool_release(&path);
1974 
1975  if (!msg->fp)
1976  return false;
1977  }
1978 
1979  /* mark this header as currently inactive so the command handler won't
1980  * also try to update it. HACK until all this code can be moved into the
1981  * command handler */
1982  e->active = false;
1983 
1984  const bool c_imap_peek = cs_subset_bool(NeoMutt->sub, "imap_peek");
1985  snprintf(buf, sizeof(buf), "UID FETCH %u %s", imap_edata_get(e)->uid,
1986  ((adata->capabilities & IMAP_CAP_IMAP4REV1) ?
1987  (c_imap_peek ? "BODY.PEEK[]" : "BODY[]") :
1988  "RFC822"));
1989 
1990  imap_cmd_start(adata, buf);
1991  do
1992  {
1993  rc = imap_cmd_step(adata);
1994  if (rc != IMAP_RES_CONTINUE)
1995  break;
1996 
1997  pc = adata->buf;
1998  pc = imap_next_word(pc);
1999  pc = imap_next_word(pc);
2000 
2001  if (mutt_istr_startswith(pc, "FETCH"))
2002  {
2003  while (*pc)
2004  {
2005  pc = imap_next_word(pc);
2006  if (pc[0] == '(')
2007  pc++;
2008  if (mutt_istr_startswith(pc, "UID"))
2009  {
2010  pc = imap_next_word(pc);
2011  if (mutt_str_atoui(pc, &uid) < 0)
2012  goto bail;
2013  if (uid != imap_edata_get(e)->uid)
2014  {
2015  mutt_error(_(
2016  "The message index is incorrect. Try reopening the mailbox."));
2017  }
2018  }
2019  else if (mutt_istr_startswith(pc, "RFC822") || mutt_istr_startswith(pc, "BODY[]"))
2020  {
2021  pc = imap_next_word(pc);
2022  if (imap_get_literal_count(pc, &bytes) < 0)
2023  {
2024  imap_error("imap_msg_open()", buf);
2025  goto bail;
2026  }
2027  if (output_progress)
2028  {
2029  progress = progress_new(_("Fetching message..."), MUTT_PROGRESS_NET, bytes);
2030  }
2031  if (imap_read_literal(msg->fp, adata, bytes, output_progress ? progress : NULL) < 0)
2032  {
2033  goto bail;
2034  }
2035  /* pick up trailing line */
2036  rc = imap_cmd_step(adata);
2037  if (rc != IMAP_RES_CONTINUE)
2038  goto bail;
2039  pc = adata->buf;
2040 
2041  fetched = true;
2042  }
2043  /* UW-IMAP will provide a FLAGS update here if the FETCH causes a
2044  * change (eg from \Unseen to \Seen).
2045  * Uncommitted changes in neomutt take precedence. If we decide to
2046  * incrementally update flags later, this won't stop us syncing */
2047  else if (!e->changed && mutt_istr_startswith(pc, "FLAGS"))
2048  {
2049  pc = imap_set_flags(m, e, pc, NULL);
2050  if (!pc)
2051  goto bail;
2052  }
2053  }
2054  }
2055  } while (rc == IMAP_RES_CONTINUE);
2056 
2057  /* see comment before command start. */
2058  e->active = true;
2059 
2060  fflush(msg->fp);
2061  if (ferror(msg->fp))
2062  goto bail;
2063 
2064  if (rc != IMAP_RES_OK)
2065  goto bail;
2066 
2067  if (!fetched || !imap_code(adata->buf))
2068  goto bail;
2069 
2070  msg_cache_commit(m, e);
2071 
2072 parsemsg:
2073  /* Update the header information. Previously, we only downloaded a
2074  * portion of the headers, those required for the main display. */
2075  rewind(msg->fp);
2076  /* It may be that the Status header indicates a message is read, but the
2077  * IMAP server doesn't know the message has been \Seen. So we capture
2078  * the server's notion of 'read' and if it differs from the message info
2079  * picked up in mutt_rfc822_read_header, we mark the message (and context
2080  * changed). Another possibility: ignore Status on IMAP? */
2081  read = e->read;
2082  newenv = mutt_rfc822_read_header(msg->fp, e, false, false);
2083  mutt_env_merge(e->env, &newenv);
2084 
2085  /* see above. We want the new status in e->read, so we unset it manually
2086  * and let mutt_set_flag set it correctly, updating context. */
2087  if (read != e->read)
2088  {
2089  e->read = read;
2090  mutt_set_flag(m, e, MUTT_NEW, read);
2091  }
2092 
2093  e->lines = 0;
2094  fgets(buf, sizeof(buf), msg->fp);
2095  while (!feof(msg->fp))
2096  {
2097  e->lines++;
2098  fgets(buf, sizeof(buf), msg->fp);
2099  }
2100 
2101  e->body->length = ftell(msg->fp) - e->body->offset;
2102 
2103  mutt_clear_error();
2104  rewind(msg->fp);
2105  imap_edata_get(e)->parsed = true;
2106 
2107  /* retry message parse if cached message is empty */
2108  if (!retried && ((e->lines == 0) || (e->body->length == 0)))
2109  {
2110  imap_cache_del(m, e);
2111  retried = true;
2112  goto parsemsg;
2113  }
2114 
2115  progress_free(&progress);
2116  return true;
2117 
2118 bail:
2119  e->active = true;
2120  mutt_file_fclose(&msg->fp);
2121  imap_cache_del(m, e);
2122  progress_free(&progress);
2123  return false;
2124 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
int lines
How many lines in the body of this message?
Definition: email.h:85
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:66
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1079
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
struct Body * body
List of MIME parts.
Definition: email.h:91
#define mutt_error(...)
Definition: logging.h:88
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
static FILE * msg_cache_put(struct Mailbox *m, struct Email *e)
Put an email into the message cache.
Definition: message.c:128
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition: message.c:1819
String manipulation buffer.
Definition: buffer.h:33
static FILE * msg_cache_get(struct Mailbox *m, struct Email *e)
Get the message cache entry for an email.
Definition: message.c:107
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
bool changed
Email has been edited.
Definition: email.h:48
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:64
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1065
int imap_read_literal(FILE *fp, struct ImapAccountData *adata, unsigned long bytes, struct Progress *pbar)
Read bytes bytes from server into file.
Definition: imap.c:600
Container for Accounts, Notifications.
Definition: neomutt.h:36
A Progress Bar.
Definition: progress.c:47
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_env_merge(struct Envelope *base, struct Envelope **extra)
Merge the headers of two Envelopes.
Definition: envelope.c:151
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:792
bool read
Email is read.
Definition: email.h:51
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
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
void imap_error(const char *where, const char *msg)
show an error and abort
Definition: util.c:665
#define IMAP_CAP_IMAP4REV1
Server supports IMAP4rev1.
Definition: private.h:124
bool active
Message is not to be removed.
Definition: email.h:59
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
New messages.
Definition: mutt.h:89
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:282
bool verbose
Display status messages?
Definition: mailbox.h:118
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
ImapCapFlags capabilities
Definition: adata.h:55
Progress tracks bytes, according to $net_inc
Definition: lib.h:48
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:228
int imap_get_literal_count(const char *buf, unsigned int *bytes)
write number of bytes in an IMAP literal into bytes
Definition: util.c:748
IMAP-specific Account data -.
Definition: adata.h:39
char * buf
Definition: adata.h:59
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:246
FILE * fp
pointer to the message data
Definition: mxapi.h:43
#define mutt_message(...)
Definition: logging.h:87
char * imap_set_flags(struct Mailbox *m, struct Email *e, char *s, bool *server_changes)
fill the message header according to the server flags
Definition: message.c:1870
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:57
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1124
bool parsed
Definition: edata.h:42
bool imap_code(const char *s)
Was the command successful.
Definition: command.c:1202
The header of an Email.
Definition: envelope.h:54
int msgno
Number displayed to the user.
Definition: email.h:87
static int msg_cache_commit(struct Mailbox *m, struct Email *e)
Add to the message cache.
Definition: message.c:149
+ Here is the call graph for this function:

◆ maildir_msg_open()

static bool maildir_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 1456 of file maildir.c.

1457 {
1458  struct Email *e = m->emails[msgno];
1459  if (!e)
1460  return false;
1461 
1462  char path[PATH_MAX];
1463 
1464  snprintf(path, sizeof(path), "%s/%s", mailbox_path(m), e->path);
1465 
1466  msg->fp = fopen(path, "r");
1467  if (!msg->fp && (errno == ENOENT))
1468  msg->fp = maildir_open_find_message(mailbox_path(m), e->path, NULL);
1469 
1470  if (!msg->fp)
1471  {
1472  mutt_perror(path);
1473  mutt_debug(LL_DEBUG1, "fopen: %s: %s (errno %d)\n", path, strerror(errno), errno);
1474  return false;
1475  }
1476 
1477  return true;
1478 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
The envelope/body of an email.
Definition: email.h:37
#define mutt_perror(...)
Definition: logging.h:89
FILE * maildir_open_find_message(const char *folder, const char *msg, char **newname)
Find a new.
Definition: maildir.c:993
#define PATH_MAX
Definition: mutt.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
FILE * fp
pointer to the message data
Definition: mxapi.h:43
int msgno
Number displayed to the user.
Definition: email.h:87
+ Here is the call graph for this function:

◆ mh_msg_open()

static bool mh_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 1112 of file mh.c.

1113 {
1114  if (!m || !m->emails || (msgno >= m->msg_count))
1115  return false;
1116 
1117  struct Email *e = m->emails[msgno];
1118  if (!e)
1119  return false;
1120 
1121  char path[PATH_MAX];
1122 
1123  snprintf(path, sizeof(path), "%s/%s", mailbox_path(m), e->path);
1124 
1125  msg->fp = fopen(path, "r");
1126  if (!msg->fp)
1127  {
1128  mutt_perror(path);
1129  mutt_debug(LL_DEBUG1, "fopen: %s: %s (errno %d)\n", path, strerror(errno), errno);
1130  return false;
1131  }
1132 
1133  return true;
1134 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
#define mutt_perror(...)
Definition: logging.h:89
#define PATH_MAX
Definition: mutt.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
Log at debug level 1.
Definition: logging.h:40
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
FILE * fp
pointer to the message data
Definition: mxapi.h:43
int msgno
Number displayed to the user.
Definition: email.h:87
+ Here is the call graph for this function:

◆ mbox_msg_open()

static bool mbox_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 1564 of file mbox.c.

1565 {
1566  struct MboxAccountData *adata = mbox_adata_get(m);
1567  if (!adata)
1568  return false;
1569 
1570  msg->fp = mutt_file_fopen(mailbox_path(m), "r");
1571  if (!msg->fp)
1572  return false;
1573 
1574  return true;
1575 }
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox&#39;s path string.
Definition: mailbox.h:215
Mbox-specific Account data -.
Definition: lib.h:48
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition: mbox.c:100
FILE * fp
pointer to the message data
Definition: mxapi.h:43
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ Here is the call graph for this function:

◆ nntp_msg_open()

static bool nntp_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 2571 of file nntp.c.

2572 {
2573  struct NntpMboxData *mdata = m->mdata;
2574  struct Email *e = m->emails[msgno];
2575  if (!e)
2576  return false;
2577 
2578  char article[16];
2579 
2580  /* try to get article from cache */
2581  struct NntpAcache *acache = &mdata->acache[e->index % NNTP_ACACHE_LEN];
2582  if (acache->path)
2583  {
2584  if (acache->index == e->index)
2585  {
2586  msg->fp = mutt_file_fopen(acache->path, "r");
2587  if (msg->fp)
2588  return true;
2589  }
2590  /* clear previous entry */
2591  else
2592  {
2593  unlink(acache->path);
2594  FREE(&acache->path);
2595  }
2596  }
2597  snprintf(article, sizeof(article), ANUM, nntp_edata_get(e)->article_num);
2598  msg->fp = mutt_bcache_get(mdata->bcache, article);
2599  if (msg->fp)
2600  {
2601  if (nntp_edata_get(e)->parsed)
2602  return true;
2603  }
2604  else
2605  {
2606  char buf[PATH_MAX];
2607  /* don't try to fetch article from removed newsgroup */
2608  if (mdata->deleted)
2609  return false;
2610 
2611  /* create new cache file */
2612  const char *fetch_msg = _("Fetching message...");
2613  mutt_message(fetch_msg);
2614  msg->fp = mutt_bcache_put(mdata->bcache, article);
2615  if (!msg->fp)
2616  {
2617  mutt_mktemp(buf, sizeof(buf));
2618  acache->path = mutt_str_dup(buf);
2619  acache->index = e->index;
2620  msg->fp = mutt_file_fopen(acache->path, "w+");
2621  if (!msg->fp)
2622  {
2623  mutt_perror(acache->path);
2624  unlink(acache->path);
2625  FREE(&acache->path);
2626  return false;
2627  }
2628  }
2629 
2630  /* fetch message to cache file */
2631  snprintf(buf, sizeof(buf), "ARTICLE %s\r\n",
2632  nntp_edata_get(e)->article_num ? article : e->env->message_id);
2633  const int rc =
2634  nntp_fetch_lines(mdata, buf, sizeof(buf), fetch_msg, fetch_tempfile, msg->fp);
2635  if (rc)
2636  {
2637  mutt_file_fclose(&msg->fp);
2638  if (acache->path)
2639  {
2640  unlink(acache->path);
2641  FREE(&acache->path);
2642  }
2643  if (rc > 0)
2644  {
2645  if (mutt_str_startswith(buf, nntp_edata_get(e)->article_num ? "423" : "430"))
2646  {
2647  mutt_error(_("Article %s not found on the server"),
2648  nntp_edata_get(e)->article_num ? article : e->env->message_id);
2649  }
2650  else
2651  mutt_error("ARTICLE: %s", buf);
2652  }
2653  return false;
2654  }
2655 
2656  if (!acache->path)
2657  mutt_bcache_commit(mdata->bcache, article);
2658  }
2659 
2660  /* replace envelope with new one
2661  * hash elements must be updated because pointers will be changed */
2662  if (m->id_hash && e->env->message_id)
2663  mutt_hash_delete(m->id_hash, e->env->message_id, e);
2664  if (m->subj_hash && e->env->real_subj)
2666 
2667  mutt_env_free(&e->env);
2668  e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
2669 
2670  if (m->id_hash && e->env->message_id)
2671  mutt_hash_insert(m->id_hash, e->env->message_id, e);
2672  if (m->subj_hash && e->env->real_subj)
2674 
2675  /* fix content length */
2676  fseek(msg->fp, 0, SEEK_END);
2677  e->body->length = ftell(msg->fp) - e->body->offset;
2678 
2679  /* this is called in neomutt before the open which fetches the message,
2680  * which is probably wrong, but we just call it again here to handle
2681  * the problem instead of fixing it */
2682  nntp_edata_get(e)->parsed = true;
2683  mutt_parse_mime_message(m, e, msg->fp);
2684 
2685  /* these would normally be updated in ctx_update(), but the
2686  * full headers aren't parsed with overview, so the information wasn't
2687  * available then */
2688  if (WithCrypto)
2689  e->security = crypt_query(e->body);
2690 
2691  rewind(msg->fp);
2692  mutt_clear_error();
2693  return true;
2694 }
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:591
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
char * path
Definition: lib.h:69
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
struct NntpAcache acache[NNTP_ACACHE_LEN]
Definition: mdata.h:48
#define WithCrypto
Definition: lib.h:113
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 Body * body
List of MIME parts.
Definition: email.h:91
#define mutt_error(...)
Definition: logging.h:88
static int fetch_tempfile(char *line, void *data)
Write line to temporary file.
Definition: nntp.c:957
int mutt_bcache_commit(struct BodyCache *bcache, const char *id)
Move a temporary file into the Body Cache.
Definition: bcache.c:247
bool parsed
Definition: edata.h:37
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
#define NNTP_ACACHE_LEN
Definition: lib.h:82
#define mutt_perror(...)
Definition: logging.h:89
char * message_id
Message ID.
Definition: envelope.h:69
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:127
FILE * mutt_bcache_get(struct BodyCache *bcache, const char *id)
Open a file in the Body Cache.
Definition: bcache.c:179
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
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
FILE * mutt_bcache_put(struct BodyCache *bcache, const char *id)
Create a file in the Body Cache.
Definition: bcache.c:207
#define ANUM
Definition: lib.h:61
#define mutt_mktemp(buf, buflen)
Definition: muttlib.h:71
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:160
struct BodyCache * bcache
Definition: mdata.h:49
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define PATH_MAX
Definition: mutt.h:40
struct NntpEmailData * nntp_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:58
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
NNTP-specific Mailbox data -.
Definition: mdata.h:32
static int nntp_fetch_lines(struct NntpMboxData *mdata, char *query, size_t qlen, const char *msg, int(*func)(char *, void *), void *data)
Read lines, calling a callback function for each.
Definition: nntp.c:768
unsigned int index
Definition: lib.h:68
bool deleted
Definition: mdata.h:44
NNTP article cache.
Definition: lib.h:66
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
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1124
int msgno
Number displayed to the user.
Definition: email.h:87
+ Here is the call graph for this function:

◆ nm_msg_open()

static bool nm_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 2364 of file notmuch.c.

2365 {
2366  struct Email *e = m->emails[msgno];
2367  if (!e)
2368  return false;
2369 
2370  char path[PATH_MAX];
2371  char *folder = nm_email_get_folder(e);
2372 
2373  snprintf(path, sizeof(path), "%s/%s", folder, e->path);
2374 
2375  msg->fp = fopen(path, "r");
2376  if (!msg->fp && (errno == ENOENT) && ((m->type == MUTT_MAILDIR) || (m->type == MUTT_NOTMUCH)))
2377  {
2378  msg->fp = maildir_open_find_message(folder, e->path, NULL);
2379  }
2380 
2381  return msg->fp != NULL;
2382 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
The envelope/body of an email.
Definition: email.h:37
FILE * maildir_open_find_message(const char *folder, const char *msg, char **newname)
Find a new.
Definition: maildir.c:993
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
#define PATH_MAX
Definition: mutt.h:40
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition: notmuch.c:1458
&#39;Notmuch&#39; (virtual) Mailbox type
Definition: mailbox.h:54
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
FILE * fp
pointer to the message data
Definition: mxapi.h:43
int msgno
Number displayed to the user.
Definition: email.h:87
+ Here is the call graph for this function:

◆ pop_msg_open()

static bool pop_msg_open ( struct Mailbox m,
struct Message msg,
int  msgno 
)
static

Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Definition at line 983 of file pop.c.

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 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
void pop_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:41
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
char err_msg[POP_CMD_RESPONSE]
Definition: adata.h:56
#define WithCrypto
Definition: lib.h:113
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
struct Body * body
List of MIME parts.
Definition: email.h:91
#define mutt_error(...)
Definition: logging.h:88
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
struct PopCache cache[POP_CACHE_LEN]
Definition: adata.h:57
int mutt_bcache_commit(struct BodyCache *bcache, const char *id)
Move a temporary file into the Body Cache.
Definition: bcache.c:247
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
String manipulation buffer.
Definition: buffer.h:33
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
char * real_subj
Offset of the real subject.
Definition: envelope.h:67
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
static const char * cache_id(const char *id)
Make a message-cache-compatible id.
Definition: pop.c:83
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
int refno
Message number on server.
Definition: edata.h:34
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
A Progress Bar.
Definition: progress.c:47
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
FILE * mutt_bcache_get(struct BodyCache *bcache, const char *id)
Open a file in the Body Cache.
Definition: bcache.c:179
#define POP_CACHE_LEN
Definition: private.h:39
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
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:112
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:128
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
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
int pop_reconnect(struct Mailbox *m)
reconnect and verify indexes if connection was lost
Definition: lib.c:604
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
void(* edata_free)(void **ptr)
Free the private data attached to the Email.
Definition: email.h:121
Progress tracks bytes, according to $net_inc
Definition: lib.h:48
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:228
POP-specific Email data -.
Definition: edata.h:31
struct PopEmailData * pop_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:65
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
unsigned int index
Definition: private.h:70
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 FREE(x)
Definition: memory.h:40
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:419
POP-specific email cache.
Definition: private.h:68
POP-specific Account data -.
Definition: adata.h:36
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
parses an RFC822 header
Definition: parse.c:1124
int msgno
Number displayed to the user.
Definition: email.h:87
static int fetch_message(const char *line, void *data)
write line to file - Implements pop_fetch_t
Definition: pop.c:98
+ Here is the call graph for this function: