NeoMutt  2025-09-05-70-gcfdde0
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mutt_mailbox.c File Reference

Mailbox helper functions. More...

#include "config.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <utime.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "mutt_mailbox.h"
#include "postpone/lib.h"
#include "muttlib.h"
#include "mx.h"
+ Include dependency graph for mutt_mailbox.c:

Go to the source code of this file.

Functions

static bool is_same_mailbox (struct Mailbox *m1, struct Mailbox *m2, struct stat *st1, struct stat *st2)
 Compare two Mailboxes to see if they're equal.
 
static void mailbox_check (struct Mailbox *m_cur, struct Mailbox *m_check, struct stat *st_cur, CheckStatsFlags flags)
 Check a mailbox for new mail.
 
int mutt_mailbox_check (struct Mailbox *m_cur, CheckStatsFlags flags)
 Check all all Mailboxes for new mail.
 
bool mutt_mailbox_notify (struct Mailbox *m_cur)
 Notify the user if there's new mail.
 
bool mutt_mailbox_list (void)
 Show a message with the list of mailboxes with new mail.
 
void mutt_mailbox_set_notified (struct Mailbox *m)
 Note when the user was last notified of new mail.
 
static struct Mailboxfind_next_mailbox (struct Buffer *s, bool find_new)
 Find the next mailbox with new or unread mail.
 
struct Mailboxmutt_mailbox_next (struct Mailbox *m_cur, struct Buffer *s)
 Incoming folders completion routine.
 
struct Mailboxmutt_mailbox_next_unread (struct Mailbox *m_cur, struct Buffer *s)
 Find next mailbox with unread mail.
 
void mailbox_restore_timestamp (const char *path, struct stat *st)
 Restore the timestamp of a mailbox.
 

Variables

static time_t MailboxTime = 0
 last time we started checking for mail
 
static time_t MailboxStatsTime = 0
 last time we check performed mail_check_stats
 
static short MailboxCount = 0
 how many boxes with new mail
 
static short MailboxNotify = 0
 

Detailed Description

Mailbox helper functions.

Authors
  • Pietro Cerutti
  • Richard Russon
  • Austin Ray

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file mutt_mailbox.c.

Function Documentation

◆ is_same_mailbox()

static bool is_same_mailbox ( struct Mailbox * m1,
struct Mailbox * m2,
struct stat * st1,
struct stat * st2 )
static

Compare two Mailboxes to see if they're equal.

Parameters
m1First mailbox
m2Second mailbox
st1stat() info for first mailbox
st2stat() info for second mailbox
Return values
trueMailboxes are the same
falseMailboxes are different

Definition at line 58 of file mutt_mailbox.c.

60{
61 if (!m1 || buf_is_empty(&m1->pathbuf) || !m2 || buf_is_empty(&m2->pathbuf) ||
62 (m1->type != m2->type))
63 {
64 return false;
65 }
66
67 const bool uses_protocol = (m2->type == MUTT_IMAP) || (m2->type == MUTT_NNTP) ||
68 (m2->type == MUTT_NOTMUCH) || (m2->type == MUTT_POP);
69
70 if (uses_protocol)
72 else
73 return ((st1->st_dev == st2->st_dev) && (st1->st_ino == st2->st_ino));
74}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition mailbox.h:214
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition mailbox.h:51
@ MUTT_POP
'POP3' Mailbox type
Definition mailbox.h:52
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition mailbox.h:49
@ MUTT_IMAP
'IMAP' Mailbox type
Definition mailbox.h:50
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
enum MailboxType type
Mailbox type.
Definition mailbox.h:102
struct Buffer pathbuf
Path of the Mailbox.
Definition mailbox.h:80
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mailbox_check()

static void mailbox_check ( struct Mailbox * m_cur,
struct Mailbox * m_check,
struct stat * st_cur,
CheckStatsFlags flags )
static

Check a mailbox for new mail.

Parameters
m_curCurrent Mailbox
m_checkMailbox to check
st_curstat() info for the current Mailbox
flagsFlags, e.g. MUTT_MAILBOX_CHECK_POSTPONED

Definition at line 83 of file mutt_mailbox.c.

85{
86 struct stat st = { 0 };
87
88 enum MailboxType mb_type = mx_path_probe(mailbox_path(m_check));
89
90 const bool c_mail_check_recent = cs_subset_bool(NeoMutt->sub, "mail_check_recent");
91 if ((m_cur == m_check) && c_mail_check_recent)
92 m_check->has_new = false;
93
94 switch (mb_type)
95 {
96 case MUTT_POP:
97 case MUTT_NNTP:
98 case MUTT_NOTMUCH:
99 case MUTT_IMAP:
100 m_check->type = mb_type;
101 break;
102 default:
103 if ((stat(mailbox_path(m_check), &st) != 0) ||
104 ((m_check->type == MUTT_UNKNOWN) && S_ISREG(st.st_mode) && (st.st_size == 0)) ||
105 ((m_check->type == MUTT_UNKNOWN) &&
106 ((m_check->type = mx_path_probe(mailbox_path(m_check))) <= 0)))
107 {
108 /* if the mailbox still doesn't exist, set the newly created flag to be
109 * ready for when it does. */
110 m_check->newly_created = true;
111 m_check->type = MUTT_UNKNOWN;
112 m_check->size = 0;
113 return;
114 }
115 break; // kept for consistency.
116 }
117
118 const bool c_check_mbox_size = cs_subset_bool(NeoMutt->sub, "check_mbox_size");
119
120 /* check to see if the folder is the currently selected folder before polling */
121 if (!is_same_mailbox(m_cur, m_check, st_cur, &st))
122 {
123 switch (m_check->type)
124 {
125 case MUTT_NOTMUCH:
126 // Remove this when non-notmuch backends only check unread, flagged,
127 // and total counts per 'mbox_check_stats' docs.
128 if ((flags & MUTT_MAILBOX_CHECK_STATS) == 0)
129 break;
131
132 case MUTT_IMAP:
133 case MUTT_MBOX:
134 case MUTT_MMDF:
135 case MUTT_MAILDIR:
136 case MUTT_MH:
137 mx_mbox_check_stats(m_check, flags);
138 break;
139 default:; /* do nothing */
140 }
141 }
142 else if (c_check_mbox_size && m_cur && buf_is_empty(&m_cur->pathbuf))
143 {
144 m_check->size = (off_t) st.st_size; /* update the size of current folder */
145 }
146
147 if (!m_check->has_new)
148 {
149 m_check->notified = false;
150 }
151 else
152 {
153 // pretend that we've already notified for the mailbox
154 if (!m_check->notify_user)
155 m_check->notified = true;
156 else if (!m_check->notified)
158 }
159}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
MailboxType
Supported mailbox formats.
Definition mailbox.h:41
@ MUTT_MMDF
'mmdf' Mailbox type
Definition mailbox.h:46
@ MUTT_MH
'MH' Mailbox type
Definition mailbox.h:47
@ MUTT_MBOX
'mbox' Mailbox type
Definition mailbox.h:45
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition mailbox.h:44
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition mailbox.h:48
#define FALLTHROUGH
Definition lib.h:113
static short MailboxNotify
static bool is_same_mailbox(struct Mailbox *m1, struct Mailbox *m2, struct stat *st1, struct stat *st2)
Compare two Mailboxes to see if they're equal.
enum MxStatus mx_mbox_check_stats(struct Mailbox *m, uint8_t flags)
Check the statistics for a mailbox - Wrapper for MxOps::mbox_check_stats()
Definition mx.c:1776
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition mx.c:1326
#define MUTT_MAILBOX_CHECK_STATS
Ignore mail_check_stats and calculate statistics (used by <check-stats>)
Definition mxapi.h:52
bool has_new
Mailbox has new mail.
Definition mailbox.h:85
bool newly_created
Mbox or mmdf just popped into existence.
Definition mailbox.h:103
bool notify_user
Notify the user of new mail.
Definition mailbox.h:113
bool notified
User has been notified.
Definition mailbox.h:101
off_t size
Size of the Mailbox.
Definition mailbox.h:84
Container for Accounts, Notifications.
Definition neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:46
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_check()

int mutt_mailbox_check ( struct Mailbox * m_cur,
CheckStatsFlags flags )

Check all all Mailboxes for new mail.

Parameters
m_curCurrent Mailbox
flagsFlags, e.g. MUTT_MAILBOX_CHECK_STATS
Return values
numNumber of mailboxes with new mail

Check all all Mailboxes for new mail and total/new/flagged messages

Definition at line 169 of file mutt_mailbox.c.

170{
171 if (ARRAY_EMPTY(&NeoMutt->accounts)) // fast return if there are no mailboxes
172 return 0;
173
176
177 const short c_mail_check = cs_subset_number(NeoMutt->sub, "mail_check");
178 const bool c_mail_check_stats = cs_subset_bool(NeoMutt->sub, "mail_check_stats");
179 const short c_mail_check_stats_interval = cs_subset_number(NeoMutt->sub, "mail_check_stats_interval");
180
181 time_t t = mutt_date_now();
182 if ((flags == MUTT_MAILBOX_CHECK_NO_FLAGS) && ((t - MailboxTime) < c_mail_check))
183 return MailboxCount;
184
185 if ((flags & MUTT_MAILBOX_CHECK_STATS) ||
186 (c_mail_check_stats && ((t - MailboxStatsTime) >= c_mail_check_stats_interval)))
187 {
190 }
191
192 MailboxTime = t;
193 MailboxCount = 0;
194 MailboxNotify = 0;
195
196 /* check device ID and serial number instead of comparing paths */
197 struct stat st_cur = { 0 };
198 if (!m_cur || (m_cur->type == MUTT_IMAP) || (m_cur->type == MUTT_POP) ||
199 (m_cur->type == MUTT_NNTP) || stat(mailbox_path(m_cur), &st_cur) != 0)
200 {
201 st_cur.st_dev = 0;
202 st_cur.st_ino = 0;
203 }
204
205 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_MAILBOX_ANY);
206 struct Mailbox **mp = NULL;
207 ARRAY_FOREACH(mp, &ma)
208 {
209 struct Mailbox *m = *mp;
210
211 if (!m->visible || !m->poll_new_mail)
212 continue;
213
214 CheckStatsFlags m_flags = flags;
215 if (!m->first_check_stats_done && c_mail_check_stats)
216 {
217 m_flags |= MUTT_MAILBOX_CHECK_STATS;
218 }
219 mailbox_check(m_cur, m, &st_cur, m_flags);
220 if (m->has_new)
221 MailboxCount++;
222 m->first_check_stats_done = true;
223 }
224 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
225
226 return MailboxCount;
227}
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition array.h:74
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:204
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
@ MUTT_MAILBOX_ANY
Match any Mailbox type.
Definition mailbox.h:42
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:455
static time_t MailboxStatsTime
last time we check performed mail_check_stats
static short MailboxCount
how many boxes with new mail
static void mailbox_check(struct Mailbox *m_cur, struct Mailbox *m_check, struct stat *st_cur, CheckStatsFlags flags)
Check a mailbox for new mail.
static time_t MailboxTime
last time we started checking for mail
#define MUTT_MAILBOX_CHECK_NO_FLAGS
No flags are set.
Definition mxapi.h:50
#define MUTT_MAILBOX_CHECK_POSTPONED
Make sure the number of postponed messages is updated.
Definition mxapi.h:51
uint8_t CheckStatsFlags
Flags for mutt_mailbox_check.
Definition mxapi.h:49
struct MailboxArray neomutt_mailboxes_get(struct NeoMutt *n, enum MailboxType type)
Get an Array of matching Mailboxes.
Definition neomutt.c:184
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition postpone.c:177
A mailbox.
Definition mailbox.h:79
bool first_check_stats_done
True when the check have been done at least one time.
Definition mailbox.h:112
bool poll_new_mail
Check for new mail.
Definition mailbox.h:115
bool visible
True if a result of "mailboxes".
Definition mailbox.h:130
struct AccountArray accounts
All Accounts.
Definition neomutt.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_notify()

bool mutt_mailbox_notify ( struct Mailbox * m_cur)

Notify the user if there's new mail.

Parameters
m_curCurrent Mailbox
Return values
trueThere is new mail

Definition at line 234 of file mutt_mailbox.c.

235{
237 {
238 return mutt_mailbox_list();
239 }
240 return false;
241}
int mutt_mailbox_check(struct Mailbox *m_cur, CheckStatsFlags flags)
Check all all Mailboxes for new mail.
bool mutt_mailbox_list(void)
Show a message with the list of mailboxes with new mail.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_list()

bool mutt_mailbox_list ( void )

Show a message with the list of mailboxes with new mail.

Return values
trueThere is new mail

Definition at line 247 of file mutt_mailbox.c.

248{
249 int have_unnotified = MailboxNotify;
250
251 struct Buffer *path = buf_pool_get();
252 struct Buffer *mailboxlist = buf_pool_get();
253
254 buf_addstr(mailboxlist, _("New mail in "));
255 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_MAILBOX_ANY);
256 struct Mailbox **mp = NULL;
257 bool any_new = false;
258 ARRAY_FOREACH(mp, &ma)
259 {
260 struct Mailbox *m = *mp;
261
262 /* Is there new mail in this mailbox? */
263 if (!m->has_new || (have_unnotified && m->notified))
264 continue;
265
266 buf_strcpy(path, mailbox_path(m));
267 buf_pretty_mailbox(path);
268
269 if (any_new)
270 {
271 buf_addstr(mailboxlist, ", ");
272 }
273
274 if (!m->notified)
275 {
276 m->notified = true;
278 }
279 buf_addstr(mailboxlist, buf_string(path));
280 any_new = true;
281 }
282 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
283
284 buf_pool_release(&path);
285
286 if (any_new)
287 {
288 mutt_message("%s", buf_string(mailboxlist));
289 buf_pool_release(&mailboxlist);
290 return true;
291 }
292
293 /* there were no mailboxes needing to be notified, so clean up since
294 * MailboxNotify has somehow gotten out of sync */
295 MailboxNotify = 0;
296 buf_pool_release(&mailboxlist);
297 return false;
298}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
#define mutt_message(...)
Definition logging2.h:92
#define _(a)
Definition message.h:28
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:518
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
String manipulation buffer.
Definition buffer.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_set_notified()

void mutt_mailbox_set_notified ( struct Mailbox * m)

Note when the user was last notified of new mail.

Parameters
mMailbox

Definition at line 304 of file mutt_mailbox.c.

305{
306 if (!m)
307 return;
308
309 m->notified = true;
311}
void mutt_time_now(struct timespec *tp)
Set the provided time field to the current time.
Definition date.c:479
struct timespec last_visited
Time of last exit from this mailbox.
Definition mailbox.h:104
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ find_next_mailbox()

static struct Mailbox * find_next_mailbox ( struct Buffer * s,
bool find_new )
static

Find the next mailbox with new or unread mail.

Parameters
sBuffer containing name of current mailbox
find_newBoolean controlling new or unread check
Return values
ptrMailbox

Given a folder name, find the next incoming folder with new or unread mail. The Mailbox will be returned and a pretty version of the path put into s.

Definition at line 322 of file mutt_mailbox.c.

323{
324 bool found = false;
325 for (int pass = 0; pass < 2; pass++)
326 {
327 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_MAILBOX_ANY);
328 struct Mailbox **mp = NULL;
329 ARRAY_FOREACH(mp, &ma)
330 {
331 struct Mailbox *m = *mp;
332
334 struct Mailbox *m_cur = m;
335
336 if ((found || (pass > 0)) && (find_new ? m_cur->has_new : m_cur->msg_unread > 0))
337 {
340 struct Mailbox *m_result = m;
341 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
342 return m_result;
343 }
345 found = true;
346 }
347 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
348 }
349
350 return NULL;
351}
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition muttlib.c:314
int msg_unread
Number of unread messages.
Definition mailbox.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_next()

struct Mailbox * mutt_mailbox_next ( struct Mailbox * m_cur,
struct Buffer * s )

Incoming folders completion routine.

Parameters
m_curCurrent Mailbox
sBuffer containing name of current mailbox
Return values
ptrMailbox

Given a folder name, find the next incoming folder with new mail. The Mailbox will be returned and a pretty version of the path put into s.

Definition at line 362 of file mutt_mailbox.c.

363{
365
367 {
368 struct Mailbox *m_res = find_next_mailbox(s, true);
369 if (m_res)
370 return m_res;
371
373 }
374
375 buf_reset(s); // no folders with new mail
376 return NULL;
377}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
static struct Mailbox * find_next_mailbox(struct Buffer *s, bool find_new)
Find the next mailbox with new or unread mail.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_next_unread()

struct Mailbox * mutt_mailbox_next_unread ( struct Mailbox * m_cur,
struct Buffer * s )

Find next mailbox with unread mail.

Parameters
m_curCurrent Mailbox
sBuffer containing name of current mailbox
Return values
ptrMailbox

Given a folder name, find the next mailbox with unread mail. The Mailbox will be returned and a pretty version of the path put into s.

Definition at line 388 of file mutt_mailbox.c.

389{
391
392 struct Mailbox *m_res = find_next_mailbox(s, false);
393 if (m_res)
394 return m_res;
395
396 buf_reset(s); // no folders with new mail
397 return NULL;
398}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mailbox_restore_timestamp()

void mailbox_restore_timestamp ( const char * path,
struct stat * st )

Restore the timestamp of a mailbox.

Parameters
pathPath to the mailbox
stTimestamp info from stat()

Fix up the atime and mtime after mbox/mmdf mailbox was modified according to stat() info taken before a modification.

Definition at line 408 of file mutt_mailbox.c.

409{
410#ifdef HAVE_UTIMENSAT
411 struct timespec ts[2] = { { 0 }, { 0 } };
412#else
413 struct utimbuf ut = { 0 };
414#endif
415
416 const bool c_check_mbox_size = cs_subset_bool(NeoMutt->sub, "check_mbox_size");
417 if (c_check_mbox_size)
418 {
419 struct Mailbox *m = mailbox_find(path);
420 if (m && !m->has_new)
422 }
423 else
424 {
425 /* fix up the times so mailbox won't get confused */
426 if (st->st_mtime > st->st_atime)
427 {
428#ifdef HAVE_UTIMENSAT
429 ts[0].tv_sec = 0;
430 ts[0].tv_nsec = UTIME_OMIT;
431 ts[1].tv_sec = 0;
432 ts[1].tv_nsec = UTIME_NOW;
433 utimensat(AT_FDCWD, buf, ts, 0);
434#else
435 ut.actime = st->st_atime;
436 ut.modtime = mutt_date_now();
437 utime(path, &ut);
438#endif
439 }
440 else
441 {
442#ifdef HAVE_UTIMENSAT
443 ts[0].tv_sec = 0;
444 ts[0].tv_nsec = UTIME_NOW;
445 ts[1].tv_sec = 0;
446 ts[1].tv_nsec = UTIME_NOW;
447 utimensat(AT_FDCWD, buf, ts, 0);
448#else
449 utime(path, NULL);
450#endif
451 }
452 }
453}
void mailbox_update(struct Mailbox *m)
Get the mailbox's current size.
Definition mailbox.c:213
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition mailbox.c:150
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ MailboxTime

time_t MailboxTime = 0
static

last time we started checking for mail

Definition at line 44 of file mutt_mailbox.c.

◆ MailboxStatsTime

time_t MailboxStatsTime = 0
static

last time we check performed mail_check_stats

Definition at line 45 of file mutt_mailbox.c.

◆ MailboxCount

short MailboxCount = 0
static

how many boxes with new mail

Definition at line 46 of file mutt_mailbox.c.

◆ MailboxNotify

short MailboxNotify = 0
static

of unnotified new boxes

Definition at line 47 of file mutt_mailbox.c.