wrapper for uwimap in lua with basic mapping
This commit is contained in:
parent
2564dba5ca
commit
19e201d447
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "imap"]
|
||||
path = imap
|
||||
url = https://git.iohub.dev/dany/imap.git
|
1
imap
Submodule
1
imap
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cab109466534e206a3652ef1c68fe88101b68bda
|
858
limap.c
Normal file
858
limap.c
Normal file
@ -0,0 +1,858 @@
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "c-client.h"
|
||||
#include "imap4r1.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
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;
|
||||
}
|
72
test.lua
Normal file
72
test.lua
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user