added sync support for the arrival date of messages
initial patch by Marc Hoersken <info@marc-hoersken.de>
This commit is contained in:
parent
6577bf3e61
commit
eb1f10762f
17
configure.ac
17
configure.ac
|
@ -11,6 +11,23 @@ fi
|
|||
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
||||
|
||||
AC_CACHE_CHECK([whether strftime supports %z], ob_cv_strftime_z,
|
||||
[AC_TRY_RUN(
|
||||
[#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
time_t t = 0;
|
||||
char buf[32];
|
||||
strftime(buf, sizeof(buf), "%z", gmtime(&t));
|
||||
return !!strcmp(buf, "+0000");
|
||||
}
|
||||
], [ob_cv_strftime_z=yes], [ob_cv_strftime_z=no], [ob_cv_strftime_z="yes (assumed)"])])
|
||||
if test "x$ob_cv_strftime_z" = x"no"; then
|
||||
AC_MSG_ERROR([libc lacks necessary feature])
|
||||
fi
|
||||
|
||||
AC_CHECK_HEADERS(sys/poll.h sys/select.h)
|
||||
AC_CHECK_FUNCS(vasprintf memrchr)
|
||||
|
||||
|
|
|
@ -362,6 +362,8 @@ load_config( const char *where, int pseudo )
|
|||
max_size = parse_size( &cfile );
|
||||
else if (!strcasecmp( "MaxMessages", cfile.cmd ))
|
||||
channel->max_messages = parse_int( &cfile );
|
||||
else if (!strcasecmp( "CopyArrivalDate", cfile.cmd ))
|
||||
channel->use_internal_date = parse_bool( &cfile );
|
||||
else if (!strcasecmp( "Pattern", cfile.cmd ) ||
|
||||
!strcasecmp( "Patterns", cfile.cmd ))
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
typedef struct imap_server_conf {
|
||||
|
@ -710,6 +711,8 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
|
|||
struct imap_cmd *cmdp;
|
||||
int uid = 0, mask = 0, status = 0, size = 0;
|
||||
unsigned i;
|
||||
time_t date = 0;
|
||||
struct tm datetime;
|
||||
|
||||
if (!is_list( list )) {
|
||||
error( "IMAP error: bogus FETCH response\n" );
|
||||
|
@ -751,6 +754,15 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
|
|||
status |= M_FLAGS;
|
||||
} else
|
||||
error( "IMAP error: unable to parse FLAGS\n" );
|
||||
} else if (!strcmp( "INTERNALDATE", tmp->val )) {
|
||||
tmp = tmp->next;
|
||||
if (is_atom( tmp )) {
|
||||
if (strptime( tmp->val, "%d-%b-%Y %H:%M:%S %z", &datetime ))
|
||||
date = mktime( &datetime );
|
||||
else
|
||||
error( "IMAP error: unable to parse INTERNALDATE format\n" );
|
||||
} else
|
||||
error( "IMAP error: unable to parse INTERNALDATE\n" );
|
||||
} else if (!strcmp( "RFC822.SIZE", tmp->val )) {
|
||||
tmp = tmp->next;
|
||||
if (is_atom( tmp ))
|
||||
|
@ -794,6 +806,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
|
|||
msgdata = ((struct imap_cmd_fetch_msg *)cmdp)->msg_data;
|
||||
msgdata->data = body;
|
||||
msgdata->len = size;
|
||||
msgdata->date = date;
|
||||
if (status & M_FLAGS)
|
||||
msgdata->flags = mask;
|
||||
} else if (uid) { /* ignore async flag updates for now */
|
||||
|
@ -1738,8 +1751,9 @@ imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data,
|
|||
cmd->gen.gen.param.uid = msg->uid;
|
||||
cmd->msg_data = data;
|
||||
imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_done_simple_msg,
|
||||
"UID FETCH %d (%sBODY.PEEK[])",
|
||||
msg->uid, (msg->status & M_FLAGS) ? "" : "FLAGS " );
|
||||
"UID FETCH %d (%s%sBODY.PEEK[])", msg->uid,
|
||||
!(msg->status & M_FLAGS) ? "FLAGS " : "",
|
||||
(data->date== -1) ? "INTERNALDATE " : "" );
|
||||
}
|
||||
|
||||
/******************* imap_set_flags *******************/
|
||||
|
@ -1888,7 +1902,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||
struct imap_cmd_out_uid *cmd;
|
||||
int d;
|
||||
char flagstr[128], buf[1024];
|
||||
char flagstr[128], datestr[64], buf[1024];
|
||||
|
||||
d = 0;
|
||||
if (data->flags) {
|
||||
|
@ -1915,9 +1929,23 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (data->date) {
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wformat"
|
||||
/* configure ensures that %z actually works. */
|
||||
#endif
|
||||
strftime( datestr, sizeof(datestr), "%d-%b-%Y %H:%M:%S %z", localtime( &data->date ) );
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
|
||||
"APPEND \"%s\" %s\"%s\" ", buf, flagstr, datestr );
|
||||
} else {
|
||||
imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
|
||||
"APPEND \"%s\" %s", buf, flagstr );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, struct imap_cmd *cmd, int response )
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <sys/file.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <utime.h>
|
||||
|
||||
#define USE_DB 1
|
||||
#ifdef __linux__
|
||||
|
@ -1124,6 +1125,8 @@ maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data,
|
|||
}
|
||||
fstat( fd, &st );
|
||||
data->len = st.st_size;
|
||||
if (data->date == -1)
|
||||
data->date = st.st_mtime;
|
||||
data->data = nfmalloc( data->len );
|
||||
if (read( fd, data->data, data->len ) != data->len) {
|
||||
sys_error( "Maildir error: cannot read %s", buf );
|
||||
|
@ -1225,6 +1228,18 @@ maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
|||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->date) {
|
||||
/* Set atime and mtime according to INTERNALDATE or mtime of source message */
|
||||
struct utimbuf utimebuf;
|
||||
utimebuf.actime = utimebuf.modtime = data->date;
|
||||
if (utime( buf, &utimebuf ) < 0) {
|
||||
sys_error( "Maildir error: cannot set times for %s", buf );
|
||||
cb( DRV_BOX_BAD, 0, aux );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Moving seen messages to cur/ is strictly speaking incorrect, but makes mutt happy. */
|
||||
nfsnprintf( nbuf, sizeof(nbuf), "%s/%s/%s%s", box, subdirs[!(data->flags & F_SEEN)], base, fbuf );
|
||||
if (rename( buf, nbuf )) {
|
||||
|
|
|
@ -166,6 +166,7 @@ typedef struct channel_conf {
|
|||
string_list_t *patterns;
|
||||
int ops[2];
|
||||
unsigned max_messages; /* for slave only */
|
||||
unsigned use_internal_date:1;
|
||||
} channel_conf_t;
|
||||
|
||||
typedef struct group_conf {
|
||||
|
@ -245,6 +246,7 @@ set_bad_callback( store_t *ctx, void (*cb)( void *aux ), void *aux )
|
|||
typedef struct {
|
||||
char *data;
|
||||
int len;
|
||||
time_t date;
|
||||
unsigned char flags;
|
||||
} msg_data_t;
|
||||
|
||||
|
|
10
src/mbsync.1
10
src/mbsync.1
|
@ -477,6 +477,16 @@ a global effect. The global settings are overridden by Channel-specific options,
|
|||
which in turn are overridden by command line switches.
|
||||
..
|
||||
.TP
|
||||
\fBCopyArrivalDate\fR {\fIyes\fR|\fIno\fR}
|
||||
Selects whether their arrival time should be propagated together with
|
||||
the messages.
|
||||
Enabling this makes sense in order to keep the time stamp based message
|
||||
sorting intact.
|
||||
Note that IMAP does not guarantee that the time stamp (termed \fBinternal
|
||||
date\fR) is actually the arrival time, but it is usually close enough.
|
||||
(Default: \fIno\fR)
|
||||
..
|
||||
.TP
|
||||
\fBSyncState\fR {\fB*\fR|\fIpath\fR}
|
||||
Set the location of this Channel's synchronization state files. \fB*\fR means
|
||||
that the state should be saved in a file named .mbsyncstate in the
|
||||
|
|
|
@ -281,6 +281,7 @@ copy_msg( copy_vars_t *vars )
|
|||
|
||||
t ^= 1;
|
||||
vars->data.flags = vars->msg->flags;
|
||||
vars->data.date = svars->chan->use_internal_date ? -1 : 0;
|
||||
DRIVER_CALL_RET(fetch_msg( svars->ctx[t], vars->msg, &vars->data, msg_fetched, vars ));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user