--- imap.c.old 2006-01-23 13:07:04.000000000 +0100 +++ imap.c 2006-01-23 13:45:14.000000000 +0100 @@ -310,13 +310,8 @@ } #endif -/* Ok, now fetch all the headers from the first UNSEEN through the - * end of the mailbox. This could be lower bandwidth (maybe) by first - * fetching all of the flags, and then only fetching the headers of - * the messages which are new, but there is a lot of protocol crap - * which would probably negate the lower bandwidth */ -static int parse_fetch (BOX_INFO *ibox, CONNECTION *conn, GList *headers, - int unseen) +/* Ok, now fetch all the headers from the supplied range */ +static int parse_fetch_range (CONNECTION *conn, GList *headers, char *range) { char from[LONG_STRING] = ""; char subject[LONG_STRING] = ""; @@ -328,7 +323,7 @@ imap_make_sequence (seq, sizeof (seq)); - snprintf (buf, sizeof (buf), "%s FETCH %d:%d (FLAGS BODY.PEEK[HEADER.FIELDS (FROM SUBJECT X-FACE)])\r\n", seq, unseen, ibox->num_messages); + snprintf (buf, sizeof (buf), "%s FETCH %s (FLAGS BODY.PEEK[HEADER.FIELDS (FROM SUBJECT X-FACE)])\r\n", seq, range); msocket_write (conn, buf); do @@ -428,6 +423,83 @@ return 0; } +/* Fetch only recent unseen information, since X-Face is unlikely to be cached + * and any mailbox with multiple threads may have people reading sub-ranges, + * leaving large gaps in the sequence range. */ +static int parse_fetch (BOX_INFO *ibox, CONNECTION *conn, GList *headers, + int unseen) +{ + char buf[LONG_STRING]; + char seq[8]; + char *s, *t, *commacopy, csave; + size_t len, slen, tlen; + int ret, line; + + imap_make_sequence (seq, sizeof (seq)); + snprintf (buf, sizeof (buf), "%s SEARCH RECENT UNSEEN\r\n", seq); + msocket_write (conn, buf); + + commacopy = NULL; + do + { + if (msocket_read_line_d (buf, sizeof (buf), conn) < 0) + { + conn->uses = 0; + return (-1); + } + line = 1; + + while (line--) + { + if (buf[0] != '*') + continue; + + s = imap_next_word (buf); + if (strncasecmp ("SEARCH", s, 6) != 0) + continue; + s = imap_next_word (s); + + t = s + strcspn (s, "\r\n"); + csave = *t; + *t = '\0'; + + if (commacopy) + { + len = strlen (commacopy); + slen = strlen (s); + tlen = len + slen + 2; + safe_realloc ((void **) &commacopy, tlen); + commacopy[len] = ' '; + strfcpy (commacopy + len + 1, s, slen); + } + else + commacopy = safe_strdup (s); + + *t = csave; + t += strspn (t, "\r\n"); + if (*t != '\0') + ++line; + } + } + while ((strncmp (buf, seq, SEQLEN) != 0)); + + s = commacopy; + /* First character guaranteed not whitespace by imap_next_word */ + while (*++s) + { + if (isspace(*s)) + *s = ','; + } + while (*--s == ',') + *s = '\0'; + + ret = parse_fetch_range (conn, headers, commacopy); + + safe_free ((void **) &commacopy); + + return ret; +} + static int imap_fetch_new_headers (BOX_INFO *ibox, CONNECTION *conn, GList *headers) { char buf[LONG_STRING];