From 19e201d4476ed20d1c9a3c6ec0ba24c30ab03b2d Mon Sep 17 00:00:00 2001 From: Dany LE Date: Fri, 26 Aug 2022 19:40:12 +0200 Subject: [PATCH] wrapper for uwimap in lua with basic mapping --- .gitmodules | 3 + imap | 1 + limap.c | 858 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test.lua | 72 +++++ 4 files changed, 934 insertions(+) create mode 100644 .gitmodules create mode 160000 imap create mode 100644 limap.c create mode 100644 test.lua diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5901993 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "imap"] + path = imap + url = https://git.iohub.dev/dany/imap.git diff --git a/imap b/imap new file mode 160000 index 0000000..cab1094 --- /dev/null +++ b/imap @@ -0,0 +1 @@ +Subproject commit cab109466534e206a3652ef1c68fe88101b68bda diff --git a/limap.c b/limap.c new file mode 100644 index 0000000..694d172 --- /dev/null +++ b/limap.c @@ -0,0 +1,858 @@ +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "c-client.h" +#include "imap4r1.h" +#include +#include +extern int errno; /* just in case */ + +#define M_LOG(a,...) syslog (LOG_NOTICE,"limap@[%s: %d]: " a "\n", __FILE__, \ + __LINE__, ##__VA_ARGS__) +#define M_WARN(a,...) syslog (LOG_WARNING, "limap@[%s: %d]: " a "\n", __FILE__, \ + __LINE__, ##__VA_ARGS__) +#define M_ERROR(a,...) syslog (LOG_ERR, "limap@[%s: %d]: " a "\n", __FILE__, \ + __LINE__, ##__VA_ARGS__) + +#define add_property_string(L,k,v) \ + lua_pushstring(L,k); \ + lua_pushstring(L,v); \ + lua_settable(L,-3); + +#define add_property_long(L,k,v) \ + lua_pushstring(L,k); \ + lua_pushnumber(L,v); \ + lua_settable(L,-3); + +unsigned long find_rightmost_bit(unsigned long *valptr); + +static size_t strlcat(char *dst, const char *src, size_t n) { + char *p = dst; + + while (n != 0 && *p != '\0') { + p++; + n--; + } + if (n != 0) { + for (; --n != 0; p++, src++) { + if ((*p = *src) == '\0') + return p - dst; + } + *p = '\0'; + } + return (p - dst) + strlen(src); +} + +static void str_trim(char* str, const char delim) +{ + if(!str || strlen(str) == 0) return; + char * p = str; + int l = strlen(p); + while(l > 0 && p[l - 1] == delim) + p[--l] = 0; + while(* p && (* p) == delim ) ++p, --l; + memmove(str, p, l + 1); +} + +/* Co-routines from MAIL library */ + + +/* Message matches a search + * Accepts: MAIL stream + * message number + */ + +void mm_searched (MAILSTREAM *stream,unsigned long msgno) +{ + /* dummy routine */ +} + + +/* Message exists (i.e. there are that many messages in the mailbox) + * Accepts: MAIL stream + * message number + */ + +void mm_exists (MAILSTREAM *stream,unsigned long number) +{ + M_LOG("New emails found in %s: %d", stream->mailbox, number); + int * n = stream->sparep; + if(!n) return; + *n = number; +} + + +/* Message expunged + * Accepts: MAIL stream + * message number + */ + +void mm_expunged (MAILSTREAM *stream,unsigned long number) +{ + /* dummy routine */ +} + + +/* Message flags update seen + * Accepts: MAIL stream + * message number + */ + +void mm_flags (MAILSTREAM *stream,unsigned long number) +{ + /* dummy routine */ +} +/* Mailbox found + * Accepts: MAIL stream + * hierarchy delimiter + * mailbox name + * mailbox attributes + */ + +void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes) +{ + lua_State *L = stream->sparep; + if(!L) + return; + if(attributes & LATT_NOSELECT) + { + return; + } + size_t cnt = lua_rawlen(L,-1) + 1; + lua_pushnumber(L,cnt); + lua_newtable(L); + char delim[2]; + delim[0] = (char) delimiter; + delim[1] = '\0'; + if(!name) + return; + lua_pushstring(L, "delimiter"); + lua_pushstring(L, delim); + lua_settable(L, -3); + + lua_pushstring(L, "name"); + lua_pushstring(L, name); + lua_settable(L, -3); + + lua_pushstring(L, "LATT_NOINFERIORS"); + lua_pushboolean(L, attributes & LATT_NOINFERIORS); + lua_settable(L, -3); + + lua_pushstring(L, "LATT_NOSELECT"); + lua_pushboolean(L, attributes & LATT_NOSELECT); + lua_settable(L, -3); + + lua_pushstring(L, "LATT_MARKED"); + lua_pushboolean(L, attributes & LATT_MARKED); + lua_settable(L, -3); + + lua_pushstring(L, "LATT_UNMARKED"); + lua_pushboolean(L, attributes & LATT_UNMARKED); + lua_settable(L, -3); + lua_settable(L, -3); +} + + +/* Subscribe mailbox found + * Accepts: MAIL stream + * hierarchy delimiter + * mailbox name + * mailbox attributes + */ + +void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes) +{ + /* dummy routine */ +} + + +/* Mailbox status + * Accepts: MAIL stream + * mailbox name + * mailbox status + */ + +void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status) +{ + if (status->recent || status->unseen) + printf ("%lu new message(s) (%lu unseen),",status->recent,status->unseen); + else fputs ("No new messages,",stdout); + printf (" %lu total in %s\n",status->messages,mailbox); +} +/* Notification event + * Accepts: MAIL stream + * string to log + * error flag + */ + +void mm_notify (MAILSTREAM *stream,char *string,long errflg) +{ + if (!errflg && (string[0] == '[') && + ((string[1] == 'T') || (string[1] == 't')) && + ((string[2] == 'R') || (string[2] == 'r')) && + ((string[3] == 'Y') || (string[3] == 'y')) && + ((string[4] == 'C') || (string[4] == 'c')) && + ((string[5] == 'R') || (string[5] == 'r')) && + ((string[6] == 'E') || (string[6] == 'e')) && + ((string[7] == 'A') || (string[7] == 'a')) && + ((string[8] == 'T') || (string[8] == 't')) && + ((string[9] == 'E') || (string[9] == 'e')) && + (string[10] == ']')) + mm_log (string,errflg); /* just do mm_log action */ +} + +/* Log an event for the user to see + * Accepts: string to log + * error flag + */ + +void mm_log (char *string,long errflg) +{ + switch (errflg) { + case BYE: + case NIL: /* no error */ + M_LOG ("[%s]",string); + break; + case PARSE: /* parsing problem */ + case WARN: /* warning */ + M_WARN("warning: %s",string); + break; + case ERROR: /* error */ + default: + M_ERROR ("%s",string); + break; + } +} + + +/* Log an event to debugging telemetry + * Accepts: string to log + */ + +void mm_dlog (char *string) +{ + M_LOG ("%s",string); +} +/* Get user name and password for this host + * Accepts: parse of network mailbox name + * where to return user name + * where to return password + * trial count + */ + +void mm_login (NETMBX *mb,char *username,char *password,long trial) +{ + if(mb->user) + { + char * tmp = mb->user; + (void)strsep(&tmp, ";"); + strncpy(username, mb->user, NETMAXUSER); + if(tmp) + { + strncpy (password,tmp,MAILTMPLEN); + } + M_LOG("host: %s", mb->host); + M_LOG("orighost: %s", mb->orighost); + M_LOG("user: %s", mb->user); + M_LOG("mailbox: %s", mb->mailbox); + M_LOG("service: %s", mb->service); + } +} + + +/* About to enter critical code + * Accepts: stream + */ + +void mm_critical (MAILSTREAM *stream) +{ + /* note in critical code */ +} + + +/* About to exit critical code + * Accepts: stream + */ + +void mm_nocritical (MAILSTREAM *stream) +{ + /* note not in critical code */ +} + + +/* Disk error found + * Accepts: stream + * system error code + * flag indicating that mailbox may be clobbered + * Returns: T if user wants to abort + */ + +long mm_diskerror (MAILSTREAM *stream,long errcode,long serious) +{ + return T; +} + + +/* Log a fatal error event + * Accepts: string to log + */ + +void mm_fatal (char *string) +{ + M_ERROR ("FATAL: %s",string); +} + + + +static int l_mail_open(lua_State *L) +{ + const char* mailbox = luaL_checkstring(L,1); + long flag = 0; + if( lua_isnumber(L,2)) + { + flag = flag | (long)luaL_checknumber(L,2); + } + MAILSTREAM *stream = mail_open (NIL,(char*)mailbox,flag); + if(!stream) + { + lua_pushnil(L); + return 1; + } + //strncpy(stream->original_mailbox, stream->mailbox, strlen(stream->mailbox)); + if(stream->original_mailbox) + { + free(stream->original_mailbox); + } + stream->original_mailbox = strdup(stream->mailbox); + M_LOG("mailbox: %s", stream->mailbox); + M_LOG("original_mailbox: %s", stream->original_mailbox); + lua_pushlightuserdata(L, stream); + lua_pushstring(L,stream->mailbox); + return 2; +} + +static int l_mail_close(lua_State *L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + if(!stream) + { + lua_pushboolean(L,0); + } + else + { + (void) mail_close(stream); + lua_pushboolean(L,1); + } + return 1; +} + +static int l_get_mailboxes(lua_State *L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + const char* reference = luaL_checkstring(L,2); + const char* pattern = luaL_checkstring(L,3); + if(!stream) + { + lua_pushboolean(L,0); + return 1; + } + stream->sparep = (void*)L; + lua_newtable(L); + mail_list(stream,(char*)reference, (char*)pattern); + return 1; +} + +static int l_mail_ping(lua_State *L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + int new_mail = 0; + stream->sparep = (void*)&new_mail; + if(!stream || mail_ping(stream) == NIL) + { + lua_pushboolean(L,0); + } + else + { + lua_pushboolean(L,1); + } + lua_pushnumber(L, new_mail); + return 2; +} + +static int l_mail_check(lua_State *L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + if(!stream) + { + return 0; + } + mail_check(stream); + return 0; +} + +static int l_mail_get_raw_header(lua_State* L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + if(!stream) + { + lua_pushnil(L); + return 1; + } + const int id = luaL_checknumber(L,2); + char* msg_header = mail_fetchheader_full(stream, id, NIL, NIL, 0); + lua_pushstring(L, msg_header); + return 1; +} + +static int l_mail_getnumber(lua_State* L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + if(!stream) + { + lua_pushnumber(L, -1); + return 1; + } + lua_pushnumber(L, stream->nmsgs); + return 1; +} + +static void _imap_parse_address (lua_State* L, ADDRESS *addresslist) +{ + ADDRESS *addresstmp; + addresstmp = addresslist; + int count = 1; + lua_newtable(L); + do { + lua_pushnumber(L,count); + lua_newtable(L); + if (addresstmp->personal) + { + add_property_string(L, "personal", addresstmp->personal); + } + if (addresstmp->adl) + { + add_property_string(L, "adl", addresstmp->adl); + } + if (addresstmp->mailbox) + { + add_property_string(L, "mailbox", addresstmp->mailbox); + } + if (addresstmp->host) + { + add_property_string(L, "host", addresstmp->host); + } + lua_settable(L, -3); + count++; + } while ((addresstmp = addresstmp->next)); +} + +static void _make_header_object(lua_State* L, ENVELOPE *en) +{ + + lua_newtable(L); + if (en->remail) + { + add_property_string(L, "remail", en->remail); + } + if(en->date) + { + add_property_string(L, "date", (char*)en->date); + } + if (en->subject) + { + add_property_string(L, "subject", en->subject); + } + if (en->in_reply_to) + { + add_property_string(L, "in_reply_to", en->in_reply_to); + } + if (en->message_id) + { + add_property_string(L, "message_id", en->message_id); + } + if (en->newsgroups) + { + add_property_string(L, "newsgroups", en->newsgroups); + } + if (en->followup_to) + { + add_property_string(L, "followup_to", en->followup_to); + } + if (en->references) + { + add_property_string(L, "references", en->references); + } + + if (en->to) { + lua_pushstring(L, "to"); + _imap_parse_address(L, en->to); + lua_settable(L, -3); + } + + if (en->from) { + lua_pushstring(L, "from"); + _imap_parse_address(L, en->from); + lua_settable(L, -3); + } + + if (en->cc) { + lua_pushstring(L, "cc"); + _imap_parse_address(L, en->cc); + lua_settable(L, -3); + } + + if (en->bcc) { + lua_pushstring(L, "bcc"); + _imap_parse_address(L, en->bcc); + lua_settable(L, -3); + } + + if (en->reply_to) { + lua_pushstring(L, "reply_to"); + _imap_parse_address(L, en->reply_to); + lua_settable(L, -3); + } + + if (en->sender) { + lua_pushstring(L, "sender"); + _imap_parse_address(L, en->sender); + lua_settable(L, -3); + } + + if (en->return_path) { + lua_pushstring(L, "return_path"); + _imap_parse_address(L, en->return_path); + lua_settable(L, -3); + } +} + +static int l_rfc822_parse_header(lua_State* L) +{ + ENVELOPE *en = NULL; + const char* headers = luaL_checkstring(L,1); + rfc822_parse_msg(&en, NULL, (char*)headers, strlen(headers), NULL, "UNKNOWN", NIL); + if(en) + { + _make_header_object(L, en); + mail_free_envelope(&en); + } + else + { + lua_pushnil(L); + } + return 1; +} + +static int l_reopen(lua_State *L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + const char* mailbox = luaL_checkstring(L,2); + long flag = 0; + if( lua_isnumber(L,3)) + { + flag = flag | (long)luaL_checknumber(L,3); + } + if(!stream) + { + lua_pushboolean(L,0); + return 1; + } + stream = mail_open (stream,(char*)mailbox,flag); + if(!stream) + { + lua_pushboolean(L,0); + return 1; + } + if(stream->original_mailbox) + { + free(stream->original_mailbox); + } + stream->original_mailbox = strdup(stream->mailbox); + M_LOG("mailbox: %s", stream->mailbox); + M_LOG("original_mailbox: %s", stream->original_mailbox); + lua_pushboolean(L,1); + lua_pushstring(L,stream->mailbox); + return 2; +} + +static int l_mail_get_header(lua_State* L) +{ + char tmp[MAILTMPLEN + 1]; + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + if(!stream) + { + lua_pushnil(L); + return 1; + } + const int msgno = luaL_checknumber(L,2); + MESSAGECACHE *cache; + ENVELOPE *en; + + if (mail_fetchstructure(stream, msgno, NIL)) { + cache = mail_elt(stream, msgno); + } else { + lua_pushnil(L); + return 1; + } + + en = mail_fetchenvelope(stream, msgno); + + /* call a function to parse all the text, so that we can use the + same function to parse text from other sources */ + _make_header_object(L, en); + //free(en); + + /* now run through properties that are only going to be returned + from a server, not text headers */ + add_property_string(L, "Recent", cache->recent ? (cache->seen ? "R": "N") : " "); + add_property_string(L, "Unseen", (cache->recent | cache->seen) ? " " : "U"); + add_property_string(L, "Flagged", cache->flagged ? "F" : " "); + add_property_string(L, "Answered", cache->answered ? "A" : " "); + add_property_string(L, "Deleted", cache->deleted ? "D" : " "); + add_property_string(L, "Draft", cache->draft ? "X" : " "); + add_property_long(L, "Msgno", cache->msgno); + mail_date(tmp, cache); + add_property_string(L, "MailDate", tmp); + add_property_long(L, "Size", cache->rfc822_size); + add_property_long(L, "udate", mail_longdate(cache)); + + if (en->from) { + tmp[0] = 0x00; + mail_fetchfrom(tmp, stream, msgno, sizeof(tmp)); + str_trim(tmp, ' '); + add_property_string(L, "fetchfrom", tmp); + } + if (en->subject) { + tmp[0] = 0x00; + mail_fetchsubject(tmp, stream, msgno, sizeof(tmp)); + str_trim(tmp, ' '); + add_property_string(L, "fetchsubject", tmp); + } + return 1; +} + +static int l_mail_get_headers(lua_State* L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + if(!stream) + { + lua_pushnil(L); + return 1; + } + char tmp[MAILTMPLEN]; + unsigned int msgno; + char *t; + unsigned long i; + lua_newtable(L); + for (msgno = 1; msgno <= stream->nmsgs; msgno++) { + lua_pushnumber(L, msgno); + MESSAGECACHE * cache = mail_elt (stream, msgno); + mail_fetchstructure(stream, msgno, NIL); + tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' '; + tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U'; + tmp[2] = cache->flagged ? 'F' : ' '; + tmp[3] = cache->answered ? 'A' : ' '; + tmp[4] = cache->deleted ? 'D' : ' '; + tmp[5] = cache->draft ? 'X' : ' '; + snprintf(tmp + 6, sizeof(tmp) - 6, "%4ld) ", cache->msgno); + mail_date(tmp+11, cache); + tmp[22] = ' '; + tmp[23] = '\0'; + mail_fetchfrom(tmp+23, stream, msgno, (long)20); + strcat(tmp, " "); + if ((i = cache->user_flags)) { + strcat(tmp, "{"); + while (i) { + strlcat(tmp, stream->user_flags[find_rightmost_bit (&i)], sizeof(tmp)); + if (i) strlcat(tmp, " ", sizeof(tmp)); + } + strlcat(tmp, "} ", sizeof(tmp)); + } + mail_fetchsubject(t = tmp + strlen(tmp), stream, msgno, (long)25); + snprintf(t += strlen(t), sizeof(tmp) - strlen(tmp), " (%ld chars)", cache->rfc822_size); + lua_pushstring(L, tmp); + lua_settable(L,-3); + } + return 1; +} + +static int l_get_raw_body(lua_State* L) +{ + char tmp[MAILTMPLEN + 1]; + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + if(!stream) + { + lua_pushnil(L); + return 1; + } + unsigned int flags = 0; + const int msgno = luaL_checknumber(L,2); + if(lua_toboolean(L,3)) + { + flags |= FT_PEEK; + } + char *body; + unsigned long body_len = 0; + body = mail_fetchtext_full(stream, msgno, &body_len, flags); + if (body_len == 0) { + lua_pushnil(L); + } else { + lua_pushstring(L, body); + } + return 1; +} +static void _imap_add_body(lua_State* L, BODY *body) +{ + PARAMETER *par, *dpar; + PART *part; + int count = 1; + lua_newtable(L); + + if (body->type <= TYPEMAX) { + add_property_long(L, "type", body->type); + } + + if (body->encoding <= ENCMAX) { + add_property_long(L, "encoding", body->encoding); + } + + if (body->subtype) { + add_property_string(L, "subtype", body->subtype); + } + + if (body->description) { + add_property_string(L, "description", body->description); + } + + if (body->id) { + add_property_string(L, "id", body->id); + } + if (body->size.lines) { + add_property_long(L, "lines", body->size.lines); + } + + if (body->size.bytes) { + add_property_long(L, "bytes", body->size.bytes); + } + + if (body->md5) { + add_property_string(L, "md5", body->md5); + } + + if (body->location) { + add_property_string(L, "location", body->location); + } + + if (body->disposition.type) { + add_property_string(L, "disposition", body->disposition.type); + } + + if (body->disposition.parameter) { + dpar = body->disposition.parameter; + lua_pushstring(L, "dparameters"); + lua_newtable(L); + count = 1; + do { + lua_pushnumber(L, count); + lua_newtable(L); + add_property_string(L, "attribute", dpar->attribute); + add_property_string(L, "value", dpar->value); + lua_settable(L,-3); + count++; + } while ((dpar = dpar->next)); + lua_settable(L, -3); + } + + if ((par = body->parameter)) { + lua_pushstring(L, "parameters"); + lua_newtable(L); + count = 1; + do { + lua_pushnumber(L, count); + lua_newtable(L); + if (par->attribute) { + add_property_string(L, "attribute", par->attribute); + } + if (par->value) { + add_property_string(L, "value", par->value); + } + + lua_settable(L,-3); + count++; + } while ((par = par->next)); + lua_settable(L, -3); + } + /* multipart message ? */ + if (body->type == TYPEMULTIPART) { + lua_pushstring(L, "parts"); + lua_newtable(L); + count = 1; + for (part = body->nested.part; part; part = part->next) { + lua_pushnumber(L, count); + _imap_add_body(L, &part->body); + lua_settable(L, -3); + count++; + } + lua_settable(L, -3); + } + + /* encapsulated message ? */ + if ((body->type == TYPEMESSAGE) && (!strcasecmp(body->subtype, "rfc822"))) { + lua_pushstring(L, "message"); + lua_newtable(L); + + lua_pushstring(L, "header"); + _make_header_object(L,body->nested.msg->env); + lua_settable(L, -3); + + lua_pushstring(L, "body"); + _imap_add_body(L, body->nested.msg->body); + lua_settable(L, -3); + + lua_settable(L, -3); + } +} +static int l_get_structure(lua_State* L) +{ + MAILSTREAM *stream = (MAILSTREAM *) lua_touserdata(L, 1); + BODY *body; + if(!stream) + { + lua_pushnil(L); + return 1; + } + const int msgno = luaL_checknumber(L,2); + mail_fetchstructure_full(stream, msgno, &body , 0); + + if (!body) { + lua_pushnil(L); + return 1; + } + + _imap_add_body(L, body); + return 1; +} + +static const struct luaL_Reg _lib [] = { + {"open", l_mail_open}, + {"close", l_mail_close}, + {"get_mail_boxes", l_get_mailboxes}, + {"reopen", l_reopen}, + {"ping", l_mail_ping}, + {"check", l_mail_check}, + {"get_raw_header", l_mail_get_raw_header}, + {"get_nmail", l_mail_getnumber}, + {"get_headers", l_mail_get_headers}, + {"get_header", l_mail_get_header}, + {"rfc822_parse_header", l_rfc822_parse_header}, + {"get_raw_body", l_get_raw_body}, + {"get_structure", l_get_structure}, + {NULL,NULL} +}; + +int luaopen_limap(lua_State *L) +{ + #include "linkage.c" + luaL_newlib(L, _lib); + return 1; +} \ No newline at end of file diff --git a/test.lua b/test.lua new file mode 100644 index 0000000..1e9d6b7 --- /dev/null +++ b/test.lua @@ -0,0 +1,72 @@ +local OP_DEBUG = 0x1 +local OP_READONLY = 0x2 +local OP_ANONYMOUS = 0x4 --/* anonymous open of newsgroup */ +local OP_SHORTCACHE = 0x8 --/* short (elt-only) caching */ +local OP_SILENT = 0x10 --/* don't pass up events (internal use) */ +local OP_PROTOTYPE = 0x20 --/* return driver prototype */ +local OP_HALFOPEN = 0x40 --/* half-open (IMAP connect but no select) */ +local OP_EXPUNGE= 0x80 --/* silently expunge recycle stream */ + + +local imap = require("limap") +local passwd = os.getenv("IMAP_PWD") or "" +local url = string.format("{iohub.dev:143/imap/tls-sslv23/novalidate-cert/user=mrsang;%s}",passwd); +local handle, box = imap.open(url,OP_HALFOPEN|OP_DEBUG) + +local r,v = false,nil; + +function dump(obj) + if(type(obj) == "table") then + for k,v in pairs(obj) do + print(k) + dump(v) + end + else + print("[",obj,"]") + end +end + +if(handle) then + print("mailbox openned") + + local boxes = imap.get_mail_boxes(handle, box:gsub("[^}]*$",""),"*") + + for k, v in ipairs(boxes) do + print("=================") + for k1, v1 in pairs(v) do + print(k1,v1) + end + end + r, box = imap.reopen(handle,box:gsub("[^}]*$","INBOX"), OP_DEBUG) + if r then + print("new box opened", box) + else + print("reopen failed") + end + r,v = imap.ping(handle) + if r then + print("Alive", v) + else + print("Unable to ping") + end + imap.check(handle); + -- get nmail + local nmail = imap.get_nmail(handle); + print("umber of mail", nmail); + + if nmail > 0 then + local headers = imap.get_headers(handle) + dump(headers) + end + print("===============================") + local header = imap.get_header(handle, nmail-3) + dump(header) + print("===============================") + local raw_body = imap.get_raw_body(handle, nmail-3, true) -- peak the message without set it to seen + print(raw_body) + print("===============================") + local structure = imap.get_structure(handle, nmail-3) + dump(structure) + + imap.close(handle) +end \ No newline at end of file