aboutsummaryrefslogtreecommitdiffstats
path: root/pop3.c
diff options
context:
space:
mode:
Diffstat (limited to 'pop3.c')
-rw-r--r--pop3.c82
1 files changed, 79 insertions, 3 deletions
diff --git a/pop3.c b/pop3.c
index adb865cf..d699bd50 100644
--- a/pop3.c
+++ b/pop3.c
@@ -40,6 +40,7 @@ int POP3_sendSTAT (int *msgcount, int socket);
int POP3_sendRETR (int msgnum, int socket);
int POP3_sendDELE (int msgnum, int socket);
int POP3_sendLAST (int *last, int socket);
+int POP3_sendUIDL (int num, int socket, char **cp);
int POP3_readmsg (int socket, int mboxfd, char *host, int topipe, int rewrite);
int POP3_BuildDigest (char *buf, struct hostrec *options);
#endif
@@ -63,7 +64,7 @@ int POP3_BuildDigest (char *buf, struct hostrec *options);
int doPOP3 (queryctl)
struct hostrec *queryctl;
{
- int ok;
+ int ok, use_uidl;
int mboxfd;
char buf [POPBUFSIZE];
int socket;
@@ -124,11 +125,39 @@ struct hostrec *queryctl;
/*
* Ask for number of last message retrieved.
* Newer, RFC-1760-conformant POP servers may not have the LAST command.
- * Therefore we don't croak if we get a nonzero return.
+ * Therefore we don't croak if we get a nonzero return. Instead, send
+ * UIDL and try to find the last received ID stored for this host in
+ * the list we get back.
*/
first = 1;
+ use_uidl = 0;
if (!queryctl->fetchall) {
+ char buf [POPBUFSIZE];
+ char id [IDLEN];
+ int num;
+
+ /* try LAST first */
ok = POP3_sendLAST(&first, socket);
+ use_uidl = (ok != 0);
+
+ /* otherwise, if we have a stored last ID for this host,
+ * send UIDL and search the returned list for it
+ */
+ if (use_uidl && queryctl->lastid[0]) {
+ if ((ok = POP3_sendUIDL(-1, socket, 0)) == 0) {
+ while (SockGets(socket, buf, sizeof(buf)) == 0) {
+ if (outlevel == O_VERBOSE)
+ fprintf(stderr,"%s\n",buf);
+ if (strcmp(buf, ".\n") == 0) {
+ break;
+ }
+ if (sscanf(buf, "%d %s\n", &num, id) == 2)
+ if (strcmp(id, queryctl->lastid) == 0)
+ first = num;
+ }
+ }
+ }
+
if (ok == 0)
first++;
}
@@ -146,6 +175,8 @@ struct hostrec *queryctl;
if (count > 0) {
for (number = queryctl->flush ? 1 : first; number <= count; number++) {
+ char *cp;
+
/* open the mail pipe if we're using an MDA */
if (queryctl->output == TO_MDA
&& (queryctl->fetchall || number >= first)) {
@@ -173,6 +204,11 @@ struct hostrec *queryctl;
if (ok != 0)
goto cleanUp;
+ /* update the last-seen field for this host */
+ if (use_uidl && (ok = POP3_sendUIDL(number, socket, &cp)) == 0)
+ (void) strcpy(queryctl->lastid, cp);
+
+ /* maybe we delete this message now? */
if ((number < first && queryctl->flush) || !queryctl->keep) {
if (outlevel > O_SILENT && outlevel < O_VERBOSE)
fprintf(stderr,"flushing message %d\n", number);
@@ -671,7 +707,7 @@ int rewrite;
arguments:
last integer buffer to receive last message#
- ret. value: non-zero on success, else zero.
+ ret. value: zero if success, else status code.
globals: SockPrintf, POP3_OK.
calls: reads outlevel.
*****************************************************************/
@@ -697,6 +733,46 @@ int socket;
return(ok);
}
+/******************************************************************
+ function: POP3_sendUIDL
+ description: send the UIDL command to the server,
+
+ arguments:
+ num number of message to query (may be -1)
+
+ ret. value: zero if success, else status code.
+ globals: SockPrintf, POP3_OK.
+ calls: reads outlevel.
+ *****************************************************************/
+
+int POP3_sendUIDL (num, socket, cp)
+int num;
+int socket;
+char **cp;
+{
+ int ok;
+ char buf [POPBUFSIZE];
+ static char id[IDLEN];
+
+ (void) strcpy(buf, "UIDL\r\n");
+ if (num > -1)
+ (void) sprintf(buf, "UIDL %d\r\n", num);
+
+ SockPrintf(socket, buf);
+ if (outlevel == O_VERBOSE)
+ fprintf(stderr,"> %s", buf);
+
+ ok = POP3_OK(buf,socket);
+ if (ok != 0 && outlevel > O_SILENT)
+ fprintf(stderr,"Server says '%s' to UIDL command.\n",buf);
+
+ if (cp) {
+ sscanf(buf, "%*d %s\n", id);
+ *cp = id;
+ }
+ return(ok);
+}
+
/******************************************************************
function: POP3_BuildDigest