NeoMutt  2024-12-12-14-g7b49f7
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()

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

726{
727 if (!m->compress_info)
728 return false;
729
730 struct CompressInfo *ci = m->compress_info;
731
732 const struct MxOps *ops = ci->child_ops;
733 if (!ops)
734 return false;
735
736 /* Delegate */
737 return ops->msg_open(m, msg, e);
738}
Private data for compress.
Definition: lib.h:60
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:65
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:121
Definition: mxapi.h:91
bool(* msg_open)(struct Mailbox *m, struct Message *msg, struct Email *e)
Definition: mxapi.h:216

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

1978{
1979 struct Envelope *newenv = NULL;
1980 char buf[1024] = { 0 };
1981 char *pc = NULL;
1982 unsigned int bytes;
1983 unsigned int uid;
1984 bool retried = false;
1985 bool read;
1986 int rc;
1987
1988 /* Sam's weird courier server returns an OK response even when FETCH
1989 * fails. Thanks Sam. */
1990 bool fetched = false;
1991
1993
1994 if (!adata || (adata->mailbox != m))
1995 return false;
1996
1997 msg->fp = msg_cache_get(m, e);
1998 if (msg->fp)
1999 {
2000 if (imap_edata_get(e)->parsed)
2001 return true;
2002 goto parsemsg;
2003 }
2004
2005 /* This function is called in a few places after endwin()
2006 * e.g. mutt_pipe_message(). */
2007 bool output_progress = !isendwin() && m->verbose;
2008 if (output_progress)
2009 mutt_message(_("Fetching message..."));
2010
2011 msg->fp = msg_cache_put(m, e);
2012 if (!msg->fp)
2013 {
2014 struct Buffer *tempfile = buf_pool_get();
2015 buf_mktemp(tempfile);
2016 msg->fp = mutt_file_fopen(buf_string(tempfile), "w+");
2017 unlink(buf_string(tempfile));
2018 buf_pool_release(&tempfile);
2019
2020 if (!msg->fp)
2021 return false;
2022 }
2023
2024 /* mark this header as currently inactive so the command handler won't
2025 * also try to update it. HACK until all this code can be moved into the
2026 * command handler */
2027 e->active = false;
2028
2029 const bool c_imap_peek = cs_subset_bool(NeoMutt->sub, "imap_peek");
2030 snprintf(buf, sizeof(buf), "UID FETCH %u %s", imap_edata_get(e)->uid,
2031 ((adata->capabilities & IMAP_CAP_IMAP4REV1) ?
2032 (c_imap_peek ? "BODY.PEEK[]" : "BODY[]") :
2033 "RFC822"));
2034
2035 imap_cmd_start(adata, buf);
2036 do
2037 {
2038 rc = imap_cmd_step(adata);
2039 if (rc != IMAP_RES_CONTINUE)
2040 break;
2041
2042 pc = adata->buf;
2043 pc = imap_next_word(pc);
2044 pc = imap_next_word(pc);
2045
2046 if (mutt_istr_startswith(pc, "FETCH"))
2047 {
2048 while (*pc)
2049 {
2050 pc = imap_next_word(pc);
2051 if (pc[0] == '(')
2052 pc++;
2053 if (mutt_istr_startswith(pc, "UID"))
2054 {
2055 pc = imap_next_word(pc);
2056 if (!mutt_str_atoui(pc, &uid))
2057 goto bail;
2058 if (uid != imap_edata_get(e)->uid)
2059 {
2060 mutt_error(_("The message index is incorrect. Try reopening the mailbox."));
2061 }
2062 }
2063 else if (mutt_istr_startswith(pc, "RFC822") || mutt_istr_startswith(pc, "BODY[]"))
2064 {
2065 pc = imap_next_word(pc);
2066 if (imap_get_literal_count(pc, &bytes) < 0)
2067 {
2068 imap_error("imap_msg_open()", buf);
2069 goto bail;
2070 }
2071
2072 const int res = imap_read_literal(msg->fp, adata, bytes, NULL);
2073 if (res < 0)
2074 {
2075 goto bail;
2076 }
2077 /* pick up trailing line */
2078 rc = imap_cmd_step(adata);
2079 if (rc != IMAP_RES_CONTINUE)
2080 goto bail;
2081 pc = adata->buf;
2082
2083 fetched = true;
2084 }
2085 else if (!e->changed && mutt_istr_startswith(pc, "FLAGS"))
2086 {
2087 /* UW-IMAP will provide a FLAGS update here if the FETCH causes a
2088 * change (eg from \Unseen to \Seen).
2089 * Uncommitted changes in neomutt take precedence. If we decide to
2090 * incrementally update flags later, this won't stop us syncing */
2091 pc = imap_set_flags(m, e, pc, NULL);
2092 if (!pc)
2093 goto bail;
2094 }
2095 }
2096 }
2097 } while (rc == IMAP_RES_CONTINUE);
2098
2099 /* see comment before command start. */
2100 e->active = true;
2101
2102 fflush(msg->fp);
2103 if (ferror(msg->fp))
2104 goto bail;
2105
2106 if (rc != IMAP_RES_OK)
2107 goto bail;
2108
2109 if (!fetched || !imap_code(adata->buf))
2110 goto bail;
2111
2112 if (msg_cache_commit(m, e) < 0)
2113 mutt_debug(LL_DEBUG1, "failed to add message to cache\n");
2114
2115parsemsg:
2116 /* Update the header information. Previously, we only downloaded a
2117 * portion of the headers, those required for the main display. */
2118 rewind(msg->fp);
2119 /* It may be that the Status header indicates a message is read, but the
2120 * IMAP server doesn't know the message has been \Seen. So we capture
2121 * the server's notion of 'read' and if it differs from the message info
2122 * picked up in mutt_rfc822_read_header, we mark the message (and context
2123 * changed). Another possibility: ignore Status on IMAP? */
2124 read = e->read;
2125 newenv = mutt_rfc822_read_header(msg->fp, e, false, false);
2126 mutt_env_merge(e->env, &newenv);
2127
2128 /* see above. We want the new status in e->read, so we unset it manually
2129 * and let mutt_set_flag set it correctly, updating context. */
2130 if (read != e->read)
2131 {
2132 e->read = read;
2133 mutt_set_flag(m, e, MUTT_NEW, read, true);
2134 }
2135
2136 e->lines = 0;
2137 while (fgets(buf, sizeof(buf), msg->fp) && !feof(msg->fp))
2138 {
2139 e->lines++;
2140 }
2141
2142 e->body->length = ftell(msg->fp) - e->body->offset;
2143
2145 rewind(msg->fp);
2146 imap_edata_get(e)->parsed = true;
2147
2148 /* retry message parse if cached message is empty */
2149 if (!retried && ((e->lines == 0) || (e->body->length == 0)))
2150 {
2151 imap_cache_del(m, e);
2152 retried = true;
2153 goto parsemsg;
2154 }
2155
2156 return true;
2157
2158bail:
2159 e->active = true;
2160 mutt_file_fclose(&msg->fp);
2161 imap_cache_del(m, e);
2162 return false;
2163}
const char * mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: atoi.c:218
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:1205
void mutt_env_merge(struct Envelope *base, struct Envelope **extra)
Merge the headers of two Envelopes.
Definition: envelope.c:193
#define mutt_file_fclose(FP)
Definition: file.h:138
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:137
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:57
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:123
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1114
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1128
bool imap_code(const char *s)
Was the command successful.
Definition: command.c:1255
struct ImapEmailData * imap_edata_get(struct Email *e)
Get the private data for this Email.
Definition: edata.c:67
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:1920
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:1869
static int msg_cache_commit(struct Mailbox *m, struct Email *e)
Add to the message cache.
Definition: message.c:150
int imap_get_literal_count(const char *buf, unsigned int *bytes)
Write number of bytes in an IMAP literal into bytes.
Definition: util.c:780
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:55
#define IMAP_CAP_IMAP4REV1
Server supports IMAP4rev1.
Definition: private.h:122
void imap_error(const char *where, const char *msg)
Show an error and abort.
Definition: util.c:660
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:56
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:824
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:589
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
#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:242
@ MUTT_NEW
New messages.
Definition: mutt.h:70
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:96
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:55
char * buf
Definition: adata.h:59
bool parsed
Definition: edata.h:43
bool verbose
Display status messages?
Definition: mailbox.h:117
FILE * fp
pointer to the message data
Definition: message.h:35
Container for Accounts, Notifications.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:46
#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 504 of file message.c.

505{
506 char path[PATH_MAX] = { 0 };
507
508 snprintf(path, sizeof(path), "%s/%s", mailbox_path(m), e->path);
509
510 msg->fp = mutt_file_fopen(path, "r");
511 if (!msg->fp && (errno == ENOENT))
512 msg->fp = maildir_open_find_message(mailbox_path(m), e->path, NULL);
513
514 if (!msg->fp)
515 {
516 mutt_perror("%s", path);
517 return false;
518 }
519
520 return true;
521}
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:223
#define mutt_perror(...)
Definition: logging2.h:93
FILE * maildir_open_find_message(const char *folder, const char *msg, char **newname)
Find a message by name.
Definition: message.c:169
#define PATH_MAX
Definition: mutt.h:42
char * path
Path of Email (for local Mailboxes)
Definition: email.h:70
+ Here is the call graph for this function:

◆ mbox_msg_open()

static 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 1473 of file mbox.c.

1474{
1476 if (!adata)
1477 return false;
1478
1479 msg->fp = mutt_file_fopen(mailbox_path(m), "r");
1480 if (!msg->fp)
1481 return false;
1482
1483 return true;
1484}
static struct MboxAccountData * mbox_adata_get(struct Mailbox *m)
Get the private data associated with a Mailbox.
Definition: mbox.c:124
Mbox-specific Account data -.
Definition: lib.h:49
+ Here is the call graph for this function:

◆ mh_msg_open()

static 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 1143 of file mh.c.

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

◆ nntp_msg_open()

static 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 2646 of file nntp.c.

2647{
2648 struct NntpMboxData *mdata = m->mdata;
2649 char article[16] = { 0 };
2650
2651 /* try to get article from cache */
2652 struct NntpAcache *acache = &mdata->acache[e->index % NNTP_ACACHE_LEN];
2653 if (acache->path)
2654 {
2655 if (acache->index == e->index)
2656 {
2657 msg->fp = mutt_file_fopen(acache->path, "r");
2658 if (msg->fp)
2659 return true;
2660 }
2661 else
2662 {
2663 /* clear previous entry */
2664 unlink(acache->path);
2665 FREE(&acache->path);
2666 }
2667 }
2668 snprintf(article, sizeof(article), ANUM_FMT, nntp_edata_get(e)->article_num);
2669 msg->fp = mutt_bcache_get(mdata->bcache, article);
2670 if (msg->fp)
2671 {
2672 if (nntp_edata_get(e)->parsed)
2673 return true;
2674 }
2675 else
2676 {
2677 /* don't try to fetch article from removed newsgroup */
2678 if (mdata->deleted)
2679 return false;
2680
2681 /* create new cache file */
2682 const char *fetch_msg = _("Fetching message...");
2683 mutt_message("%s", fetch_msg);
2684 msg->fp = mutt_bcache_put(mdata->bcache, article);
2685 if (!msg->fp)
2686 {
2687 struct Buffer *tempfile = buf_pool_get();
2688 buf_mktemp(tempfile);
2689 acache->path = buf_strdup(tempfile);
2690 buf_pool_release(&tempfile);
2691 acache->index = e->index;
2692 msg->fp = mutt_file_fopen(acache->path, "w+");
2693 if (!msg->fp)
2694 {
2695 mutt_perror("%s", acache->path);
2696 unlink(acache->path);
2697 FREE(&acache->path);
2698 return false;
2699 }
2700 }
2701
2702 /* fetch message to cache file */
2703 char buf[2048] = { 0 };
2704 snprintf(buf, sizeof(buf), "ARTICLE %s\r\n",
2705 nntp_edata_get(e)->article_num ? article : e->env->message_id);
2706 const int rc = nntp_fetch_lines(mdata, buf, sizeof(buf), NULL, fetch_tempfile, msg->fp);
2707 if (rc)
2708 {
2709 mutt_file_fclose(&msg->fp);
2710 if (acache->path)
2711 {
2712 unlink(acache->path);
2713 FREE(&acache->path);
2714 }
2715 if (rc > 0)
2716 {
2717 if (mutt_str_startswith(buf, nntp_edata_get(e)->article_num ? "423" : "430"))
2718 {
2719 mutt_error(_("Article %s not found on the server"),
2720 nntp_edata_get(e)->article_num ? article : e->env->message_id);
2721 }
2722 else
2723 {
2724 mutt_error("ARTICLE: %s", buf);
2725 }
2726 }
2727 return false;
2728 }
2729
2730 if (!acache->path)
2731 mutt_bcache_commit(mdata->bcache, article);
2732 }
2733
2734 /* replace envelope with new one
2735 * hash elements must be updated because pointers will be changed */
2736 if (m->id_hash && e->env->message_id)
2738 if (m->subj_hash && e->env->real_subj)
2740
2741 mutt_env_free(&e->env);
2742 e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
2743
2744 if (m->id_hash && e->env->message_id)
2746 if (m->subj_hash && e->env->real_subj)
2748
2749 /* fix content length */
2750 if (!mutt_file_seek(msg->fp, 0, SEEK_END))
2751 {
2752 return false;
2753 }
2754 e->body->length = ftell(msg->fp) - e->body->offset;
2755
2756 /* this is called in neomutt before the open which fetches the message,
2757 * which is probably wrong, but we just call it again here to handle
2758 * the problem instead of fixing it */
2759 nntp_edata_get(e)->parsed = true;
2760 mutt_parse_mime_message(e, msg->fp);
2761
2762 /* these would normally be updated in mview_update(), but the
2763 * full headers aren't parsed with overview, so the information wasn't
2764 * available then */
2765 if (WithCrypto)
2766 e->security = crypt_query(e->body);
2767
2768 rewind(msg->fp);
2770 return true;
2771}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:596
int mutt_bcache_commit(struct BodyCache *bcache, const char *id)
Move a temporary file into the Body Cache.
Definition: bcache.c:252
FILE * mutt_bcache_get(struct BodyCache *bcache, const char *id)
Open a file in the Body Cache.
Definition: bcache.c:185
FILE * mutt_bcache_put(struct BodyCache *bcache, const char *id)
Create a file in the Body Cache.
Definition: bcache.c:212
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:571
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:687
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:126
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:778
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:55
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:230
#define WithCrypto
Definition: lib.h:122
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:84
#define ANUM_FMT
Definition: lib.h:63
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:814
static int fetch_tempfile(char *line, void *data)
Write line to temporary file.
Definition: nntp.c:1009
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:132
struct HashTable * subj_hash
Hash Table: "subject" -> Email.
Definition: mailbox.h:124
struct HashTable * id_hash
Hash Table: "message-id" -> Email.
Definition: mailbox.h:123
NNTP article cache.
Definition: lib.h:69
char * path
Cache path.
Definition: lib.h:71
unsigned int index
Index number.
Definition: lib.h:70
bool parsed
Email has been parse.
Definition: edata.h:37
NNTP-specific Mailbox data -.
Definition: mdata.h:34
bool deleted
Definition: mdata.h:45
struct BodyCache * bcache
Definition: mdata.h:50
struct NntpAcache acache[NNTP_ACACHE_LEN]
Definition: mdata.h:49
+ Here is the call graph for this function:

◆ nm_msg_open()

static 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 2366 of file notmuch.c.

2367{
2368 char path[PATH_MAX] = { 0 };
2369 char *folder = nm_email_get_folder(e);
2370
2371 snprintf(path, sizeof(path), "%s/%s", folder, e->path);
2372
2373 msg->fp = mutt_file_fopen(path, "r");
2374 if (!msg->fp && (errno == ENOENT) && ((m->type == MUTT_MAILDIR) || (m->type == MUTT_NOTMUCH)))
2375 {
2376 msg->fp = maildir_open_find_message(folder, e->path, NULL);
2377 }
2378
2379 return msg->fp != NULL;
2380}
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:48
char * nm_email_get_folder(struct Email *e)
Get the folder for a Email.
Definition: notmuch.c:1469
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,
struct Email e 
)
static

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

Definition at line 975 of file pop.c.

976{
977 char buf[1024] = { 0 };
979 struct PopEmailData *edata = pop_edata_get(e);
980 bool bcache = true;
981 bool success = false;
982 struct Buffer *path = NULL;
983
984 /* see if we already have the message in body cache */
985 msg->fp = mutt_bcache_get(adata->bcache, cache_id(edata->uid));
986 if (msg->fp)
987 return true;
988
989 /* see if we already have the message in our cache in
990 * case $message_cache_dir is unset */
991 struct PopCache *cache = &adata->cache[e->index % POP_CACHE_LEN];
992
993 if (cache->path)
994 {
995 if (cache->index == e->index)
996 {
997 /* yes, so just return a pointer to the message */
998 msg->fp = mutt_file_fopen(cache->path, "r");
999 if (msg->fp)
1000 return true;
1001
1002 mutt_perror("%s", cache->path);
1003 return false;
1004 }
1005 else
1006 {
1007 /* clear the previous entry */
1008 unlink(cache->path);
1009 FREE(&cache->path);
1010 }
1011 }
1012
1013 path = buf_pool_get();
1014
1015 while (true)
1016 {
1017 if (pop_reconnect(m) < 0)
1018 goto cleanup;
1019
1020 /* verify that massage index is correct */
1021 if (edata->refno < 0)
1022 {
1023 mutt_error(_("The message index is incorrect. Try reopening the mailbox."));
1024 goto cleanup;
1025 }
1026
1027 /* see if we can put in body cache; use our cache as fallback */
1028 msg->fp = mutt_bcache_put(adata->bcache, cache_id(edata->uid));
1029 if (!msg->fp)
1030 {
1031 /* no */
1032 bcache = false;
1034 msg->fp = mutt_file_fopen(buf_string(path), "w+");
1035 if (!msg->fp)
1036 {
1037 mutt_perror("%s", buf_string(path));
1038 goto cleanup;
1039 }
1040 }
1041
1042 snprintf(buf, sizeof(buf), "RETR %d\r\n", edata->refno);
1043
1044 struct Progress *progress = progress_new(MUTT_PROGRESS_NET,
1045 e->body->length + e->body->offset - 1);
1046 progress_set_message(progress, _("Fetching message..."));
1047 const int rc = pop_fetch_data(adata, buf, progress, fetch_message, msg->fp);
1048 progress_free(&progress);
1049
1050 if (rc == 0)
1051 break;
1052
1053 mutt_file_fclose(&msg->fp);
1054
1055 /* if RETR failed (e.g. connection closed), be sure to remove either
1056 * the file in bcache or from POP's own cache since the next iteration
1057 * of the loop will re-attempt to put() the message */
1058 if (!bcache)
1059 unlink(buf_string(path));
1060
1061 if (rc == -2)
1062 {
1063 mutt_error("%s", adata->err_msg);
1064 goto cleanup;
1065 }
1066
1067 if (rc == -3)
1068 {
1069 mutt_error(_("Can't write message to temporary file"));
1070 goto cleanup;
1071 }
1072 }
1073
1074 /* Update the header information. Previously, we only downloaded a
1075 * portion of the headers, those required for the main display. */
1076 if (bcache)
1077 {
1078 mutt_bcache_commit(adata->bcache, cache_id(edata->uid));
1079 }
1080 else
1081 {
1082 cache->index = e->index;
1083 cache->path = buf_strdup(path);
1084 }
1085 rewind(msg->fp);
1086
1087 /* Detach the private data */
1088 e->edata = NULL;
1089
1090 /* we replace envelope, key in subj_hash has to be updated as well */
1091 if (m->subj_hash && e->env->real_subj)
1094 mutt_env_free(&e->env);
1095 e->env = mutt_rfc822_read_header(msg->fp, e, false, false);
1096 if (m->subj_hash && e->env->real_subj)
1098 mutt_label_hash_add(m, e);
1099
1100 /* Reattach the private data */
1101 e->edata = edata;
1103
1104 e->lines = 0;
1105 while (fgets(buf, sizeof(buf), msg->fp) && !feof(msg->fp))
1106 {
1107 e->lines++;
1108 }
1109
1110 e->body->length = ftello(msg->fp) - e->body->offset;
1111
1112 /* This needs to be done in case this is a multipart message */
1113 if (!WithCrypto)
1114 e->security = crypt_query(e->body);
1115
1117 rewind(msg->fp);
1118
1119 success = true;
1120
1121cleanup:
1122 buf_pool_release(&path);
1123 return success;
1124}
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:98
void mutt_label_hash_remove(struct Mailbox *m, struct Email *e)
Remove a message's labels from the Hash Table.
Definition: mutt_header.c:430
void mutt_label_hash_add(struct Mailbox *m, struct Email *e)
Add a message's labels to the Hash Table.
Definition: mutt_header.c:417
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:510
int pop_reconnect(struct Mailbox *m)
Reconnect and verify indexes if connection was lost.
Definition: lib.c:608
#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:81
@ MUTT_PROGRESS_NET
Progress tracks bytes, according to $net_inc
Definition: lib.h:82
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]
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: