NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
mutt_mailbox.c File Reference
#include "config.h"
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <utime.h>
#include "mutt/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt_mailbox.h"
#include "mbox/lib.h"
#include "mutt_globals.h"
#include "mutt_menu.h"
#include "muttlib.h"
#include "mx.h"
#include "protos.h"
+ Include dependency graph for mutt_mailbox.c:

Go to the source code of this file.

Functions

static void mailbox_check (struct Mailbox *m_cur, struct Mailbox *m_check, struct stat *ctx_sb, bool check_stats)
 Check a mailbox for new mail. More...
 
int mutt_mailbox_check (struct Mailbox *m_cur, int force)
 Check all all Mailboxes for new mail. More...
 
bool mutt_mailbox_notify (struct Mailbox *m_cur)
 Notify the user if there's new mail. More...
 
bool mutt_mailbox_list (void)
 List the mailboxes with new mail. More...
 
void mutt_mailbox_set_notified (struct Mailbox *m)
 Note when the user was last notified of new mail. More...
 
struct Mailboxmutt_mailbox_next (struct Mailbox *m_cur, struct Buffer *s)
 incoming folders completion routine More...
 
void mutt_mailbox_cleanup (const char *path, struct stat *st)
 Restore the timestamp of a mailbox. More...
 

Variables

static time_t MailboxTime = 0
 last time we started checking for mail More...
 
static time_t MailboxStatsTime = 0
 last time we check performed mail_check_stats More...
 
static short MailboxCount = 0
 how many boxes with new mail More...
 
static short MailboxNotify = 0
 
short C_MailCheck
 Config: Number of seconds before NeoMutt checks for new mail. More...
 
bool C_MailCheckStats
 Config: Periodically check for new mail. More...
 
short C_MailCheckStatsInterval
 Config: How often to check for new mail. More...
 

Detailed Description

Mailbox helper functions

  • Richard Russon

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

◆ mailbox_check()

static void mailbox_check ( struct Mailbox m_cur,
struct Mailbox m_check,
struct stat *  ctx_sb,
bool  check_stats 
)
static

Check a mailbox for new mail.

Parameters
m_curCurrent Mailbox
m_checkMailbox to check
ctx_sbstat() info for the current Mailbox
check_statsIf true, also count the total, new and flagged messages

Definition at line 62 of file mutt_mailbox.c.

64 {
65  struct stat sb = { 0 };
66 
67  enum MailboxType mb_type = mx_path_probe(mailbox_path(m_check));
68 
69  if ((m_cur == m_check) && C_MailCheckRecent)
70  m_check->has_new = false;
71 
72  switch (mb_type)
73  {
74  case MUTT_POP:
75  case MUTT_NNTP:
76  case MUTT_NOTMUCH:
77  case MUTT_IMAP:
78  m_check->type = mb_type;
79  break;
80  default:
81  if ((stat(mailbox_path(m_check), &sb) != 0) ||
82  ((m_check->type == MUTT_UNKNOWN) && S_ISREG(sb.st_mode) && (sb.st_size == 0)) ||
83  ((m_check->type == MUTT_UNKNOWN) &&
84  ((m_check->type = mx_path_probe(mailbox_path(m_check))) <= 0)))
85  {
86  /* if the mailbox still doesn't exist, set the newly created flag to be
87  * ready for when it does. */
88  m_check->newly_created = true;
89  m_check->type = MUTT_UNKNOWN;
90  m_check->size = 0;
91  return;
92  }
93  break; // kept for consistency.
94  }
95 
96  /* check to see if the folder is the currently selected folder before polling */
97  if (!m_cur || mutt_buffer_is_empty(&m_cur->pathbuf) ||
98  (((m_check->type == MUTT_IMAP) || (m_check->type == MUTT_NNTP) ||
99  (m_check->type == MUTT_NOTMUCH) || (m_check->type == MUTT_POP)) ?
100  !mutt_str_equal(mailbox_path(m_check), mailbox_path(m_cur)) :
101  ((sb.st_dev != ctx_sb->st_dev) || (sb.st_ino != ctx_sb->st_ino))))
102  {
103  switch (m_check->type)
104  {
105  case MUTT_IMAP:
106  case MUTT_MBOX:
107  case MUTT_MMDF:
108  case MUTT_MAILDIR:
109  case MUTT_MH:
110  case MUTT_NOTMUCH:
111  if ((mx_mbox_check_stats(m_check, check_stats) != MX_STATUS_ERROR) &&
112  m_check->has_new)
113  {
114  MailboxCount++;
115  }
116  break;
117  default:; /* do nothing */
118  }
119  }
120  else if (C_CheckMboxSize && m_cur && mutt_buffer_is_empty(&m_cur->pathbuf))
121  m_check->size = (off_t) sb.st_size; /* update the size of current folder */
122 
123  if (!m_check->has_new)
124  m_check->notified = false;
125  else if (!m_check->notified)
126  MailboxNotify++;
127 }
+ 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,
int  force 
)

Check all all Mailboxes for new mail.

Parameters
m_curCurrent Mailbox
forceForce flags, see below
Return values
numNumber of mailboxes with new mail

The force argument may be any combination of the following values:

  • MUTT_MAILBOX_CHECK_FORCE ignore MailboxTime and check for new mail
  • MUTT_MAILBOX_CHECK_FORCE_STATS ignore MailboxTime and calculate statistics

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

Definition at line 141 of file mutt_mailbox.c.

142 {
143  struct stat contex_sb;
144  time_t t;
145  bool check_stats = false;
146  contex_sb.st_dev = 0;
147  contex_sb.st_ino = 0;
148 
149 #ifdef USE_IMAP
150  /* update postponed count as well, on force */
151  if (force & MUTT_MAILBOX_CHECK_FORCE)
153 #endif
154 
155  /* fastest return if there are no mailboxes */
157  return 0;
158 
159  t = mutt_date_epoch();
160  if (!force && (t - MailboxTime < C_MailCheck))
161  return MailboxCount;
162 
163  if ((force & MUTT_MAILBOX_CHECK_FORCE_STATS) ||
165  {
166  check_stats = true;
167  MailboxStatsTime = t;
168  }
169 
170  MailboxTime = t;
171  MailboxCount = 0;
172  MailboxNotify = 0;
173 
174  /* check device ID and serial number instead of comparing paths */
175  if (!m_cur || (m_cur->type == MUTT_IMAP) || (m_cur->type == MUTT_POP)
176 #ifdef USE_NNTP
177  || (m_cur->type == MUTT_NNTP)
178 #endif
179  || stat(mailbox_path(m_cur), &contex_sb) != 0)
180  {
181  contex_sb.st_dev = 0;
182  contex_sb.st_ino = 0;
183  }
184 
185  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
187  struct MailboxNode *np = NULL;
188  STAILQ_FOREACH(np, &ml, entries)
189  {
190  if (np->mailbox->flags & MB_HIDDEN)
191  continue;
192 
193  mailbox_check(m_cur, np->mailbox, &contex_sb,
194  check_stats || (!np->mailbox->first_check_stats_done && C_MailCheckStats));
195  np->mailbox->first_check_stats_done = true;
196  }
198 
199  return MailboxCount;
200 }
+ 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
trueIf there is new mail

Definition at line 207 of file mutt_mailbox.c.

208 {
209  if ((mutt_mailbox_check(m_cur, 0) > 0) && MailboxNotify)
210  {
211  return mutt_mailbox_list();
212  }
213  return false;
214 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_list()

bool mutt_mailbox_list ( void  )

List the mailboxes with new mail.

Return values
trueIf there is new mail

Definition at line 220 of file mutt_mailbox.c.

221 {
222  char mailboxlist[512];
223  size_t pos = 0;
224  int first = 1;
225 
226  int have_unnotified = MailboxNotify;
227 
228  struct Buffer *path = mutt_buffer_pool_get();
229 
230  mailboxlist[0] = '\0';
231  pos += strlen(strncat(mailboxlist, _("New mail in "), sizeof(mailboxlist) - 1 - pos));
232  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
234  struct MailboxNode *np = NULL;
235  STAILQ_FOREACH(np, &ml, entries)
236  {
237  /* Is there new mail in this mailbox? */
238  if (!np->mailbox->has_new || (have_unnotified && np->mailbox->notified))
239  continue;
240 
243 
244  if (!first && (MessageWindow->state.cols >= 7) &&
245  ((pos + mutt_buffer_len(path)) >= ((size_t) MessageWindow->state.cols - 7)))
246  {
247  break;
248  }
249 
250  if (!first)
251  pos += strlen(strncat(mailboxlist + pos, ", ", sizeof(mailboxlist) - 1 - pos));
252 
253  /* Prepend an asterisk to mailboxes not already notified */
254  if (!np->mailbox->notified)
255  {
256  /* pos += strlen (strncat(mailboxlist + pos, "*", sizeof(mailboxlist)-1-pos)); */
257  np->mailbox->notified = true;
258  MailboxNotify--;
259  }
260  pos += strlen(strncat(mailboxlist + pos, mutt_buffer_string(path),
261  sizeof(mailboxlist) - 1 - pos));
262  first = 0;
263  }
265 
266  if (!first && np)
267  {
268  strncat(mailboxlist + pos, ", ...", sizeof(mailboxlist) - 1 - pos);
269  }
270 
272 
273  if (!first)
274  {
275  mutt_message("%s", mailboxlist);
276  return true;
277  }
278 
279  /* there were no mailboxes needing to be notified, so clean up since
280  * MailboxNotify has somehow gotten out of sync */
281  MailboxNotify = 0;
282  return false;
283 }
+ 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 289 of file mutt_mailbox.c.

290 {
291  if (!m)
292  return;
293 
294  m->notified = true;
295 #ifdef HAVE_CLOCK_GETTIME
296  clock_gettime(CLOCK_REALTIME, &m->last_visited);
297 #else
299  m->last_visited.tv_nsec = 0;
300 #endif
301 }
+ 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 312 of file mutt_mailbox.c.

313 {
315 
316  if (mutt_mailbox_check(m_cur, 0) > 0)
317  {
318  bool found = false;
319  for (int pass = 0; pass < 2; pass++)
320  {
321  struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
323  struct MailboxNode *np = NULL;
324  STAILQ_FOREACH(np, &ml, entries)
325  {
326  if (np->mailbox->type == MUTT_NOTMUCH) /* only match real mailboxes */
327  continue;
329  if ((found || (pass > 0)) && np->mailbox->has_new)
330  {
333  struct Mailbox *m_result = np->mailbox;
335  return m_result;
336  }
338  found = true;
339  }
341  }
342 
343  mutt_mailbox_check(m_cur, MUTT_MAILBOX_CHECK_FORCE); /* mailbox was wrong - resync things */
344  }
345 
346  mutt_buffer_reset(s); // no folders with new mail
347  return NULL;
348 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_mailbox_cleanup()

void mutt_mailbox_cleanup ( 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 358 of file mutt_mailbox.c.

359 {
360 #ifdef HAVE_UTIMENSAT
361  struct timespec ts[2];
362 #else
363  struct utimbuf ut;
364 #endif
365 
366  if (C_CheckMboxSize)
367  {
368  struct Mailbox *m = mailbox_find(path);
369  if (m && !m->has_new)
370  mailbox_update(m);
371  }
372  else
373  {
374  /* fix up the times so mailbox won't get confused */
375  if (st->st_mtime > st->st_atime)
376  {
377 #ifdef HAVE_UTIMENSAT
378  ts[0].tv_sec = 0;
379  ts[0].tv_nsec = UTIME_OMIT;
380  ts[1].tv_sec = 0;
381  ts[1].tv_nsec = UTIME_NOW;
382  utimensat(AT_FDCWD, buf, ts, 0);
383 #else
384  ut.actime = st->st_atime;
385  ut.modtime = mutt_date_epoch();
386  utime(path, &ut);
387 #endif
388  }
389  else
390  {
391 #ifdef HAVE_UTIMENSAT
392  ts[0].tv_sec = 0;
393  ts[0].tv_nsec = UTIME_NOW;
394  ts[1].tv_sec = 0;
395  ts[1].tv_nsec = UTIME_NOW;
396  utimensat(AT_FDCWD, buf, ts, 0);
397 #else
398  utime(path, NULL);
399 #endif
400  }
401  }
402 }
+ 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 45 of file mutt_mailbox.c.

◆ MailboxStatsTime

time_t MailboxStatsTime = 0
static

last time we check performed mail_check_stats

Definition at line 46 of file mutt_mailbox.c.

◆ MailboxCount

short MailboxCount = 0
static

how many boxes with new mail

Definition at line 47 of file mutt_mailbox.c.

◆ MailboxNotify

short MailboxNotify = 0
static

of unnotified new boxes

Definition at line 48 of file mutt_mailbox.c.

◆ C_MailCheck

short C_MailCheck

Config: Number of seconds before NeoMutt checks for new mail.

Definition at line 51 of file mutt_mailbox.c.

◆ C_MailCheckStats

bool C_MailCheckStats

Config: Periodically check for new mail.

Definition at line 52 of file mutt_mailbox.c.

◆ C_MailCheckStatsInterval

short C_MailCheckStatsInterval

Config: How often to check for new mail.

Definition at line 53 of file mutt_mailbox.c.

MUTT_MMDF
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:49
MailboxNode
List of Mailboxes.
Definition: mailbox.h:152
NeoMutt::accounts
struct AccountList accounts
List of all Accounts.
Definition: neomutt.h:40
MessageWindow
struct MuttWindow * MessageWindow
Message Window, ":set", etc.
Definition: mutt_window.c:47
_
#define _(a)
Definition: message.h:28
Mailbox
A mailbox.
Definition: mailbox.h:81
mutt_mailbox_list
bool mutt_mailbox_list(void)
List the mailboxes with new mail.
Definition: mutt_mailbox.c:220
Buffer
String manipulation buffer.
Definition: buffer.h:33
mx_mbox_check_stats
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:1798
mutt_buffer_pretty_mailbox
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:599
mutt_buffer_is_empty
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
MUTT_POP
@ MUTT_POP
'POP3' Mailbox type
Definition: mailbox.h:55
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:714
neomutt_mailboxlist_get_all
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:160
Mailbox::notified
bool notified
User has been notified.
Definition: mailbox.h:104
Mailbox::flags
uint8_t flags
e.g. MB_NORMAL
Definition: mailbox.h:134
Mailbox::size
off_t size
Size of the Mailbox.
Definition: mailbox.h:87
Mailbox::has_new
bool has_new
Mailbox has new mail.
Definition: mailbox.h:88
MailboxStatsTime
static time_t MailboxStatsTime
last time we check performed mail_check_stats
Definition: mutt_mailbox.c:46
C_CheckMboxSize
bool C_CheckMboxSize
Config: (mbox,mmdf) Use mailbox size as an indicator of new mail.
Definition: config.c:36
MailboxNode::mailbox
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
mutt_buffer_reset
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
mx_path_probe
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1335
mailbox_check
static void mailbox_check(struct Mailbox *m_cur, struct Mailbox *m_check, struct stat *ctx_sb, bool check_stats)
Check a mailbox for new mail.
Definition: mutt_mailbox.c:62
STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
Mailbox::first_check_stats_done
bool first_check_stats_done
True when the check have been done at least on time.
Definition: mailbox.h:116
timespec::tv_nsec
long tv_nsec
Definition: file.h:52
mutt_str_equal
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
MB_HIDDEN
#define MB_HIDDEN
Definition: mailbox.h:38
MailboxCount
static short MailboxCount
how many boxes with new mail
Definition: mutt_mailbox.c:47
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
MUTT_NNTP
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
Definition: mailbox.h:52
timespec::tv_sec
time_t tv_sec
Definition: file.h:51
Mailbox::type
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
C_MailCheckStatsInterval
short C_MailCheckStatsInterval
Config: How often to check for new mail.
Definition: mutt_mailbox.c:53
mutt_mailbox_check
int mutt_mailbox_check(struct Mailbox *m_cur, int force)
Check all all Mailboxes for new mail.
Definition: mutt_mailbox.c:141
MUTT_MAILBOX_ANY
@ MUTT_MAILBOX_ANY
Match any Mailbox type.
Definition: mailbox.h:45
MUTT_UNKNOWN
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:47
Mailbox::newly_created
bool newly_created
Mbox or mmdf just popped into existence.
Definition: mailbox.h:106
MUTT_NOTMUCH
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:54
MUTT_IMAP
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:53
MUTT_MH
@ MUTT_MH
'MH' Mailbox type
Definition: mailbox.h:50
mutt_update_num_postponed
void mutt_update_num_postponed(void)
Force the update of the number of postponed messages.
Definition: postpone.c:203
mailbox_update
void mailbox_update(struct Mailbox *m)
Get the mailbox's current size.
Definition: mailbox.c:168
MailboxNotify
static short MailboxNotify
Definition: mutt_mailbox.c:48
mutt_buffer_expand_path
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
MX_STATUS_ERROR
@ MX_STATUS_ERROR
An error occurred.
Definition: mx.h:73
mutt_buffer_string
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
mutt_date_epoch
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:416
MuttWindow::state
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
STAILQ_HEAD_INITIALIZER
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:321
MailboxTime
static time_t MailboxTime
last time we started checking for mail
Definition: mutt_mailbox.c:45
C_MailCheck
short C_MailCheck
Config: Number of seconds before NeoMutt checks for new mail.
Definition: mutt_mailbox.c:51
C_MailCheckRecent
WHERE bool C_MailCheckRecent
Config: Notify the user about new mail since the last time the mailbox was opened.
Definition: mutt_globals.h:150
MUTT_MAILBOX_CHECK_FORCE
#define MUTT_MAILBOX_CHECK_FORCE
Definition: mutt_mailbox.h:16
Mailbox::last_visited
struct timespec last_visited
Time of last exit from this mailbox.
Definition: mailbox.h:108
NeoMutt
Container for Accounts, Notifications.
Definition: neomutt.h:36
mutt_buffer_len
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
MailboxType
MailboxType
Supported mailbox formats.
Definition: mailbox.h:43
MUTT_MAILDIR
@ MUTT_MAILDIR
'Maildir' Mailbox type
Definition: mailbox.h:51
WindowState::cols
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
mailbox_path
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:206
timespec
Time value with nanosecond precision.
Definition: file.h:49
mutt_message
#define mutt_message(...)
Definition: logging.h:83
C_MailCheckStats
bool C_MailCheckStats
Config: Periodically check for new mail.
Definition: mutt_mailbox.c:52
MUTT_MAILBOX_CHECK_FORCE_STATS
#define MUTT_MAILBOX_CHECK_FORCE_STATS
Definition: mutt_mailbox.h:17
MUTT_MBOX
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:48
mutt_buffer_strcpy
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
neomutt_mailboxlist_clear
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:137
Mailbox::pathbuf
struct Buffer pathbuf
Definition: mailbox.h:83
mailbox_find
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:103