diff options
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | fetchmail.c | 34 | ||||
-rw-r--r-- | fetchmail.h | 19 | ||||
-rw-r--r-- | fetchmail.man | 25 | ||||
-rw-r--r-- | options.c | 18 |
6 files changed, 88 insertions, 14 deletions
diff --git a/Makefile.in b/Makefile.in index d502f717..81975167 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,7 +73,7 @@ CTAGS = ctags -tw popobjs = socket.o getpass.o pop2.o pop3.o imap.o fetchmail.o options.o \ rcfile_l.o rcfile_y.o rcfile.o daemon.o driver.o smtp.o xmalloc.o \ - md5c.o md5ify.o + uid.o md5c.o md5ify.o objs = $(popobjs) $(extras) $(EXTRAOBJ) @@ -81,7 +81,7 @@ srcs = $(srcdir)/socket.c $(srcdir)/getpass.c $(srcdir)/pop2.c \ $(srcdir)/pop3.c $(srcdir)/imap.c $(srcdir)/fetchmail.c \ $(srcdir)/options.c $(srcdir)/rcfile.c $(srcdir)/daemon.c \ $(srcdir)/driver.c $(srcdir)/smtp.c $(srcdir)/xmalloc.c \ - $(srcdir)/md5c.c $(srcdir)/md5ify.c + $(srcdir)/uid.c $(srcdir)/md5c.c $(srcdir)/md5ify.c .SUFFIXES: .SUFFIXES: .o .c .h .y .l .ps .dvi .info .texi @@ -37,6 +37,8 @@ features -- * New --check option for asking server whether there is mail without actually retrieving or deleting it. +* UID support is back by popular demand. Bletch. + bugs -- * Fix buggy getopt specification of P and p options. diff --git a/fetchmail.c b/fetchmail.c index 7d9073c8..d65de5f4 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -58,6 +58,7 @@ int check_only; /* if --probe was set */ /* miscellaneous global controls */ char *rcfile; /* path name of rc file */ +char *idfile; /* UID list file */ int versioninfo; /* emit only version info */ /********************************************************************* @@ -130,6 +131,12 @@ char **argv; strcat(rcfile, "/"); strcat(rcfile, tmpdir); +#define IDFILE_NAME ".fetchids" + idfile = (char *) xmalloc(strlen(home)+strlen(IDFILE_NAME)+2); + strcpy(idfile, home); + strcat(idfile, "/"); + strcat(idfile, IDFILE_NAME); + outlevel = O_NORMAL; if ((parsestatus = parsecmdline(argc,argv,&cmd_opts)) < 0) @@ -233,6 +240,12 @@ char **argv; strcat(tmpbuf, "/fetchmail-"); strcat(tmpbuf, user); + /* initialize UID handling */ + if ((st = prc_filecheck(idfile)) != 0) + exit(st); + else + initialize_saved_lists(hostlist, idfile); + /* perhaps we just want to check options? */ if (versioninfo) { printf("Taking options from command line"); @@ -351,7 +364,10 @@ char **argv; do { for (hostp = hostlist; hostp; hostp = hostp->next) { if (hostp->active && !(implicitmode && hostp->skip)) + { popstatus = query_host(hostp); + update_uid_lists(hostp); + } } sleep(poll_interval); @@ -371,6 +387,8 @@ void termhook(int sig) if (sig != 0) fprintf(stderr, "terminated with signal %d\n", sig); + write_saved_lists(hostlist, idfile); + unlink(lockfile); exit(popstatus); } @@ -520,6 +538,22 @@ struct hostrec *queryctl; } else printf(" Messages will be SMTP-forwarded to '%s'\n", queryctl->smtphost); + if (queryctl->protocol > P_POP2) + if (!queryctl->saved) + printf(" No UIDs saved from this host.\n"); + else + { + struct idlist *idp; + int count = 0; + + for (idp = hostp->saved; idp; idp = idp->next) + ++count; + + printf(" %d UIDs saved.\n", count); + if (outlevel == O_VERBOSE) + for (idp = hostp->saved; idp; idp = idp->next) + fprintf(stderr, "\t%s %s\n", hostp->servername, idp->id); + } } /********************************************************************* diff --git a/fetchmail.h b/fetchmail.h index a5dcb39c..8c4ee3a3 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -55,6 +55,13 @@ #define SIZETICKER 1024 /* print 1 dot per this many bytes */ +struct idlist +{ + int num; + char *id; + struct idlist *next; +}; + struct hostrec { /* per-host data */ @@ -80,6 +87,9 @@ struct hostrec int norewrite; int skip; + /* current, previous state of mailbox (initially from .fetchids) */ + struct idlist *saved, *current; + /* internal use */ int active; struct hostrec *next; /* next host in chain */ @@ -121,6 +131,7 @@ extern int check_only; /* if --check was set */ /* miscellaneous global controls */ extern char *rcfile; /* path name of rc file */ +extern char *idfile; /* path name of UID file */ extern int linelimit; /* limit # lines retrieved per site */ extern int versioninfo; /* emit only version info */ @@ -134,6 +145,14 @@ int doPOP2 (struct hostrec *); int doPOP3 (struct hostrec *); int doIMAP (struct hostrec *); +void initialize_saved_lists(struct hostrec *, char *); +void save_uid(struct idlist **, int, char *); +void free_uid_list(struct idlist **); +int delete_uid(struct idlist **, char *); +int uid_in_list(struct idlist **, char *); +void update_uid_lists(struct hostrec *); +void write_saved_lists(struct hostrec *, char *); + struct hostrec *hostalloc(struct hostrec *); int parsecmdline (int, char **, struct hostrec *); void optmerge(struct hostrec *, struct hostrec *); diff --git a/fetchmail.man b/fetchmail.man index 13a4df11..c0a5f8e8 100644 --- a/fetchmail.man +++ b/fetchmail.man @@ -85,6 +85,10 @@ Specify a non-default name for the .I .fetchmailrc run control file. .TP +.B \-i pathname, --idfile pathname +Specify an alternate name for the .fetchids file used to save POP3 +UIDs. +.TP .B \-k, --keep Keep retrieved messages in folder on remote mailserver. Normally, messages are deleted from the folder on the mailserver after they have been retrieved. @@ -300,13 +304,15 @@ One could be that you're using POP2. The POP2 protocol includes no representation of `new' or `old' state in messages, so \fIfetchmail\fR must treat all messages as new all the time. POP2 is obsolete. .PP -Under POP3, blame RFC1725. That late version of the POP3 protocol -specification ill-advisedly removed the LAST command, and some POP -servers (including the one distributed with at least some versions of -SunOS) follow it (you can verify this by invoking \fIfetchmail -v\fR -to the mail server and watching the response to LAST early in the -query). The fix is to install an older POP3 server with LAST or -(better) switch to an IMAP server. +Under POP3, blame RFC1725. That version of the POP3 protocol +specification removed the LAST command, and some POP servers follow it +(you can verify this by invoking \fIfetchmail -v\fR to the mail server +and watching the response to LAST early in the query). The +\fIfetchmail\fR code tries to compensate by using POP3's UID feature, +storing the identifiers of messages seen in each session until the +next session,in the \fI.fetchids\fR file. But this doesn't track +messages seen with other clients or read but not deleted directly with +a mailer on the host. A better solution would be to switch to IMAP. .PP Another potential POP3 problem might be servers that insert messages in the middle of mailboxes (some VMS implementations of mail are @@ -580,6 +586,11 @@ created by the new SMTP forwarding default. ~/.fetchmailrc default run control file .TP 5 +~/.fetchids +default location of file associating hosts with last message IDs seen +(used only with newer RFC1725-compliant POP3 servers supporting the +UIDL command). +.TP 5 ${TMPDIR}/fetchmail-${HOST}-${USER} lock file to help prevent concurrent runs. .SH ENVIRONMENT @@ -36,11 +36,12 @@ #define LA_SMTPHOST 16 #define LA_MDA 17 #define LA_LOGFILE 18 -#define LA_QUIT 19 -#define LA_NOREWRITE 20 -#define LA_CHECK 21 -#define LA_HELP 22 -#define LA_YYDEBUG 23 +#define LA_IDFILE 19 +#define LA_QUIT 20 +#define LA_NOREWRITE 21 +#define LA_CHECK 22 +#define LA_HELP 23 +#define LA_YYDEBUG 24 static char *shortoptions = "P:p:VaKkvS:m:sFd:f:u:r:L:qN?"; static struct option longoptions[] = { @@ -63,6 +64,7 @@ static struct option longoptions[] = { {"smtphost", required_argument, (int *) 0, LA_SMTPHOST }, {"mda", required_argument, (int *) 0, LA_MDA }, {"logfile", required_argument, (int *) 0, LA_LOGFILE }, + {"idfile", required_argument, (int *) 0, LA_IDFILE }, {"quit", no_argument, (int *) 0, LA_QUIT }, {"norewrite", no_argument, (int *) 0, LA_NOREWRITE }, {"check", no_argument, (int *) 0, LA_CHECK }, @@ -174,6 +176,11 @@ struct hostrec *queryctl; rcfile = (char *) xmalloc(strlen(optarg)+1); strcpy(rcfile,optarg); break; + case 'i': + case LA_IDFILE: + idfile = (char *) xmalloc(strlen(optarg)+1); + strcpy(idfile,optarg); + break; case 'u': case LA_USERNAME: strncpy(queryctl->remotename,optarg,sizeof(queryctl->remotename)-1); @@ -248,6 +255,7 @@ struct hostrec *queryctl; fputs(" -L, --logfile specify logfile name\n", stderr); fputs(" -q, --quit kill daemon process\n", stderr); fputs(" -f, --fetchmailrc specify alternate run control file\n", stderr); + fputs(" -i, --idfile specify alternate UIDs file\n", stderr); fputs(" -p, --protocol specify pop2, pop3, imap, apop, rpop, kpop\n", stderr); fputs(" -P, --port TCP/IP service port to connect to\n",stderr); |