Package: fetchmail
Version: 6.2.5-12
Severity: wishlist
Tags: patch

Hello!

I have POP3 account shared between M$OE and fetchmail.
While the former has an option for e.g. removing
messages which are older than specified maximum age
from server, the latter (i.e. fetchmail) lacks any
comparable capability.

While adding support for message ageing IMO would
require changes to .fetchids file format, cleaning
mailbox by another principle, like "remove all except
first N messages" is easy to implement.

So what I propose is to add an option which limits max
number of messages kept on server.

I thus attach a patch which adds "maxkeep" option to
fetchmail.

I think it's also a good idea to have an ability to
limit account usage not only by # of msgs, but by their
size sum too (e.g. 5MBytes max). This remains to be
implemented, though -- I didn't find an easy way to add
a support for this.

-- 
WBR,
xrgtn

P.S. actually I had "Version: 6.2.5-13" in BTS
pseudo-header, because I have already packaged and
installed the version of fetchmail with my patch
applied.

-- System Information:
Debian Release: 3.1
  APT prefers testing
  APT policy: (501, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i586)
Kernel: Linux 2.4.29-grsec
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)

Versions of packages fetchmail depends on:
ii  adduser                     3.63         Add and remove users and groups
ii  base-files                  3.1.2        Debian base system miscellaneous f
ii  debconf                     1.4.30.13    Debian configuration management sy
ii  debianutils                 2.8.4        Miscellaneous utilities specific t
ii  libc6                       2.3.2.ds1-21 GNU C Library: Shared libraries an
ii  libssl0.9.7                 0.9.7e-3     SSL shared libraries

-- debconf information:
* fetchmail/confwarn:
* fetchmail/systemwide: false
  fetchmail/initdefaultswarn:
  fetchmail/runasroot: false
  fetchmail/fetchidswarn:
diff -rup fetchmail-6.2.5/conf.c fetchmail-6.2.5.maxkeep/conf.c
--- fetchmail-6.2.5/conf.c      2003-10-15 22:22:31.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/conf.c      2005-05-01 01:51:41.000000000 +0300
@@ -350,6 +350,7 @@ void dump_config(struct runctl *runp, st
 
        booldump("fetchall", ctl->fetchall);
        booldump("keep", ctl->keep);
+       numdump("maxkeep", ctl->maxkeep);
        booldump("flush", ctl->flush);
        booldump("rewrite", ctl->rewrite);
        booldump("stripcr", ctl->stripcr); 
diff -rup fetchmail-6.2.5/driver.c fetchmail-6.2.5.maxkeep/driver.c
--- fetchmail-6.2.5/driver.c    2005-05-01 03:57:26.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/driver.c    2005-05-01 03:57:00.000000000 +0300
@@ -767,7 +767,9 @@ flagthemail:
                 && !suppress_delete
                 && ((msgcode >= 0 && !ctl->keep)
                     || (msgcode == MSGLEN_OLD||
-                        msgcode == MSGLEN_TOOLARGE) && ctl->flush))
+                        msgcode == MSGLEN_TOOLARGE) && ctl->flush)
+                    || msgcode == MSGLEN_OLD && ctl->maxkeep > 0
+                        && num + ctl->maxkeep <= count)
        {
            (*deletions)++;
            if (outlevel > O_SILENT) 
diff -rup fetchmail-6.2.5/etrn.c fetchmail-6.2.5.maxkeep/etrn.c
--- fetchmail-6.2.5/etrn.c      2003-10-15 22:17:36.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/etrn.c      2005-05-01 02:30:00.000000000 +0300
@@ -155,6 +155,10 @@ int doETRN (struct query *ctl)
        fprintf(stderr, GT_("Option --keep is not supported with ETRN\n"));
        return(PS_SYNTAX);
     }
+    if (ctl->maxkeep) {
+       fprintf(stderr, GT_("Option --maxkeep is not supported with ETRN\n"));
+       return(PS_SYNTAX);
+    }
     if (ctl->flush) {
        fprintf(stderr, GT_("Option --flush is not supported with ETRN\n"));
        return(PS_SYNTAX);
diff -rup fetchmail-6.2.5/fetchmail.c fetchmail-6.2.5.maxkeep/fetchmail.c
--- fetchmail-6.2.5/fetchmail.c 2005-05-01 03:57:26.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/fetchmail.c 2005-05-01 02:04:04.000000000 +0300
@@ -863,6 +863,7 @@ static void optmerge(struct query *h2, s
     FLAG_MERGE(postconnect);
 
     FLAG_MERGE(keep);
+    FLAG_MERGE(maxkeep);
     FLAG_MERGE(flush);
     FLAG_MERGE(fetchall);
     FLAG_MERGE(rewrite);
@@ -1595,6 +1596,11 @@ static void dump_params (struct runctl *
            printf(GT_("  Fetched messages %s be kept on the server (--keep 
%s).\n"),
                   ctl->keep ? GT_("will") : GT_("will not"),
                   ctl->keep ? "on" : "off");
+           if (NUM_NONZERO(ctl->maxkeep))
+               printf(GT_("  Max number of old msgs to keep is %d (--maxkeep 
%d).\n"),
+                      ctl->maxkeep, ctl->maxkeep);
+           else if (outlevel >= O_VERBOSE)
+               printf(GT_("  Keep any number of old messages (--maxkeep 
0).\n"));
            printf(GT_("  Old messages %s be flushed before message retrieval 
(--flush %s).\n"),
                   ctl->flush ? GT_("will") : GT_("will not"),
                   ctl->flush ? "on" : "off");
diff -rup fetchmail-6.2.5/fetchmail.h fetchmail-6.2.5.maxkeep/fetchmail.h
--- fetchmail-6.2.5/fetchmail.h 2005-05-01 03:57:26.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/fetchmail.h 2005-05-01 01:48:42.000000000 +0300
@@ -278,6 +278,7 @@ struct query
 
     /* per-user control flags */
     flag keep;                 /* if TRUE, leave messages undeleted */
+    int        maxkeep;                /* max # of msgs to keep on server */
     flag fetchall;             /* if TRUE, fetch all (not just unseen) */
     flag flush;                        /* if TRUE, delete messages already 
seen */
     flag rewrite;              /* if TRUE, canonicalize recipient addresses */
diff -rup fetchmail-6.2.5/fetchmailconf fetchmail-6.2.5.maxkeep/fetchmailconf
--- fetchmail-6.2.5/fetchmailconf       2003-10-15 22:22:31.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/fetchmailconf       2005-05-01 02:10:21.000000000 
+0300
@@ -237,6 +237,7 @@ class User:
        self.lmtp = FALSE       # Use LMTP rather than SMTP?
        self.antispam = ""      # Listener's spam-block code
        self.keep = FALSE       # Keep messages
+       self.maxkeep = 0        # Max number of old msgs to keep on server
        self.flush = FALSE      # Flush messages
        self.fetchall = FALSE   # Fetch old messages
        self.rewrite = TRUE     # Rewrite message headers
@@ -276,6 +277,7 @@ class User:
            ('lmtp',    'Boolean'),
            ('antispam',    'String'),
            ('keep',    'Boolean'),
+           ('maxkeep',     'Int'),
            ('flush',       'Boolean'),
            ('fetchall',    'Boolean'),
            ('rewrite',     'Boolean'),
@@ -325,6 +327,8 @@ class User:
            res = res + " options"
        if self.keep != UserDefaults.keep:
            res = res + flag2str(self.keep, 'keep')
+       if self.maxkeep != UserDefaults.maxkeep:
+           res = res + " maxkeep " + `self.maxkeep`
        if self.flush != UserDefaults.flush:
            res = res + flag2str(self.flush, 'flush')
        if self.fetchall != UserDefaults.fetchall:
@@ -1703,6 +1707,8 @@ class UserEdit(Frame, MyWidget):
        if mode != 'novice':
            limwin = Frame(rightwin, relief=RAISED, bd=5)
            Label(limwin, text="Resource Limits").pack(side=TOP)
+           LabeledEntry(limwin, 'Max old msgs to keep on server:',
+                     self.maxkeep, '30').pack(side=TOP, fill=X)
            LabeledEntry(limwin, 'Message size limit:',
                      self.limit, '30').pack(side=TOP, fill=X)
            LabeledEntry(limwin, 'Size warning interval:',
diff -rup fetchmail-6.2.5/odmr.c fetchmail-6.2.5.maxkeep/odmr.c
--- fetchmail-6.2.5/odmr.c      2005-05-01 03:57:26.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/odmr.c      2005-05-01 02:30:41.000000000 +0300
@@ -241,6 +241,10 @@ int doODMR (struct query *ctl)
        fprintf(stderr, GT_("Option --keep is not supported with ODMR\n"));
        return(PS_SYNTAX);
     }
+    if (ctl->maxkeep) {
+       fprintf(stderr, GT_("Option --maxkeep is not supported with ODMR\n"));
+       return(PS_SYNTAX);
+    }
     if (ctl->flush) {
        fprintf(stderr, GT_("Option --flush is not supported with ODMR\n"));
        return(PS_SYNTAX);
diff -rup fetchmail-6.2.5/options.c fetchmail-6.2.5.maxkeep/options.c
--- fetchmail-6.2.5/options.c   2003-10-15 22:22:31.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/options.c   2005-05-01 01:47:30.000000000 +0300
@@ -88,10 +88,11 @@
 
 #define LA_FETCHSIZELIMIT      61
 #define LA_FASTUIDL    62
+#define LA_MAXKEEP     163
 
-/* options still left: CDgGhHjJoORwWxXYz */
+/* options still left: CDgGhHjJoORwWxYz */
 static const char *shortoptions = 
-       "?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKFnl:r:S:Z:b:B:e:m:T:I:M:yw:D:";
+       "?Vcsvd:NqL:f:i:p:UP:A:t:E:Q:u:akKX:Fnl:r:S:Z:b:B:e:m:T:I:M:yw:D:";
 
 static const struct option longoptions[] = {
 /* this can be const because all flag fields are 0 and will never get set */
@@ -128,6 +129,7 @@ static const struct option longoptions[]
   {"all",      no_argument,       (int *) 0, LA_ALL         },
   {"nokeep",   no_argument,       (int *) 0, LA_NOKEEP      },
   {"keep",     no_argument,       (int *) 0, LA_KEEP        },
+  {"maxkeep",  required_argument, (int *) 0, LA_MAXKEEP     },
   {"flush",    no_argument,       (int *) 0, LA_FLUSH       },
   {"norewrite",        no_argument,       (int *) 0, LA_NOREWRITE   },
   {"limit",    required_argument, (int *) 0, LA_LIMIT       },
@@ -461,6 +463,11 @@ struct query *ctl; /* option record to b
        case LA_KEEP:
            ctl->keep = FLAG_TRUE;
            break;
+       case 'X':
+       case LA_MAXKEEP:
+           c = xatoi(optarg, &errflag);
+           ctl->maxkeep = NUM_VALUE_IN(c);
+           break;
        case 'F':
        case LA_FLUSH:
            ctl->flush = FLAG_TRUE;
@@ -702,6 +709,7 @@ struct query *ctl;  /* option record to b
        P(GT_("  -a, --all         retrieve old and new messages\n"));
        P(GT_("  -K, --nokeep      delete new messages after retrieval\n"));
        P(GT_("  -k, --keep        save new messages after retrieval\n"));
+       P(GT_("  -X, --maxkeep     keep specified number of msgs max\n"));
        P(GT_("  -F, --flush       delete old messages from server\n"));
        P(GT_("  -n, --norewrite   don't rewrite header addresses\n"));
        P(GT_("  -l, --limit       don't fetch messages over given size\n"));
diff -rup fetchmail-6.2.5/rcfile_l.l fetchmail-6.2.5.maxkeep/rcfile_l.l
--- fetchmail-6.2.5/rcfile_l.l  2003-10-15 22:22:31.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/rcfile_l.l  2005-05-01 02:34:28.000000000 +0300
@@ -159,6 +159,7 @@ noidle              {
 no             {return NO;}
 
 keep           { return KEEP; }
+maxkeep                { return MAXKEEP; }
 flush          { return FLUSH; }
 fetchall       { return FETCHALL; }
 rewrite                { return REWRITE; }
diff -rup fetchmail-6.2.5/rcfile_y.y fetchmail-6.2.5.maxkeep/rcfile_y.y
--- fetchmail-6.2.5/rcfile_y.y  2003-10-15 22:22:31.000000000 +0300
+++ fetchmail-6.2.5.maxkeep/rcfile_y.y  2005-05-01 02:33:18.000000000 +0300
@@ -73,7 +73,7 @@ extern char * yytext;
 %token <proto> PROTO AUTHTYPE
 %token <sval>  STRING
 %token <number> NUMBER
-%token NO KEEP FLUSH FETCHALL REWRITE FORCECR STRIPCR PASS8BITS 
+%token NO KEEP MAXKEEP FLUSH FETCHALL REWRITE FORCECR STRIPCR PASS8BITS 
 %token DROPSTATUS DROPDELIVERED
 %token DNS SERVICE PORT UIDL INTERVAL MIMEDECODE IDLE CHECKALIAS 
 %token SSL SSLKEY SSLCERT SSLPROTO SSLCERTCK SSLCERTPATH SSLFINGERPRINT
@@ -332,6 +332,7 @@ user_option : TO localnames HERE
                | POSTCONNECT STRING    {current.postconnect = xstrdup($2);}
 
                | KEEP                  {current.keep        = FLAG_TRUE;}
+               | MAXKEEP NUMBER        {current.maxkeep     = 
NUM_VALUE_IN($2);}
                | FLUSH                 {current.flush       = FLAG_TRUE;}
                | FETCHALL              {current.fetchall    = FLAG_TRUE;}
                | REWRITE               {current.rewrite     = FLAG_TRUE;}
--- fetchmail-6.2.5/fetchmail.man       2005-05-01 03:57:26.000000000 +0300
+++ fetchmail-6.2.5.maxkeep.tmp/fetchmail.man   2005-05-01 13:54:28.000000000 
+0300
@@ -155,6 +155,16 @@
 you have specified a default of \fBkeep\fR in your
 \&\fI.fetchmailrc\fR.  This option is forced on with ETRN and ODMR.
 .TP
+.B \-X <count> | \-\-maxkeep <count>
+(Keyword: maxkeep)
+Specify the maximum number of messages that will be kept on server
+(defaults to 0, meaning no limit).  An explicit \-\-maxkeep of 0
+overrides \fBmaxkeep\fR set in your run control file.  Current
+implementation does not delete "new" messages, so you can get more
+mail left on server upon \fIfetchmail\fR exit than maxkeep number, if
+number of new messages is greater than \fBmaxkeep\fR.
+This option does not work with ETRN or ODMR.
+.TP
 .B \-F | \-\-flush
 POP3/IMAP only.  Delete old (previously retrieved) messages from the
 mailserver before retrieving new messages. This option does not work
@@ -1423,6 +1433,9 @@
 keep           -k      T{
 Don't delete seen messages from server
 T}
+maxkeep                -X      T{
+Max # messages to keep on server
+T}
 flush          -F      T{
 Flush all seen messages before querying
 T}

Reply via email to