/* * 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; }
/* * 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; }
/* * 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; }
/* * Get mailbox's status. */ int request_status(const char *server, const char *port, const char *user, const char *mbox, unsigned int *exists, unsigned int *recent, unsigned int *unseen, unsigned int *uidnext) { 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); if (s->protocol == PROTOCOL_IMAP4REV1) { t = imap_status(s, m, "MESSAGES RECENT UNSEEN UIDNEXT"); if ((r = response_status(s, t, exists, recent, unseen, uidnext)) == -1) goto fail; } else { t = imap_examine(s, m); if ((r = response_examine(s, t, exists, recent)) == -1) goto fail; } return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * 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; }
/* * List subscribed mailboxes. */ int request_lsub(session *ssn, const char *refer, const char *name, char **mboxs, char **folders) { int t, r; const char *n; n = apply_namespace(name, ssn->ns.prefix, ssn->ns.delim); TRY(t = send_request(ssn, "LSUB \"%s\" \"%s\"", refer, n)); TRY(r = response_list(ssn, t, mboxs, folders)); return r; }
/* * Open mailbox in read-write mode. */ int request_select(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, "SELECT \"%s\"", m)); TRY(r = response_select(ssn, t)); if (r == STATUS_OK) ssn->selected = xstrdup(mbox); 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; }
/* * 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; }
/* * Get mailbox's status. */ int request_status(session *ssn, const char *mbox, unsigned int *exists, unsigned int *recent, unsigned int *unseen, unsigned int *uidnext) { int t, r; const char *m; m = apply_namespace(mbox, ssn->ns.prefix, ssn->ns.delim); if (ssn->protocol == PROTOCOL_IMAP4REV1) { TRY(t = send_request(ssn, "STATUS \"%s\" (MESSAGES RECENT UNSEEN UIDNEXT)", m)); TRY(r = response_status(ssn, t, exists, recent, unseen, uidnext)); } else { TRY(t = send_request(ssn, "EXAMINE \"%s\"", m)); TRY(r = response_examine(ssn, t, exists, recent)); } 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; }
/* * 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; }
/* * 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; }
/* * List subscribed mailboxes. */ int request_lsub(const char *server, const char *port, const char *user, const char *refer, const char *name, char **mboxs, char **folders) { int t, r; session *s; const char *n; if (!(s = session_find(server, port, user))) return -1; n = apply_namespace(name, s->ns.prefix, s->ns.delim); t = imap_lsub(s, refer, n); if ((r = response_list(s, t, mboxs, folders)) == -1) goto fail; return r; fail: close_connection(s); session_destroy(s); return -1; }
/* * Connect to the server, login to the IMAP server, get it's capabilities, get * the namespace of the mailboxes. */ int request_login(session **ssnptr, const char *server, const char *port, const char *ssl, const char *user, const char *pass) { int t, r, rg = -1, rl = -1; session *ssn = *ssnptr; if (*ssnptr && (*ssnptr)->socket != -1) return STATUS_PREAUTH; if (!*ssnptr) { ssn = *ssnptr = session_new(); ssn->server = server; ssn->port = port; ssn->username = user; ssn->password = pass; if (strlen(ssl) != 0) ssn->sslproto = ssl; } else { debug("recovering connection: %s://%s@%s:%s/%s\n", ssn->sslproto ?"imaps" : "imap", ssn->username, ssn->server, ssn->port, ssn->selected ? ssn->selected : ""); } if (open_connection(ssn) == -1) goto fail; CHECK(rg = response_greeting(ssn)); if (opts.debug) { CHECK(t = send_request(ssn, "NOOP")); CHECK(response_generic(ssn, t)); } CHECK(t = send_request(ssn, "CAPABILITY")); CHECK(response_capability(ssn, t)); if (!ssn->sslproto && ssn->capabilities & CAPABILITY_STARTTLS && get_option_boolean("starttls")) { CHECK(t = send_request(ssn, "STARTTLS")); CHECK(r = response_generic(ssn, t)); if (r == STATUS_OK) { if (open_secure_connection(ssn) == -1) goto fail; CHECK(t = send_request(ssn, "CAPABILITY")); CHECK(response_capability(ssn, t)); } } if (rg != STATUS_PREAUTH) { if (ssn->capabilities & CAPABILITY_CRAMMD5 && get_option_boolean("crammd5")) { unsigned char *in, *out; CHECK(t = send_request(ssn, "AUTHENTICATE CRAM-MD5")); CHECK(r = response_authenticate(ssn, t, &in)); if (r == STATUS_CONTINUE) { if ((out = auth_cram_md5(ssn->username, ssn->password, in)) == NULL) goto abort; CHECK(send_continuation(ssn, (char *)(out), strlen((char *)(out)))); xfree(out); CHECK(rl = response_generic(ssn, t)); } else goto abort; } if (rl != STATUS_OK) { CHECK(t = send_request(ssn, "LOGIN \"%s\" \"%s\"", ssn->username, ssn->password)); CHECK(rl = response_generic(ssn, t)); } if (rl == STATUS_NO) { error("username %s or password rejected at %s\n", ssn->username, ssn->server); close_connection(ssn); session_destroy(ssn); return STATUS_NO; } } else { rl = STATUS_PREAUTH; } CHECK(t = send_request(ssn, "CAPABILITY")); CHECK(response_capability(ssn, t)); if (ssn->capabilities & CAPABILITY_NAMESPACE && get_option_boolean("namespace")) { CHECK(t = send_request(ssn, "NAMESPACE")); CHECK(response_namespace(ssn, t)); } if (ssn->selected) { CHECK(t = send_request(ssn, "SELECT \"%s\"", apply_namespace(ssn->selected, ssn->ns.prefix, ssn->ns.delim))); CHECK(response_select(ssn, t)); } return rl; abort: close_connection(ssn); fail: session_destroy(ssn); return -1; }