add ExpireUnread option
This commit is contained in:
parent
f586c0bee5
commit
8d5bd62537
|
@ -233,6 +233,8 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
|
||||||
conf->use_internal_date = parse_bool( cfile );
|
conf->use_internal_date = parse_bool( cfile );
|
||||||
else if (!strcasecmp( "MaxMessages", cfile->cmd ))
|
else if (!strcasecmp( "MaxMessages", cfile->cmd ))
|
||||||
conf->max_messages = parse_int( cfile );
|
conf->max_messages = parse_int( cfile );
|
||||||
|
else if (!strcasecmp( "ExpireUnread", cfile->cmd ))
|
||||||
|
conf->expire_unread = parse_bool( cfile );
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -347,6 +349,7 @@ load_config( const char *where, int pseudo )
|
||||||
cfile.err = 0;
|
cfile.err = 0;
|
||||||
|
|
||||||
gcops = 0;
|
gcops = 0;
|
||||||
|
global_conf.expire_unread = -1;
|
||||||
reloop:
|
reloop:
|
||||||
while (getcline( &cfile )) {
|
while (getcline( &cfile )) {
|
||||||
if (!cfile.cmd)
|
if (!cfile.cmd)
|
||||||
|
@ -369,6 +372,7 @@ load_config( const char *where, int pseudo )
|
||||||
channel = nfcalloc( sizeof(*channel) );
|
channel = nfcalloc( sizeof(*channel) );
|
||||||
channel->name = nfstrdup( cfile.val );
|
channel->name = nfstrdup( cfile.val );
|
||||||
channel->max_messages = global_conf.max_messages;
|
channel->max_messages = global_conf.max_messages;
|
||||||
|
channel->expire_unread = global_conf.expire_unread;
|
||||||
channel->use_internal_date = global_conf.use_internal_date;
|
channel->use_internal_date = global_conf.use_internal_date;
|
||||||
cops = 0;
|
cops = 0;
|
||||||
max_size = -1;
|
max_size = -1;
|
||||||
|
|
|
@ -167,6 +167,7 @@ typedef struct channel_conf {
|
||||||
string_list_t *patterns;
|
string_list_t *patterns;
|
||||||
int ops[2];
|
int ops[2];
|
||||||
unsigned max_messages; /* for slave only */
|
unsigned max_messages; /* for slave only */
|
||||||
|
signed char expire_unread;
|
||||||
char use_internal_date;
|
char use_internal_date;
|
||||||
} channel_conf_t;
|
} channel_conf_t;
|
||||||
|
|
||||||
|
|
14
src/mbsync.1
14
src/mbsync.1
|
@ -400,12 +400,22 @@ This is useful for mailboxes where you keep a complete archive on the server,
|
||||||
but want to mirror only the last messages (for instance, for mailing lists).
|
but want to mirror only the last messages (for instance, for mailing lists).
|
||||||
The messages that were the first to arrive in the mailbox (independently of
|
The messages that were the first to arrive in the mailbox (independently of
|
||||||
the actual date of the message) will be deleted first.
|
the actual date of the message) will be deleted first.
|
||||||
Messages that are flagged (marked as important) and unread messages will not
|
Messages that are flagged (marked as important) and (by default) unread
|
||||||
be automatically deleted.
|
messages will not be automatically deleted.
|
||||||
If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR
|
If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR
|
||||||
(Default: \fI0\fR).
|
(Default: \fI0\fR).
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
|
\fBExpireUnread\fR \fIyes\fR|\fIno\fR
|
||||||
|
Selects whether unread messages should be affected by \fBMaxMessages\fR.
|
||||||
|
Normally, unread messages are considered important and thus never expired.
|
||||||
|
This ensures that you never miss new messages even after an extended absence.
|
||||||
|
However, if your archive contains large amounts of unread messages by design,
|
||||||
|
treating them as important would practically defeat \fBMaxMessages\fR. In this
|
||||||
|
case you need to enable this option.
|
||||||
|
(Default: \fIno\fR).
|
||||||
|
..
|
||||||
|
.TP
|
||||||
\fBSync\fR {\fINone\fR|[\fIPull\fR] [\fIPush\fR] [\fINew\fR] [\fIReNew\fR] [\fIDelete\fR] [\fIFlags\fR]|\fIAll\fR}
|
\fBSync\fR {\fINone\fR|[\fIPull\fR] [\fIPush\fR] [\fINew\fR] [\fIReNew\fR] [\fIDelete\fR] [\fIFlags\fR]|\fIAll\fR}
|
||||||
Select the synchronization operation(s) to perform:
|
Select the synchronization operation(s) to perform:
|
||||||
.br
|
.br
|
||||||
|
|
|
@ -191,6 +191,18 @@ my @X31 = (
|
||||||
);
|
);
|
||||||
test("max messages", \@x30, \@X31, @O31);
|
test("max messages", \@x30, \@X31, @O31);
|
||||||
|
|
||||||
|
my @O32 = ("", "", "MaxMessages 3\nExpireUnread yes\n");
|
||||||
|
#show("30", "32", "32");
|
||||||
|
my @X32 = (
|
||||||
|
[ 6,
|
||||||
|
1, 1, "F", 2, 2, "", 3, 3, "S", 4, 4, "", 5, 5, "S", 6, 6, "" ],
|
||||||
|
[ 4,
|
||||||
|
1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ],
|
||||||
|
[ 6, 1, 0,
|
||||||
|
1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ],
|
||||||
|
);
|
||||||
|
test("max messages vs. unread", \@x30, \@X32, @O32);
|
||||||
|
|
||||||
my @x50 = (
|
my @x50 = (
|
||||||
[ 6,
|
[ 6,
|
||||||
1, 1, "FS", 2, 2, "FS", 3, 3, "S", 4, 4, "", 5, 5, "", 6, 6, "" ],
|
1, 1, "FS", 2, 2, "FS", 3, 3, "S", 4, 4, "", 5, 5, "", 6, 6, "" ],
|
||||||
|
|
13
src/sync.c
13
src/sync.c
|
@ -1370,6 +1370,7 @@ box_loaded( int sts, void *aux )
|
||||||
}
|
}
|
||||||
todel = alive - svars->chan->max_messages;
|
todel = alive - svars->chan->max_messages;
|
||||||
debug( "%d alive messages, %d excess - expiring\n", alive, todel );
|
debug( "%d alive messages, %d excess - expiring\n", alive, todel );
|
||||||
|
alive = 0;
|
||||||
for (tmsg = svars->ctx[S]->msgs; tmsg; tmsg = tmsg->next) {
|
for (tmsg = svars->ctx[S]->msgs; tmsg; tmsg = tmsg->next) {
|
||||||
if (tmsg->status & M_DEAD)
|
if (tmsg->status & M_DEAD)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1381,7 +1382,7 @@ box_loaded( int sts, void *aux )
|
||||||
nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S];
|
nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S];
|
||||||
if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) {
|
if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) {
|
||||||
/* The message is not deleted, or is already (being) expired. */
|
/* The message is not deleted, or is already (being) expired. */
|
||||||
if ((nflags & F_FLAGGED) || !(nflags & F_SEEN)) {
|
if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
|
||||||
/* Important messages are always kept. */
|
/* Important messages are always kept. */
|
||||||
debug( " old pair(%d,%d) important\n", srec->uid[M], srec->uid[S] );
|
debug( " old pair(%d,%d) important\n", srec->uid[M], srec->uid[S] );
|
||||||
todel--;
|
todel--;
|
||||||
|
@ -1400,7 +1401,7 @@ box_loaded( int sts, void *aux )
|
||||||
if ((srec = tmsg->srec) && srec->tuid[0]) {
|
if ((srec = tmsg->srec) && srec->tuid[0]) {
|
||||||
nflags = tmsg->flags;
|
nflags = tmsg->flags;
|
||||||
if (!(nflags & F_DELETED)) {
|
if (!(nflags & F_DELETED)) {
|
||||||
if ((nflags & F_FLAGGED) || !(nflags & F_SEEN)) {
|
if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
|
||||||
/* Important messages are always fetched. */
|
/* Important messages are always fetched. */
|
||||||
debug( " new pair(%d,%d) important\n", srec->uid[M], srec->uid[S] );
|
debug( " new pair(%d,%d) important\n", srec->uid[M], srec->uid[S] );
|
||||||
todel--;
|
todel--;
|
||||||
|
@ -1415,6 +1416,14 @@ box_loaded( int sts, void *aux )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug( "%d excess messages remain\n", todel );
|
debug( "%d excess messages remain\n", todel );
|
||||||
|
if (svars->chan->expire_unread < 0 && (unsigned)alive * 2 > svars->chan->max_messages) {
|
||||||
|
error( "%s: %d unread messages in excess of MaxMessages (%d).\n"
|
||||||
|
"Please set ExpireUnread to decide outcome. Skipping mailbox.\n",
|
||||||
|
svars->ctx[S]->orig_name, alive, svars->chan->max_messages );
|
||||||
|
svars->ret |= SYNC_FAIL;
|
||||||
|
cancel_sync( svars );
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (srec = svars->srecs; srec; srec = srec->next) {
|
for (srec = svars->srecs; srec; srec = srec->next) {
|
||||||
if (srec->status & S_DEAD)
|
if (srec->status & S_DEAD)
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user