NeoMutt  2023-03-22-27-g3cb248
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
Precondition
m is not NULL
msg is not NULL
0 <= msgno < msg->msg_count

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 746 of file compress.c.

747{
748 if (!m->compress_info)
749 return false;
750
751 struct CompressInfo *ci = m->compress_info;
752
753 const struct MxOps *ops = ci->child_ops;
754 if (!ops)
755 return false;
756
757 /* Delegate */
758 return ops->msg_open(m, msg, msgno);
759}
Private data for compress.
Definition: lib.h:47
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:52
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:120
Definition: mxapi.h:112
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Definition: mxapi.h:237

◆ 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 1942 of file message.c.

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

1459{
1460 struct Email *e = m->emails[msgno];
1461 if (!e)
1462 return false;
1463
1464 char path[PATH_MAX] = { 0 };
1465
1466 snprintf(path, sizeof(path), "%s/%s", mailbox_path(m), e->path);
1467
1468 msg->fp = fopen(path, "r");
1469 if (!msg->fp && (errno == ENOENT))
1470 msg->fp = maildir_open_find_message(mailbox_path(m), e->path, NULL);
1471
1472 if (!msg->fp)
1473 {
1475 mutt_debug(LL_DEBUG1, "fopen: %s: %s (errno %d)\n", path, strerror(errno), errno);
1476 return false;
1477 }
1478
1479 return true;
1480}
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
#define mutt_perror(...)
Definition: logging.h:88
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:209
FILE * maildir_open_find_message(const char *folder, const char *msg, char **newname)
Find a message by name.
Definition: maildir.c:998
#define PATH_MAX
Definition: mutt.h:41
char * path
Path of Email (for local Mailboxes)
Definition: email.h:68
+ 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 1122 of file mh.c.

1123{
1124 if (!m || !m->emails || (msgno >= m->msg_count))
1125 return false;
1126
1127 struct Email *e = m->emails[msgno];
1128 if (!e)
1129 return false;
1130
1131 char path[PATH_MAX] = { 0 };
1132
1133 snprintf(path, sizeof(path), "%s/%s", mailbox_path(m), e->path);
1134
1135 msg->fp = fopen(path, "r");
1136 if (!msg->fp)
1137 {
1139 mutt_debug(LL_DEBUG1, "fopen: %s: %s (errno %d)\n", path, strerror(errno), errno);
1140 return false;
1141 }
1142
1143 return true;
1144}
int msg_count
Total number of messages.
Definition: mailbox.h:88
+ 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 1586 of file mbox.c.

1587{
1589 if (!adata)
1590 return false;
1591
1592 msg->fp = mutt_file_fopen(mailbox_path(m), "r");
1593 if (!msg->fp)
1594 return false;
1595
1596 return true;
1597}
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition: mbox.c:119
Mbox-specific Account data -.
Definition: lib.h:49
+ 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 2590 of file nntp.c.

2591{
2592 struct NntpMboxData *mdata = m->mdata;
2593 struct Email *e = m->emails[msgno];
2594 if (!e)
2595 return false;
2596
2597 char article[16] = { 0 };
2598
2599 /* try to get article from cache */
2600 struct NntpAcache *acache = &mdata->acache[e->index % NNTP_ACACHE_LEN];
2601 if (acache->path)
2602 {
2603 if (acache->index == e->index)
2604 {
2605 msg->fp = mutt_file_fopen(acache->path, "r");
2606 if (msg->fp)
2607 return true;
2608 }
2609 /* clear previous entry */
2610 else
2611 {
2612 unlink(acache->path);
2613 FREE(&acache->path);
2614 }
2615 }
2616 snprintf(article, sizeof(article), ANUM, nntp_edata_get(e)->article_num);
2617 msg->fp = mutt_bcache_get(mdata->bcache, article);
2618 if (msg->fp)
2619 {
2620 if (nntp_edata_get(e)->parsed)
2621 return true;
2622 }
2623 else
2624 {
2625 char buf[PATH_MAX] = { 0 };
2626 /* don't try to fetch article from removed newsgroup */
2627 if (mdata->deleted)
2628 return false;
2629
2630 /* create new cache file */
2631 const char *fetch_msg = _("Fetching message...");
2632 mutt_message(fetch_msg);
2633 msg->fp = mutt_bcache_put(mdata->bcache, article);
2634 if (!msg->fp)
2635 {
2636 mutt_mktemp(buf, sizeof(buf));
2637 acache->path = mutt_str_dup(buf);
2638 acache->index = e->index;
2639 msg->fp = mutt_file_fopen(acache->path, "w+");
2640 if (!msg->fp)
2641 {
2642 mutt_perror(acache->path);
2643 unlink(acache->path);
2644 FREE(&acache->path);
2645 return false;
2646 }
2647 }
2648
2649 /* fetch message to cache file */
2650 snprintf(buf, sizeof(buf), "ARTICLE %s\r\n",
2651 nntp_edata_get(e)->article_num ? article : e->env->message_id);
2652 const int rc = nntp_fetch_lines(mdata, buf, sizeof(buf), fetch_msg,
2653 fetch_tempfile, msg->fp);
2654 if (rc)
2655 {
2656 mutt_file_fclose(&msg->fp);
2657 if (acache->path)
2658 {
2659 unlink(acache->path);
2660 FREE(&acache->path);
2661 }
2662 if (rc > 0)
2663 {
2664 if (mutt_str_startswith(buf, nntp_edata_get(e)->article_num ? "423" : "430"))
2665 {
2666 mutt_error(_("Article %s not found on the server"),
2667 nntp_edata_get(e)->article_num ? article : e->env->message_id);
2668 }
2669 else
2670 {
2671 mutt_error("ARTICLE: %s", buf);
2672 }
2673 }
2674 return false;
2675 }
2676
2677 if (!acache->path)
2678 mutt_bcache_commit(mdata->bcache, article);
2679 }
2680
2681 /* replace envelope with new one
2682 * hash elements must be updated because pointers will be changed */
2683 if (m->id_hash && e->env->message_id)
2685 if (m->subj_hash && e->env->real_subj)
2687
2688 mutt_env_free(&e->env);
2689 e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
2690
2691 if (m->id_hash && e->env->message_id)
2693 if (m->subj_hash && e->env->real_subj)
2695
2696 /* fix content length */
2697 if (!mutt_file_seek(msg->fp, 0, SEEK_END))
2698 {
2699 return false;
2700 }
2701 e->body->length = ftell(msg->fp) - e->body->offset;
2702
2703 /* this is called in neomutt before the open which fetches the message,
2704 * which is probably wrong, but we just call it again here to handle
2705 * the problem instead of fixing it */
2706 nntp_edata_get(e)->parsed = true;
2707 mutt_parse_mime_message(e, msg->fp);
2708
2709 /* these would normally be updated in mview_update(), but the
2710 * full headers aren't parsed with overview, so the information wasn't
2711 * available then */
2712 if (WithCrypto)
2713 e->security = crypt_query(e->body);
2714
2715 rewind(msg->fp);
2717 return true;
2718}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:592
int mutt_bcache_commit(struct BodyCache *bcache, const char *id)
Move a temporary file into the Body Cache.
Definition: bcache.c:248
FILE * mutt_bcache_get(struct BodyCache *bcache, const char *id)
Open a file in the Body Cache.
Definition: bcache.c:180
FILE * mutt_bcache_put(struct BodyCache *bcache, const char *id)
Create a file in the Body Cache.
Definition: bcache.c:208
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:672
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:708
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:335
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition: hash.c:427
#define FREE(x)
Definition: memory.h:43
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
#define WithCrypto
Definition: lib.h:116
struct NntpEmailData * nntp_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:58
#define NNTP_ACACHE_LEN
Definition: lib.h:82
#define ANUM
Definition: lib.h:61
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:775
static int fetch_tempfile(char *line, void *data)
Write line to temporary file.
Definition: nntp.c:968
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:41
int index
The absolute (unsorted) message number.
Definition: email.h:109
char * message_id
Message ID.
Definition: envelope.h:73
char * real_subj
Offset of the real subject.
Definition: envelope.h:71
void * mdata
Driver specific data.
Definition: mailbox.h:132
struct HashTable * subj_hash
Hash Table by subject.
Definition: mailbox.h:124
struct HashTable * id_hash
Hash Table by msg id.
Definition: mailbox.h:123
NNTP article cache.
Definition: lib.h:67
char * path
Cache path.
Definition: lib.h:69
unsigned int index
Index number.
Definition: lib.h:68
bool parsed
Email has been parse.
Definition: edata.h:37
NNTP-specific Mailbox data -.
Definition: mdata.h:33
bool deleted
Definition: mdata.h:44
struct BodyCache * bcache
Definition: mdata.h:49
struct NntpAcache acache[NNTP_ACACHE_LEN]
Definition: mdata.h:48
#define mutt_mktemp(buf, buflen)
Definition: tmp.h:34
+ 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 2348 of file notmuch.c.

2349{
2350 struct Email *e = m->emails[msgno];
2351 if (!e)
2352 return false;
2353
2354 char path[PATH_MAX] = { 0 };
2355 char *folder = nm_email_get_folder(e);
2356
2357 snprintf(path, sizeof(path), "%s/%s", folder, e->path);
2358
2359 msg->fp = fopen(path, "r");
2360 if (!msg->fp && (errno == ENOENT) && ((m->type == MUTT_MAILDIR) || (m->type == MUTT_NOTMUCH)))
2361 {
2362 msg->fp = maildir_open_find_message(folder, e->path, NULL);
2363 }
2364
2365 return msg->fp != NULL;
2366}
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:48
FILE * maildir_open_find_message(const char *folder, const char *msg, char **newname)
Find a message by name.
Definition: maildir.c:998
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition: notmuch.c:1456
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
+ 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 976 of file pop.c.

977{
978 char buf[1024] = { 0 };
980 struct Email *e = m->emails[msgno];
981 struct PopEmailData *edata = pop_edata_get(e);
982 bool bcache = true;
983 bool success = false;
984 struct Buffer *path = NULL;
985
986 /* see if we already have the message in body cache */
987 msg->fp = mutt_bcache_get(adata->bcache, cache_id(edata->uid));
988 if (msg->fp)
989 return true;
990
991 /* see if we already have the message in our cache in
992 * case $message_cache_dir is unset */
993 struct PopCache *cache = &adata->cache[e->index % POP_CACHE_LEN];
994
995 if (cache->path)
996 {
997 if (cache->index == e->index)
998 {
999 /* yes, so just return a pointer to the message */
1000 msg->fp = fopen(cache->path, "r");
1001 if (msg->fp)
1002 return true;
1003
1004 mutt_perror(cache->path);
1005 return false;
1006 }
1007 else
1008 {
1009 /* clear the previous entry */
1010 unlink(cache->path);
1011 FREE(&cache->path);
1012 }
1013 }
1014
1016
1017 while (true)
1018 {
1019 if (pop_reconnect(m) < 0)
1020 goto cleanup;
1021
1022 /* verify that massage index is correct */
1023 if (edata->refno < 0)
1024 {
1025 mutt_error(_("The message index is incorrect. Try reopening the mailbox."));
1026 goto cleanup;
1027 }
1028
1029 /* see if we can put in body cache; use our cache as fallback */
1030 msg->fp = mutt_bcache_put(adata->bcache, cache_id(edata->uid));
1031 if (!msg->fp)
1032 {
1033 /* no */
1034 bcache = false;
1037 if (!msg->fp)
1038 {
1040 goto cleanup;
1041 }
1042 }
1043
1044 snprintf(buf, sizeof(buf), "RETR %d\r\n", edata->refno);
1045
1046 struct Progress *progress = progress_new(_("Fetching message..."), MUTT_PROGRESS_NET,
1047 e->body->length + e->body->offset - 1);
1048 const int rc = pop_fetch_data(adata, buf, progress, fetch_message, msg->fp);
1049 progress_free(&progress);
1050
1051 if (rc == 0)
1052 break;
1053
1054 mutt_file_fclose(&msg->fp);
1055
1056 /* if RETR failed (e.g. connection closed), be sure to remove either
1057 * the file in bcache or from POP's own cache since the next iteration
1058 * of the loop will re-attempt to put() the message */
1059 if (!bcache)
1060 unlink(mutt_buffer_string(path));
1061
1062 if (rc == -2)
1063 {
1064 mutt_error("%s", adata->err_msg);
1065 goto cleanup;
1066 }
1067
1068 if (rc == -3)
1069 {
1070 mutt_error(_("Can't write message to temporary file"));
1071 goto cleanup;
1072 }
1073 }
1074
1075 /* Update the header information. Previously, we only downloaded a
1076 * portion of the headers, those required for the main display. */
1077 if (bcache)
1078 {
1079 mutt_bcache_commit(adata->bcache, cache_id(edata->uid));
1080 }
1081 else
1082 {
1083 cache->index = e->index;
1084 cache->path = mutt_buffer_strdup(path);
1085 }
1086 rewind(msg->fp);
1087
1088 /* Detach the private data */
1089 e->edata = NULL;
1090
1091 /* we replace envelope, key in subj_hash has to be updated as well */
1092 if (m->subj_hash && e->env->real_subj)
1095 mutt_env_free(&e->env);
1096 e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
1097 if (m->subj_hash && e->env->real_subj)
1099 mutt_label_hash_add(m, e);
1100
1101 /* Reattach the private data */
1102 e->edata = edata;
1104
1105 e->lines = 0;
1106 fgets(buf, sizeof(buf), msg->fp);
1107 while (!feof(msg->fp))
1108 {
1109 m->emails[msgno]->lines++;
1110 fgets(buf, sizeof(buf), msg->fp);
1111 }
1112
1113 e->body->length = ftello(msg->fp) - e->body->offset;
1114
1115 /* This needs to be done in case this is a multipart message */
1116 if (!WithCrypto)
1117 e->security = crypt_query(e->body);
1118
1120 rewind(msg->fp);
1121
1122 success = true;
1123
1124cleanup:
1126 return success;
1127}
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:485
static int fetch_message(const char *line, void *data)
Write line to file - Implements pop_fetch_t -.
Definition: pop.c:97
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message's labels from the Hash Table.
Definition: mutt_header.c:438
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message's labels to the Hash Table.
Definition: mutt_header.c:425
struct PopAccountData * pop_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:73
void pop_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free()
Definition: edata.c:41
struct PopEmailData * pop_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:65
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:502
int pop_reconnect(struct Mailbox *m)
Reconnect and verify indexes if connection was lost.
Definition: lib.c:599
#define POP_CACHE_LEN
Definition: private.h:39
static const char * cache_id(const char *id)
Make a message-cache-compatible id.
Definition: pop.c:82
@ MUTT_PROGRESS_NET
Progress tracks bytes, according to $net_inc
Definition: lib.h:51
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:86
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:118
void * edata
Driver-specific data.
Definition: email.h:72
void(* edata_free)(void **ptr)
Free the private data attached to the Email.
Definition: email.h:86
POP-specific Account data -.
Definition: adata.h:37
char err_msg[POP_CMD_RESPONSE]
Definition: adata.h:56
struct PopCache cache[POP_CACHE_LEN]
Definition: adata.h:57
struct BodyCache * bcache
body cache
Definition: adata.h:55
POP-specific email cache.
Definition: private.h:69
unsigned int index
Definition: private.h:70
char * path
Definition: private.h:71
POP-specific Email data -.
Definition: edata.h:32
int refno
Message number on server.
Definition: edata.h:34
const char * uid
UID of email.
Definition: edata.h:33
+ Here is the call graph for this function: