NeoMutt  2024-02-01-23-g345d7b
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 <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 57 of file mutt_mailbox.c.

59{
60 if (!m1 || buf_is_empty(&m1->pathbuf) || !m2 || buf_is_empty(&m2->pathbuf) ||
61 (m1->type != m2->type))
62 {
63 return false;
64 }
65
66 const bool uses_protocol = (m2->type == MUTT_IMAP) || (m2->type == MUTT_NNTP) ||
67 (m2->type == MUTT_NOTMUCH) || (m2->type == MUTT_POP);
68
69 if (uses_protocol)
71 else
72 return ((st1->st_dev == st2->st_dev) && (st1->st_ino == st2->st_ino));
73}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:211
@ 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:709
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_FORCE

Definition at line 82 of file mutt_mailbox.c.

84{
85 struct stat st = { 0 };
86
87 enum MailboxType mb_type = mx_path_probe(mailbox_path(m_check));
88
89 const bool c_mail_check_recent = cs_subset_bool(NeoMutt->sub, "mail_check_recent");
90 if ((m_cur == m_check) && c_mail_check_recent)
91 m_check->has_new = false;
92
93 switch (mb_type)
94 {
95 case MUTT_POP:
96 case MUTT_NNTP:
97 case MUTT_NOTMUCH:
98 case MUTT_IMAP:
99 m_check->type = mb_type;
100 break;
101 default:
102 if ((stat(mailbox_path(m_check), &st) != 0) ||
103 ((m_check->type == MUTT_UNKNOWN) && S_ISREG(st.st_mode) && (st.st_size == 0)) ||
104 ((m_check->type == MUTT_UNKNOWN) &&
105 ((m_check->type = mx_path_probe(mailbox_path(m_check))) <= 0)))
106 {
107 /* if the mailbox still doesn't exist, set the newly created flag to be
108 * ready for when it does. */
109 m_check->newly_created = true;
110 m_check->type = MUTT_UNKNOWN;
111 m_check->size = 0;
112 return;
113 }
114 break; // kept for consistency.
115 }
116
117 const bool c_check_mbox_size = cs_subset_bool(NeoMutt->sub, "check_mbox_size");
118
119 /* check to see if the folder is the currently selected folder before polling */
120 if (!is_same_mailbox(m_cur, m_check, st_cur, &st))
121 {
122 switch (m_check->type)
123 {
124 case MUTT_NOTMUCH:
125 // Remove this when non-notmuch backends only check unread, flagged,
126 // and total counts per 'mbox_check_stats' docs.
127 if ((flags & MUTT_MAILBOX_CHECK_FORCE_STATS) == 0)
128 break;
130
131 case MUTT_IMAP:
132 case MUTT_MBOX:
133 case MUTT_MMDF:
134 case MUTT_MAILDIR:
135 case MUTT_MH:
136 mx_mbox_check_stats(m_check, flags);
137 break;
138 default:; /* do nothing */
139 }
140 }
141 else if (c_check_mbox_size && m_cur && buf_is_empty(&m_cur->pathbuf))
142 {
143 m_check->size = (off_t) st.st_size; /* update the size of current folder */
144 }
145
146 if (!m_check->has_new)
147 {
148 m_check->notified = false;
149 }
150 else
151 {
152 // pretend that we've already notified for the mailbox
153 if (!m_check->notify_user)
154 m_check->notified = true;
155 else if (!m_check->notified)
157 }
158}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
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:111
static short MailboxNotify
Definition: mutt_mailbox.c:46
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.
Definition: mutt_mailbox.c:57
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:1757
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1319
#define MUTT_MAILBOX_CHECK_FORCE_STATS
Ignore MailboxType and calculate statistics.
Definition: mxapi.h:55
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:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ 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_FORCE
Return values
numNumber of mailboxes with new mail

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

Definition at line 168 of file mutt_mailbox.c.

169{
170 if (TAILQ_EMPTY(&NeoMutt->accounts)) // fast return if there are no mailboxes
171 return 0;
172
173 if (flags & MUTT_MAILBOX_CHECK_FORCE)
175
176 const short c_mail_check = cs_subset_number(NeoMutt->sub, "mail_check");
177 const bool c_mail_check_stats = cs_subset_bool(NeoMutt->sub, "mail_check_stats");
178 const short c_mail_check_stats_interval = cs_subset_number(NeoMutt->sub, "mail_check_stats_interval");
179
180 time_t t = mutt_date_now();
181 if ((flags == MUTT_MAILBOX_CHECK_NO_FLAGS) && ((t - MailboxTime) < c_mail_check))
182 return MailboxCount;
183
184 if ((flags & MUTT_MAILBOX_CHECK_FORCE_STATS) ||
185 (c_mail_check_stats && ((t - MailboxStatsTime) >= c_mail_check_stats_interval)))
186 {
189 }
190
191 MailboxTime = t;
192 MailboxCount = 0;
193 MailboxNotify = 0;
194
195 /* check device ID and serial number instead of comparing paths */
196 struct stat st_cur = { 0 };
197 if (!m_cur || (m_cur->type == MUTT_IMAP) || (m_cur->type == MUTT_POP) ||
198 (m_cur->type == MUTT_NNTP) || stat(mailbox_path(m_cur), &st_cur) != 0)
199 {
200 st_cur.st_dev = 0;
201 st_cur.st_ino = 0;
202 }
203
204 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
206 struct MailboxNode *np = NULL;
207 STAILQ_FOREACH(np, &ml, entries)
208 {
209 struct Mailbox *m = np->mailbox;
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 {
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 }
225
226 return MailboxCount;
227}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:144
@ 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
Definition: mutt_mailbox.c:44
static short MailboxCount
how many boxes with new mail
Definition: mutt_mailbox.c:45
static void mailbox_check(struct Mailbox *m_cur, struct Mailbox *m_check, struct stat *st_cur, CheckStatsFlags flags)
Check a mailbox for new mail.
Definition: mutt_mailbox.c:82
static time_t MailboxTime
last time we started checking for mail
Definition: mutt_mailbox.c:43
#define MUTT_MAILBOX_CHECK_NO_FLAGS
No flags are set.
Definition: mxapi.h:53
#define MUTT_MAILBOX_CHECK_FORCE
Ignore MailboxTime and check for new mail.
Definition: mxapi.h:54
uint8_t CheckStatsFlags
Flags for mutt_mailbox_check.
Definition: mxapi.h:52
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:163
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:186
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition: postpone.c:177
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define TAILQ_EMPTY(head)
Definition: queue.h:721
List of Mailboxes.
Definition: mailbox.h:154
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:155
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 AccountList accounts
List of all Accounts.
Definition: neomutt.h:46
+ 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.
Definition: mutt_mailbox.c:168
bool mutt_mailbox_list(void)
Show a message with the list of mailboxes with new mail.
Definition: mutt_mailbox.c:247
+ 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 char mailboxlist[512] = { 0 };
250 size_t pos = 0;
251 int first = 1;
252
253 int have_unnotified = MailboxNotify;
254
255 struct Buffer *path = buf_pool_get();
256
257 mailboxlist[0] = '\0';
258 pos += strlen(strncat(mailboxlist, _("New mail in "), sizeof(mailboxlist) - 1 - pos));
259 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
261 struct MailboxNode *np = NULL;
262 STAILQ_FOREACH(np, &ml, entries)
263 {
264 /* Is there new mail in this mailbox? */
265 if (!np->mailbox->has_new || (have_unnotified && np->mailbox->notified))
266 continue;
267
268 buf_strcpy(path, mailbox_path(np->mailbox));
269 buf_pretty_mailbox(path);
270
271 if (!first)
272 pos += strlen(strncat(mailboxlist + pos, ", ", sizeof(mailboxlist) - 1 - pos));
273
274 if (!np->mailbox->notified)
275 {
276 np->mailbox->notified = true;
278 }
279 pos += strlen(strncat(mailboxlist + pos, buf_string(path), sizeof(mailboxlist) - 1 - pos));
280 first = 0;
281 }
283
284 buf_pool_release(&path);
285
286 if (!first)
287 {
288 mutt_message("%s", mailboxlist);
289 return true;
290 }
291
292 /* there were no mailboxes needing to be notified, so clean up since
293 * MailboxNotify has somehow gotten out of sync */
294 MailboxNotify = 0;
295 return false;
296}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:412
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
#define mutt_message(...)
Definition: logging2.h:91
#define _(a)
Definition: message.h:28
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:557
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
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 302 of file mutt_mailbox.c.

303{
304 if (!m)
305 return;
306
307 m->notified = true;
309}
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 320 of file mutt_mailbox.c.

321{
322 bool found = false;
323 for (int pass = 0; pass < 2; pass++)
324 {
325 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
327 struct MailboxNode *np = NULL;
328 STAILQ_FOREACH(np, &ml, entries)
329 {
331 struct Mailbox *m_cur = np->mailbox;
332
333 if ((found || (pass > 0)) && (find_new ? m_cur->has_new : m_cur->msg_unread > 0))
334 {
337 struct Mailbox *m_result = np->mailbox;
339 return m_result;
340 }
342 found = true;
343 }
345 }
346
347 return NULL;
348}
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:331
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 359 of file mutt_mailbox.c.

360{
362
364 {
365 struct Mailbox *m_res = find_next_mailbox(s, true);
366 if (m_res)
367 return m_res;
368
369 mutt_mailbox_check(m_cur, MUTT_MAILBOX_CHECK_FORCE); /* mailbox was wrong - resync things */
370 }
371
372 buf_reset(s); // no folders with new mail
373 return NULL;
374}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:93
static struct Mailbox * find_next_mailbox(struct Buffer *s, bool find_new)
Find the next mailbox with new or unread mail.
Definition: mutt_mailbox.c:320
+ 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 385 of file mutt_mailbox.c.

386{
388
389 struct Mailbox *m_res = find_next_mailbox(s, false);
390 if (m_res)
391 return m_res;
392
393 buf_reset(s); // no folders with new mail
394 return NULL;
395}
+ 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 405 of file mutt_mailbox.c.

406{
407#ifdef HAVE_UTIMENSAT
408 struct timespec ts[2] = { { 0 }, { 0 } };
409#else
410 struct utimbuf ut = { 0 };
411#endif
412
413 const bool c_check_mbox_size = cs_subset_bool(NeoMutt->sub, "check_mbox_size");
414 if (c_check_mbox_size)
415 {
416 struct Mailbox *m = mailbox_find(path);
417 if (m && !m->has_new)
419 }
420 else
421 {
422 /* fix up the times so mailbox won't get confused */
423 if (st->st_mtime > st->st_atime)
424 {
425#ifdef HAVE_UTIMENSAT
426 ts[0].tv_sec = 0;
427 ts[0].tv_nsec = UTIME_OMIT;
428 ts[1].tv_sec = 0;
429 ts[1].tv_nsec = UTIME_NOW;
430 utimensat(AT_FDCWD, buf, ts, 0);
431#else
432 ut.actime = st->st_atime;
433 ut.modtime = mutt_date_now();
434 utime(path, &ut);
435#endif
436 }
437 else
438 {
439#ifdef HAVE_UTIMENSAT
440 ts[0].tv_sec = 0;
441 ts[0].tv_nsec = UTIME_NOW;
442 ts[1].tv_sec = 0;
443 ts[1].tv_nsec = UTIME_NOW;
444 utimensat(AT_FDCWD, buf, ts, 0);
445#else
446 utime(path, NULL);
447#endif
448 }
449 }
450}
void mailbox_update(struct Mailbox *m)
Get the mailbox's current size.
Definition: mailbox.c:208
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:143
Time value with nanosecond precision.
Definition: file.h:51
long tv_nsec
Number of nanosecond, on top.
Definition: file.h:53
time_t tv_sec
Number of seconds since the epoch.
Definition: file.h:52
+ 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 43 of file mutt_mailbox.c.

◆ MailboxStatsTime

time_t MailboxStatsTime = 0
static

last time we check performed mail_check_stats

Definition at line 44 of file mutt_mailbox.c.

◆ MailboxCount

short MailboxCount = 0
static

how many boxes with new mail

Definition at line 45 of file mutt_mailbox.c.

◆ MailboxNotify

short MailboxNotify = 0
static

of unnotified new boxes

Definition at line 46 of file mutt_mailbox.c.