|
|
@ -150,9 +150,13 @@ buffer_gets (buffer_t * b, char **s) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
static int |
|
|
|
parse_fetch (imap_t * imap, list_t * list, message_t * cur) |
|
|
|
parse_fetch (imap_t * imap, list_t * list) |
|
|
|
{ |
|
|
|
{ |
|
|
|
list_t *tmp; |
|
|
|
list_t *tmp; |
|
|
|
|
|
|
|
unsigned int uid = 0; |
|
|
|
|
|
|
|
unsigned int mask = 0; |
|
|
|
|
|
|
|
unsigned int size = 0; |
|
|
|
|
|
|
|
message_t *cur; |
|
|
|
|
|
|
|
|
|
|
|
if (!is_list (list)) |
|
|
|
if (!is_list (list)) |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
@ -165,7 +169,14 @@ parse_fetch (imap_t * imap, list_t * list, message_t * cur) |
|
|
|
{ |
|
|
|
{ |
|
|
|
tmp = tmp->next; |
|
|
|
tmp = tmp->next; |
|
|
|
if (is_atom (tmp)) |
|
|
|
if (is_atom (tmp)) |
|
|
|
cur->uid = atoi (tmp->val); |
|
|
|
{ |
|
|
|
|
|
|
|
uid = atoi (tmp->val); |
|
|
|
|
|
|
|
if (uid < imap->minuid) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/* already saw this message */ |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
puts ("Error, unable to parse UID"); |
|
|
|
puts ("Error, unable to parse UID"); |
|
|
|
} |
|
|
|
} |
|
|
@ -181,20 +192,17 @@ parse_fetch (imap_t * imap, list_t * list, message_t * cur) |
|
|
|
if (is_atom (flags)) |
|
|
|
if (is_atom (flags)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!strcmp ("\\Seen", flags->val)) |
|
|
|
if (!strcmp ("\\Seen", flags->val)) |
|
|
|
cur->flags |= D_SEEN; |
|
|
|
mask |= D_SEEN; |
|
|
|
else if (!strcmp ("\\Flagged", flags->val)) |
|
|
|
else if (!strcmp ("\\Flagged", flags->val)) |
|
|
|
cur->flags |= D_FLAGGED; |
|
|
|
mask |= D_FLAGGED; |
|
|
|
else if (!strcmp ("\\Deleted", flags->val)) |
|
|
|
else if (!strcmp ("\\Deleted", flags->val)) |
|
|
|
{ |
|
|
|
mask |= D_DELETED; |
|
|
|
cur->flags |= D_DELETED; |
|
|
|
|
|
|
|
imap->deleted++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (!strcmp ("\\Answered", flags->val)) |
|
|
|
else if (!strcmp ("\\Answered", flags->val)) |
|
|
|
cur->flags |= D_ANSWERED; |
|
|
|
mask |= D_ANSWERED; |
|
|
|
else if (!strcmp ("\\Draft", flags->val)) |
|
|
|
else if (!strcmp ("\\Draft", flags->val)) |
|
|
|
cur->flags |= D_DRAFT; |
|
|
|
mask |= D_DRAFT; |
|
|
|
else if (!strcmp ("\\Recent", flags->val)) |
|
|
|
else if (!strcmp ("\\Recent", flags->val)) |
|
|
|
cur->flags |= D_RECENT; |
|
|
|
mask |= D_RECENT; |
|
|
|
else |
|
|
|
else |
|
|
|
printf ("Warning, unknown flag %s\n", |
|
|
|
printf ("Warning, unknown flag %s\n", |
|
|
|
flags->val); |
|
|
|
flags->val); |
|
|
@ -206,8 +214,26 @@ parse_fetch (imap_t * imap, list_t * list, message_t * cur) |
|
|
|
else |
|
|
|
else |
|
|
|
puts ("Error, unable to parse FLAGS"); |
|
|
|
puts ("Error, unable to parse FLAGS"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else if (!strcmp ("RFC822.SIZE", tmp->val)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
tmp = tmp->next; |
|
|
|
|
|
|
|
if (is_atom (tmp)) |
|
|
|
|
|
|
|
size = atol (tmp->val); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cur = calloc (1, sizeof (message_t)); |
|
|
|
|
|
|
|
cur->next = imap->msgs; |
|
|
|
|
|
|
|
imap->msgs = cur; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mask & D_DELETED) |
|
|
|
|
|
|
|
imap->deleted++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cur->uid = uid; |
|
|
|
|
|
|
|
cur->flags = mask; |
|
|
|
|
|
|
|
cur->size = size; |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -246,8 +272,6 @@ imap_exec (imap_t * imap, const char *fmt, ...) |
|
|
|
char *cmd; |
|
|
|
char *cmd; |
|
|
|
char *arg; |
|
|
|
char *arg; |
|
|
|
char *arg1; |
|
|
|
char *arg1; |
|
|
|
message_t **cur = 0; |
|
|
|
|
|
|
|
message_t **rec = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
va_start (ap, fmt); |
|
|
|
va_start (ap, fmt); |
|
|
|
vsnprintf (tmp, sizeof (tmp), fmt, ap); |
|
|
|
vsnprintf (tmp, sizeof (tmp), fmt, ap); |
|
|
@ -281,22 +305,6 @@ imap_exec (imap_t * imap, const char *fmt, ...) |
|
|
|
imap->ns_other = parse_list (cmd, &cmd); |
|
|
|
imap->ns_other = parse_list (cmd, &cmd); |
|
|
|
imap->ns_shared = parse_list (cmd, 0); |
|
|
|
imap->ns_shared = parse_list (cmd, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (!strcmp ("SEARCH", arg)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (!rec) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
rec = &imap->recent_msgs; |
|
|
|
|
|
|
|
while (*rec) |
|
|
|
|
|
|
|
rec = &(*rec)->next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* parse rest of `cmd' */ |
|
|
|
|
|
|
|
while ((arg = next_arg (&cmd))) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
*rec = calloc (1, sizeof (message_t)); |
|
|
|
|
|
|
|
(*rec)->uid = atoi (arg); |
|
|
|
|
|
|
|
rec = &(*rec)->next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (!strcmp ("OK", arg) || !strcmp ("BAD", arg) || |
|
|
|
else if (!strcmp ("OK", arg) || !strcmp ("BAD", arg) || |
|
|
|
!strcmp ("NO", arg) || !strcmp ("PREAUTH", arg) || |
|
|
|
!strcmp ("NO", arg) || !strcmp ("PREAUTH", arg) || |
|
|
|
!strcmp ("BYE", arg)) |
|
|
|
!strcmp ("BYE", arg)) |
|
|
@ -313,25 +321,15 @@ imap_exec (imap_t * imap, const char *fmt, ...) |
|
|
|
{ |
|
|
|
{ |
|
|
|
list_t *list; |
|
|
|
list_t *list; |
|
|
|
|
|
|
|
|
|
|
|
if (!cur) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
cur = &imap->msgs; |
|
|
|
|
|
|
|
while (*cur) |
|
|
|
|
|
|
|
cur = &(*cur)->next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
list = parse_list (cmd, 0); |
|
|
|
list = parse_list (cmd, 0); |
|
|
|
|
|
|
|
|
|
|
|
*cur = calloc (1, sizeof (message_t)); |
|
|
|
if (parse_fetch (imap, list)) |
|
|
|
if (parse_fetch (imap, list, *cur)) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
free_list (list); |
|
|
|
free_list (list); |
|
|
|
return -1; |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
free_list (list); |
|
|
|
free_list (list); |
|
|
|
|
|
|
|
|
|
|
|
cur = &(*cur)->next; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
@ -357,66 +355,20 @@ imap_exec (imap_t * imap, const char *fmt, ...) |
|
|
|
/* not reached */ |
|
|
|
/* not reached */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
/* `box' is the config info for the maildrop to sync. `minuid' is the
|
|
|
|
fetch_recent_flags (imap_t * imap) |
|
|
|
* minimum UID to consider. in normal mode this will be 1, but in --fast |
|
|
|
{ |
|
|
|
* mode we only fetch messages newer than the last one seen in the local |
|
|
|
char buf[1024]; |
|
|
|
* mailbox. |
|
|
|
message_t **cur = &imap->recent_msgs; |
|
|
|
*/ |
|
|
|
message_t *tmp; |
|
|
|
|
|
|
|
unsigned int start = -1; |
|
|
|
|
|
|
|
unsigned int last = -1; |
|
|
|
|
|
|
|
int ret = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf[0] = 0; |
|
|
|
|
|
|
|
while (*cur) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
tmp = *cur; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (last == (unsigned int) -1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/* init */ |
|
|
|
|
|
|
|
start = tmp->uid; |
|
|
|
|
|
|
|
last = tmp->uid; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (tmp->uid == last + 1) |
|
|
|
|
|
|
|
last++; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
/* out of sequence */ |
|
|
|
|
|
|
|
if (start == last) |
|
|
|
|
|
|
|
ret = imap_exec (imap, "UID FETCH %d (UID FLAGS)", start); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
ret = |
|
|
|
|
|
|
|
imap_exec (imap, "UID FETCH %d:%d (UID FLAGS)", start, |
|
|
|
|
|
|
|
last); |
|
|
|
|
|
|
|
start = tmp->uid; |
|
|
|
|
|
|
|
last = tmp->uid; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
free (tmp); |
|
|
|
|
|
|
|
*cur = (*cur)->next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (start != (unsigned int) -1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (start == last) |
|
|
|
|
|
|
|
ret = imap_exec (imap, "UID FETCH %d (UID FLAGS)", start); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
ret = |
|
|
|
|
|
|
|
imap_exec (imap, "UID FETCH %d:%d (UID FLAGS)", start, last); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
imap_t * |
|
|
|
imap_t * |
|
|
|
imap_open (config_t * box, int fast) |
|
|
|
imap_open (config_t * box, unsigned int minuid) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int ret; |
|
|
|
int ret; |
|
|
|
imap_t *imap; |
|
|
|
imap_t *imap; |
|
|
|
int s; |
|
|
|
int s; |
|
|
|
struct sockaddr_in sin; |
|
|
|
struct sockaddr_in sin; |
|
|
|
struct hostent *he; |
|
|
|
struct hostent *he; |
|
|
|
char *ns_prefix = 0; |
|
|
|
char *ns_prefix = ""; |
|
|
|
#if HAVE_LIBSSL |
|
|
|
#if HAVE_LIBSSL |
|
|
|
int use_ssl = 0; |
|
|
|
int use_ssl = 0; |
|
|
|
#endif |
|
|
|
#endif |
|
|
@ -463,6 +415,7 @@ imap_open (config_t * box, int fast) |
|
|
|
imap->buf = calloc (1, sizeof (buffer_t)); |
|
|
|
imap->buf = calloc (1, sizeof (buffer_t)); |
|
|
|
imap->buf->sock = imap->sock; |
|
|
|
imap->buf->sock = imap->sock; |
|
|
|
imap->box = box; |
|
|
|
imap->box = box; |
|
|
|
|
|
|
|
imap->minuid = minuid; |
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_LIBSSL |
|
|
|
#if HAVE_LIBSSL |
|
|
|
if (!box->use_imaps) |
|
|
|
if (!box->use_imaps) |
|
|
@ -520,28 +473,18 @@ imap_open (config_t * box, int fast) |
|
|
|
{ |
|
|
|
{ |
|
|
|
fputs ("Selecting mailbox... ", stdout); |
|
|
|
fputs ("Selecting mailbox... ", stdout); |
|
|
|
fflush (stdout); |
|
|
|
fflush (stdout); |
|
|
|
ret = imap_exec (imap, "SELECT %s%s", |
|
|
|
ret = imap_exec (imap, "SELECT %s%s", ns_prefix, box->box); |
|
|
|
ns_prefix ? ns_prefix : "", box->box); |
|
|
|
|
|
|
|
if (!ret) |
|
|
|
if (!ret) |
|
|
|
printf ("%d messages, %d recent\n", imap->count, imap->recent); |
|
|
|
printf ("%d messages, %d recent\n", imap->count, imap->recent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!ret) |
|
|
|
if (!ret) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (fast) |
|
|
|
puts ("Reading IMAP mailbox index"); |
|
|
|
{ |
|
|
|
if (imap->count > 0) |
|
|
|
if (imap->recent > 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
puts ("Fetching info for recent messages"); |
|
|
|
|
|
|
|
ret = imap_exec (imap, "UID SEARCH RECENT"); |
|
|
|
|
|
|
|
if (!ret) |
|
|
|
|
|
|
|
ret = fetch_recent_flags (imap); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (imap->count > 0) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
puts ("Reading IMAP mailbox index"); |
|
|
|
ret = imap_exec (imap, "UID FETCH %d:* (FLAGS RFC822.SIZE)", |
|
|
|
ret = imap_exec (imap, "FETCH 1:%d (UID FLAGS)", imap->count); |
|
|
|
imap->minuid); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|