diff options
-rw-r--r-- | imap.h | 7 | ||||
-rw-r--r-- | imbox.c | 125 |
2 files changed, 65 insertions, 67 deletions
diff --git a/imap.h b/imap.h index c6d96f5..2730d1a 100644 --- a/imap.h +++ b/imap.h @@ -157,6 +157,13 @@ struct Resp { const char *text; }; +static inline struct Resp respOk(struct Resp resp) { + if (resp.resp == AtomNo || resp.resp == AtomBad || resp.resp == AtomBye) { + errx(EX_CONFIG, "%s: %s", Atoms[resp.tag], resp.text); + } + return resp; +} + static inline void respFree(struct Resp resp) { listFree(resp.code); listFree(resp.data); diff --git a/imbox.c b/imbox.c index 8c4d351..f1ed24a 100644 --- a/imbox.c +++ b/imbox.c @@ -108,80 +108,71 @@ int main(int argc, char *argv[]) { ); if (!pass) err(EX_UNAVAILABLE, "readpassphrase"); - enum Atom login = 0; - enum Atom examine = atom("examine"); - + struct Resp resp; struct IMAP imap = imapOpen(host, port); - for ( - struct Resp resp; - resp = imapResp(&imap), resp.resp != AtomBye; - respFree(resp) - ) { - if (resp.resp == AtomNo || resp.resp == AtomBad) { - errx(EX_CONFIG, "%s: %s", Atoms[resp.resp], resp.text); - } + respFree(respOk(imapResp(&imap))); - if (!login) { - login = atom("login"); - fprintf( - imap.w, "%s LOGIN \"%s\" \"%s\"\r\n", - Atoms[login], user, pass - ); - } + enum Atom login = atom("login"); + fprintf(imap.w, "%s LOGIN \"%s\" \"%s\"\r\n", Atoms[login], user, pass); + for (; resp = respOk(imapResp(&imap)), resp.tag != login; respFree(resp)); + respFree(resp); - if (resp.tag == login) { - fprintf(imap.w, "%s EXAMINE \"%s\"\r\n", Atoms[examine], mailbox); - } - - if (resp.tag == examine) { - fprintf(imap.w, "%s SEARCH CHARSET UTF-8", Atoms[AtomSearch]); - if (subject) fprintf(imap.w, " SUBJECT \"%s\"", subject); - if (from) fprintf(imap.w, " FROM \"%s\"", from); - if (to) fprintf(imap.w, " TO \"%s\"", to); - if (cc) fprintf(imap.w, " CC \"%s\"", cc); - fprintf(imap.w, "\r\n"); - } - - if (resp.resp == AtomSearch) { - if (!resp.data.len) errx(EX_TEMPFAIL, "no matching messages"); - fprintf(imap.w, "%s FETCH ", Atoms[AtomFetch]); - for (size_t i = 0; i < resp.data.len; ++i) { - uint32_t num = dataCheck(resp.data.ptr[i], Number).number; - fprintf(imap.w, "%s%" PRIu32, (i ? "," : ""), num); - } - fprintf( - imap.w, - " (BODY[HEADER.FIELDS (" FETCH_HEADERS ")] BODY[TEXT])\r\n" - ); - } + enum Atom examine = atom("examine"); + fprintf(imap.w, "%s EXAMINE \"%s\"\r\n", Atoms[examine], mailbox); + for (; resp = respOk(imapResp(&imap)), resp.tag != examine; respFree(resp)); + respFree(resp); + + struct List nums = {0}; + enum Atom search = atom("search"); + fprintf(imap.w, "%s SEARCH CHARSET UTF-8", Atoms[search]); + if (subject) fprintf(imap.w, " SUBJECT \"%s\"", subject); + if (from) fprintf(imap.w, " FROM \"%s\"", from); + if (to) fprintf(imap.w, " TO \"%s\"", to); + if (cc) fprintf(imap.w, " CC \"%s\"", cc); + fprintf(imap.w, "\r\n"); + for (; resp = respOk(imapResp(&imap)), resp.tag != search; respFree(resp)) { + if (resp.resp != AtomSearch) continue; + if (!resp.data.len) errx(EX_TEMPFAIL, "no matching messages"); + nums = resp.data; + resp.data = (struct List) {0}; + } + respFree(resp); - if (resp.resp == AtomFetch) { - if (!resp.data.len) errx(EX_PROTOCOL, "missing fetch data"); - struct List items = dataCheck(resp.data.ptr[0], List).list; - struct Data header = {0}; - struct Data body = {0}; - for (size_t i = 0; i < items.len; ++i) { - struct Data item = items.ptr[i]; - if (item.type != List) continue; - if (!item.list.len) continue; - if (item.list.ptr[0].type != Atom) continue; - if (item.list.ptr[0].atom == AtomHeader) { - if (i + 1 < items.len) header = items.ptr[i + 1]; - } - if (item.list.ptr[0].atom == AtomText) { - if (i + 1 < items.len) body = items.ptr[i + 1]; - } + enum Atom fetch = atom("fetch"); + fprintf(imap.w, "%s FETCH ", Atoms[fetch]); + for (size_t i = 0; i < nums.len; ++i) { + uint32_t num = dataCheck(nums.ptr[i], Number).number; + fprintf(imap.w, "%s%" PRIu32, (i ? "," : ""), num); + } + fprintf( + imap.w, " (BODY[HEADER.FIELDS (" FETCH_HEADERS ")] BODY[TEXT])\r\n" + ); + for (; resp = respOk(imapResp(&imap)), resp.tag != fetch; respFree(resp)) { + if (resp.resp != AtomFetch) continue; + if (!resp.data.len) errx(EX_PROTOCOL, "missing fetch data"); + struct List items = dataCheck(resp.data.ptr[0], List).list; + struct Data header = {0}; + struct Data body = {0}; + for (size_t i = 0; i + 2 < items.len; ++i) { + struct Data item = items.ptr[i]; + if (item.type != Atom || item.atom != AtomBody) continue; + if (items.ptr[i + 1].type != List) continue; + struct List sect = items.ptr[i + 1].list; + if (!sect.len || sect.ptr[0].type != Atom) continue; + if (sect.ptr[0].atom == AtomHeader) { + header = items.ptr[i + 2]; + } else if (sect.ptr[0].atom == AtomText) { + body = items.ptr[i + 2]; } - mboxrd( - dataCheck(header, String).string, - dataCheck(body, String).string - ); - } - - if (resp.tag == AtomFetch) { - fprintf(imap.w, "ayy LOGOUT\r\n"); } + mboxrd( + dataCheck(header, String).string, + dataCheck(body, String).string + ); } + respFree(resp); + + fprintf(imap.w, "ayy LOGOUT\r\n"); fclose(imap.r); fclose(imap.w); } |