Monday, November 10, 2008

Fun with IMAP

The iSync package (specifically mbsync) is designed to move mail between stores. However, it does not push the date/time in the APPEND when pushing mail into an IMAP store.

This is a patch that forces that, getting the date/time from the first received line. It probably needs a lot more error checking before becoming production code.

The patch is against isync-1.0.4, and tested on NetBSD 4.99.70 (precursor to NetBSD 5.0). There is a chance that the util lib used is a NetBSDism, in which case the parsedate() function needs to be replaced with strptime() calls and with a lot more error checking.




--- Makefile 2008-11-10 22:09:54.000000000 -0800
+++ /tmp/Makefile 2008-11-10 22:09:06.000000000 -0800
@@ -107,7 +107,7 @@
INSTALL_PROGRAM = /usr/bin/install -c -s -o root -g wheel -m 555
INSTALL_SCRIPT = /usr/bin/install -c -o root -g wheel -m 555
INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
-LDFLAGS = -L/usr/pkg/lib -lcrypto -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -L/usr/lib
+LDFLAGS = -L/usr/pkg/lib -lcrypto -L/usr/lib -Wl,-R/usr/lib -Wl,-R/usr/pkg/lib -L/usr/lib -lutil
LIBOBJS =
LIBS =
LTLIBOBJS =

--- drv_imap.c 2007-09-22 01:44:12.000000000 -0700
+++ /tmp/drv_imap.c 2008-11-10 22:09:14.000000000 -0800
@@ -44,6 +44,7 @@
#include
#include
#include
+#include
#if HAVE_LIBSSL
# include
# include
@@ -1545,6 +1546,40 @@
msg->uid, ctx->prefix, gctx->conf->trash ); }

+
+int
+_get_rd (char* msg, char *t_str) {
+ t_str[0] = '\0';
+ char look[] = "Received:";
+ char * start = strstr(msg, look);
+ if (start == NULL) return -1;
+
+ char * end = start + strlen(look) - 1;
+ while (strncmp(++end, " ", 1) == 0) {
+ end = strchr (end, '\n');
+ if (end == NULL) return -1;
+ }
+
+ char * coln = strchr(start, ';');
+ if (coln > end) return -1;
+
+ coln++; // skip the ';' itself
+ while (*coln == ' ' || *coln == '\n') coln++;
+
+ char *bprn = strchr(coln, '(');
+ bprn--;
+
+ if (bprn < end) end = bprn;
+
+ while (*end == ' ' || *end == '\n') end--;
+
+ char * work = strndup(coln, (end - coln + 1));
+ time_t t = parsedate(work, NULL, NULL);
+
+ return strftime(t_str, 32, " \"%d-%b-%G %T %z\"", gmtime(&t));
+}
+
+
#define TUIDL 8 static int
static int
@@ -1557,7 +1592,7 @@
const char *prefix, *box;
int ret, i, j, d, len, extra, nocr;
int start, sbreak = 0, ebreak = 0;
- char flagstr[128], tuid[TUIDL * 2 + 1];
+ char flagstr[129], tuid[TUIDL * 2 + 1];
memset( &cb, 0, sizeof(cb) );
@@ -1631,10 +1666,14 @@
d = 0;
if (data->flags) {
- d = imap_make_flags( data->flags, flagstr );
- flagstr[d++] = ' ';
+ flagstr[d] = ' ';
+ char *bufflag = flagstr;
+ d = imap_make_flags( data->flags, ++bufflag );
}
- flagstr[d] = 0;
+ flagstr[++d] = 0;
+
+ char t_str[32];
+ _get_rd(data->data, t_str);

if (!uid) {
box = gctx->conf->trash;
prefix = ctx->prefix;
@@ -1650,7 +1689,7 @@
imap->caps = imap->rcaps & ~(1 << LITERALPLUS);*/
}
cb.ctx = uid;
- ret = imap_exec_m( ctx, &cb, "APPEND \"%s%s\" %s", prefix, box, flagstr );
+ ret = imap_exec_m( ctx, &cb, "APPEND \"%s%s\"%s%s ", prefix, box, flagstr, t_str);
imap->caps = imap->rcaps;
if (ret != DRV_OK)
return ret;