From aaeb3055402a95323d97a7807c0b92848afb0aa5 Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Tue, 1 Oct 1996 07:14:12 +0000 Subject: Better IMAP support. svn path=/trunk/; revision=185 --- imap.c | 93 +++++++++++++++++------------------------------------------------- 1 file changed, 24 insertions(+), 69 deletions(-) (limited to 'imap.c') diff --git a/imap.c b/imap.c index 70e29150..cd7e4bdf 100644 --- a/imap.c +++ b/imap.c @@ -9,54 +9,11 @@ programmer: Eric S. Raymond description: IMAP client code -Chris Newman, one of the IMAP maintainers, criticized this as follows: -------------------------------- CUT HERE ----------------------------------- -On Wed, 18 Sep 1996, Eric S. Raymond wrote: -> 1. I do one one SELECT, at the beginning of the fetch. -> -> 2. I assume that I can pick an upper bound on message numbers from the EXISTS -> reponse. - -Correct. - -> 3. If there is an UNSEEN nnn trailer on the OK response to SELECT, I assume -> that the unseen messages have message numbers which are the nnn consecutive -> integers up to and including the upper bound. -> -> 4. Otherwise, if the response included RECENT nnn, I assume that the unseen -> messages have message numbers which are the nnn consecutive integers up to -> and including the upper bound. - -These will only work if your client is the only client that accesses the -INBOX. There is no requirement that the UNSEEN and RECENT messages are at -the end of the folder in general. - -If you want to present all UNSEEN messages and flag all the messages you -download as SEEN, you could do a SEARCH UNSEEN and just fetch those -messages. - -However, the proper thing to do if you want to present the messages when -disconnected from the server is to use UIDs. To do this, you remember the -highest UID you have (you can initialize to 0), and fetch everything with -a higher UID. Ideally, you shouldn't cause the SEEN flag to be set until -the user has actually seen the message. This requires STORE +FLAGS SEEN -for those messages which have been seen since the last update. - -The key thing to remember is that in IMAP the server holds the -authoratative list of messages and the client just holds a cache. This is -a very different model from POP. -------------------------------- CUT HERE ----------------------------------- - -A problem with this recommendation is that the UID commands don't exist -in IMAP2bis. Since we want to preserve IMAP2bis capability (so fetchmail -will continue to work with the pre-IMAP4 imapd) and we've warned the user -that multiple concurrent fetchmail runs are a Bad Idea, we'll stick with -this logic for now. - ***********************************************************************/ #include #include +#include #include "socket.h" #include "fetchmail.h" @@ -66,8 +23,7 @@ this logic for now. *********************************************************************/ -static int count, first; -static int exists, unseen, recent; +static int count, seen; int imap_ok (argbuf,socket) /* parse command response */ @@ -79,6 +35,7 @@ int socket; char *bufp; int n; + seen = 0; do { if (SockGets(socket, buf, sizeof(buf)) < 0) return(PS_SOCKET); @@ -88,12 +45,9 @@ int socket; /* interpret untagged status responses */ if (strstr(buf, "EXISTS")) - exists = atoi(buf+2); - if (strstr(buf, "RECENT")) - recent = atoi(buf+2); - if (sscanf(buf + 2, "OK [UNSEEN %d]", &n) == 1) - unseen = n; - + count = atoi(buf+2); + if (strstr(buf, "FLAGS")) + seen = (strstr(buf, "Seen") != (char *)NULL); } while (tag[0] != '\0' && strncmp(buf, tag, strlen(tag))); @@ -146,31 +100,32 @@ int *firstp; int ok; /* find out how many messages are waiting */ - exists = unseen = recent = -1; ok = gen_transact(socket, "SELECT %s", queryctl->remotefolder[0] ? queryctl->remotefolder : "INBOX"); if (ok != 0) return(ok); - /* compute size of message run */ - *countp = exists; - if (queryctl->fetchall) - *firstp = 1; - else { - if (exists > 0 && unseen == -1) { - fprintf(stderr, - "no UNSEEN response; assuming all %d RECENT messages are unseen\n", - recent); - *firstp = exists - recent + 1; - } else { - *firstp = unseen; - } - } + *countp = count; + *firstp = 1; return(0); } +static imap_is_old(socket, queryctl, num) +int socket; +struct hostrec *queryctl; +int num; +{ + char buf [POPBUFSIZE+1]; + int ok; + + if ((ok = gen_transact(socket, "FETCH %d FLAGS", num)) != 0) + exit(PS_ERROR); + + return(seen); +} + static int imap_fetch(socket, number, lenp) /* request nth message */ int socket; @@ -215,7 +170,7 @@ int socket; struct hostrec *queryctl; int number; { - return(socket, gen_transact("STORE %d +FLAGS (\\Deleted)", number)); + return(gen_transact(socket, "STORE %d +FLAGS (\\Deleted)", number)); } static struct method imap = @@ -227,7 +182,7 @@ static struct method imap = imap_ok, /* parse command response */ imap_getauth, /* get authorization */ imap_getrange, /* query range of messages */ - NULL, /* no UID check */ + imap_is_old, /* no UID check */ imap_fetch, /* request given message */ imap_trail, /* eat message trailer */ imap_delete, /* set IMAP delete flag */ -- cgit v1.2.3