added MaxSize configuration variable

fixed --fast to work robustly without relying on the \Recent flag in
messages
This commit is contained in:
Michael Elkins 2000-12-22 07:14:32 +00:00
parent a8f9af4296
commit 0527181f45
10 changed files with 347 additions and 159 deletions

View File

@ -1,5 +1,55 @@
2000-12-21 Michael Elkins <me@sigipe.org> 2000-12-21 Michael Elkins <me@sigipe.org>
* imap.c, isync.h, maildir.c, sync.c:
RFC822.PEEK is obsolete in RFC2060. Use BODY.PEEK[] instead, which does
the same thing
keep track of the uidvalidity so isync can detect if the mailbox on the
server has changed since the last sync.
* NEWS: updated NEWS for 0.3 release
* Makefile.am, isync.spec:
added support for building RPMS
* Makefile.am, isync.1:
added target for creating html version of the man page
documented the imaps: prefix to the Host command
* imap.c, sync.c:
can't assume flag order when fetching a message. just search for the
first `{' to find the message size.
* isync.1, sync.c:
added BUGS section to manpage detailing the fact that we break the
maildir(5) spec by parsing the filename
change message delivery to use the method described in maildir(5)
* configure.in, main.c, sync.c:
use getpass() to get the user's password
unlink the temp file if we are unable to fetch a new message from the
server.
update version to 0.3
* isync.1: fixed typo in man page for --verbose option
* Makefile.am, README, TODO, imap.c, isync.h, list.c:
added generic IMAP list parser and rewrote imap_exec() to handle
arbitrary data instead of hardcoded
* Makefile.am, README, configure.in, main.c:
fixes to compile cleanly under Solaris 2.7
* configure.in, imap.c, isync.1, isync.h, main.c:
added OpenSSL support
* ChangeLog, configure.in, main.c:
config options were not case insensitive
* imap.c, isync.h, maildir.c, main.c, sync.c: * imap.c, isync.h, maildir.c, main.c, sync.c:
don't fetch deleted messages when expunging don't fetch deleted messages when expunging

14
NEWS
View File

@ -1,3 +1,17 @@
[0.4]
Added MaxSize configuration option to limit downloading of new messages from
the server to less than some threshold.
More robust --fast option works without using \Recent flags, so the previous
problem with multiple accesses killing these flags is no longer a problem.
RFC2060 obsoleted RFC822.PEEK, use BODY.PEEK[] instead which does the same
job.
Don't need to request UID in a FETCH when doing UID FETCH (RFC2060 states
that its automatically returned).
[0.3] [0.3]
Fixed to clean up temp maildir files when the fetch of a new message failed. Fixed to clean up temp maildir files when the fetch of a new message failed.

View File

@ -1,5 +1,5 @@
AC_INIT(isync.h) AC_INIT(isync.h)
AM_INIT_AUTOMAKE(isync,0.3) AM_INIT_AUTOMAKE(isync,0.4)
AM_PROG_CC_STDC AM_PROG_CC_STDC
if test $CC = gcc; then if test $CC = gcc; then
CFLAGS="$CFLAGS -pipe" CFLAGS="$CFLAGS -pipe"

159
imap.c
View File

@ -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) ret = imap_exec (imap, "UID FETCH %d:* (FLAGS RFC822.SIZE)",
{ imap->minuid);
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, "FETCH 1:%d (UID FLAGS)", imap->count);
} }
} }

15
isync.1
View File

@ -66,12 +66,6 @@ Causes
to skip the step of synchronzing message flags between the local maildir to skip the step of synchronzing message flags between the local maildir
mailbox and the IMAP mailbox. Only new messages existing on the server will mailbox and the IMAP mailbox. Only new messages existing on the server will
be fetched into the local mailbox. be fetched into the local mailbox.
.B NOTE:
This command works by checking the \\Recent flag on messages in the IMAP
mailbox. If you access the IMAP mailbox from multiple locations, the
\\Recent flag will be lost between sessions, so you must do a full
synchronization to fetch the messages which do not exist in the local
mailbox.
.TP .TP
.B -h, --help .B -h, --help
Displays a summary of command line options Displays a summary of command line options
@ -158,6 +152,15 @@ Defines an alias for the mailbox which can be used as a shortcut on the
command line. command line.
.. ..
.TP .TP
\fBMaxSize\fR \fIbytes\fR
Sets a threshold for the maximum message size (in bytes) for which
.B isync
should fetch from the server. This is useful for weeding out messages with
large attachments. If
.I bytes
is 0, the maximum file size is
.B unlimited.
.TP
\fBRequireSSL\fR \fIyes|no\fR \fBRequireSSL\fR \fIyes|no\fR
.B isync .B isync
will abort the connection if a TLS/SSL session to the IMAP will abort the connection if a TLS/SSL session to the IMAP

17
isync.h
View File

@ -54,6 +54,7 @@ struct config
char *pass; char *pass;
char *box; char *box;
char *alias; char *alias;
unsigned int max_size;
config_t *next; config_t *next;
#if HAVE_LIBSSL #if HAVE_LIBSSL
char *cert_file; char *cert_file;
@ -69,7 +70,9 @@ struct mailbox
message_t *msgs; message_t *msgs;
unsigned int deleted; /* # of deleted messages */ unsigned int deleted; /* # of deleted messages */
unsigned int uidvalidity; unsigned int uidvalidity;
unsigned int maxuid; /* largest uid we know about */
unsigned int changed:1; unsigned int changed:1;
unsigned int maxuidchanged:1;
}; };
/* message dispositions */ /* message dispositions */
@ -86,6 +89,7 @@ struct message
char *file; char *file;
unsigned int uid; unsigned int uid;
unsigned int flags; unsigned int flags;
unsigned int size;
message_t *next; message_t *next;
unsigned int processed:1; /* message has already been evaluated */ unsigned int processed:1; /* message has already been evaluated */
unsigned int new:1; /* message is in the new/ subdir */ unsigned int new:1; /* message is in the new/ subdir */
@ -119,6 +123,8 @@ typedef struct
*/ */
unsigned int deleted; /* # of deleted messages */ unsigned int deleted; /* # of deleted messages */
unsigned int uidvalidity; unsigned int uidvalidity;
unsigned int maxuid;
unsigned int minuid;
/* NAMESPACE info */ /* NAMESPACE info */
list_t *ns_personal; list_t *ns_personal;
list_t *ns_other; list_t *ns_other;
@ -127,9 +133,8 @@ typedef struct
imap_t; imap_t;
/* flags for sync_mailbox */ /* flags for sync_mailbox */
#define SYNC_FAST (1<<0) /* don't sync flags, only fetch new msgs */ #define SYNC_DELETE (1<<0) /* delete local that don't exist on server */
#define SYNC_DELETE (1<<1) /* delete local that don't exist on server */ #define SYNC_EXPUNGE (1<<1) /* don't fetch deleted messages */
#define SYNC_EXPUNGE (1<<2) /* don't fetch deleted messages */
extern config_t global; extern config_t global;
extern unsigned int Tag; extern unsigned int Tag;
@ -142,19 +147,21 @@ extern SSL_CTX *SSLContext;
char *next_arg (char **); char *next_arg (char **);
int sync_mailbox (mailbox_t *, imap_t *, int); int sync_mailbox (mailbox_t *, imap_t *, int, unsigned int);
void imap_close (imap_t *); void imap_close (imap_t *);
int imap_fetch_message (imap_t *, unsigned int, int); int imap_fetch_message (imap_t *, unsigned int, int);
int imap_set_flags (imap_t *, unsigned int, unsigned int); int imap_set_flags (imap_t *, unsigned int, unsigned int);
int imap_expunge (imap_t *); int imap_expunge (imap_t *);
imap_t *imap_open (config_t *, int); imap_t *imap_open (config_t *, unsigned int);
mailbox_t *maildir_open (const char *, int fast); mailbox_t *maildir_open (const char *, int fast);
int maildir_expunge (mailbox_t *, int); int maildir_expunge (mailbox_t *, int);
int maildir_sync (mailbox_t *); int maildir_sync (mailbox_t *);
int maildir_set_uidvalidity (mailbox_t *, unsigned int uidvalidity); int maildir_set_uidvalidity (mailbox_t *, unsigned int uidvalidity);
message_t * find_msg (message_t * list, unsigned int uid);
/* parse an IMAP list construct */ /* parse an IMAP list construct */
list_t * parse_list (char *s, char **end); list_t * parse_list (char *s, char **end);
int is_atom (list_t *list); int is_atom (list_t *list);

View File

@ -6,6 +6,8 @@
User me User me
#Port 143 #Port 143
#Box INBOX #Box INBOX
# don't download messages larger than 200K bytes
MaxSize 200000
### ###
### work mailbox ### work mailbox

174
maildir.c
View File

@ -25,8 +25,38 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include "isync.h" #include "isync.h"
static int
do_lock (int fd, int flag)
{
struct flock lck;
struct stat sb;
if (fstat (fd, &sb))
{
perror ("fstat");
return -1;
}
memset (&lck, 0, sizeof (lck));
lck.l_type = flag;
lck.l_whence = SEEK_SET;
lck.l_start = 0;
lck.l_len = sb.st_size;
if (fcntl (fd, F_SETLK, &lck))
{
perror ("fcntl");
close (fd);
return -1;
}
return 0;
}
/* 2,<flags> */ /* 2,<flags> */
static void static void
parse_info (message_t * m, char *s) parse_info (message_t * m, char *s)
@ -49,6 +79,45 @@ parse_info (message_t * m, char *s)
} }
} }
static unsigned int
read_uid (const char *path, const char *file)
{
char full[_POSIX_PATH_MAX];
int fd;
int ret;
int len;
char buf[64];
unsigned int uid = 0;
snprintf (full, sizeof (full), "%s/%s", path, file);
fd = open (full, O_RDONLY);
if (fd == -1)
{
if (errno != ENOENT)
{
perror ("open");
return -1;
}
return 0; /* doesn't exist */
}
ret = do_lock (fd, F_RDLCK);
if (!ret)
{
len = read (fd, buf, sizeof (buf) - 1);
if (len == -1)
ret = -1;
else
{
buf[len] = 0;
uid = atol (buf);
}
}
ret |= do_lock (fd, F_UNLCK);
close (fd);
return ret ? ret : uid;
}
/* open a maildir mailbox. if `fast' is nonzero, we just check to make /* open a maildir mailbox. if `fast' is nonzero, we just check to make
* sure its a valid mailbox and don't actually parse it. any IMAP messages * sure its a valid mailbox and don't actually parse it. any IMAP messages
* with the \Recent flag set are guaranteed not to be in the mailbox yet, * with the \Recent flag set are guaranteed not to be in the mailbox yet,
@ -66,7 +135,6 @@ maildir_open (const char *path, int fast)
mailbox_t *m; mailbox_t *m;
char *s; char *s;
int count = 0; int count = 0;
FILE *fp;
/* check to make sure this looks like a valid maildir box */ /* check to make sure this looks like a valid maildir box */
snprintf (buf, sizeof (buf), "%s/new", path); snprintf (buf, sizeof (buf), "%s/new", path);
@ -84,16 +152,22 @@ maildir_open (const char *path, int fast)
m = calloc (1, sizeof (mailbox_t)); m = calloc (1, sizeof (mailbox_t));
m->path = strdup (path); m->path = strdup (path);
m->uidvalidity = -1;
/* check for the uidvalidity value */ /* check for the uidvalidity value */
snprintf (buf, sizeof (buf), "%s/isyncuidvalidity", path); m->uidvalidity = read_uid (path, "isyncuidvalidity");
if ((fp = fopen (buf, "r"))) if (m->uidvalidity == (unsigned int) -1)
{ {
buf[sizeof (buf) - 1] = 0; free (m->path);
if (fgets (buf, sizeof (buf) - 1, fp)) free (m);
m->uidvalidity = atol (buf); return NULL;
fclose (fp); }
/* load the current maxuid */
if ((m->maxuid = read_uid (path, "isyncmaxuid")) == (unsigned int) -1)
{
free (m->path);
free (m);
return NULL;
} }
if (fast) if (fast)
@ -108,6 +182,8 @@ maildir_open (const char *path, int fast)
d = opendir (buf); d = opendir (buf);
if (!d) if (!d)
{ {
free (m->path);
free (m);
perror ("opendir"); perror ("opendir");
return 0; return 0;
} }
@ -130,10 +206,15 @@ maildir_open (const char *path, int fast)
*/ */
s = strstr (p->file, "UID"); s = strstr (p->file, "UID");
if (!s) if (!s)
puts ("warning, no uid for message"); puts ("Warning, no uid for message");
else else
{ {
p->uid = strtol (s + 3, &s, 10); p->uid = strtol (s + 3, &s, 10);
if (p->uid > m->maxuid)
{
m->maxuid = p->uid;
m->maxuidchanged = 1;
}
if (*s && *s != ':') if (*s && *s != ':')
{ {
puts ("warning, unable to parse uid"); puts ("warning, unable to parse uid");
@ -183,6 +264,70 @@ maildir_expunge (mailbox_t * mbox, int dead)
return 0; return 0;
} }
static int
update_maxuid (mailbox_t * mbox)
{
int fd;
char buf[64];
size_t len;
unsigned int uid;
char path[_POSIX_PATH_MAX];
int ret = 0;
snprintf (path, sizeof (path), "%s/isyncmaxuid", mbox->path);
fd = open (path, O_RDWR | O_CREAT, 0600);
if (fd == -1)
{
perror ("open");
return -1;
}
/* lock the file */
if (do_lock (fd, F_WRLCK))
{
close (fd);
return -1;
}
/* read the file again just to make sure it wasn't updated while
* we were doing something else
*/
len = read (fd, buf, sizeof (buf) - 1);
buf[len] = 0;
uid = atol (buf);
if (uid > mbox->maxuid)
{
puts ("Error, maxuid is now higher (fatal)");
ret = -1;
}
if (!ret)
{
/* rewind */
lseek (fd, 0, SEEK_SET);
/* write out the file */
snprintf (buf, sizeof (buf), "%u\n", mbox->maxuid);
len = write (fd, buf, strlen (buf));
if (len == (size_t) - 1)
{
perror ("write");
ret = -1;
}
else
{
ret = ftruncate (fd, len);
if (ret)
perror ("ftruncate");
}
}
ret |= do_lock (fd, F_UNLCK);
ret |= close (fd);
return ret;
}
int int
maildir_sync (mailbox_t * mbox) maildir_sync (mailbox_t * mbox)
{ {
@ -190,6 +335,7 @@ maildir_sync (mailbox_t * mbox)
char path[_POSIX_PATH_MAX]; char path[_POSIX_PATH_MAX];
char oldpath[_POSIX_PATH_MAX]; char oldpath[_POSIX_PATH_MAX];
char *p; char *p;
int ret = 0;
if (mbox->changed) if (mbox->changed)
{ {
@ -219,7 +365,11 @@ maildir_sync (mailbox_t * mbox)
} }
} }
} }
return 0;
if (mbox->maxuidchanged)
ret = update_maxuid (mbox);
return ret;
} }
int int
@ -242,7 +392,7 @@ maildir_set_uidvalidity (mailbox_t * mbox, unsigned int uidvalidity)
ret = write (fd, buf, strlen (buf)); ret = write (fd, buf, strlen (buf));
if (ret == -1) if (ret == -1)
perror("write"); perror ("write");
else if ((size_t) ret != strlen (buf)) else if ((size_t) ret != strlen (buf))
ret = -1; ret = -1;
else else
@ -250,7 +400,7 @@ maildir_set_uidvalidity (mailbox_t * mbox, unsigned int uidvalidity)
if (close (fd)) if (close (fd))
{ {
perror("close"); perror ("close");
ret = -1; ret = -1;
} }

19
main.c
View File

@ -95,6 +95,7 @@ config_defaults (config_t * conf)
conf->port = global.port; conf->port = global.port;
conf->box = global.box; conf->box = global.box;
conf->host = global.host; conf->host = global.host;
conf->max_size = global.max_size;
#if HAVE_LIBSSL #if HAVE_LIBSSL
conf->require_ssl = global.require_ssl; conf->require_ssl = global.require_ssl;
conf->use_imaps = global.use_imaps; conf->use_imaps = global.use_imaps;
@ -206,6 +207,13 @@ load_config (char *where)
if (*cur) if (*cur)
(*cur)->alias = strdup (p); (*cur)->alias = strdup (p);
} }
else if (!strncasecmp ("maxsize", buf, 7))
{
if (*cur)
(*cur)->max_size = atol (p);
else
global.max_size = atol (p);
}
#if HAVE_LIBSSL #if HAVE_LIBSSL
else if (!strncasecmp ("CertificateFile", buf, 15)) else if (!strncasecmp ("CertificateFile", buf, 15))
{ {
@ -285,6 +293,7 @@ main (int argc, char **argv)
global.port = 143; global.port = 143;
global.box = "INBOX"; global.box = "INBOX";
global.user = strdup (pw->pw_name); global.user = strdup (pw->pw_name);
global.max_size = 100000;
#if HAVE_LIBSSL #if HAVE_LIBSSL
/* this will probably annoy people, but its the best default just in /* this will probably annoy people, but its the best default just in
* case people forget to turn it on * case people forget to turn it on
@ -380,16 +389,14 @@ main (int argc, char **argv)
exit (1); exit (1);
} }
imap = imap_open (box, fast); imap = imap_open (box, fast ? mail->maxuid + 1 : 1);
if (!imap) if (!imap)
exit (1); exit (1);
puts ("Synchronizing"); puts ("Synchronizing");
i = 0; i = delete ? SYNC_DELETE : 0;
i |= (fast) ? SYNC_FAST : 0; i |= expunge ? SYNC_EXPUNGE : 0;
i |= (delete) ? SYNC_DELETE : 0; if (sync_mailbox (mail, imap, i, box->max_size))
i |= (expunge) ? SYNC_EXPUNGE : 0;
if (sync_mailbox (mail, imap, i))
exit (1); exit (1);
if (!fast) if (!fast)

54
sync.c
View File

@ -31,7 +31,7 @@
static unsigned int MaildirCount = 0; static unsigned int MaildirCount = 0;
static message_t * message_t *
find_msg (message_t * list, unsigned int uid) find_msg (message_t * list, unsigned int uid)
{ {
for (; list; list = list->next) for (; list; list = list->next)
@ -41,7 +41,7 @@ find_msg (message_t * list, unsigned int uid)
} }
int int
sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags) sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags, unsigned int max_size)
{ {
message_t *cur; message_t *cur;
message_t *tmp; message_t *tmp;
@ -69,12 +69,21 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
return -1; return -1;
} }
if (mbox->maxuid == (unsigned int) -1 || imap->maxuid > mbox->maxuid)
{
mbox->maxuid = imap->maxuid;
mbox->maxuidchanged = 1;
}
/* if we are --fast mode, the mailbox wont have been loaded, so
* this next step is skipped.
*/
for (cur = mbox->msgs; cur; cur = cur->next) for (cur = mbox->msgs; cur; cur = cur->next)
{ {
tmp = find_msg (imap->msgs, cur->uid); tmp = find_msg (imap->msgs, cur->uid);
if (!tmp) if (!tmp)
{ {
printf ("warning, uid %d doesn't exist on server\n", cur->uid); printf ("Warning, uid %d doesn't exist on server\n", cur->uid);
if (flags & SYNC_DELETE) if (flags & SYNC_DELETE)
{ {
cur->flags |= D_DELETED; cur->flags |= D_DELETED;
@ -85,25 +94,22 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
} }
tmp->processed = 1; tmp->processed = 1;
if (!(flags & SYNC_FAST)) /* check if local flags are different from server flags.
* ignore \Recent and \Draft
*/
if (cur->flags != (tmp->flags & ~(D_RECENT | D_DRAFT)))
{ {
/* check if local flags are different from server flags. /* set local flags that don't exist on the server */
* ignore \Recent and \Draft if (!(tmp->flags & D_DELETED) && (cur->flags & D_DELETED))
*/ imap->deleted++;
if (cur->flags != (tmp->flags & ~(D_RECENT | D_DRAFT))) imap_set_flags (imap, cur->uid, cur->flags & ~tmp->flags);
{
/* set local flags that don't exist on the server */
if (!(tmp->flags & D_DELETED) && (cur->flags & D_DELETED))
imap->deleted++;
imap_set_flags (imap, cur->uid, cur->flags & ~tmp->flags);
/* update local flags */ /* update local flags */
if((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED)) if((cur->flags & D_DELETED) == 0 && (tmp->flags & D_DELETED))
mbox->deleted++; mbox->deleted++;
cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT)); cur->flags |= (tmp->flags & ~(D_RECENT | D_DRAFT));
cur->changed = 1; cur->changed = 1;
mbox->changed = 1; mbox->changed = 1;
}
} }
} }
@ -124,6 +130,13 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
continue; continue;
} }
if (max_size && cur->size > max_size)
{
printf ("Warning, message skipped because it is too big (%u)\n",
cur->size);
continue;
}
for (;;) for (;;)
{ {
/* create new file */ /* create new file */
@ -150,7 +163,6 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags)
(cur->flags & D_ANSWERED) ? "R" : "", (cur->flags & D_ANSWERED) ? "R" : "",
(cur->flags & D_SEEN) ? "S" : "", (cur->flags & D_SEEN) ? "S" : "",
(cur->flags & D_DELETED) ? "T" : ""); (cur->flags & D_DELETED) ? "T" : "");
} }
/* give some visual feedback that something is happening */ /* give some visual feedback that something is happening */