typedef struct Imap Imap;
struct Imap {
- long lastread;
-
char *mbox;
/* free this to free the strings below */
char *freep;
int nuid;
int muid;
- Thumbprint *thumb;
-
/* open network connection */
Biobuf bin;
Biobuf bout;
return buf;
}
-static int
-starttls(Imap *imap, TLSconn *tls)
-{
- char buf[Pathlen];
- uchar digest[SHA1dlen];
- int sfd, fd;
-
- memset(tls, 0, sizeof *tls);
- sfd = tlsClient(imap->fd, tls);
- if(sfd < 0){
- werrstr("tlsClient: %r");
- return -1;
- }
- if(tls->cert == nil || tls->certlen <= 0){
- close(sfd);
- werrstr("server did not provide TLS certificate");
- return -1;
- }
- sha1(tls->cert, tls->certlen, digest, nil);
- if(!imap->thumb || !okThumbprint(digest, imap->thumb)){
- close(sfd);
- werrstr("server certificate %.*H not recognized",
- SHA1dlen, digest);
- return -1;
- }
- close(imap->fd);
- imap->fd = sfd;
-
- if(imap->flags & Fdebug){
- snprint(buf, sizeof buf, "%s/ctl", tls->dir);
- fd = open(buf, OWRITE);
- fprint(fd, "debug");
- close(fd);
- }
-
- return 1;
-}
-
static void
imap4disconnect(Imap *imap)
{
Bterm(&imap->bout);
imap->binit = 0;
}
- close(imap->fd);
- imap->fd = -1;
+ if(imap->fd >= 0){
+ close(imap->fd);
+ imap->fd = -1;
+ }
}
char*
imap4dial(Imap *imap)
{
char *err, *port;
- TLSconn conn;
if(imap->fd >= 0){
imap4cmd(imap, "noop");
port = "imap";
if((imap->fd = dial(netmkaddr(imap->host, "net", port), 0, 0, 0)) < 0)
return imaperrstr(imap->host, port);
- if(imap->flags & Fssl && starttls(imap, &conn) == -1){
+ if(imap->flags & Fssl && (imap->fd = wraptls(imap->fd, imap->host)) < 0){
err = imaperrstr(imap->host, port);
- free(conn.cert);
imap4disconnect(imap);
return err;
}
return vcmp(f1->uid, f2->uid);
}
-static int
-setsize(Mailbox *, Message *m, Fetchi *f)
-{
- if(f->sizes >= Maxmsg)
- return -1;
-// if(!gmailmbox(mb))
- return m->size = f->sizes;
-}
-
static char*
imap4read(Imap *imap, Mailbox *mb, int doplumb, int *new)
{
Message *m, **ll;
*new = 0;
- if(time(0) - imap->lastread < 10)
- return nil;
- imap->lastread = time(0);
imap4cmd(imap, "status %Z (messages uidvalidity)", imap->mbox);
if(!isokay(s = imap4resp(imap)))
return s;
qsort(f, n, sizeof f[0], (int(*)(void*, void*))fetchicmp);
nnew = ndel = 0;
ll = &mb->root->part;
- for(i = 0; *ll || i < n; ){
+ for(i = 0; (m = *ll) != nil || i < n; ){
c = -1;
if(i >= n)
c = 1;
- else if(*ll){
- if((*ll)->imapuid == 0)
- (*ll)->imapuid = strtoull((*ll)->idxaux, 0, 0);
- c = vcmp(f[i].uid, (*ll)->imapuid);
+ else if(m){
+ if(m->imapuid == 0)
+ m->imapuid = strtoull(m->idxaux, 0, 0);
+ c = vcmp(f[i].uid, m->imapuid);
}
- idprint(imap, "consider %U and %U -> %d\n", i<n? f[i].uid: 0, *ll? (*ll)->imapuid: 1, c);
+ idprint(imap, "consider %U and %U -> %d\n", i<n? f[i].uid: 0, m? m->imapuid: 1, c);
if(c < 0){
/* new message */
- idprint(imap, "new: %U (%U)\n", f[i].uid, *ll? (*ll)->imapuid: 0);
+ idprint(imap, "new: %U (%U)\n", f[i].uid, m? m->imapuid: 0);
+ if(f[i].sizes > Maxmsg){
+ idprint(imap, "skipping bad size: %lud\n", f[i].sizes);
+ i++;
+ continue;
+ }
+ nnew++;
m = newmessage(mb->root);
m->inmbox = 1;
m->idxaux = smprint("%llud", f[i].uid);
m->imapuid = f[i].uid;
m->fileid = datesec(imap, i);
- if(setsize(mb, m, f + i) < 0 || m->size >= Maxmsg){
- /* message disappeared? unchain */
- idprint(imap, "deleted → %r (%U)\n", m->imapuid);
- logmsg(m, "disappeared");
- if(doplumb)
- mailplumb(mb, m, 1); /* redundant */
- unnewmessage(mb, mb->root, m);
- /* we're out of sync; here's were to signal that */
- break;
- }
- nnew++;
- logmsg(m, "new %s", m->idxaux);
+ m->size = f[i].sizes;
m->next = *ll;
*ll = m;
ll = &m->next;
- i++;
newcachehash(mb, m, doplumb);
putcache(mb, m);
+ i++;
}else if(c > 0){
/* deleted message; */
- idprint(imap, "deleted: %U (%U)\n", i<n? f[i].uid: 0, *ll? (*ll)->imapuid: 0);
+ idprint(imap, "deleted: %U (%U)\n", i<n? f[i].uid: 0, m? m->imapuid: 0);
ndel++;
- logmsg(*ll, "deleted");
- markdel(mb, *ll, doplumb);
- ll = &(*ll)->next;
+ markdel(mb, m, doplumb);
+ ll = &m->next;
}else{
- //logmsg(*ll, "duplicate %s", d[i].name);
+ ll = &m->next;
i++;
- ll = &(*ll)->next;
}
}
imap = mb->aux;
if(err = imap4dial(imap))
goto out;
- if((err = imap4read(imap, mb, doplumb, new)) == nil)
- mb->d->atime = mb->d->mtime = time(0);
+ err = imap4read(imap, mb, doplumb, new);
out:
- mb->waketime = time(0) + imap->refreshtime;
+ mb->waketime = (ulong)time(0) + imap->refreshtime;
return err;
}
static char*
imap4ctl(Mailbox *mb, int argc, char **argv)
{
- char *a, *b;
Imap *imap;
imap = mb->aux;
imap->flags ^= Fdebug;
return nil;
}
- if(strcmp(argv[0], "thumbprint") == 0){
- if(imap->thumb){
- freeThumbprints(imap->thumb);
- imap->thumb = 0;
- }
- a = "/sys/lib/tls/mail";
- b = "/sys/lib/tls/mail.exclude";
- switch(argc){
- default:
- return Eimap4ctl;
- case 4:
- b = argv[2];
- case 3:
- a = argv[1];
- case 2:
- break;
- }
- imap->thumb = initThumbprints(a, b);
- return nil;
- }
if(argc == 2 && strcmp(argv[0], "uid") == 0){
uvlong l;
Message *m;
else
imap->mbox = strdup(f[4]);
mkmbox(imap, mb->path, mb->path + sizeof mb->path);
- if(imap->flags & Fssl)
- imap->thumb = initThumbprints("/sys/lib/tls/mail", "/sys/lib/tls/mail.exclude");
-
mb->aux = imap;
mb->sync = imap4sync;
mb->close = imap4close;
mb->rename = imap4rename;
// mb->remove = imap4remove;
mb->modflags = imap4modflags;
- mb->d = emalloc(sizeof *mb->d);
mb->addfrom = 1;
return nil;
}