/* Wait for append response. */ int deliver_imap_waitappend(struct account *a, struct fetch_ctx *fctx, struct io *io, char **line) { struct fetch_imap_data *data = a->data; int tag; for (;;) { if (deliver_imap_poll(a, io) != 0) { line = NULL; return (IMAP_TAG_ERROR); } if (data->getln(a, fctx, line) != 0) { line = NULL; return (IMAP_TAG_ERROR); } if (*line == NULL) continue; tag = imap_tag(*line); if (tag != IMAP_TAG_NONE) break; } if (tag == IMAP_TAG_CONTINUE) return (IMAP_TAG_CONTINUE); if (tag != data->tag) return (IMAP_TAG_ERROR); return (tag); }
/* GMail extensions body state. */ int imap_state_gmext_body(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; struct mail *m = fctx->mail; char *line, *lb; int tag; u_int n; uint64_t thrid, msgid; size_t lblen; for (;;) { if (imap_getln(a, fctx, IMAP_RAW, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); tag = imap_tag(line); if (tag == IMAP_TAG_NONE) break; if (tag == data->tag) { fctx->state = imap_state_next; return (FETCH_MAIL); } return (FETCH_ERROR); } 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); }
/* User state. */ int imap_state_user(struct account *a, struct fetch_ctx *fctx) { struct fetch_imap_data *data = a->data; char *line; int tag; if (data->capa & IMAP_CAPA_NOSPACE) { if (imap_getln(a, fctx, IMAP_CONTINUE, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); } else { for (;;) { if (imap_getln(a, fctx, IMAP_RAW, &line) != 0) return (FETCH_ERROR); if (line == NULL) return (FETCH_BLOCK); tag = imap_tag(line); if (tag == IMAP_TAG_NONE) continue; if (tag == IMAP_TAG_CONTINUE || tag == data->tag) break; return (FETCH_ERROR); } if (tag != IMAP_TAG_CONTINUE) { log_debug("%s: didn't accept user (%s); " "trying without space", a->name, line); data->capa |= IMAP_CAPA_NOSPACE; return (imap_pick_auth(a, fctx)); } } if (imap_putln(a, "%s", data->pass) != 0) return (FETCH_ERROR); fctx->state = imap_state_pass; return (FETCH_BLOCK); }
/* * Parse line based on type. Returns -1 on error, 0 on success, 1 to ignore * this line. */ int imap_parse(struct account *a, int type, char *line) { struct fetch_imap_data *data = a->data; int tag; if (type == IMAP_RAW) return (0); tag = imap_tag(line); switch (type) { case IMAP_TAGGED: if (tag == IMAP_TAG_NONE) return (1); if (tag == IMAP_TAG_CONTINUE) goto invalid; if (tag != data->tag) goto invalid; break; case IMAP_UNTAGGED: if (tag != IMAP_TAG_NONE) goto invalid; break; case IMAP_CONTINUE: if (tag == IMAP_TAG_NONE) return (1); if (tag != IMAP_TAG_CONTINUE) goto invalid; break; } return (0); invalid: imap_bad(a, line); return (-1); }