Skip to content

Commit

Permalink
Fetch GMail IMAP extensions and stick them in tags, from David Lazar.
Browse files Browse the repository at this point in the history
  • Loading branch information
nicm committed Feb 17, 2016
1 parent 0f6b52f commit 68a95b4
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
12 changes: 12 additions & 0 deletions child-fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ fetch_enqueue(struct account *a, struct io *pio, struct mail *m)
int error;
struct tm *tm;
time_t t;
const char *tptr;

/*
* Check for oversize mails. This must be first since there is no
Expand Down Expand Up @@ -622,6 +623,17 @@ fetch_enqueue(struct account *a, struct io *pio, struct mail *m)
log_debug3("%s: couldn't add received header", a->name);
}

/* Insert Gmail-specific headers. */
if ((tptr = find_tag(m->tags, "gmail_msgid")) != NULL &&
insert_header(m, "message-id", "X-GM-MSGID: %s", tptr) != 0)
log_warnx("%s: failed to add header X-GM-MSGID", a->name);
if ((tptr = find_tag(m->tags, "gmail_thrid")) != NULL &&
insert_header(m, "message-id", "X-GM-THRID: %s", tptr) != 0)
log_warnx("%s: failed to add header X-GM-THRID", a->name);
if ((tptr = find_tag(m->tags, "gmail_labels")) != NULL &&
insert_header(m, "message-id", "X-GM-LABELS: %s", tptr) != 0)
log_warnx("%s: failed to add header X-GM-LABELS", a->name);

/* Fill wrapped line list. */
n = fill_wrapped(m);
log_debug2("%s: found %u wrapped lines", a->name, n);
Expand Down
1 change: 1 addition & 0 deletions fetch.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ struct fetch_imap_mail {
#define IMAP_CAPA_XYZZY 0x2
#define IMAP_CAPA_STARTTLS 0x4
#define IMAP_CAPA_NOSPACE 0x8
#define IMAP_CAPA_GMEXT 0x10

/* fetch-maildir.c */
extern struct fetch fetch_maildir;
Expand Down
82 changes: 82 additions & 0 deletions imap-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ int imap_state_next(struct account *, struct fetch_ctx *);
int imap_state_body(struct account *, struct fetch_ctx *);
int imap_state_line(struct account *, struct fetch_ctx *);
int imap_state_mail(struct account *, struct fetch_ctx *);
int imap_state_gmext_start(struct account *, struct fetch_ctx *);
int imap_state_gmext_body(struct account *, struct fetch_ctx *);
int imap_state_gmext_done(struct account *, struct fetch_ctx *);
int imap_state_commit(struct account *, struct fetch_ctx *);
int imap_state_expunge(struct account *, struct fetch_ctx *);
int imap_state_close(struct account *, struct fetch_ctx *);
Expand Down Expand Up @@ -402,6 +405,10 @@ imap_state_capability1(struct account *a, struct fetch_ctx *fctx)
if (strstr(line, "XYZZY") != NULL)
data->capa |= IMAP_CAPA_XYZZY;

/* GMail IMAP extensions. */
if (strstr(line, "X-GM-EXT-1") != NULL)
data->capa |= IMAP_CAPA_GMEXT;

if (strstr(line, "STARTTLS") != NULL)
data->capa |= IMAP_CAPA_STARTTLS;

Expand Down Expand Up @@ -952,6 +959,81 @@ imap_state_line(struct account *a, struct fetch_ctx *fctx)
/* Mail state. */
int
imap_state_mail(struct account *a, struct fetch_ctx *fctx)
{
struct fetch_imap_data *data = a->data;
char *line;

if (imap_getln(a, fctx, IMAP_TAGGED, &line) != 0)
return (FETCH_ERROR);
if (line == NULL)
return (FETCH_BLOCK);
if (!imap_okay(line))
return (imap_bad(a, line));

if (data->capa & IMAP_CAPA_GMEXT) {
fctx->state = imap_state_gmext_start;
return (FETCH_AGAIN);
}

fctx->state = imap_state_next;
return (FETCH_MAIL);
}

/* GMail extensions start state. */
int
imap_state_gmext_start(struct account *a, struct fetch_ctx *fctx)
{
struct fetch_imap_data *data = a->data;
struct mail *m = fctx->mail;
struct fetch_imap_mail *aux = m->auxdata;

if (imap_putln(a, "%u FETCH %u (X-GM-MSGID X-GM-THRID X-GM-LABELS)",
++data->tag, aux->uid) != 0)
return (FETCH_ERROR);

fctx->state = imap_state_gmext_body;
return (FETCH_AGAIN);
}

/* GMail extensions body state. */
int
imap_state_gmext_body(struct account *a, struct fetch_ctx *fctx)
{
struct mail *m = fctx->mail;
char *line, *lb;
u_int n;
uint64_t thrid, msgid;
size_t lblen;

if (imap_getln(a, fctx, IMAP_UNTAGGED, &line) != 0)
return (FETCH_ERROR);
if (line == NULL)
return (FETCH_BLOCK);

if (sscanf(line, "* %u FETCH (X-GM-THRID %llu X-GM-MSGID %llu ", &n,
&thrid, &msgid) != 3)
return (imap_invalid(a, line));
if ((lb = strstr(line, "X-GM-LABELS")) == NULL)
return (imap_invalid(a, line));
if ((lb = strchr(lb, '(')) == NULL)
return (imap_invalid(a, line));
lb++; /* drop '(' */
lblen = strlen(lb);
if (lblen < 2 || lb[lblen - 1] != ')' || lb[lblen - 2] != ')')
return (imap_invalid(a, line));
lblen -= 2; /* drop '))' from the end */

add_tag(&m->tags, "gmail_msgid", "%llu", msgid);
add_tag(&m->tags, "gmail_thrid", "%llu", thrid);
add_tag(&m->tags, "gmail_labels", "%.*s", (int)lblen, lb);

fctx->state = imap_state_gmext_done;
return (FETCH_AGAIN);
}

/* GMail extensions done state. */
int
imap_state_gmext_done(struct account *a, struct fetch_ctx *fctx)
{
char *line;

Expand Down

3 comments on commit 68a95b4

@brynet
Copy link

@brynet brynet commented on 68a95b4 Feb 18, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit actually breaks Google IMAP for me..

brynet: unexpected data: 6 OK Success
brynet: fetching error. aborted
brynet: 0 messages processed in 2.226 seconds

@nicm
Copy link
Owner Author

@nicm nicm commented on 68a95b4 Feb 18, 2016 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brynet
Copy link

@brynet brynet commented on 68a95b4 Feb 18, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replied via email.

Please sign in to comment.