Bunch 'o patches from Oswald Buddenhagen:

i implemented some cool stuff (tm).
first, the long missing "create server-side missing mailboxes". -C now
creates both local and remote boxes; -L and -R create only local/remote.
second, i implemented a 1:1 remote:local folder mapping (-1) with an
optional INBOX exception (inbox/-I). the remote folder is specified with
the folder keyword (or -F switch) and takes precedence over the
namespace setting. the local directory with the mailboxes can now be
specified on the command line, too (-M).

another patch:
- made the -1 switch settable permanently (OneToOne). after all, you
  usually define your mailbox layout once forever. removed -A, as it is
  semantically -a modified by -1.
- cleaned up message output a bit. still, the quiet variable should be
  used throughout the program. at best, create some generic output
  function, which obeys a global verbosity level variable.
- optimized + cleaned up configuration parser slightly
- minor cleanups

add an (almost) unique id to every uploaded message and search for it
right after. i thought about using the message-id, but a) it is not
guaranteed to be unique in a mailbox (imagine you edit a mail and store
the dupe in the same box) and b) some mails (e.g., postponed) don't even
have one. a downside of the current implementation is, that this
id-header remains in the mailbox, but given that it wastes only 27 bytes
per mail and removing it would mean several roundtrips more, this seems
acceptable.
i changed the line-counting loop to use a mmapped file instead of
reading it in chunks, as it makes things simpler and is probably even
faster for big mails.
the amount of goto statements in my code may be scary, but c is simply
lacking a multi-level break statement. :)

this is the "shut up" patch. :) it makes the -q option consequent, so to
say.
additionally it adds an -l option which gathers all defined/found
mailboxes and just outputs the list. don't ask what i need it for. ;)
This commit is contained in:
Michael Elkins 2002-10-30 02:23:05 +00:00
parent 0bd3709a9d
commit 7cd74a1179
8 changed files with 780 additions and 664 deletions

12
.cvsignore Normal file
View File

@ -0,0 +1,12 @@
.deps
Makefile
Makefile.in
autom4te.cache
aclocal.m4
build-stamp
config.cache
config.log
config.status
configure
configure-stamp
isync

205
config.c
View File

@ -91,13 +91,23 @@ expand_strdup (const char *s)
return strdup (s); return strdup (s);
} }
static int
is_true (const char *val)
{
return
!strcasecmp (val, "yes") ||
!strcasecmp (val, "true") ||
!strcasecmp (val, "on") ||
!strcmp (val, "1");
}
void void
load_config (const char *where) load_config (const char *where, int *o2o)
{ {
char path[_POSIX_PATH_MAX]; char path[_POSIX_PATH_MAX];
char buf[1024]; char buf[1024];
struct passwd *pw; struct passwd *pw;
config_t **cur = &boxes; config_t **cur = &boxes, *cfg;
int line = 0; int line = 0;
FILE *fp; FILE *fp;
char *p, *cmd, *val; char *p, *cmd, *val;
@ -109,7 +119,7 @@ load_config (const char *where)
where = path; where = path;
} }
printf ("Reading %s\n", where); info ("Reading configuration file %s\n", where);
fp = fopen (where, "r"); fp = fopen (where, "r");
if (!fp) if (!fp)
@ -119,6 +129,7 @@ load_config (const char *where)
return; return;
} }
buf[sizeof buf - 1] = 0; buf[sizeof buf - 1] = 0;
cfg = &global;
while ((fgets (buf, sizeof (buf) - 1, fp))) while ((fgets (buf, sizeof (buf) - 1, fp)))
{ {
p = buf; p = buf;
@ -129,174 +140,116 @@ load_config (const char *where)
continue; continue;
if (!strcasecmp ("mailbox", cmd)) if (!strcasecmp ("mailbox", cmd))
{ {
if (*cur) if (*o2o)
cur = &(*cur)->next; break;
*cur = calloc (1, sizeof (config_t)); cur = &(*cur)->next;
config_defaults (*cur); cfg = *cur = malloc (sizeof (config_t));
config_defaults (cfg);
/* not expanded at this point */ /* not expanded at this point */
(*cur)->path = strdup (val); cfg->path = strdup (val);
}
else if (!strcasecmp ("OneToOne", cmd))
{
if (*cur) {
forbid:
fprintf (stderr,
"%s:%d: keyword '%s' allowed only in global section\n",
path, line, cmd);
continue;
}
*o2o = is_true (val);
} }
else if (!strcasecmp ("maildir", cmd)) else if (!strcasecmp ("maildir", cmd))
{ {
if (*cur)
goto forbid;
/* this only affects the global setting */ /* this only affects the global setting */
free (global.maildir); free (global.maildir);
global.maildir = expand_strdup (val); global.maildir = expand_strdup (val);
} }
else if (!strcasecmp ("folder", cmd))
{
if (*cur)
goto forbid;
/* this only affects the global setting */
global.folder = strdup (val);
}
else if (!strcasecmp ("inbox", cmd))
{
if (*cur)
goto forbid;
/* this only affects the global setting */
global.inbox = strdup (val);
}
else if (!strcasecmp ("host", cmd)) else if (!strcasecmp ("host", cmd))
{ {
#if HAVE_LIBSSL #if HAVE_LIBSSL
if (!strncasecmp ("imaps:", val, 6)) if (!strncasecmp ("imaps:", val, 6))
{ {
val += 6; val += 6;
if (*cur) cfg->use_imaps = 1;
{ cfg->port = 993;
(*cur)->use_imaps = 1; cfg->use_sslv2 = 1;
(*cur)->port = 993; cfg->use_sslv3 = 1;
(*cur)->use_sslv2 = 1;
(*cur)->use_sslv3 = 1;
}
else
{
global.use_imaps = 1;
global.port = 993;
global.use_sslv2 = 1;
global.use_sslv3 = 1;
}
} }
#endif #endif
if (*cur) cfg->host = strdup (val);
(*cur)->host = strdup (val);
else
global.host = strdup (val);
} }
else if (!strcasecmp ("user", cmd)) else if (!strcasecmp ("user", cmd))
{ {
if (*cur) if (*cur)
(*cur)->user = strdup (val); (*cur)->user = strdup (val);
else else {
free (global.user);
global.user = strdup (val); global.user = strdup (val);
}
} }
else if (!strcasecmp ("pass", cmd)) else if (!strcasecmp ("pass", cmd))
{ cfg->pass = strdup (val);
if (*cur)
(*cur)->pass = strdup (val);
else
global.pass = strdup (val);
}
else if (!strcasecmp ("port", cmd)) else if (!strcasecmp ("port", cmd))
{ cfg->port = atoi (val);
if (*cur)
(*cur)->port = atoi (val);
else
global.port = atoi (val);
}
else if (!strcasecmp ("box", cmd)) else if (!strcasecmp ("box", cmd))
{ cfg->box = strdup (val);
if (*cur)
(*cur)->box = strdup (val);
else
global.box = strdup (val);
}
else if (!strcasecmp ("alias", cmd)) else if (!strcasecmp ("alias", cmd))
{ {
if (*cur) if (!*cur) {
(*cur)->alias = strdup (val); fprintf (stderr,
"%s:%d: keyword 'alias' allowed only in mailbox specification\n",
path, line);
continue;
}
cfg->alias = strdup (val);
} }
else if (!strcasecmp ("maxsize", cmd)) else if (!strcasecmp ("maxsize", cmd))
{ cfg->max_size = atol (val);
if (*cur)
(*cur)->max_size = atol (val);
else
global.max_size = atol (val);
}
else if (!strcasecmp ("MaxMessages", cmd)) else if (!strcasecmp ("MaxMessages", cmd))
{ cfg->max_messages = atol (val);
if (*cur)
(*cur)->max_messages = atol (val);
else
global.max_messages = atol (val);
}
else if (!strcasecmp ("UseNamespace", cmd)) else if (!strcasecmp ("UseNamespace", cmd))
{ cfg->use_namespace = is_true (val);
if (*cur)
(*cur)->use_namespace = (strcasecmp (val, "yes") == 0);
else
global.use_namespace = (strcasecmp (val, "yes") == 0);
}
else if (!strcasecmp ("CopyDeletedTo", cmd)) else if (!strcasecmp ("CopyDeletedTo", cmd))
{ cfg->copy_deleted_to = strdup (val);
if (*cur)
(*cur)->copy_deleted_to = strdup (val);
else
global.copy_deleted_to = strdup (val);
}
else if (!strcasecmp ("Tunnel", cmd)) else if (!strcasecmp ("Tunnel", cmd))
{ cfg->tunnel = strdup (val);
if (*cur)
(*cur)->tunnel = strdup (val);
else
global.tunnel = strdup (val);
}
else if (!strcasecmp ("Expunge", cmd)) else if (!strcasecmp ("Expunge", cmd))
{ cfg->expunge = is_true (val);
if (*cur)
(*cur)->expunge = (strcasecmp (val, "yes") == 0);
else
global.expunge = (strcasecmp (val, "yes") == 0);
}
else if (!strcasecmp ("Delete", cmd)) else if (!strcasecmp ("Delete", cmd))
{ cfg->delete = is_true (val);
if (*cur)
(*cur)->delete = (strcasecmp (val, "yes") == 0);
else
global.delete = (strcasecmp (val, "yes") == 0);
}
#if HAVE_LIBSSL #if HAVE_LIBSSL
else if (!strcasecmp ("CertificateFile", cmd)) else if (!strcasecmp ("CertificateFile", cmd))
{ cfg->cert_file = expand_strdup (val);
if (*cur)
(*cur)->cert_file = expand_strdup (val);
else
global.cert_file = expand_strdup (val);
}
else if (!strcasecmp ("RequireSSL", cmd)) else if (!strcasecmp ("RequireSSL", cmd))
{ cfg->require_ssl = is_true (val);
if (*cur)
(*cur)->require_ssl = (strcasecmp (val, "yes") == 0);
else
global.require_ssl = (strcasecmp (val, "yes") == 0);
}
else if (!strcasecmp ("UseSSLv2", cmd)) else if (!strcasecmp ("UseSSLv2", cmd))
{ cfg->use_sslv2 = is_true (val);
if (*cur)
(*cur)->use_sslv2 = (strcasecmp (val, "yes") == 0);
else
global.use_sslv2 = (strcasecmp (val, "yes") == 0);
}
else if (!strcasecmp ("UseSSLv3", cmd)) else if (!strcasecmp ("UseSSLv3", cmd))
{ cfg->use_sslv3 = is_true (val);
if (*cur)
(*cur)->use_sslv3 = (strcasecmp (val, "yes") == 0);
else
global.use_sslv3 = (strcasecmp (val, "yes") == 0);
}
else if (!strcasecmp ("UseTLSv1", cmd)) else if (!strcasecmp ("UseTLSv1", cmd))
{ cfg->use_tlsv1 = is_true (val);
if (*cur)
(*cur)->use_tlsv1 = (strcasecmp (val, "yes") == 0);
else
global.use_tlsv1 = (strcasecmp (val, "yes") == 0);
}
else if (!strcasecmp ("RequireCRAM", cmd)) else if (!strcasecmp ("RequireCRAM", cmd))
{ cfg->require_cram = is_true (val);
if (*cur)
(*cur)->require_cram = (strcasecmp (val, "yes") == 0);
else
global.require_cram = (strcasecmp (val, "yes") == 0);
}
#endif #endif
else if (buf[0]) else if (buf[0])
printf ("%s:%d:unknown keyword:%s\n", path, line, cmd); fprintf (stderr, "%s:%d: unknown keyword '%s'\n", path, line, cmd);
} }
fclose (fp); fclose (fp);
} }

614
imap.c

File diff suppressed because it is too large Load Diff

314
isync.1
View File

@ -1,6 +1,6 @@
.ig .ig
\" isync - IMAP4 to maildir mailbox synchronizer \" isync - IMAP4 to maildir mailbox synchronizer
\" Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org> \" Copyright (C) 2000-2002 Michael R. Elkins <me@mutt.org>
\" \"
\" This program is free software; you can redistribute it and/or modify \" This program is free software; you can redistribute it and/or modify
\" it under the terms of the GNU General Public License as published by \" it under the terms of the GNU General Public License as published by
@ -16,66 +16,70 @@
\" along with this program; if not, write to the Free Software \" along with this program; if not, write to the Free Software
\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
.. ..
.TH isync 1 "2002 Jun 17" .TH isync 1 "2002 Oct 14"
.. ..
.SH NAME .SH NAME
isync - synchronize IMAP4 and maildir mailboxes isync - synchronize IMAP4 and maildir mailboxes
.. ..
.SH SYNOPSIS .SH SYNOPSIS
.B isync \fBisync\fR [\fIoptions...\fR] \fImailbox\fR [\fImailbox ...\fR]
[ .br
.I options... \fBisync\fR [\fIoptions...\fR] \fI-a\fR
] .br
.I mailbox \fBisync\fR [\fIoptions...\fR] \fI-l\fR
[
.I mailbox ...
]
.. ..
.SH DESCRIPTION .SH DESCRIPTION
.B isync \fBisync\fR is a command line application which synchronizes a local
is a command line application which synchronizes a local maildir-style maildir-style mailbox with a remote IMAP4 mailbox, suitable for use in
mailbox with a remote IMAP4 mailbox, suitable for use in IMAP-disconnected IMAP-disconnected mode. Multiple copies of the remote IMAP4 mailbox can
mode. Multiple copies of the remote IMAP4 mailbox can be maintained, and be maintained, and all flags are synchronized.
all flags are synchronized.
.. ..
.SH OPTIONS .SH OPTIONS
.TP .TP
\fB-a\fR, \fB--all\fR \fB-c\fR, \fB--config\fR \fIfile\fR
Synchronize all mailboxes specified in the user's ~/.isyncrc. Read configuration from \fIfile\fR.
By default, the configuration is read from ~/.isyncrc if it exists.
.TP .TP
\fB-C\fR, \fB--create\fR \fB-1\fR, \fB--one-to-one\fR
Instead of using the mailbox specifications in ~/.isyncrc, isync will pick up
all mailboxes from the local directory and remote folder and map them 1:1
onto each other according to their names.
.TP
\fB-I\fR, \fB--inbox\fR \fImailbox\fR
Exception to the 1:1 mapping created by -1: the special IMAP mailbox \fIINBOX\fR
is mapped to the local \fImailbox\fR (relative to the maildir).
.TP
\fB-a\fR, \fB--all\fR
Synchronize all mailboxes (either specified in ~/.isyncrc or determined by the
1:1 mapping).
.TP
\fB-l\fR, \fB--list\fR
Don't synchronize anything, but list all mailboxes and exit.
.TP
\fB-L\fR, \fB--create-local\fR
Automatically create the local maildir-style mailbox if it doesn't already Automatically create the local maildir-style mailbox if it doesn't already
exist. exist.
.TP .TP
\fB-c\fR, \fB--config\fR \fIfile\fR \fB-R\fR, \fB--create-remote\fR
Read configuration from Automatically create the remote IMAP mailbox if it doesn't already exist.
.I file
By default, configuration is read from ~/.isyncrc if it exists.
.TP .TP
.B -d, --delete \fB-C\fR, \fB--create\fR
Causes Automatically create any mailboxes if they doesn't already exist.
.B isync .TP
to delete messages from the local maildir mailbox which do not exist on the \fB-d\fR, \fB--delete\fR
IMAP server. By default, Causes \fBisync\fR to delete messages from the local maildir mailbox
.I dead which do not exist on the IMAP server. By default, \fIdead\fR messages
messages are are \fBnot\fR deleted.
.B not
deleted.
.TP .TP
\fB-e\fR, \fB--expunge\fR \fB-e\fR, \fB--expunge\fR
Causes Causes \fBisync\fR to permanently remove all messages marked for deletion
.B isync in both the local maildir mailbox and the remote IMAP mailbox. By default,
to permanently remove all messages marked for deletion in both the local messages are \fBnot\fR expunged.
maildir mailbox and the remote IMAP mailbox. By default, messages are
.B not
expunged.
.TP .TP
\fB-f\fR, \fB--fast\fR \fB-f\fR, \fB--fast\fR
Causes Causes \fBisync\fR to skip the step of synchronzing message flags between the
.B isync local maildir mailbox and the IMAP mailbox. Only new messages existing on the
to skip the step of synchronzing message flags between the local maildir server will be fetched into the local mailbox.
mailbox and the IMAP mailbox. Only new messages existing on the server will
be fetched into the local mailbox.
.TP .TP
\fB-h\fR, \fB--help\fR \fB-h\fR, \fB--help\fR
Displays a summary of command line options Displays a summary of command line options
@ -96,44 +100,34 @@ Specifies the hostname of the IMAP server
\fB-u\fR, \fB--user\fR \fIuser\fR \fB-u\fR, \fB--user\fR \fIuser\fR
Specifies the login name to access the IMAP server (default: $USER) Specifies the login name to access the IMAP server (default: $USER)
.TP .TP
.B -v, --version \fB-M\fR, \fB--maildir\fR \fIdir\fR
Displays Specifies the location for your local mailboxes.
.B isync
version information
.TP .TP
.B -V, --verbose \fB-F\fR, \fB--folder\fR \fIfolder\fR/
Enables Specifies the location for your remote mailboxes.
.I verbose .TP
mode, which displays the IMAP4 network traffic. \fB-v\fR, \fB--version\fR
Displays \fBisync\fR version information.
.TP
\fB-V\fR, \fB--verbose\fR
Enables \fIverbose\fR mode, which displays the IMAP4 network traffic.
.. ..
.SH CONFIGURATION .SH CONFIGURATION
.B isync \fBisync\fR reads \fI~/.isyncrc\fR to load default configuration data.
reads Each line of the configuration file consists of a command.
.I ~/.isyncrc The following commands are understood:
to load default configuration data. Each line of the configuration file
consists of a command. The following commands are understood:
.TP .TP
\fBMailbox\fR \fIpath\fR \fBMailbox\fR \fIpath\fR
Defines a local maildir mailbox. All configuration commands following this Defines a local maildir mailbox. All configuration commands following this
line, up until the next line, up until the next \fIMailbox\fR command, apply to this mailbox only.
.I Mailbox
command, apply to this mailbox only.
.. ..
.TP .TP
\fBHost\fR \fB[\fRimaps:\fB]\fR\fIname\fR \fBHost\fR \fB[\fRimaps:\fB]\fR\fIname\fR
Defines the DNS name or IP address of the IMAP server. If the hostname is Defines the DNS name or IP address of the IMAP server. If the hostname is
prefixed with prefixed with \fIimaps:\fR the connection is assumed to be a SSL connection
.I imaps: to port 993 (though you can change this by placing a \fBPort\fR command
the connection is assumed to be a SSL connection to port 993 (though you can \fBafter\fR the \fBHost\fR command. Note that some servers support SSL on
change this by placing a the default port 143. \fBisync\fR will always attempt to use SSL if available.
.B Port
command
.B after
the
.B Host
command. Note that some servers support SSL on the default port 143.
.B isync
will always attempt to use SSL if available.
.. ..
.TP .TP
\fBPort\fR \fIport\fR \fBPort\fR \fIport\fR
@ -150,12 +144,9 @@ Defines the login name on the IMAP server (Default: current user)
.. ..
.TP .TP
\fBPass\fR \fIpassword\fR \fBPass\fR \fIpassword\fR
Defines the password for Defines the password for \fIusername\fR on the IMAP server.
.I username Note that this option is \fBNOT\fR required.
on the IMAP server. Note that this option is If no password is specified in the configuration file, \fBisync\fR
.B NOT
required. If no password is specified in the configuration file,
.B isync
will prompt you for it. will prompt you for it.
.. ..
.TP .TP
@ -164,64 +155,58 @@ Defines an alias for the mailbox which can be used as a shortcut on the
command line. command line.
.. ..
.TP .TP
\fBCopyDeletedTo\fR \fIstring\fR \fBCopyDeletedTo\fR \fImailbox\fR
Specifies the remote IMAP mailbox to copy deleted messages prior to Specifies the remote IMAP mailbox to copy deleted messages prior to
expunging (Default: none). expunging (Default: none).
.. ..
.TP .TP
\fBDelete\fR \fIyes|no\fR \fBDelete\fR \fIyes\fR|\fIno\fR
Specifies whether messages in the local copy of the mailbox which don't Specifies whether messages in the local copy of the mailbox which don't
exist on the server are automatically deleted. (Default: no). exist on the server are automatically deleted. (Default: no).
\fBNOTE:\fR The \fI-d\fR command line option overrides this setting when
set to \fIno\fR.
.. ..
.TP .TP
\fBExpunge\fR \fIyes|no\fR \fBExpunge\fR \fIyes\fR|\fIno\fR
Specifies whether deleted messages are expunged by default (Default: no). Specifies whether deleted messages are expunged by default (Default: no).
\fBNOTE:\fR The \fBNOTE:\fR The \fI-e\fR command line option overrides this setting when
.I -e set to \fIno\fR.
command line option overrides this setting when set to
\fIno\fR.
.. ..
.TP .TP
\fBMailDir\fR \fIstring\fR \fBMailDir\fR \fIdirectory\fR
Specifies the location for your mailboxes if a relative path is Specifies the location of your local mailboxes if a relative path is
specified in a specified in a \fIMailbox\fR command (Default: \fI~\fR).
.I Mailbox \fBNOTE:\fR This directive is only meaningful in the \fIglobal\fR
command (Default: \fI~\fR). section (see below).
.B NOTE: ..
This directive is only meaningful the in .TP
.I global \fBFolder\fR \fIdirectory\fR/
Specifies the location of your IMAP mailboxes
specified in \fIBox\fR commands (Default: \fI""\fR).
\fBNOTE:\fR You \fBmust\fR append the hierarchy delimiter (usually
a slash) to this specification.
\fBNOTE 2:\fR This directive is only meaningful in the \fIglobal\fR
section (see below). section (see below).
.. ..
.TP .TP
\fBMaxMessages\fR \fIcount\fR \fBMaxMessages\fR \fIcount\fR
Sets the number of messages Sets the number of messages \fBisync\fR should keep in a mailbox.
.B isync
should keep in a mailbox.
This is useful for mailboxes where you keep a complete archive on the This is useful for mailboxes where you keep a complete archive on the
server, but want to mirror only the last messages (for instance, for mailing server, but want to mirror only the last messages (for instance, for mailing
lists.) lists.)
The messages that were the first to arrive in the mailbox (independent of the The messages that were the first to arrive in the mailbox (independent of the
actual date of the message) will automatically be deleted if you tell actual date of the message) will automatically be deleted if you
pass pass \fBisync\fR the delete (-d, --delete) flag.
.B isync
the delete (-d, --delete) flag.
Messages that are flagged (marked as important) will not be automatically Messages that are flagged (marked as important) will not be automatically
deleted. deleted.
If If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR
.I count
is 0, the maximum number of messages is
.B unlimited
(Default: 0). (Default: 0).
.. ..
.TP .TP
\fBMaxSize\fR \fIbytes\fR \fBMaxSize\fR \fIbytes\fR
Sets a threshold for the maximum message size (in bytes) for which Sets a threshold for the maximum message size (in bytes) for which \fBisync\fR
.B isync
should fetch from the server. This is useful for weeding out messages with should fetch from the server. This is useful for weeding out messages with
large attachments. If large attachments. If \fIbytes\fR is 0, the maximum file size is \fBunlimited\fR.
.I bytes
is 0, the maximum file size is
.B unlimited.
.. ..
.TP .TP
\fBTunnel\fR \fIcommand\fR \fBTunnel\fR \fIcommand\fR
@ -229,79 +214,64 @@ Specify a command to run to establish a connection rather than opening a TCP
socket. This allows you to run an IMAP session over an SSH tunnel, for socket. This allows you to run an IMAP session over an SSH tunnel, for
example. example.
.TP .TP
\fBUseNamespace\fR \fIyes|no\fR \fBUseNamespace\fR \fIyes\fR|\fIno\fR
Selects whether Selects whether \fBisync\fR should select mailboxes using the namespace given
.B isync by the NAMESPACE command. This is useful with broken IMAP servers. (Default:
should select mailboxes using the namespace given by the NAMESPACE command. \fIyes\fR)
This is useful with broken IMAP servers. (Default:
.I yes
)
.. ..
.TP .TP
\fBRequireCRAM\fR \fIyes|no\fR \fBRequireCRAM\fR \fIyes\fR|\fIno\fR
If set to If set to \fIyes\fR, \fBisync\fR will require that the server accept CRAM-MD5
.I yes intead of PLAIN to authenticate the user.
,
.B isync
will require that the server accept CRAM-MD5 intead of PLAIN to authenticate
the user.
.. ..
.TP .TP
\fBRequireSSL\fR \fIyes|no\fR \fBRequireSSL\fR \fIyes\fR|\fIno\fR
.B isync \fBisync\fR will abort the connection if a TLS/SSL session to the IMAP
will abort the connection if a TLS/SSL session to the IMAP server can not be established. (Default: \fIyes\fR)
server can not be established. (Default:
.I yes
)
.. ..
.TP .TP
\fBCertificateFile\fR \fIpath\fR \fBCertificateFile\fR \fIpath\fR
File containing X.509 CA certificates used to verify server identities. File containing X.509 CA certificates used to verify server identities.
.. ..
.TP .TP
\fBUseSSLv2\fR \fIyes|no\fR \fBUseSSLv2\fR \fIyes\fR|\fIno\fR
Should Should \fBisync\fR use SSLv2 for communication with the IMAP server over SSL?
.B isync (Default: \fIyes\fR if the imaps port is used, otherwise \fIno\fR)
use SSLv2 for communication with the IMAP server over SSL? (Default:
.I yes
if the imaps port is used, otherwise
.I no
)
.. ..
.TP .TP
\fBUseSSLv3\fR \fIyes|no\fR \fBUseSSLv3\fR \fIyes\fR|\fIno\fR
Should Should \fBisync\fR use SSLv3 for communication with the IMAP server over SSL?
.B isync (Default: \fIyes\fR if the imaps port is used, otherwise \fIno\fR)
use SSLv3 for communication with the IMAP server over SSL? (Default:
.I yes
if the imaps port is used, otherwise
.I no
)
.. ..
.TP .TP
\fBUseTLSv1\fR \fIyes|no\fR \fBUseTLSv1\fR \fIyes\fR|\fIno\fR
Should Should \fBisync\fR use TLSv1 for communication with the IMAP server over SSL?
.B isync (Default: \fIyes\fR)
use TLSv1 for communication with the IMAP server over SSL? (Default: ..
.I yes .TP
) \fBOneToOne\fR
\fBisync\fR will ignore any \fIMailbox\fR specifications and instead pick up
all mailboxes from the local \fIMailDir\fR and remote \fIFolder\fR and map
them 1:1 onto each other according to their names.
\fBNOTE:\fR This directive is only meaningful in the \fIglobal\fR
section (see below).
..
.TP
\fBInbox\fR \fImailbox\fR
Exception to the OneToOne mapping: the special IMAP mailbox \fIINBOX\fR
is mapped to the local \fImailbox\fR (relative to the \fIMailDir\fR).
\fBNOTE:\fR This directive is only meaningful in the \fIglobal\fR
section (see below).
.. ..
.P .P
Configuration commands that appear prior to the first Configuration commands that appear prior to the first \fBMailbox\fR
.B Mailbox command are considered to be \fIglobal\fR
command are considered to be
.I global
options which are used as defaults when those specific options are not options which are used as defaults when those specific options are not
specifically set for a defined Mailbox. For example, if you use the same specifically set for a defined Mailbox. For example, if you use the same
login name for several IMAP servers, you can put a login name for several IMAP servers, you can put a \fBUser\fR command before
.B User the first \fBMailbox\fR command, and then leave out the \fBUser\fR command
command before the first in the sections for each mailbox.
.B Mailbox \fBisync\fR will then use the global value by default.
command, and then leave out the
.B User
command in the sections for each mailbox.
.B isync
will then use the global value by default.
.. ..
.SH FILES .SH FILES
.TP .TP
@ -309,20 +279,16 @@ will then use the global value by default.
Default configuration file Default configuration file
.. ..
.SH BUGS .SH BUGS
.B isync \fBisync\fR does not use NFS-safe locking. It will correctly prevent
does not use NFS-safe locking. It will correctly prevent concurrent concurrent synchronization of a mailbox on the same host, but not across NFS.
synchronization of a mailbox on the same host, but not across NFS.
.P .P
When synchronizing multiple mailboxes on the same IMAP server, it is not When synchronizing multiple mailboxes on the same IMAP server, it is not
possible to select different SSL options for each mailbox. Only the options possible to select different SSL options for each mailbox. Only the options
from the first mailbox are applied since the SSL session is reused. from the first mailbox are applied since the SSL session is reused.
.P .P
If new mail arrives in the IMAP mailbox after If new mail arrives in the IMAP mailbox after \fBisync\fR
.B isync
has retrieved the initial message list, the new mail will not be fetched has retrieved the initial message list, the new mail will not be fetched
until the next time until the next time \fBisync\fR is invoked.
.B isync
is invoked.
.P .P
It is currently impossible to unset the \\Flagged attribute of a message It is currently impossible to unset the \\Flagged attribute of a message
once it is set. It has to be manually unset everywhere since isync once it is set. It has to be manually unset everywhere since isync
@ -331,12 +297,12 @@ message.
.P .P
The ndbm database created for each mailbox is not portable across different The ndbm database created for each mailbox is not portable across different
architectures. It currently stores the UID in host byte order. architectures. It currently stores the UID in host byte order.
.P
The configuration file takes precedence over command line options.
.SH SEE ALSO .SH SEE ALSO
mutt(1), maildir(5) mutt(1), maildir(5)
.P .P
Up to date information on Up to date information on \fBisync\fR can be found at
.B isync
can be found at
http://www.cs.hmc.edu/~me/isync/. http://www.cs.hmc.edu/~me/isync/.
.. ..
.SH AUTHOR .SH AUTHOR

13
isync.h
View File

@ -62,7 +62,9 @@ struct config
int port; int port;
char *user; char *user;
char *pass; char *pass;
char *folder;
char *box; char *box;
char *inbox;
char *alias; char *alias;
char *copy_deleted_to; char *copy_deleted_to;
char *tunnel; char *tunnel;
@ -151,6 +153,7 @@ typedef struct
list_t *ns_personal; list_t *ns_personal;
list_t *ns_other; list_t *ns_other;
list_t *ns_shared; list_t *ns_shared;
unsigned int have_uidplus:1;
unsigned int have_namespace:1; unsigned int have_namespace:1;
#if HAVE_LIBSSL #if HAVE_LIBSSL
unsigned int have_cram:1; unsigned int have_cram:1;
@ -163,7 +166,6 @@ imap_t;
/* flags for sync_mailbox */ /* flags for sync_mailbox */
#define SYNC_DELETE (1<<0) /* delete local that don't exist on server */ #define SYNC_DELETE (1<<0) /* delete local that don't exist on server */
#define SYNC_EXPUNGE (1<<1) /* don't fetch deleted messages */ #define SYNC_EXPUNGE (1<<1) /* don't fetch deleted messages */
#define SYNC_QUIET (1<<2) /* only display critical errors */
/* flags for maildir_open */ /* flags for maildir_open */
#define OPEN_FAST (1<<0) /* fast open - don't parse */ #define OPEN_FAST (1<<0) /* fast open - don't parse */
@ -173,7 +175,10 @@ extern config_t global;
extern config_t *boxes; extern config_t *boxes;
extern unsigned int Tag; extern unsigned int Tag;
extern char Hostname[256]; extern char Hostname[256];
extern int Verbose; extern int Verbose, Quiet;
extern void info (const char *, ...);
extern void infoc (char);
#if HAVE_LIBSSL #if HAVE_LIBSSL
extern SSL_CTX *SSLContext; extern SSL_CTX *SSLContext;
@ -185,7 +190,7 @@ char *next_arg (char **);
int sync_mailbox (mailbox_t *, imap_t *, int, unsigned int, unsigned int); int sync_mailbox (mailbox_t *, imap_t *, int, unsigned int, unsigned int);
void load_config (const char *); void load_config (const char *, int *);
char * expand_strdup (const char *s); char * expand_strdup (const char *s);
config_t *find_box (const char *); config_t *find_box (const char *);
void free_config (void); void free_config (void);
@ -195,8 +200,10 @@ int imap_copy_message (imap_t * imap, unsigned int uid, const char *mailbox);
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_connect (config_t *);
imap_t *imap_open (config_t *, unsigned int, imap_t *, int); imap_t *imap_open (config_t *, unsigned int, imap_t *, int);
int imap_append_message (imap_t *, int, message_t *); int imap_append_message (imap_t *, int, message_t *);
int imap_list (imap_t *);
mailbox_t *maildir_open (const char *, int flags); mailbox_t *maildir_open (const char *, int flags);
int maildir_expunge (mailbox_t *, int); int maildir_expunge (mailbox_t *, int);

View File

@ -242,7 +242,7 @@ maildir_open (const char *path, int flags)
if (p->uid > m->maxuid) if (p->uid > m->maxuid)
m->maxuid = p->uid; m->maxuid = p->uid;
} }
else else /* XXX remove. every locally generated message triggers this */
puts ("Warning, no UID for message"); puts ("Warning, no UID for message");
if (s) if (s)
@ -341,7 +341,7 @@ maildir_clean_tmp (const char *mbox)
char path[_POSIX_PATH_MAX]; char path[_POSIX_PATH_MAX];
DIR *dirp; DIR *dirp;
struct dirent *entry; struct dirent *entry;
struct stat info; struct stat st;
time_t now; time_t now;
snprintf (path, sizeof (path), "%s/tmp", mbox); snprintf (path, sizeof (path), "%s/tmp", mbox);
@ -359,10 +359,10 @@ maildir_clean_tmp (const char *mbox)
while ((entry = readdir (dirp))) while ((entry = readdir (dirp)))
{ {
snprintf (path, sizeof (path), "%s/tmp/%s", mbox, entry->d_name); snprintf (path, sizeof (path), "%s/tmp/%s", mbox, entry->d_name);
if (stat (path, &info)) if (stat (path, &st))
fprintf (stderr, "maildir_clean_tmp: stat: %s: %s (errno %d)\n", fprintf (stderr, "maildir_clean_tmp: stat: %s: %s (errno %d)\n",
path, strerror (errno), errno); path, strerror (errno), errno);
else if (S_ISREG (info.st_mode) && now - info.st_ctime >= _24_HOURS) else if (S_ISREG (st.st_mode) && now - st.st_ctime >= _24_HOURS)
{ {
/* this should happen infrequently enough that it won't be /* this should happen infrequently enough that it won't be
* bothersome to the user to display when it occurs. * bothersome to the user to display when it occurs.

220
main.c
View File

@ -18,29 +18,61 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <stdarg.h>
#include <limits.h> #include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <dirent.h>
#include "isync.h" #include "isync.h"
#if HAVE_GETOPT_LONG #if HAVE_GETOPT_LONG
#define _GNU_SOURCE #define _GNU_SOURCE
#include <getopt.h> #include <getopt.h>
int Quiet;
void
info (const char *msg, ...)
{
va_list va;
if (!Quiet)
{
va_start (va, msg);
vprintf (msg, va);
va_end (va);
}
}
void
infoc (char c)
{
if (!Quiet)
putchar (c);
}
struct option Opts[] = { struct option Opts[] = {
{"all", 0, NULL, 'a'}, {"all", 0, NULL, 'a'},
{"list", 0, NULL, 'l'},
{"config", 1, NULL, 'c'}, {"config", 1, NULL, 'c'},
{"create", 0, NULL, 'C'}, {"create", 0, NULL, 'C'},
{"create-local", 0, NULL, 'L'},
{"create-remote", 0, NULL, 'R'},
{"delete", 0, NULL, 'd'}, {"delete", 0, NULL, 'd'},
{"expunge", 0, NULL, 'e'}, {"expunge", 0, NULL, 'e'},
{"fast", 0, NULL, 'f'}, {"fast", 0, NULL, 'f'},
{"help", 0, NULL, 'h'}, {"help", 0, NULL, 'h'},
{"remote", 1, NULL, 'r'}, {"remote", 1, NULL, 'r'},
{"folder", 1, NULL, 'F'},
{"maildir", 1, NULL, 'M'},
{"one-to-one", 0, NULL, '1'},
{"inbox", 1, NULL, 'I'},
{"host", 1, NULL, 's'}, {"host", 1, NULL, 's'},
{"port", 1, NULL, 'p'}, {"port", 1, NULL, 'p'},
{"quiet", 0, NULL, 'q'}, {"quiet", 0, NULL, 'q'},
@ -59,36 +91,49 @@ int Verbose = 0;
static void static void
version (void) version (void)
{ {
printf ("%s %s\n", PACKAGE, VERSION); puts (PACKAGE " " VERSION);
exit (0); exit (0);
} }
static void static void
usage (void) usage (int code)
{ {
printf ("%s %s IMAP4 to maildir synchronizer\n", PACKAGE, VERSION); fputs (
puts ("Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>"); PACKAGE " " VERSION " IMAP4 to maildir synchronizer\n"
printf ("usage: %s [ flags ] mailbox [mailbox ...]\n", PACKAGE); "Copyright (C) 2000-2 Michael R. Elkins <me@mutt.org>\n"
puts (" -a, --all Synchronize all defined mailboxes"); "usage:\n"
puts (" -c, --config CONFIG read an alternate config file (default: ~/.isyncrc)"); " " PACKAGE " [ flags ] mailbox [mailbox ...]\n"
puts (" -C, --create create local maildir mailbox if nonexistent"); " " PACKAGE " [ flags ] -a\n"
puts (" -d, --delete delete local msgs that don't exist on the server"); " " PACKAGE " [ flags ] -l\n"
puts (" -e, --expunge expunge deleted messages from the server"); " -a, --all synchronize all defined mailboxes\n"
puts (" -f, --fast only fetch new messages"); " -l, --list list all defined mailboxes and exit\n"
puts (" -h, --help display this help message"); " -L, --create-local create local maildir mailbox if nonexistent\n"
puts (" -p, --port PORT server IMAP port"); " -R, --create-remote create remote imap mailbox if nonexistent\n"
puts (" -r, --remote BOX remote mailbox"); " -C, --create create both local and remote mailboxes if nonexistent\n"
puts (" -s, --host HOST IMAP server address"); " -d, --delete delete local msgs that don't exist on the server\n"
puts (" -u, --user USER IMAP user name"); " -e, --expunge expunge deleted messages from the server\n"
puts (" -v, --version display version"); " -f, --fast only fetch new messages\n"
puts (" -V, --verbose verbose mode (display network traffic)"); " -r, --remote BOX remote mailbox\n"
puts ("Compile time options:"); " -F, --folder DIR remote IMAP folder containing mailboxes\n"
" -M, --maildir DIR local directory containing mailboxes\n"
" -1, --one-to-one map every IMAP <folder>/box to <maildir>/box\n"
" -I, --inbox BOX map IMAP INBOX to <maildir>/BOX (exception to -1)\n"
" -s, --host HOST IMAP server address\n"
" -p, --port PORT server IMAP port\n"
" -u, --user USER IMAP user name\n"
" -c, --config CONFIG read an alternate config file (default: ~/.isyncrc)\n"
" -V, --verbose verbose mode (display network traffic)\n"
" -q, --quiet don't display progress info\n"
" -v, --version display version\n"
" -h, --help display this help message\n"
"Compile time options:\n"
#if HAVE_LIBSSL #if HAVE_LIBSSL
puts (" +HAVE_LIBSSL"); " +HAVE_LIBSSL\n"
#else #else
puts (" -HAVE_LIBSSL"); " -HAVE_LIBSSL\n"
#endif #endif
exit (0); , code ? stderr : stdout);
exit (code);
} }
char * char *
@ -141,32 +186,33 @@ main (int argc, char **argv)
int delete = 0; int delete = 0;
char *config = 0; char *config = 0;
struct passwd *pw; struct passwd *pw;
int quiet = 0;
int all = 0; int all = 0;
int create = 0; int list = 0;
int o2o = 0;
int mbox_open_mode = 0;
int imap_create = 0;
pw = getpwuid (getuid ()); pw = getpwuid (getuid ());
/* defaults */ /* defaults */
memset (&global, 0, sizeof (global)); memset (&global, 0, sizeof (global));
/* XXX the precedence is borked:
it's defaults < cmdline < file instead of defaults < file < cmdline */
global.port = 143; global.port = 143;
global.box = "INBOX"; global.box = "INBOX";
global.folder = "";
global.user = strdup (pw->pw_name); global.user = strdup (pw->pw_name);
global.maildir = strdup (pw->pw_dir); global.maildir = strdup (pw->pw_dir);
global.max_size = 0;
global.max_messages = 0;
global.use_namespace = 1; global.use_namespace = 1;
#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
*/ */
global.require_ssl = 1; global.require_ssl = 1;
global.use_sslv2 = 0;
global.use_sslv3 = 0;
global.use_tlsv1 = 1; global.use_tlsv1 = 1;
#endif #endif
#define FLAGS "aCc:defhp:qu:r:s:vV" #define FLAGS "alCLRc:defhp:qu:r:F:M:1I:s:vV"
#if HAVE_GETOPT_LONG #if HAVE_GETOPT_LONG
while ((i = getopt_long (argc, argv, FLAGS, Opts, NULL)) != -1) while ((i = getopt_long (argc, argv, FLAGS, Opts, NULL)) != -1)
@ -176,11 +222,24 @@ main (int argc, char **argv)
{ {
switch (i) switch (i)
{ {
case 'l':
list = 1;
/* plopp */
case 'a': case 'a':
all = 1; all = 1;
break; break;
case '1':
o2o = 1;
break;
case 'C': case 'C':
create = 1; mbox_open_mode |= OPEN_CREATE;
imap_create = 1;
break;
case 'L':
mbox_open_mode |= OPEN_CREATE;
break;
case 'R':
imap_create = 1;
break; break;
case 'c': case 'c':
config = optarg; config = optarg;
@ -192,18 +251,29 @@ main (int argc, char **argv)
expunge = 1; expunge = 1;
break; break;
case 'f': case 'f':
mbox_open_mode |= OPEN_FAST;
fast = 1; fast = 1;
break; break;
case 'p': case 'p':
global.port = atoi (optarg); global.port = atoi (optarg);
break; break;
case 'q': case 'q':
quiet = 1; Quiet = 1;
Verbose = 0; Verbose = 0;
break; break;
case 'r': case 'r':
global.box = optarg; global.box = optarg;
break; break;
case 'F':
global.folder = optarg;
break;
case 'M':
free (global.maildir);
global.maildir = strdup (optarg);
break;
case 'I':
global.inbox = optarg;
break;
case 's': case 's':
#if HAVE_LIBSSL #if HAVE_LIBSSL
if (!strncasecmp ("imaps:", optarg, 6)) if (!strncasecmp ("imaps:", optarg, 6))
@ -223,26 +293,70 @@ main (int argc, char **argv)
break; break;
case 'v': case 'v':
version (); version ();
case 'h':
usage (0);
default: default:
usage (); usage (1);
} }
} }
if (!argv[optind] && !all) if (!argv[optind] && !all)
{ {
puts ("No mailbox specified"); fprintf (stderr, "No mailbox specified");
usage (); usage (1);
} }
gethostname (Hostname, sizeof (Hostname)); gethostname (Hostname, sizeof (Hostname));
load_config (config); load_config (config, &o2o);
if (all && o2o)
{
DIR *dir;
struct dirent *de;
if (global.inbox) {
boxes = malloc (sizeof (config_t));
memcpy (boxes, &global, sizeof (config_t));
boxes->box = "INBOX";
boxes->path = global.inbox;
}
if (!(dir = opendir (global.maildir))) {
fprintf (stderr, "%s: %s\n", global.maildir, strerror(errno));
return 1;
}
while ((de = readdir (dir))) {
if (*de->d_name == '.')
continue;
if (global.inbox && !strcmp (global.inbox, de->d_name))
continue;
box = malloc (sizeof (config_t));
memcpy (box, &global, sizeof (config_t));
box->path = strdup (de->d_name);
box->box = box->path;
box->next = boxes;
boxes = box;
}
closedir (dir);
imap = imap_connect (&global);
if (!imap)
goto bork;
if (imap_list (imap))
goto bork;
}
if (list)
{
for (box = boxes; box; box = box->next)
puts (box->path);
exit (0);
}
for (box = boxes; (all && box) || (!all && argv[optind]); optind++) for (box = boxes; (all && box) || (!all && argv[optind]); optind++)
{ {
if (!all) if (!all)
{ {
if (NULL == (box = find_box (argv[optind]))) if (o2o || NULL == (box = find_box (argv[optind])))
{ {
/* if enough info is given on the command line, don't worry if /* if enough info is given on the command line, don't worry if
* the mailbox isn't defined. * the mailbox isn't defined.
@ -257,25 +371,23 @@ main (int argc, char **argv)
} }
global.path = argv[optind]; global.path = argv[optind];
box = &global; box = &global;
if (o2o)
global.box =
(global.inbox && !strcmp (global.path, global.inbox)) ?
"INBOX" : global.path;
} }
} }
do { do {
if (!quiet) info ("Mailbox %s\n", box->path);
printf ("Reading %s\n", box->path); mail = maildir_open (box->path, mbox_open_mode);
i = 0;
if (fast)
i |= OPEN_FAST;
if (create)
i |= OPEN_CREATE;
mail = maildir_open (box->path, i);
if (!mail) if (!mail)
{ {
fprintf (stderr, "%s: unable to open mailbox\n", box->path); fprintf (stderr, "%s: unable to open mailbox\n", box->path);
break; break;
} }
imap = imap_open (box, fast ? mail->maxuid + 1 : 1, imap, 0); imap = imap_open (box, fast ? mail->maxuid + 1 : 1, imap, imap_create);
if (!imap) if (!imap)
{ {
fprintf (stderr, "%s: skipping mailbox due to IMAP error\n", fprintf (stderr, "%s: skipping mailbox due to IMAP error\n",
@ -283,12 +395,8 @@ main (int argc, char **argv)
break; break;
} }
if (!quiet) info ("Synchronizing\n");
puts ("Synchronizing"); i = (delete || box->delete) ? SYNC_DELETE : 0;
i = 0;
if (quiet)
i |= SYNC_QUIET;
i |= (delete || box->delete) ? SYNC_DELETE : 0;
i |= (expunge || box->expunge) ? SYNC_EXPUNGE : 0; i |= (expunge || box->expunge) ? SYNC_EXPUNGE : 0;
if (sync_mailbox (mail, imap, i, box->max_size, box->max_messages)) if (sync_mailbox (mail, imap, i, box->max_size, box->max_messages))
{ {
@ -305,18 +413,15 @@ main (int argc, char **argv)
(imap->deleted || mail->deleted)) (imap->deleted || mail->deleted))
{ {
/* remove messages marked for deletion */ /* remove messages marked for deletion */
if (!quiet) info ("Expunging %d messages from server\n", imap->deleted);
printf ("Expunging %d messages from server\n",
imap->deleted);
if (imap_expunge (imap)) if (imap_expunge (imap))
{ {
imap_close (imap); imap_close (imap);
imap = NULL; imap = NULL;
break; break;
} }
if (!quiet) info ("Expunging %d messages from local mailbox\n",
printf ("Expunging %d messages from local mailbox\n", mail->deleted);
mail->deleted);
if (maildir_expunge (mail, 0)) if (maildir_expunge (mail, 0))
break; break;
} }
@ -344,6 +449,7 @@ main (int argc, char **argv)
/* gracefully close connection to the IMAP server */ /* gracefully close connection to the IMAP server */
imap_close (imap); imap_close (imap);
bork:
free_config (); free_config ();
#if DEBUG #if DEBUG

58
sync.c
View File

@ -119,14 +119,11 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
continue; continue;
} }
if ((flags & SYNC_QUIET) == 0) if (!upload)
{ info ("Uploading messages");
if (!upload) infoc ('.');
fputs ("Uploading messages", stdout); fflush (stdout);
fputc ('.', stdout); upload++;
fflush (stdout);
upload++;
}
/* upload the message if its not too big */ /* upload the message if its not too big */
snprintf (path, sizeof (path), "%s/%s/%s", mbox->path, snprintf (path, sizeof (path), "%s/%s/%s", mbox->path,
@ -139,16 +136,14 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
if (imap->box->max_size > 0 if (imap->box->max_size > 0
&& sb.st_size > imap->box->max_size) && sb.st_size > imap->box->max_size)
{ {
if ((flags & SYNC_QUIET) == 0) info ("Warning, local message is too large (%lu), skipping...\n",
printf (unsigned long) sb.st_size);
("Warning, local message is too large (%lu), skipping...\n",
(unsigned long) sb.st_size);
continue; continue;
} }
fd = open (path, O_RDONLY); fd = open (path, O_RDONLY);
if (fd == -1) if (fd == -1)
{ {
printf ("Error, unable to open %s: %s (errno %d)\n", fprintf (stderr, "Error, unable to open %s: %s (errno %d)\n",
path, strerror (errno), errno); path, strerror (errno), errno);
continue; continue;
} }
@ -156,8 +151,11 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
cur->size = sb.st_size; cur->size = sb.st_size;
cur->uid = imap_append_message (imap, fd, cur); cur->uid = imap_append_message (imap, fd, cur);
/* if the server gave us back a uid, update the db */ /* if the server gave us back a uid, update the db */
if (cur->uid != (unsigned int) -1) if (cur->uid != (unsigned int) -1) {
set_uid (mbox->db, cur->file, cur->uid); set_uid (mbox->db, cur->file, cur->uid);
if (!cur->uid)
printf("warning: no uid for new messge %s\n", cur->file);
}
close (fd); close (fd);
} }
@ -174,9 +172,8 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
/* if the user doesn't want local msgs deleted when they don't /* if the user doesn't want local msgs deleted when they don't
* exist on the server, warn that such messages exist. * exist on the server, warn that such messages exist.
*/ */
else if ((flags & SYNC_QUIET) == 0) else
printf ("Warning, uid %u doesn't exist on server\n", info ("Warning, uid %u doesn't exist on server\n", cur->uid);
cur->uid);
continue; continue;
} }
tmp->processed = 1; tmp->processed = 1;
@ -255,13 +252,10 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
} }
if (upload) if (upload)
fprintf (stdout, " %d messages.\n", upload); info (" %d messages.\n", upload);
if ((flags & SYNC_QUIET) == 0) info ("Fetching new messages");
{ fflush (stdout);
fputs ("Fetching new messages", stdout);
fflush (stdout);
}
if (max_msgs == 0) if (max_msgs == 0)
max_msgs = UINT_MAX; max_msgs = UINT_MAX;
@ -308,10 +302,8 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
if (max_size && cur->size > max_size) if (max_size && cur->size > max_size)
{ {
if ((flags & SYNC_QUIET) == 0) info ("Warning, message skipped because it is too big (%u)\n",
printf cur->size);
("Warning, message skipped because it is too big (%u)\n",
cur->size);
continue; continue;
} }
@ -348,12 +340,9 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
if (fd < 0) if (fd < 0)
continue; continue;
if ((flags & SYNC_QUIET) == 0) /* give some visual feedback that something is happening */
{ infoc ('.');
/* give some visual feedback that something is happening */ fflush (stdout);
fputs (".", stdout);
fflush (stdout);
}
fetched++; fetched++;
ret = imap_fetch_message (imap, cur->uid, fd); ret = imap_fetch_message (imap, cur->uid, fd);
@ -389,8 +378,7 @@ sync_mailbox (mailbox_t * mbox, imap_t * imap, int flags,
} }
} }
if ((flags & SYNC_QUIET) == 0) info (" %d messages\n", fetched);
printf (" %d messages\n", fetched);
return 0; return 0;
} }