/* * Add, remove or replace the specified flags of the messages. */ int request_store(const char *server, const char *port, const char *user, const char *mesg, const char *mode, const char *flags) { int t, r; session *s; if (!(s = session_find(server, port, user))) return -1; t = imap_store(s, mesg, mode, flags); if ((r = response_generic(s, t)) == -1) goto fail; if (xstrcasestr(flags, "\\Deleted") && get_option_boolean("expunge")) if (response_generic(s, imap_expunge(s)) == -1) goto fail; return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * Process the data that server sent due to IMAP STATUS client request. */ int response_status(session *ssn, int tag, unsigned int *exist, unsigned int *recent, unsigned int *unseen) { int r; char *s; regexp *re; if ((r = response_generic(ssn, tag)) == -1) return -1; re = &responses[DATA_RESPONSE_STATUS]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); re = &responses[DATA_RESPONSE_STATUS_MESSAGES]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *exist = strtol(s + re->pmatch[1].rm_so, NULL, 10); re = &responses[DATA_RESPONSE_STATUS_RECENT]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *recent = strtol(s + re->pmatch[1].rm_so, NULL, 10); re = &responses[DATA_RESPONSE_STATUS_UNSEEN]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *unseen = strtol(s + re->pmatch[1].rm_so, NULL, 10); xfree(s); } return r; }
/* * Copy the specified messages to another mailbox. */ int request_copy(const char *server, const char *port, const char *user, const char *mesg, const char *mbox) { int t, r; session *s; const char *m; if (!(s = session_find(server, port, user))) return -1; m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); do { t = imap_copy(s, mesg, m); switch (r = response_generic(s, t)) { case STATUS_RESPONSE_TRYCREATE: if (create_mailbox(s, mbox) == -1) goto fail; break; case -1: goto fail; break; } } while (r == STATUS_RESPONSE_TRYCREATE); return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * Process the data that server sent due to IMAP FETCH RFC822.SIZE client * request. */ int response_fetchsize(session *ssn, int tag, char **size) { int r; char *s; regexp *re; if ((r = response_generic(ssn, tag)) == -1) return -1; re = &responses[DATA_RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); re = &responses[DATA_RESPONSE_FETCH_SIZE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *size = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); xfree(s); } return r; }
/* * Process the data that server sent due to IMAP NAMESPACE client request. */ int response_namespace(session *ssn, int tag) { int r, n; regexp *re; r = response_generic(ssn, tag); if (r == -1 || r == STATUS_BYE) return r; ssn->ns.prefix = NULL; ssn->ns.delim = '\0'; re = &responses[RESPONSE_NAMESPACE]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { n = re->pmatch[2].rm_eo - re->pmatch[2].rm_so; if (n > 0) ssn->ns.prefix = xstrndup(ibuf.data + re->pmatch[2].rm_so, n); ssn->ns.delim = *(ibuf.data + re->pmatch[3].rm_so); } debug("namespace (%d): '%s' '%c'\n", ssn->socket, (ssn->ns.prefix ? ssn->ns.prefix : ""), ssn->ns.delim); return r; }
/* * Rename a mailbox. */ int request_rename(const char *server, const char *port, const char *user, const char *oldmbox, const char *newmbox) { int r; session *s; char *o, *n; if (!(s = session_find(server, port, user))) return -1; o = xstrdup(apply_namespace(oldmbox, s->ns.prefix, s->ns.delim)); n = xstrdup(apply_namespace(newmbox, s->ns.prefix, s->ns.delim)); r = response_generic(s, imap_rename(s, o, n)); xfree(o); xfree(n); if (r == -1) goto fail; return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * Process the data that server sent due to IMAP FETCH BODYSTRUCTURE client * request. */ int response_fetchstructure(session *ssn, int tag, char **structure) { int r; char *s; regexp *re; r = response_generic(ssn, tag); if (r == -1 || r == STATUS_BYE) return r; re = &responses[RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); re = &responses[RESPONSE_FETCH_STRUCTURE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) { *structure = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); } xfree(s); } return r; }
/* * Auxiliary function to create a mailbox. */ int create_mailbox(session *ssn, const char *mbox) { int r; const char *m; m = apply_namespace(mbox, ssn->ns.prefix, ssn->ns.delim); if ((r = response_generic(ssn, imap_create(ssn, m))) == -1) return -1; if (get_option_boolean("subscribe")) if (response_generic(ssn, imap_subscribe(ssn, m)) == -1) return -1; return r; }
/* * Add, remove or replace the specified flags of the messages. */ int request_store(session *ssn, const char *mesg, const char *mode, const char *flags) { int t, r; TRY(t = send_request(ssn, "UID STORE %s %sFLAGS.SILENT (%s)", mesg, (!strncasecmp(mode, "add", 3) ? "+" : !strncasecmp(mode, "remove", 6) ? "-" : ""), flags)); TRY(r = response_generic(ssn, t)); if (xstrcasestr(flags, "\\Deleted") && get_option_boolean("expunge")) { TRY(t = send_request(ssn, "EXPUNGE")); TRY(response_generic(ssn, t)); } return r; }
/* * Reset any inactivity autologout timer on the server. */ int request_noop(session *ssn) { int t, r; TRY(t = send_request(ssn, "NOOP")); TRY(r = response_generic(ssn, t)); return r; }
/* * Remove all messages marked for deletion from selected mailbox. */ int request_expunge(session *ssn) { int t, r; TRY(t = send_request(ssn, "EXPUNGE")); TRY(r = response_generic(ssn, t)); return r; }
/* * Logout from the IMAP server and disconnect from the server. */ int request_logout(session *ssn) { if (response_generic(ssn, send_request(ssn, "LOGOUT")) == -1) { session_destroy(ssn); } else { close_connection(ssn); session_destroy(ssn); } return STATUS_OK; }
/* * Process the data that server sent due to IMAP SELECT client request. */ int response_select(session *ssn, int tag) { int r; if ((r = response_generic(ssn, tag)) == -1) return -1; if (xstrcasestr(ibuf.data, "[READ-ONLY]")) return STATUS_RESPONSE_READONLY; return r; }
/* * Unsubscribe the specified mailbox. */ int request_unsubscribe(session *ssn, const char *mbox) { int t, r; const char *m; m = apply_namespace(mbox, ssn->ns.prefix, ssn->ns.delim); TRY(t = send_request(ssn, "UNSUBSCRIBE \"%s\"", m)); TRY(r = response_generic(ssn, t)); return r; }
/* * Delete the specified mailbox. */ int request_delete(session *ssn, const char *mbox) { int t, r; const char *m; m = apply_namespace(mbox, ssn->ns.prefix, ssn->ns.delim); TRY(t = send_request(ssn, "DELETE \"%s\"", m)); TRY(r = response_generic(ssn, t)); return r; }
/* * Append supplied message to the specified mailbox. */ int request_append(session *ssn, const char *mbox, const char *mesg, size_t mesglen, const char *flags, const char *date) { int t, r; const char *m; m = apply_namespace(mbox, ssn->ns.prefix, ssn->ns.delim); TRY(t = send_request(ssn, "APPEND \"%s\"%s%s%s%s%s%s {%d}", m, (flags ? " (" : ""), (flags ? flags : ""), (flags ? ")" : ""), (date ? " \"" : ""), (date ? date : ""), (date ? "\"" : ""), mesglen)); TRY(r = response_continuation(ssn, t)); if (r == STATUS_CONTINUE) { TRY(send_continuation(ssn, mesg, mesglen)); TRY(r = response_generic(ssn, t)); } if (r == STATUS_TRYCREATE) { TRY(t = send_request(ssn, "CREATE \"%s\"", m)); TRY(response_generic(ssn, t)); if (get_option_boolean("subscribe")) { TRY(t = send_request(ssn, "SUBSCRIBE \"%s\"", m)); TRY(response_generic(ssn, t)); } TRY(t = send_request(ssn, "APPEND \"%s\"%s%s%s%s%s%s {%d}", m, (flags ? " (" : ""), (flags ? flags : ""), (flags ? ")" : ""), (date ? " \"" : ""), (date ? date : ""), (date ? "\"" : ""), mesglen)); TRY(r = response_continuation(ssn, t)); if (r == STATUS_CONTINUE) { TRY(send_continuation(ssn, mesg, mesglen)); TRY(r = response_generic(ssn, t)); } } return r; }
/* * Copy the specified messages to another mailbox. */ int request_copy(session *ssn, const char *mesg, const char *mbox) { int t, r; const char *m; m = apply_namespace(mbox, ssn->ns.prefix, ssn->ns.delim); TRY(t = send_request(ssn, "UID COPY %s \"%s\"", mesg, m)); TRY(r = response_generic(ssn, t)); if (r == STATUS_TRYCREATE) { TRY(t = send_request(ssn, "CREATE \"%s\"", m)); TRY(response_generic(ssn, t)); if (get_option_boolean("subscribe")) { TRY(t = send_request(ssn, "SUBSCRIBE \"%s\"", m)); TRY(response_generic(ssn, t)); } TRY(t = send_request(ssn, "UID COPY %s \"%s\"", mesg, m)); TRY(r = response_generic(ssn, t)); } return r; }
/* * Process the data that server sent due to IMAP SELECT client request. */ int response_select(session *ssn, int tag) { int r; r = response_generic(ssn, tag); if (r == -1 || r == STATUS_BYE) return r; if (xstrcasestr(ibuf.data, "[READ-ONLY]")) return STATUS_READONLY; return r; }
/* * Rename a mailbox. */ int request_rename(session *ssn, const char *oldmbox, const char *newmbox) { int t, r; char *o, *n; o = xstrdup(apply_namespace(oldmbox, ssn->ns.prefix, ssn->ns.delim)); n = xstrdup(apply_namespace(newmbox, ssn->ns.prefix, ssn->ns.delim)); TRY(t = send_request(ssn, "RENAME \"%s\" \"%s\"", o, n)); TRY(r = response_generic(ssn, t)); return r; }
/* * Close examined/selected mailbox. */ int request_close(session *ssn) { int t, r; TRY(t = send_request(ssn, "CLOSE")); TRY(r = response_generic(ssn, t)); if (r == STATUS_OK && ssn->selected) { xfree(ssn->selected); ssn->selected = NULL; } return r; }
/* * Process the data that server sent due to IMAP AUTHENTICATE client request. */ int response_authenticate(session *ssn, int tag, unsigned char **cont) { int r; regexp *re; re = &responses[DATA_RESPONSE_AUTHENTICATE]; if ((r = response_generic(ssn, tag)) == STATUS_RESPONSE_CONTINUE && !regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) *cont = (unsigned char *)xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); return r; }
/* * Process the data that server sent due to IMAP CAPABILITY client request. */ int response_capability(session *ssn, int tag) { int r; char *s; regexp *re; r = response_generic(ssn, tag); if (r == -1 || r == STATUS_BYE) return r; ssn->protocol = PROTOCOL_NONE; re = &responses[RESPONSE_CAPABILITY]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); if (xstrcasestr(s, "IMAP4rev1")) ssn->protocol = PROTOCOL_IMAP4REV1; else if (xstrcasestr(s, "IMAP4")) ssn->protocol = PROTOCOL_IMAP4; else { error("server supports neither the IMAP4rev1 nor the " "IMAP4 protocol\n"); return -1; } ssn->capabilities = CAPABILITY_NONE; if (xstrcasestr(s, "NAMESPACE")) ssn->capabilities |= CAPABILITY_NAMESPACE; if (xstrcasestr(s, "AUTH=CRAM-MD5")) ssn->capabilities |= CAPABILITY_CRAMMD5; if (xstrcasestr(s, "STARTTLS")) ssn->capabilities |= CAPABILITY_STARTTLS; if (xstrcasestr(s, "CHILDREN")) ssn->capabilities |= CAPABILITY_CHILDREN; if (xstrcasestr(s, "IDLE")) ssn->capabilities |= CAPABILITY_IDLE; xfree(s); } return r; }
/* * Logout from the IMAP server and disconnect from the server. */ int request_logout(const char *server, const char *port, const char *user) { int r; session *s; if (!(s = session_find(server, port, user))) return -1; r = response_generic(s, imap_logout(s)); close_connection(s); session_destroy(s); return r; }
/* * Append supplied message to the specified mailbox. */ int request_append(const char *server, const char *port, const char *user, const char *mbox, const char *mesg, size_t mesglen, const char *flags, const char *date) { int t, r; session *s; const char *m; if (!(s = session_find(server, port, user))) return -1; m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); do { if ((t = imap_append(s, m, flags, date, mesglen)) == -1) goto fail; if ((r = response_continuation(s)) == -1) goto fail; switch (r) { case STATUS_RESPONSE_CONTINUE: if (imap_continuation(s, mesg, mesglen) == -1) goto fail; if ((r = response_generic(s, t)) == -1) goto fail; break; case STATUS_RESPONSE_TRYCREATE: if (create_mailbox(s, mbox) == -1) goto fail; break; case -1: goto fail; break; } } while (r == STATUS_RESPONSE_TRYCREATE); return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * Remove all messages marked for deletion from selected mailbox. */ int request_expunge(const char *server, const char *port, const char *user) { int r; session *s; if (!(s = session_find(server, port, user))) return -1; if ((r = response_generic(s, imap_expunge(s))) == -1) goto fail; return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * Process the data that server sent due to IMAP EXAMINE client request. */ int response_examine(session *ssn, int tag, unsigned int *exist, unsigned int *recent) { int r; regexp *re; if ((r = response_generic(ssn, tag)) == -1) return -1; re = &responses[DATA_RESPONSE_EXAMINE_EXISTS]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) *exist = strtol(ibuf.data + re->pmatch[1].rm_so, NULL, 10); re = &responses[DATA_RESPONSE_EXAMINE_RECENT]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) *recent = strtol(ibuf.data + re->pmatch[1].rm_so, NULL, 10); return r; }
int request_idle(session *ssn, char **event) { int t, r, ri; if (!(ssn->capabilities & CAPABILITY_IDLE)) return STATUS_BAD; do { ri = 0; TRY(t = send_request(ssn, "IDLE")); TRY(r = response_continuation(ssn, t)); if (r == STATUS_CONTINUE) { TRY(ri = response_idle(ssn, t, event)); TRY(send_continuation(ssn, "DONE", strlen("DONE"))); TRY(r = response_generic(ssn, t)); } } while (ri == STATUS_TIMEOUT); return r; }
int request_idle(const char *server, const char *port, const char *user) { int t, rg, ri; session *s; if (!(s = session_find(server, port, user))) return -1; if (!(s->capabilities & CAPABILITY_IDLE)) return -1; do { ri = 0; t = imap_idle(s); if ((rg = response_continuation(s)) == -1) goto fail; if (rg == STATUS_RESPONSE_CONTINUE) { if ((ri = response_idle(s, t)) == -1) goto fail; imap_done(s); if ((rg = response_generic(s, t)) == -1) goto fail; } } while (ri == STATUS_RESPONSE_TIMEOUT); return rg; fail: close_connection(s); session_destroy(s); return -1; }
/* * Unsubscribe the specified mailbox. */ int request_unsubscribe(const char *server, const char *port, const char *user, const char *mbox) { int r; session *s; const char *m; if (!(s = session_find(server, port, user))) return -1; m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); if ((r = response_generic(s, imap_unsubscribe(s, m))) == -1) goto fail; return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * Process the data that server sent due to IMAP FETCH FAST client request. */ int response_fetchfast(session *ssn, int tag, char **flags, char **date, char **size) { int r; char *s; regexp *re; r = response_generic(ssn, tag); if (r == -1 || r == STATUS_BYE) return r; re = &responses[RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); re = &responses[RESPONSE_FETCH_FLAGS]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *flags = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); re = &responses[RESPONSE_FETCH_DATE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *date = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); re = &responses[RESPONSE_FETCH_SIZE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *size = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); xfree(s); } return r; }