aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.in4
-rw-r--r--NEWS2
-rw-r--r--fetchmail.c34
-rw-r--r--fetchmail.h19
-rw-r--r--fetchmail.man25
-rw-r--r--options.c18
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
diff --git a/NEWS b/NEWS
index 37d4aa1c..6fb6dd2d 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/options.c b/options.c
index 77e29f16..cc6efff1 100644
--- a/options.c
+++ b/options.c
@@ -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);