NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
bool imap_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
bool maildir_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
static bool mbox_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
static bool mh_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
static bool nntp_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
static bool nm_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.
static bool pop_msg_open (struct Mailbox *m, struct Message *msg, struct Email *e)
 Open an email message in a Mailbox - Implements MxOps::msg_open() -.

Detailed Description

Open an email message in a Mailbox.

Parameters
mMailbox
msgMessage to open
eEmail to open
Return values
trueSuccess
falseError
Precondition
m is not NULL
msg is not NULL
e is not NULL

Function Documentation

◆ comp_msg_open()

bool comp_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )
static

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

Definition at line 682 of file compress.c.

683{
684 if (!m->compress_info)
685 return false;
686
687 struct CompressInfo *ci = m->compress_info;
688
689 const struct MxOps *ops = ci->child_ops;
690 if (!ops)
691 return false;
692
693 /* Delegate */
694 return ops->msg_open(m, msg, e);
695}
Private data for compress.
Definition lib.h:62
const struct MxOps * child_ops
callbacks of de-compressed file
Definition lib.h:67
void * compress_info
Compressed mbox module private data.
Definition mailbox.h:123
Definition mxapi.h:98
bool(* msg_open)(struct Mailbox *m, struct Message *msg, struct Email *e)
Definition mxapi.h:223

◆ imap_msg_open()

bool imap_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )

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

Definition at line 2015 of file message.c.

2016{
2017 struct Envelope *newenv = NULL;
2018 char buf[1024] = { 0 };
2019 char *pc = NULL;
2020 unsigned int bytes = 0;
2021 unsigned int uid = 0;
2022 bool retried = false;
2023 bool read;
2024 int rc;
2025
2026 /* Sam's weird courier server returns an OK response even when FETCH
2027 * fails. Thanks Sam. */
2028 bool fetched = false;
2029
2031
2032 if (!adata || (adata->mailbox != m))
2033 return false;
2034
2035 msg->fp = msg_cache_get(m, e);
2036 if (msg->fp)
2037 {
2038 if (imap_edata_get(e)->parsed)
2039 return true;
2040 goto parsemsg;
2041 }
2042
2043 /* This function is called in a few places after endwin()
2044 * e.g. mutt_pipe_message(). */
2045 bool output_progress = !isendwin() && m->verbose;
2046 if (output_progress)
2047 mutt_message(_("Fetching message..."));
2048
2049 msg->fp = msg_cache_put(m, e);
2050 if (!msg->fp)
2051 {
2052 struct Buffer *tempfile = buf_pool_get();
2053 buf_mktemp(tempfile);
2054 msg->fp = mutt_file_fopen(buf_string(tempfile), "w+");
2055 unlink(buf_string(tempfile));
2056 buf_pool_release(&tempfile);
2057
2058 if (!msg->fp)
2059 return false;
2060 }
2061
2062 /* mark this header as currently inactive so the command handler won't
2063 * also try to update it. HACK until all this code can be moved into the
2064 * command handler */
2065 e->active = false;
2066
2067 const bool c_imap_peek = cs_subset_bool(NeoMutt->sub, "imap_peek");
2068 snprintf(buf, sizeof(buf), "UID FETCH %u %s", imap_edata_get(e)->uid,
2069 ((adata->capabilities & IMAP_CAP_IMAP4REV1) ?
2070 (c_imap_peek ? "BODY.PEEK[]" : "BODY[]") :
2071 "RFC822"));
2072
2073 imap_cmd_start(adata, buf);
2074 do
2075 {
2076 rc = imap_cmd_step(adata);
2077 if (rc != IMAP_RES_CONTINUE)
2078 break;
2079
2080 pc = adata->buf;
2081 pc = imap_next_word(pc);
2082 pc = imap_next_word(pc);
2083
2084 if (mutt_istr_startswith(pc, "FETCH"))
2085 {
2086 while (*pc)
2087 {
2088 pc = imap_next_word(pc);
2089 if (pc[0] == '(')
2090 pc++;
2091 if (mutt_istr_startswith(pc, "UID"))
2092 {
2093 pc = imap_next_word(pc);
2094 if (!mutt_str_atoui(pc, &uid))
2095 goto bail;
2096 if (uid != imap_edata_get(e)->uid)
2097 {
2098 mutt_error(_("The message index is incorrect. Try reopening the mailbox."));
2099 }
2100 }
2101 else if (mutt_istr_startswith(pc, "RFC822") || mutt_istr_startswith(pc, "BODY[]"))
2102 {
2103 pc = imap_next_word(pc);
2104 if (imap_get_literal_count(pc, &bytes) < 0)
2105 {
2106 imap_error("imap_msg_open()", buf);
2107 goto bail;
2108 }
2109
2110 const int res = imap_read_literal(msg->fp, adata, bytes, NULL);
2111 if (res < 0)
2112 {
2113 goto bail;
2114 }
2115 /* pick up trailing line */
2116 rc = imap_cmd_step(adata);
2117 if (rc != IMAP_RES_CONTINUE)
2118 goto bail;
2119 pc = adata->buf;
2120
2121 fetched = true;
2122 }
2123 else if (!e->changed && mutt_istr_startswith(pc, "FLAGS"))
2124 {
2125 /* UW-IMAP will provide a FLAGS update here if the FETCH causes a
2126 * change (eg from \Unseen to \Seen).
2127 * Uncommitted changes in neomutt take precedence. If we decide to
2128 * incrementally update flags later, this won't stop us syncing */
2129 pc = imap_set_flags(m, e, pc, NULL);
2130 if (!pc)
2131 goto bail;
2132 }
2133 }
2134 }
2135 } while (rc == IMAP_RES_CONTINUE);
2136
2137 /* see comment before command start. */
2138 e->active = true;
2139
2140 fflush(msg->fp);
2141 if (ferror(msg->fp))
2142 goto bail;
2143
2144 if (rc != IMAP_RES_OK)
2145 goto bail;
2146
2147 if (!fetched || !imap_code(adata->buf))
2148 goto bail;
2149
2150 if (msg_cache_commit(m, e) < 0)
2151 mutt_debug(LL_DEBUG1, "failed to add message to cache\n");
2152
2153parsemsg:
2154 /* Update the header information. Previously, we only downloaded a
2155 * portion of the headers, those required for the main display. */
2156 fseek(msg->fp, 0, SEEK_SET);
2157 clearerr(msg->fp);
2158 /* It may be that the Status header indicates a message is read, but the
2159 * IMAP server doesn't know the message has been \Seen. So we capture
2160 * the server's notion of 'read' and if it differs from the message info
2161 * picked up in mutt_rfc822_read_header, we mark the message (and context
2162 * changed). Another possibility: ignore Status on IMAP? */
2163 read = e->read;
2164 newenv = mutt_rfc822_read_header(msg->fp, e, false, false);
2165 mutt_env_merge(e->env, &newenv);
2166
2167 /* see above. We want the new status in e->read, so we unset it manually
2168 * and let mutt_set_flag set it correctly, updating context. */
2169 if (read != e->read)
2170 {
2171 e->read = read;
2172 mutt_set_flag(m, e, MUTT_NEW, read, true);
2173 }
2174
2175 e->lines = 0;
2176 while (fgets(buf, sizeof(buf), msg->fp) && !feof(msg->fp))
2177 {
2178 e->lines++;
2179 }
2180
2181 e->body->length = ftell(msg->fp) - e->body->offset;
2182
2184 fseek(msg->fp, 0, SEEK_SET);
2185 clearerr(msg->fp);
2186 imap_edata_get(e)->parsed = true;
2187
2188 /* retry message parse if cached message is empty */
2189 if (!retried && ((e->lines == 0) || (e->body->length == 0)))
2190 {
2191 imap_cache_del(m, e);
2192 retried = true;
2193 goto parsemsg;
2194 }
2195
2196 return true;
2197
2198bail:
2199 e->active = true;
2200 mutt_file_fclose(&msg->fp);
2201 imap_cache_del(m, e);
2202 return false;
2203}
const char * mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition atoi.c:217
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
struct Envelope * mutt_rfc822_read_header(FILE *fp, struct Email *e, bool user_hdrs, bool weed)
Parses an RFC822 header.
Definition parse.c:1358
void mutt_env_merge(struct Envelope *base, struct Envelope **extra)
Merge the headers of two Envelopes.
Definition envelope.c:192
#define mutt_file_fclose(FP)
Definition file.h:144
#define mutt_file_fopen(PATH, MODE)
Definition file.h:143
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition flags.c:54
#define mutt_error(...)
Definition logging2.h:94
#define mutt_message(...)
Definition logging2.h:93
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition adata.c:162
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition command.c:1216
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition command.c:1230
bool imap_code(const char *s)
Was the command successful.
Definition command.c:1372
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition edata.c:66
static FILE * msg_cache_put(struct Mailbox *m, struct Email *e)
Put an email into the message cache.
Definition message.c:129
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:1958
static FILE * msg_cache_get(struct Mailbox *m, struct Email *e)
Get the message cache entry for an email.
Definition message.c:108
int imap_cache_del(struct Mailbox *m, struct Email *e)
Delete an email from the body cache.
Definition message.c:1907
static int msg_cache_commit(struct Mailbox *m, struct Email *e)
Add to the message cache.
Definition message.c:150
#define IMAP_RES_OK
<tag> OK ...
Definition private.h:54
int imap_get_literal_count(char *buf, unsigned int *bytes)
Write number of bytes in an IMAP literal into bytes.
Definition util.c:787
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition util.c:668
@ IMAP_CAP_IMAP4REV1
Server supports IMAP4rev1.
Definition private.h:136
#define IMAP_RES_CONTINUE
* ...
Definition private.h:55
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition util.c:831
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:704
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
#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:246
@ MUTT_NEW
New messages.
Definition mutt.h:89
void mutt_clear_error(void)
Clear the message line (bottom line of screen).
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
void * adata
Private data (for Mailbox backends).
Definition account.h:42
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:36
bool read
Email is read.
Definition email.h:50
struct Envelope * env
Envelope information.
Definition email.h:68
int lines
How many lines in the body of this message?
Definition email.h:62
struct Body * body
List of MIME parts.
Definition email.h:69
bool active
Message is not to be removed.
Definition email.h:76
bool changed
Email has been edited.
Definition email.h:77
The header of an Email.
Definition envelope.h:57
IMAP-specific Account data -.
Definition adata.h:40
ImapCapFlags capabilities
Capability flags.
Definition adata.h:56
char * buf
Command buffer.
Definition adata.h:61
bool parsed
Email has been parsed.
Definition edata.h:43
bool verbose
Display status messages?
Definition mailbox.h:119
FILE * fp
pointer to the message data
Definition message.h:35
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
#define buf_mktemp(buf)
Definition tmp.h:33
Here is the call graph for this function:

◆ maildir_msg_open()

bool maildir_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )

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

Definition at line 523 of file message.c.

524{
525 char path[PATH_MAX] = { 0 };
526
527 snprintf(path, sizeof(path), "%s/%s", mailbox_path(m), e->path);
528
529 msg->fp = mutt_file_fopen(path, "r");
530 if (!msg->fp && (errno == ENOENT))
531 msg->fp = maildir_open_find_message(mailbox_path(m), e->path, NULL);
532
533 if (!msg->fp)
534 {
535 mutt_perror("%s", path);
536 return false;
537 }
538
539 return true;
540}
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:216
#define mutt_perror(...)
Definition logging2.h:95
FILE * maildir_open_find_message(const char *folder, const char *msg, char **newname)
Find a message by name.
Definition message.c:168
#define PATH_MAX
Definition mutt.h:49
char * path
Path of Email (for local Mailboxes).
Definition email.h:70
Here is the call graph for this function:

◆ mbox_msg_open()

bool mbox_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )
static

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

Definition at line 1502 of file mbox.c.

1503{
1505 if (!adata)
1506 return false;
1507
1508 msg->fp = mutt_file_fopen(mailbox_path(m), "r");
1509 if (!msg->fp)
1510 return false;
1511
1512 return true;
1513}
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition mbox.c:121
Mbox-specific Account data -.
Definition lib.h:50
Here is the call graph for this function:

◆ mh_msg_open()

bool mh_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )
static

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

Definition at line 1147 of file mh.c.

1148{
1149 char path[PATH_MAX] = { 0 };
1150
1151 snprintf(path, sizeof(path), "%s/%s", mailbox_path(m), e->path);
1152
1153 msg->fp = mutt_file_fopen(path, "r");
1154 if (!msg->fp)
1155 {
1156 mutt_perror("%s", path);
1157 return false;
1158 }
1159
1160 return true;
1161}
Here is the call graph for this function:

◆ nntp_msg_open()

bool nntp_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )
static

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

Definition at line 2661 of file nntp.c.

2662{
2663 struct NntpMboxData *mdata = m->mdata;
2664 char article[16] = { 0 };
2665
2666 /* try to get article from cache */
2667 struct NntpAcache *acache = &mdata->acache[e->index % NNTP_ACACHE_LEN];
2668 if (acache->path)
2669 {
2670 if (acache->index == e->index)
2671 {
2672 msg->fp = mutt_file_fopen(acache->path, "r");
2673 if (msg->fp)
2674 return true;
2675 }
2676 else
2677 {
2678 /* clear previous entry */
2679 unlink(acache->path);
2680 FREE(&acache->path);
2681 }
2682 }
2683 snprintf(article, sizeof(article), ANUM_FMT, nntp_edata_get(e)->article_num);
2684 msg->fp = mutt_bcache_get(mdata->bcache, article);
2685 if (msg->fp)
2686 {
2687 if (nntp_edata_get(e)->parsed)
2688 return true;
2689 }
2690 else
2691 {
2692 /* don't try to fetch article from removed newsgroup */
2693 if (mdata->deleted)
2694 return false;
2695
2696 /* create new cache file */
2697 const char *fetch_msg = _("Fetching message...");
2698 mutt_message("%s", fetch_msg);
2699 msg->fp = mutt_bcache_put(mdata->bcache, article);
2700 if (!msg->fp)
2701 {
2702 struct Buffer *tempfile = buf_pool_get();
2703 buf_mktemp(tempfile);
2704 acache->path = buf_strdup(tempfile);
2705 buf_pool_release(&tempfile);
2706 acache->index = e->index;
2707 msg->fp = mutt_file_fopen(acache->path, "w+");
2708 if (!msg->fp)
2709 {
2710 mutt_perror("%s", acache->path);
2711 unlink(acache->path);
2712 FREE(&acache->path);
2713 return false;
2714 }
2715 }
2716
2717 /* fetch message to cache file */
2718 char buf[2048] = { 0 };
2719 snprintf(buf, sizeof(buf), "ARTICLE %s\r\n",
2720 nntp_edata_get(e)->article_num ? article : e->env->message_id);
2721 const int rc = nntp_fetch_lines(mdata, buf, sizeof(buf), NULL, fetch_tempfile, msg->fp);
2722 if (rc)
2723 {
2724 mutt_file_fclose(&msg->fp);
2725 if (acache->path)
2726 {
2727 unlink(acache->path);
2728 FREE(&acache->path);
2729 }
2730 if (rc > 0)
2731 {
2732 if (mutt_str_startswith(buf, nntp_edata_get(e)->article_num ? "423" : "430"))
2733 {
2734 mutt_error(_("Article %s not found on the server"),
2735 nntp_edata_get(e)->article_num ? article : e->env->message_id);
2736 }
2737 else
2738 {
2739 mutt_error("ARTICLE: %s", buf);
2740 }
2741 }
2742 return false;
2743 }
2744
2745 if (!acache->path)
2746 mutt_bcache_commit(mdata->bcache, article);
2747 }
2748
2749 /* replace envelope with new one
2750 * hash elements must be updated because pointers will be changed */
2751 if (m->id_hash && e->env->message_id)
2753 if (m->subj_hash && e->env->real_subj)
2755
2756 mutt_env_free(&e->env);
2757 e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
2758
2759 if (m->id_hash && e->env->message_id)
2761 if (m->subj_hash && e->env->real_subj)
2763
2764 /* fix content length */
2765 if (!mutt_file_seek(msg->fp, 0, SEEK_END))
2766 {
2767 return false;
2768 }
2769 e->body->length = ftell(msg->fp) - e->body->offset;
2770
2771 /* this is called in neomutt before the open which fetches the message,
2772 * which is probably wrong, but we just call it again here to handle
2773 * the problem instead of fixing it */
2774 nntp_edata_get(e)->parsed = true;
2775 mutt_parse_mime_message(e, msg->fp);
2776
2777 /* these would normally be updated in mview_update(), but the
2778 * full headers aren't parsed with overview, so the information wasn't
2779 * available then */
2780 if (WithCrypto)
2781 e->security = crypt_query(e->body);
2782
2783 fseek(msg->fp, 0, SEEK_SET);
2784 clearerr(msg->fp);
2786 return true;
2787}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition commands.c:629
int mutt_bcache_commit(struct BodyCache *bcache, const char *id)
Move a temporary file into the Body Cache.
Definition bcache.c:270
FILE * mutt_bcache_get(struct BodyCache *bcache, const char *id)
Open a file in the Body Cache.
Definition bcache.c:201
FILE * mutt_bcache_put(struct BodyCache *bcache, const char *id)
Create a file in the Body Cache.
Definition bcache.c:228
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:577
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition crypt.c:693
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition envelope.c:125
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:648
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:338
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition hash.c:430
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition string.c:234
#define WithCrypto
Definition lib.h:132
struct NntpEmailData * nntp_edata_get(struct Email *e)
Get the private data for this Email.
Definition edata.c:60
#define NNTP_ACACHE_LEN
Definition lib.h:85
#define ANUM_FMT
Definition lib.h:64
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:817
static int fetch_tempfile(char *line, void *data)
Write line to temporary file.
Definition nntp.c:1012
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition email.h:43
int index
The absolute (unsorted) message number.
Definition email.h:110
char * message_id
Message ID.
Definition envelope.h:73
char *const real_subj
Offset of the real subject.
Definition envelope.h:71
void * mdata
Driver specific data.
Definition mailbox.h:134
struct HashTable * subj_hash
Hash Table: "Subject" -> Email.
Definition mailbox.h:126
struct HashTable * id_hash
Hash Table: "Message-ID" -> Email.
Definition mailbox.h:125
NNTP article cache.
Definition lib.h:70
char * path
Cache path.
Definition lib.h:72
unsigned int index
Index number.
Definition lib.h:71
bool parsed
Email has been parse.
Definition edata.h:37
NNTP-specific Mailbox data -.
Definition mdata.h:34
bool deleted
Newsgroup is deleted.
Definition mdata.h:45
struct BodyCache * bcache
Body cache.
Definition mdata.h:50
struct NntpAcache acache[NNTP_ACACHE_LEN]
Article cache.
Definition mdata.h:49
Here is the call graph for this function:

◆ nm_msg_open()

bool nm_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )
static

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

Definition at line 2385 of file notmuch.c.

2386{
2387 char path[PATH_MAX] = { 0 };
2388 char *folder = nm_email_get_folder(e);
2389 if (!folder)
2390 return false;
2391
2392 snprintf(path, sizeof(path), "%s/%s", folder, e->path);
2393
2394 msg->fp = mutt_file_fopen(path, "r");
2395 if (!msg->fp && (errno == ENOENT) && ((m->type == MUTT_MAILDIR) || (m->type == MUTT_NOTMUCH)))
2396 {
2397 msg->fp = maildir_open_find_message(folder, e->path, NULL);
2398 }
2399
2400 return msg->fp != NULL;
2401}
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:50
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition mailbox.h:47
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition notmuch.c:1505
enum MailboxType type
Mailbox type.
Definition mailbox.h:104
Here is the call graph for this function:

◆ pop_msg_open()

bool pop_msg_open ( struct Mailbox * m,
struct Message * msg,
struct Email * e )
static

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

Definition at line 999 of file pop.c.

1000{
1001 char buf[1024] = { 0 };
1002 struct PopAccountData *adata = pop_adata_get(m);
1003 struct PopEmailData *edata = pop_edata_get(e);
1004 bool bcache = true;
1005 bool success = false;
1006 struct Buffer *path = NULL;
1007
1008 /* see if we already have the message in body cache */
1009 msg->fp = mutt_bcache_get(adata->bcache, cache_id(edata->uid));
1010 if (msg->fp)
1011 return true;
1012
1013 /* see if we already have the message in our cache in
1014 * case $message_cache_dir is unset */
1015 struct PopCache *cache = &adata->cache[e->index % POP_CACHE_LEN];
1016
1017 if (cache->path)
1018 {
1019 if (cache->index == e->index)
1020 {
1021 /* yes, so just return a pointer to the message */
1022 msg->fp = mutt_file_fopen(cache->path, "r");
1023 if (msg->fp)
1024 return true;
1025
1026 mutt_perror("%s", cache->path);
1027 return false;
1028 }
1029 else
1030 {
1031 /* clear the previous entry */
1032 unlink(cache->path);
1033 FREE(&cache->path);
1034 }
1035 }
1036
1037 path = buf_pool_get();
1038
1039 while (true)
1040 {
1041 if (pop_reconnect(m) < 0)
1042 goto cleanup;
1043
1044 /* verify that massage index is correct */
1045 if (edata->refno < 0)
1046 {
1047 mutt_error(_("The message index is incorrect. Try reopening the mailbox."));
1048 goto cleanup;
1049 }
1050
1051 /* see if we can put in body cache; use our cache as fallback */
1052 msg->fp = mutt_bcache_put(adata->bcache, cache_id(edata->uid));
1053 if (!msg->fp)
1054 {
1055 /* no */
1056 bcache = false;
1058 msg->fp = mutt_file_fopen(buf_string(path), "w+");
1059 if (!msg->fp)
1060 {
1061 mutt_perror("%s", buf_string(path));
1062 goto cleanup;
1063 }
1064 }
1065
1066 snprintf(buf, sizeof(buf), "RETR %d\r\n", edata->refno);
1067
1068 struct Progress *progress = progress_new(MUTT_PROGRESS_NET,
1069 e->body->length + e->body->offset - 1);
1070 progress_set_message(progress, _("Fetching message..."));
1071 const int rc = pop_fetch_data(adata, buf, progress, fetch_message, msg->fp);
1072 progress_free(&progress);
1073
1074 if (rc == 0)
1075 break;
1076
1077 mutt_file_fclose(&msg->fp);
1078
1079 /* if RETR failed (e.g. connection closed), be sure to remove either
1080 * the file in bcache or from POP's own cache since the next iteration
1081 * of the loop will re-attempt to put() the message */
1082 if (!bcache)
1083 unlink(buf_string(path));
1084
1085 if (rc == -2)
1086 {
1087 mutt_error("%s", adata->err_msg);
1088 goto cleanup;
1089 }
1090
1091 if (rc == -3)
1092 {
1093 mutt_error(_("Can't write message to temporary file"));
1094 goto cleanup;
1095 }
1096 }
1097
1098 /* Update the header information. Previously, we only downloaded a
1099 * portion of the headers, those required for the main display. */
1100 if (bcache)
1101 {
1102 mutt_bcache_commit(adata->bcache, cache_id(edata->uid));
1103 }
1104 else
1105 {
1106 cache->index = e->index;
1107 cache->path = buf_strdup(path);
1108 }
1109 fseek(msg->fp, 0, SEEK_SET);
1110 clearerr(msg->fp);
1111
1112 /* Detach the private data */
1113 e->edata = NULL;
1114
1115 /* we replace envelope, key in subj_hash has to be updated as well */
1116 if (m->subj_hash && e->env->real_subj)
1119 mutt_env_free(&e->env);
1120 e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
1121 if (m->subj_hash && e->env->real_subj)
1123 mutt_label_hash_add(m, e);
1124
1125 /* Reattach the private data */
1126 e->edata = edata;
1128
1129 e->lines = 0;
1130 while (fgets(buf, sizeof(buf), msg->fp) && !feof(msg->fp))
1131 {
1132 e->lines++;
1133 }
1134
1135 e->body->length = ftello(msg->fp) - e->body->offset;
1136
1137 /* This needs to be done in case this is a multipart message */
1138 if (!WithCrypto)
1139 e->security = crypt_query(e->body);
1140
1142 fseek(msg->fp, 0, SEEK_SET);
1143 clearerr(msg->fp);
1144
1145 success = true;
1146
1147cleanup:
1148 buf_pool_release(&path);
1149 return success;
1150}
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message's labels from the Hash Table.
Definition header.c:431
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message's labels to the Hash Table.
Definition header.c:418
void pop_edata_free(void **ptr)
Free the private Email data - Implements Email::edata_free() -.
Definition edata.c:41
static int fetch_message(const char *line, void *data)
Parse a Message response - Implements pop_fetch_t -.
Definition pop.c:102
struct PopAccountData * pop_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition adata.c:73
struct PopEmailData * pop_edata_get(struct Email *e)
Get the private data for this Email.
Definition edata.c:68
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:512
int pop_reconnect(struct Mailbox *m)
Reconnect and verify indexes if connection was lost.
Definition lib.c:610
#define POP_CACHE_LEN
Number of entries in the POP cache hash table.
Definition private.h:38
static const char * cache_id(const char *id)
Make a message-cache-compatible id.
Definition pop.c:85
@ MUTT_PROGRESS_NET
Progress tracks bytes, according to $net_inc.
Definition lib.h:83
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
void * edata
Driver-specific data.
Definition email.h:74
void(* edata_free)(void **ptr)
Definition email.h:90
POP-specific Account data -.
Definition adata.h:37
char err_msg[POP_CMD_RESPONSE]
Last error message.
Definition adata.h:57
struct PopCache cache[POP_CACHE_LEN]
Message cache.
Definition adata.h:58
struct BodyCache * bcache
body cache
Definition adata.h:56
POP-specific email cache.
Definition private.h:67
unsigned int index
Message index.
Definition private.h:68
char * path
Filesystem path.
Definition private.h:69
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: