mirror of
https://github.com/moparisthebest/imapfilter
synced 2025-03-11 07:00:06 -04:00
Improve robustness and recoverability
Many extensive changes were made to better handle network errors, while on some cases it is now possible to recover from previously fatal failures.
This commit is contained in:
parent
dc5b33b60a
commit
18b012c2a2
@ -45,13 +45,13 @@ function Account._login_user(self)
|
||||
|
||||
local r = ifcore.login(self._imap)
|
||||
|
||||
if (r == nil) then
|
||||
return true
|
||||
elseif (r == true) then
|
||||
if (r == true) then
|
||||
self._selected = nil
|
||||
return true
|
||||
elseif (r == false) then
|
||||
error("login failure", 3)
|
||||
return true
|
||||
elseif (r == nil) then
|
||||
error("login request failed", 3)
|
||||
end
|
||||
end
|
||||
|
||||
@ -90,7 +90,13 @@ function Account.list_all(self, folder, mbox)
|
||||
return
|
||||
end
|
||||
|
||||
local _, mailboxes, folders = ifcore.list(self._imap, '', folder .. mbox)
|
||||
local r, mailboxes, folders = ifcore.list(self._imap, '', folder .. mbox)
|
||||
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("list request failed", 2)
|
||||
end
|
||||
|
||||
local m = {}
|
||||
for s in string.gmatch(mailboxes, '%C+') do
|
||||
@ -131,7 +137,13 @@ function Account.list_subscribed(self, folder, mbox)
|
||||
return
|
||||
end
|
||||
|
||||
local _, mailboxes, folders = ifcore.lsub(self._imap, '', folder .. mbox)
|
||||
local r, mailboxes, folders = ifcore.lsub(self._imap, '', folder .. mbox)
|
||||
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("lsub request failed", 2)
|
||||
end
|
||||
|
||||
local m = {}
|
||||
for s in string.gmatch(mailboxes, '%C+') do
|
||||
@ -158,6 +170,8 @@ function Account.create_mailbox(self, name)
|
||||
|
||||
local r = ifcore.create(self._imap, name)
|
||||
|
||||
if (r == nil) then error("create request failed", 2) end
|
||||
|
||||
if (type(options) == 'table' and options.info == true) then
|
||||
print(string.format("Created mailbox %s@%s/%s.",
|
||||
self._imap.username, self._imap.server, name))
|
||||
@ -175,6 +189,8 @@ function Account.delete_mailbox(self, name)
|
||||
|
||||
local r = ifcore.delete(self._imap, name)
|
||||
|
||||
if (r == nil) then error("delete request failed", 2) end
|
||||
|
||||
if (type(options) == 'table' and options.info == true) then
|
||||
print(string.format("Deleted mailbox %s@%s/%s.",
|
||||
self._imap.username, self._imap.server, name))
|
||||
@ -193,6 +209,8 @@ function Account.rename_mailbox(self, oldname, newname)
|
||||
|
||||
local r = ifcore.rename(self._imap, oldname, newname)
|
||||
|
||||
if (r == nil) then error("rename request failed", 2) end
|
||||
|
||||
if (type(options) == 'table' and options.info == true) then
|
||||
print(string.format("Renamed mailbox %s@%s/%s to %s@%s/%s.",
|
||||
self._imap.username, self._imap.server, oldname,
|
||||
@ -211,6 +229,8 @@ function Account.subscribe_mailbox(self, name)
|
||||
|
||||
local r = ifcore.subscribe(self._imap, name)
|
||||
|
||||
if (r == nil) then error("subscribe request failed", 2) end
|
||||
|
||||
if (type(options) == 'table' and options.info == true) then
|
||||
print(string.format("Subscribed mailbox %s@%s/%s.",
|
||||
self._imap.username, self._imap.server, name))
|
||||
@ -228,6 +248,8 @@ function Account.unsubscribe_mailbox(self, name)
|
||||
|
||||
local r = ifcore.unsubscribe(self._imap, name)
|
||||
|
||||
if (r == nil) then error("unsubscribe request failed", 2) end
|
||||
|
||||
if (type(options) == 'table' and options.info == true) then
|
||||
print(string.format("Unsubscribed mailbox %s@%s/%s.",
|
||||
self._imap.username, self._imap.server, name))
|
||||
|
@ -38,7 +38,7 @@ get_cert(session *ssn)
|
||||
|
||||
mdlen = 0;
|
||||
|
||||
if (!(cert = SSL_get_peer_certificate(ssn->ssl)))
|
||||
if (!(cert = SSL_get_peer_certificate(ssn->sslsocket)))
|
||||
return -1;
|
||||
|
||||
if (!(X509_digest(cert, EVP_md5(), md, &mdlen)))
|
||||
|
77
src/core.c
77
src/core.c
@ -106,6 +106,9 @@ ifcore_noop(lua_State *lua)
|
||||
r = request_noop(s, p, u);
|
||||
|
||||
lua_pop(lua, 1);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
@ -139,7 +142,7 @@ ifcore_login(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 1);
|
||||
|
||||
if (r == STATUS_RESPONSE_NONE)
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK ||
|
||||
@ -173,6 +176,9 @@ ifcore_logout(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 1);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -210,6 +216,9 @@ ifcore_status(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
lua_pushnumber(lua, (lua_Number) (exists));
|
||||
lua_pushnumber(lua, (lua_Number) (recent));
|
||||
@ -247,6 +256,9 @@ ifcore_select(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -277,6 +289,9 @@ ifcore_close(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 1);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -307,6 +322,9 @@ ifcore_expunge(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 1);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -345,6 +363,9 @@ ifcore_list(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 3);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!mboxs && !folders)
|
||||
@ -392,6 +413,9 @@ ifcore_lsub(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 3);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!mboxs)
|
||||
@ -482,6 +506,9 @@ ifcore_fetchfast(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!flags || !date || !size)
|
||||
@ -529,6 +556,9 @@ ifcore_fetchflags(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!flags)
|
||||
@ -572,6 +602,9 @@ ifcore_fetchdate(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!date)
|
||||
@ -658,6 +691,9 @@ ifcore_fetchstructure(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 3);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!structure)
|
||||
@ -701,6 +737,9 @@ ifcore_fetchheader(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!header)
|
||||
@ -744,6 +783,9 @@ ifcore_fetchtext(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!text)
|
||||
@ -789,6 +831,9 @@ ifcore_fetchfields(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 3);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!fields)
|
||||
@ -834,6 +879,9 @@ ifcore_fetchpart(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 3);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
if (!part)
|
||||
@ -875,6 +923,9 @@ ifcore_store(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 4);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -909,6 +960,9 @@ ifcore_copy(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 3);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -955,6 +1009,9 @@ ifcore_append(lua_State *lua)
|
||||
|
||||
lua_pop(lua, lua_gettop(lua));
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -988,6 +1045,9 @@ ifcore_create(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -1021,6 +1081,9 @@ ifcore_delete(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -1055,6 +1118,9 @@ ifcore_rename(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 3);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -1088,6 +1154,9 @@ ifcore_subscribe(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -1121,6 +1190,9 @@ ifcore_unsubscribe(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 2);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
@ -1151,6 +1223,9 @@ ifcore_idle(lua_State *lua)
|
||||
|
||||
lua_pop(lua, 1);
|
||||
|
||||
if (r == -1)
|
||||
return 0;
|
||||
|
||||
lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));
|
||||
|
||||
return 1;
|
||||
|
@ -250,10 +250,12 @@ imap_delete(session *ssn, const char *mbox)
|
||||
* IMAP RENAME: renames mailbox.
|
||||
*/
|
||||
int
|
||||
imap_rename(session *ssn, const char *oldmbox, const char *newmbox)
|
||||
imap_rename(session *ssn, char *oldmbox, char *newmbox)
|
||||
{
|
||||
|
||||
prepare_command("%04X RENAME \"%s\" \"%s\"\r\n", tag, oldmbox, newmbox);
|
||||
xfree(oldmbox);
|
||||
xfree(newmbox);
|
||||
|
||||
return send_command(ssn, obuf.data, NULL);
|
||||
}
|
||||
|
@ -49,7 +49,6 @@
|
||||
#define STATUS_RESPONSE_TRYCREATE 9
|
||||
#define STATUS_RESPONSE_TIMEOUT 10
|
||||
|
||||
|
||||
/* Initial buffer size for input, output and namespace buffers. */
|
||||
#define INPUT_BUF 4096
|
||||
#define OUTPUT_BUF 1024
|
||||
@ -114,7 +113,7 @@ int imap_select(session *ssn, const char *mbox);
|
||||
int imap_examine(session *ssn, const char *mbox);
|
||||
int imap_create(session *ssn, const char *mbox);
|
||||
int imap_delete(session *ssn, const char *mbox);
|
||||
int imap_rename(session *ssn, const char *oldmbox, const char *newmbox);
|
||||
int imap_rename(session *ssn, char *oldmbox, char *newmbox);
|
||||
int imap_subscribe(session *ssn, const char *mbox);
|
||||
int imap_unsubscribe(session *ssn, const char *mbox);
|
||||
int imap_list(session *ssn, const char *refer, const char *name);
|
||||
@ -184,7 +183,7 @@ LUALIB_API int luaopen_ifre(lua_State *lua);
|
||||
|
||||
/* request.c */
|
||||
int request_noop(const char *server, const char *port, const char *user);
|
||||
int request_login(const char *server, const char *port, const char *ssl,
|
||||
int request_login(const char *server, const char *port, const char *protocol,
|
||||
const char *user, const char *pass);
|
||||
int request_logout(const char *server, const char *port, const char *user);
|
||||
int request_status(const char *server, const char *port, const char *user,
|
||||
@ -266,15 +265,13 @@ void catch_signals(void);
|
||||
void release_signals(void);
|
||||
|
||||
/* socket.c */
|
||||
int open_connection(session *ssn, const char *server, const char *port,
|
||||
const char *protocol);
|
||||
int open_connection(session *ssn);
|
||||
int close_connection(session *ssn);
|
||||
ssize_t socket_read(session *ssn, char *buf, size_t len, long timeout,
|
||||
int timeoutfail);
|
||||
ssize_t socket_write(session *ssn, const char *buf, size_t len);
|
||||
#ifndef NO_SSLTLS
|
||||
int open_secure_connection(session *ssn, const char *server, const char *port,
|
||||
const char *protocol);
|
||||
int open_secure_connection(session *ssn);
|
||||
int close_secure_connection(session *ssn);
|
||||
ssize_t socket_secure_read(session *ssn, char *buf, size_t len);
|
||||
ssize_t socket_secure_write(session *ssn, const char *buf, size_t len);
|
||||
|
108
src/mailbox.lua
108
src/mailbox.lua
@ -41,11 +41,14 @@ end
|
||||
function Mailbox._cached_select(self)
|
||||
if (self._account._selected == nil or
|
||||
self._account._selected ~= self._mailbox) then
|
||||
if (ifcore.select(self._account._imap, self._mailbox) == true) then
|
||||
local r = ifcore.select(self._account._imap, self._mailbox)
|
||||
if (r == true) then
|
||||
self._account._selected = self._mailbox
|
||||
return true
|
||||
else
|
||||
elseif (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("select request failed", 3)
|
||||
end
|
||||
else
|
||||
return true
|
||||
@ -54,7 +57,9 @@ end
|
||||
|
||||
function Mailbox._cached_close(self)
|
||||
self._account._selected = nil
|
||||
return ifcore.close(self._account._imap)
|
||||
local r = ifcore.close(self._account._imap)
|
||||
if (r == nil) then error("close request failed", 3) end
|
||||
return r
|
||||
end
|
||||
|
||||
|
||||
@ -87,7 +92,13 @@ function Mailbox._send_query(self, criteria, charset)
|
||||
return {}
|
||||
end
|
||||
|
||||
local _, results = ifcore.search(self._account._imap, query, charset)
|
||||
local r, results = ifcore.search(self._account._imap, query, charset)
|
||||
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("search request failed", 3)
|
||||
end
|
||||
|
||||
if (type(options) == 'table' and options.close == true) then
|
||||
self._cached_close(self)
|
||||
@ -134,8 +145,10 @@ function Mailbox._flag_messages(self, mode, flags, messages)
|
||||
end
|
||||
r = ifcore.store(self._account._imap, table.concat(m, ',', i, j),
|
||||
mode, f)
|
||||
if r == false then
|
||||
if (r == false) then
|
||||
break
|
||||
elseif (r == nil) then
|
||||
error("store request failed", 3)
|
||||
end
|
||||
end
|
||||
|
||||
@ -171,8 +184,10 @@ function Mailbox._copy_messages(self, dest, messages)
|
||||
end
|
||||
r = ifcore.copy(self._account._imap, table.concat(m, ',', i, j),
|
||||
dest._mailbox)
|
||||
if r == false then
|
||||
if (r == false) then
|
||||
break
|
||||
elseif (r == nil) then
|
||||
error("copy request failed", 3)
|
||||
end
|
||||
end
|
||||
|
||||
@ -196,6 +211,7 @@ function Mailbox._copy_messages(self, dest, messages)
|
||||
|
||||
r = ifcore.append(dest._account._imap, dest._mailbox, mesgs[i],
|
||||
table.concat(fast[i]['flags'], ' '), fast[i]['date'])
|
||||
if (r == nil) then error("append request failed", 3) end
|
||||
end
|
||||
end
|
||||
|
||||
@ -218,8 +234,13 @@ function Mailbox._fetch_fast(self, messages)
|
||||
|
||||
local results = {}
|
||||
for _, m in ipairs(messages) do
|
||||
local _, flags, date, size = ifcore.fetchfast(self._account._imap,
|
||||
local r, flags, date, size = ifcore.fetchfast(self._account._imap,
|
||||
tostring(m))
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchfast request failed", 3)
|
||||
end
|
||||
if (flags ~= nil and date ~= nil and size ~= nil ) then
|
||||
local f = {}
|
||||
for s in string.gmatch(flags, '%S+') do
|
||||
@ -254,7 +275,12 @@ function Mailbox._fetch_flags(self, messages)
|
||||
|
||||
local results = {}
|
||||
for _, m in ipairs(messages) do
|
||||
local _, flags = ifcore.fetchflags(self._account._imap, tostring(m))
|
||||
local r, flags = ifcore.fetchflags(self._account._imap, tostring(m))
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchflags request failed", 3)
|
||||
end
|
||||
if (flags ~= nil) then
|
||||
local f = {}
|
||||
for s in string.gmatch(flags, '%S+') do
|
||||
@ -290,7 +316,12 @@ function Mailbox._fetch_date(self, messages)
|
||||
self[m]._date) then
|
||||
results[m] = self[m]._date
|
||||
else
|
||||
local _, date = ifcore.fetchdate(self._account._imap, tostring(m))
|
||||
local r, date = ifcore.fetchdate(self._account._imap, tostring(m))
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchdate request failed", 3)
|
||||
end
|
||||
if (date ~= nil) then
|
||||
results[m] = date
|
||||
if (type(options) == 'table' and options.cache == true) then
|
||||
@ -326,7 +357,12 @@ function Mailbox._fetch_size(self, messages)
|
||||
self[m]._size) then
|
||||
results[m] = self[m]._size
|
||||
else
|
||||
local _, size = ifcore.fetchsize(self._account._imap, tostring(m))
|
||||
local r, size = ifcore.fetchsize(self._account._imap, tostring(m))
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchsize request failed", 3)
|
||||
end
|
||||
if (size ~= nil) then
|
||||
results[m] = tonumber(size)
|
||||
if (type(options) == 'table' and options.cache == true) then
|
||||
@ -362,8 +398,13 @@ function Mailbox._fetch_header(self, messages)
|
||||
self[m]._header) then
|
||||
results[m] = self[m]._header
|
||||
else
|
||||
local _, header = ifcore.fetchheader(self._account._imap,
|
||||
local r, header = ifcore.fetchheader(self._account._imap,
|
||||
tostring(m))
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchheader request failed", 3)
|
||||
end
|
||||
if (header ~= nil) then
|
||||
results[m] = header
|
||||
if (type(options) == 'table' and options.cache == true) then
|
||||
@ -399,7 +440,12 @@ function Mailbox._fetch_body(self, messages)
|
||||
self[m]._body) then
|
||||
results[m] = self[m]._body
|
||||
else
|
||||
local _, body = ifcore.fetchbody(self._account._imap, tostring(m))
|
||||
local r, body = ifcore.fetchbody(self._account._imap, tostring(m))
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchbody request failed", 3)
|
||||
end
|
||||
if (body ~= nil) then
|
||||
results[m] = body
|
||||
if (type(options) == 'table' and options.cache == true) then
|
||||
@ -460,8 +506,13 @@ function Mailbox._fetch_fields(self, fields, messages)
|
||||
self[m]._fields[f]) then
|
||||
results[m] = results[m] .. self[m]._fields[f]
|
||||
else
|
||||
local _, field = ifcore.fetchfields(self._account._imap,
|
||||
local r, field = ifcore.fetchfields(self._account._imap,
|
||||
tostring(m), f)
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchfields request failed", 3)
|
||||
end
|
||||
if (field ~= nil) then
|
||||
field = string.gsub(field, "\r\n\r\n$", "\n")
|
||||
results[m] = results[m] .. field
|
||||
@ -500,8 +551,13 @@ function Mailbox._fetch_structure(self, messages)
|
||||
self[m]._structure) then
|
||||
results[m] = self[m]._structure
|
||||
else
|
||||
local _, structure = ifcore.fetchstructure(self._account._imap,
|
||||
local r, structure = ifcore.fetchstructure(self._account._imap,
|
||||
tostring(m))
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchstructure request failed", 3)
|
||||
end
|
||||
if (structure ~= nil) then
|
||||
local parsed = _parse_structure({ ['s'] = structure, ['i'] = 1 })
|
||||
results[m] = parsed
|
||||
@ -535,8 +591,13 @@ function Mailbox._fetch_parts(self, parts, message)
|
||||
self[message]._parts[part]) then
|
||||
results[part] = self[message]._parts[part]
|
||||
else
|
||||
local _, bodypart = ifcore.fetchpart(self._account._imap,
|
||||
local r, bodypart = ifcore.fetchpart(self._account._imap,
|
||||
tostring(message), part)
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("fetchparts request failed", 3)
|
||||
end
|
||||
if (bodypart ~= nil) then
|
||||
results[part] = bodypart
|
||||
self[message]._parts[part] = bodypart
|
||||
@ -557,8 +618,13 @@ function Mailbox.check_status(self)
|
||||
return
|
||||
end
|
||||
|
||||
local _, exist, recent, unseen, uidnext = ifcore.status(self._account._imap,
|
||||
local r, exist, recent, unseen, uidnext = ifcore.status(self._account._imap,
|
||||
self._mailbox)
|
||||
if (r == false) then
|
||||
return false
|
||||
elseif (r == nil) then
|
||||
error("status request failed", 2)
|
||||
end
|
||||
|
||||
if (type(options) == 'table' and options.info == true) then
|
||||
print(string.format("%d messages, %d recent, %d unseen, in %s@%s/%s.",
|
||||
@ -924,8 +990,11 @@ function Mailbox.append_message(self, message, flags, date)
|
||||
flags = table.concat(flags, ' ')
|
||||
end
|
||||
|
||||
return ifcore.append(self._account._imap, self._mailbox, message, flags,
|
||||
r = ifcore.append(self._account._imap, self._mailbox, message, flags,
|
||||
date)
|
||||
if (r == nil) then error("append request failed", 2) end
|
||||
|
||||
return r
|
||||
end
|
||||
|
||||
|
||||
@ -1239,7 +1308,10 @@ function Mailbox.enter_idle(self)
|
||||
return false
|
||||
end
|
||||
|
||||
return ifcore.idle(self._account._imap)
|
||||
local r = ifcore.idle(self._account._imap)
|
||||
if (r == nil) then error("idle request failed", 2) end
|
||||
|
||||
return r
|
||||
end
|
||||
|
||||
Mailbox._mt.__index = function () end
|
||||
|
449
src/request.c
449
src/request.c
@ -10,7 +10,24 @@
|
||||
extern options opts;
|
||||
|
||||
|
||||
int create_mailbox(session *ssn, const char *mbox);
|
||||
#define TRY(F) \
|
||||
switch ((F)) { \
|
||||
case -1: \
|
||||
if (request_login(s->server, \
|
||||
s->port, \
|
||||
s->ssl, \
|
||||
s->username, \
|
||||
s->password) != -1) \
|
||||
F; \
|
||||
else \
|
||||
return -1; \
|
||||
break; \
|
||||
case STATUS_RESPONSE_BYE: \
|
||||
close_connection(s); \
|
||||
session_destroy(s); \
|
||||
return -1; \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -19,21 +36,16 @@ int create_mailbox(session *ssn, const char *mbox);
|
||||
int
|
||||
request_noop(const char *server, const char *port, const char *user)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
if ((r = response_generic(s, imap_noop(s))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_noop(s));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -46,22 +58,26 @@ request_login(const char *server, const char *port, const char *ssl,
|
||||
const char *user, const char *pass)
|
||||
{
|
||||
int r = -1, rg = -1;
|
||||
session *s;
|
||||
session *s = NULL;
|
||||
|
||||
if ((s = session_find(server, port, user)))
|
||||
if ((s = session_find(server, port, user)) && s->socket != -1)
|
||||
return STATUS_RESPONSE_NONE;
|
||||
|
||||
s = session_new();
|
||||
if (!s) {
|
||||
s = session_new();
|
||||
|
||||
s->server = xstrdup(server);
|
||||
s->port = xstrdup(port);
|
||||
s->username = xstrdup(user);
|
||||
s->server = xstrdup(server);
|
||||
s->port = xstrdup(port);
|
||||
s->username = xstrdup(user);
|
||||
s->password = xstrdup(pass);
|
||||
|
||||
if (ssl && strncasecmp(ssl, "tls1", 4) &&
|
||||
strncasecmp(ssl, "ssl3", 4) && strncasecmp(ssl, "ssl2", 4))
|
||||
ssl = NULL;
|
||||
if (ssl && (!strncasecmp(ssl, "tls1", 4) ||
|
||||
!strncasecmp(ssl, "ssl3", 4) ||
|
||||
strncasecmp(ssl, "ssl2", 4)))
|
||||
s->ssl = xstrdup(ssl);
|
||||
}
|
||||
|
||||
if (open_connection(s, server, port, ssl) == -1)
|
||||
if (open_connection(s) == -1)
|
||||
goto fail;
|
||||
|
||||
if ((rg = response_greeting(s)) == -1)
|
||||
@ -79,8 +95,7 @@ request_login(const char *server, const char *port, const char *ssl,
|
||||
get_option_boolean("starttls"))
|
||||
switch (response_generic(s, imap_starttls(s))) {
|
||||
case STATUS_RESPONSE_OK:
|
||||
if (open_secure_connection(s, server, port, "tls1")
|
||||
== -1)
|
||||
if (open_secure_connection(s) == -1)
|
||||
goto fail;
|
||||
if (response_capability(s, imap_capability(s)) == -1)
|
||||
goto fail;
|
||||
@ -94,10 +109,9 @@ request_login(const char *server, const char *port, const char *ssl,
|
||||
if (rg != STATUS_RESPONSE_PREAUTH) {
|
||||
#ifndef NO_CRAMMD5
|
||||
if (s->capabilities & CAPABILITY_CRAMMD5 &&
|
||||
get_option_boolean("crammd5")) {
|
||||
get_option_boolean("crammd5"))
|
||||
if ((r = auth_cram_md5(s, user, pass)) == -1)
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
if (r != STATUS_RESPONSE_OK &&
|
||||
(r = response_generic(s, imap_login(s, user, pass))) == -1)
|
||||
@ -116,10 +130,13 @@ request_login(const char *server, const char *port, const char *ssl,
|
||||
goto fail;
|
||||
|
||||
if (s->capabilities & CAPABILITY_NAMESPACE &&
|
||||
get_option_boolean("namespace")) {
|
||||
get_option_boolean("namespace"))
|
||||
if (response_namespace(s, imap_namespace(s)) == -1)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (s->selected)
|
||||
if (response_select(s, imap_select(s, s->selected)) == -1)
|
||||
goto fail;
|
||||
|
||||
return r;
|
||||
fail:
|
||||
@ -169,21 +186,14 @@ request_status(const char *server, const char *port, const char *user,
|
||||
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;
|
||||
TRY(t = imap_status(s, m, "MESSAGES RECENT UNSEEN UIDNEXT"));
|
||||
TRY(r = response_status(s, t, exists, recent, unseen, uidnext));
|
||||
} else {
|
||||
t = imap_examine(s, m);
|
||||
if ((r = response_examine(s, t, exists, recent)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_examine(s, m));
|
||||
TRY(r = response_examine(s, t, exists, recent));
|
||||
}
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -194,7 +204,7 @@ int
|
||||
request_select(const char *server, const char *port, const char *user,
|
||||
const char *mbox)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
const char *m;
|
||||
|
||||
@ -203,15 +213,16 @@ request_select(const char *server, const char *port, const char *user,
|
||||
|
||||
m = apply_namespace(mbox, s->ns.prefix, s->ns.delim);
|
||||
|
||||
if ((r = response_select(s, imap_select(s, m))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_select(s, m));
|
||||
TRY(r = response_select(s, t));
|
||||
|
||||
if (r == STATUS_RESPONSE_OK) {
|
||||
if (s && s->selected)
|
||||
xfree(s->selected);
|
||||
s->selected = xstrdup(m);
|
||||
}
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -221,21 +232,21 @@ fail:
|
||||
int
|
||||
request_close(const char *server, const char *port, const char *user)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
if ((r = response_generic(s, imap_close(s))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_close(s));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
if (r == STATUS_RESPONSE_OK && s->selected) {
|
||||
xfree(s->selected);
|
||||
s->selected = NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -245,21 +256,16 @@ fail:
|
||||
int
|
||||
request_expunge(const char *server, const char *port, const char *user)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
if ((r = response_generic(s, imap_expunge(s))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_expunge(s));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -279,16 +285,10 @@ request_list(const char *server, const char *port, const char *user,
|
||||
|
||||
n = apply_namespace(name, s->ns.prefix, s->ns.delim);
|
||||
|
||||
t = imap_list(s, refer, n);
|
||||
if ((r = response_list(s, t, mboxs, folders)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_list(s, refer, n));
|
||||
TRY(r = response_list(s, t, mboxs, folders));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -308,16 +308,10 @@ request_lsub(const char *server, const char *port, const char *user,
|
||||
|
||||
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;
|
||||
TRY(t = imap_lsub(s, refer, n));
|
||||
TRY(r = response_list(s, t, mboxs, folders));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -334,16 +328,10 @@ request_search(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_search(s, charset, criteria);
|
||||
if ((r = response_search(s, t, mesgs)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_search(s, charset, criteria));
|
||||
TRY(r = response_search(s, t, mesgs));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -360,16 +348,10 @@ request_fetchfast(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, "FAST");
|
||||
if ((r = response_fetchfast(s, t, flags, date, size)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_fetch(s, mesg, "FAST"));
|
||||
TRY(r = response_fetchfast(s, t, flags, date, size));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -386,16 +368,10 @@ request_fetchflags(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, "FLAGS");
|
||||
if ((r = response_fetchflags(s, t, flags)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_fetch(s, mesg, "FLAGS"));
|
||||
TRY(r = response_fetchflags(s, t, flags));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -412,16 +388,10 @@ request_fetchdate(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, "INTERNALDATE");
|
||||
if ((r = response_fetchdate(s, t, date)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_fetch(s, mesg, "INTERNALDATE"));
|
||||
TRY(r = response_fetchdate(s, t, date));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Fetch the RFC822.SIZE of the messages.
|
||||
@ -436,16 +406,10 @@ request_fetchsize(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, "RFC822.SIZE");
|
||||
if ((r = response_fetchsize(s, t, size)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_fetch(s, mesg, "RFC822.SIZE"));
|
||||
TRY(r = response_fetchsize(s, t, size));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -462,16 +426,10 @@ request_fetchstructure(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, "BODYSTRUCTURE");
|
||||
if ((r = response_fetchstructure(s, t, structure)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_fetch(s, mesg, "BODYSTRUCTURE"));
|
||||
TRY(r = response_fetchstructure(s, t, structure));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -488,16 +446,10 @@ request_fetchheader(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, "BODY.PEEK[HEADER]");
|
||||
if ((r = response_fetchbody(s, t, header, len)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_fetch(s, mesg, "BODY.PEEK[HEADER]"));
|
||||
TRY(r = response_fetchbody(s, t, header, len));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -514,16 +466,10 @@ request_fetchtext(const char *server, const char *port, const char *user,
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, "BODY.PEEK[TEXT]");
|
||||
if ((r = response_fetchbody(s, t, text, len)) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_fetch(s, mesg, "BODY.PEEK[TEXT]"));
|
||||
TRY(r = response_fetchbody(s, t, text, len));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -535,29 +481,24 @@ int
|
||||
request_fetchfields(const char *server, const char *port, const char *user,
|
||||
const char *mesg, const char *headerfields, char **fields, size_t *len)
|
||||
{
|
||||
int t, r, n;
|
||||
int t, r;
|
||||
session *s;
|
||||
char *f;
|
||||
|
||||
n = strlen("BODY.PEEK[HEADER.FIELDS ()]") + strlen(headerfields) + 1;
|
||||
f = (char *)xmalloc(n * sizeof(char));
|
||||
snprintf(f, n, "%s%s%s", "BODY.PEEK[HEADER.FIELDS (", headerfields, ")]");
|
||||
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, f);
|
||||
if ((r = response_fetchbody(s, t, fields, len)) == -1)
|
||||
goto fail;
|
||||
{
|
||||
int n = strlen("BODY.PEEK[HEADER.FIELDS ()]") +
|
||||
strlen(headerfields) + 1;
|
||||
char f[n];
|
||||
|
||||
xfree(f);
|
||||
snprintf(f, n, "%s%s%s", "BODY.PEEK[HEADER.FIELDS (",
|
||||
headerfields, ")]");
|
||||
TRY(t = imap_fetch(s, mesg, f));
|
||||
}
|
||||
TRY(r = response_fetchbody(s, t, fields, len));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -569,29 +510,22 @@ int
|
||||
request_fetchpart(const char *server, const char *port, const char *user,
|
||||
const char *mesg, const char *part, char **bodypart, size_t *len)
|
||||
{
|
||||
int t, r, n;
|
||||
int t, r;
|
||||
session *s;
|
||||
char *f;
|
||||
|
||||
n = strlen("BODY.PEEK[]") + strlen(part) + 1;
|
||||
f = (char *)xmalloc(n * sizeof(char));
|
||||
snprintf(f, n, "%s%s%s", "BODY.PEEK[", part, "]");
|
||||
|
||||
if (!(s = session_find(server, port, user)))
|
||||
return -1;
|
||||
|
||||
t = imap_fetch(s, mesg, f);
|
||||
if ((r = response_fetchbody(s, t, bodypart, len)) == -1)
|
||||
goto fail;
|
||||
{
|
||||
int n = strlen("BODY.PEEK[]") + strlen(part) + 1;
|
||||
char f[n];
|
||||
|
||||
xfree(f);
|
||||
snprintf(f, n, "%s%s%s", "BODY.PEEK[", part, "]");
|
||||
TRY(t = imap_fetch(s, mesg, f));
|
||||
}
|
||||
TRY(r = response_fetchbody(s, t, bodypart, len));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -608,20 +542,15 @@ request_store(const char *server, const char *port, const char *user,
|
||||
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;
|
||||
TRY(t = imap_store(s, mesg, mode, flags));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
if (xstrcasestr(flags, "\\Deleted") && get_option_boolean("expunge"))
|
||||
if (response_generic(s, imap_expunge(s)) == -1)
|
||||
goto fail;
|
||||
if (xstrcasestr(flags, "\\Deleted") && get_option_boolean("expunge")) {
|
||||
TRY(t = imap_expunge(s));
|
||||
TRY(response_generic(s, t));
|
||||
}
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -642,24 +571,25 @@ request_copy(const char *server, const char *port, const char *user,
|
||||
m = apply_namespace(mbox, s->ns.prefix, s->ns.delim);
|
||||
|
||||
do {
|
||||
t = imap_copy(s, mesg, m);
|
||||
switch (r = response_generic(s, t)) {
|
||||
TRY(t = imap_copy(s, mesg, m));
|
||||
TRY(r = response_generic(s, t));
|
||||
switch (r) {
|
||||
case STATUS_RESPONSE_TRYCREATE:
|
||||
if (create_mailbox(s, mbox) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_create(s, m));
|
||||
TRY(response_generic(s, t));
|
||||
|
||||
if (get_option_boolean("subscribe")) {
|
||||
TRY(t = imap_subscribe(s, m));
|
||||
TRY(response_generic(s, t));
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
goto fail;
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
} while (r == STATUS_RESPONSE_TRYCREATE);
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -681,34 +611,30 @@ request_append(const char *server, const char *port, const char *user,
|
||||
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;
|
||||
TRY(t = imap_append(s, m, flags, date, mesglen));
|
||||
TRY(r = response_continuation(s));
|
||||
|
||||
switch (r) {
|
||||
case STATUS_RESPONSE_CONTINUE:
|
||||
if (imap_continuation(s, mesg, mesglen) == -1)
|
||||
goto fail;
|
||||
if ((r = response_generic(s, t)) == -1)
|
||||
goto fail;
|
||||
TRY(imap_continuation(s, mesg, mesglen));
|
||||
TRY(r = response_generic(s, t));
|
||||
break;
|
||||
case STATUS_RESPONSE_TRYCREATE:
|
||||
if (create_mailbox(s, mbox) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_create(s, m));
|
||||
TRY(response_generic(s, t));
|
||||
|
||||
if (get_option_boolean("subscribe")) {
|
||||
TRY(t = imap_subscribe(s, m));
|
||||
TRY(response_generic(s, t));
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
goto fail;
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
} while (r == STATUS_RESPONSE_TRYCREATE);
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -719,7 +645,7 @@ int
|
||||
request_create(const char *server, const char *port, const char *user,
|
||||
const char *mbox)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
const char *m;
|
||||
|
||||
@ -728,15 +654,10 @@ request_create(const char *server, const char *port, const char *user,
|
||||
|
||||
m = apply_namespace(mbox, s->ns.prefix, s->ns.delim);
|
||||
|
||||
if ((r = response_generic(s, imap_create(s, m))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_create(s, m));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -747,7 +668,7 @@ int
|
||||
request_delete(const char *server, const char *port, const char *user,
|
||||
const char *mbox)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
const char *m;
|
||||
|
||||
@ -756,15 +677,10 @@ request_delete(const char *server, const char *port, const char *user,
|
||||
|
||||
m = apply_namespace(mbox, s->ns.prefix, s->ns.delim);
|
||||
|
||||
if ((r = response_generic(s, imap_delete(s, m))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_delete(s, m));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -775,7 +691,7 @@ int
|
||||
request_rename(const char *server, const char *port, const char *user,
|
||||
const char *oldmbox, const char *newmbox)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
char *o, *n;
|
||||
|
||||
@ -785,20 +701,10 @@ request_rename(const char *server, const char *port, const char *user,
|
||||
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;
|
||||
TRY(t = imap_rename(s, o, n));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -809,7 +715,7 @@ int
|
||||
request_subscribe(const char *server, const char *port, const char *user,
|
||||
const char *mbox)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
const char *m;
|
||||
|
||||
@ -818,15 +724,10 @@ request_subscribe(const char *server, const char *port, const char *user,
|
||||
|
||||
m = apply_namespace(mbox, s->ns.prefix, s->ns.delim);
|
||||
|
||||
if ((r = response_generic(s, imap_subscribe(s, m))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_subscribe(s, m));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -837,7 +738,7 @@ int
|
||||
request_unsubscribe(const char *server, const char *port, const char *user,
|
||||
const char *mbox)
|
||||
{
|
||||
int r;
|
||||
int t, r;
|
||||
session *s;
|
||||
const char *m;
|
||||
|
||||
@ -846,22 +747,17 @@ request_unsubscribe(const char *server, const char *port, const char *user,
|
||||
|
||||
m = apply_namespace(mbox, s->ns.prefix, s->ns.delim);
|
||||
|
||||
if ((r = response_generic(s, imap_unsubscribe(s, m))) == -1)
|
||||
goto fail;
|
||||
TRY(t = imap_unsubscribe(s, m));
|
||||
TRY(r = response_generic(s, t));
|
||||
|
||||
return r;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
request_idle(const char *server, const char *port, const char *user)
|
||||
{
|
||||
int t, rg, ri;
|
||||
int t, r, ri;
|
||||
session *s;
|
||||
|
||||
if (!(s = session_find(server, port, user)))
|
||||
@ -874,49 +770,14 @@ request_idle(const char *server, const char *port, const char *user)
|
||||
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;
|
||||
TRY(t = imap_idle(s));
|
||||
TRY(r = response_continuation(s));
|
||||
if (r == STATUS_RESPONSE_CONTINUE) {
|
||||
TRY(ri = response_idle(s, t));
|
||||
TRY(imap_done(s));
|
||||
TRY(r = response_generic(s, t));
|
||||
}
|
||||
} while (ri == STATUS_RESPONSE_TIMEOUT);
|
||||
|
||||
return rg;
|
||||
fail:
|
||||
close_connection(s);
|
||||
session_destroy(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ response_generic(session *ssn, int tag)
|
||||
ibuf.len += n;
|
||||
|
||||
if (check_bye(ibuf.data))
|
||||
return -1;
|
||||
return STATUS_RESPONSE_BYE;
|
||||
} while ((r = check_tag(ibuf.data, ssn, tag)) == STATUS_RESPONSE_NONE);
|
||||
|
||||
if (r == STATUS_RESPONSE_NO &&
|
||||
@ -252,7 +252,7 @@ response_continuation(session *ssn)
|
||||
ibuf.len += n;
|
||||
|
||||
if (check_bye(ibuf.data))
|
||||
return -1;
|
||||
return STATUS_RESPONSE_BYE;
|
||||
} while (!check_continuation(ibuf.data));
|
||||
|
||||
return STATUS_RESPONSE_CONTINUE;
|
||||
@ -274,7 +274,7 @@ response_greeting(session *ssn)
|
||||
verbose("S (%d): %s", ssn->socket, ibuf.data);
|
||||
|
||||
if (check_bye(ibuf.data))
|
||||
return -1;
|
||||
return STATUS_RESPONSE_BYE;
|
||||
|
||||
if (check_preauth(ibuf.data))
|
||||
return STATUS_RESPONSE_PREAUTH;
|
||||
@ -793,7 +793,7 @@ response_fetchbody(session *ssn, int tag, char **body, size_t *len)
|
||||
|
||||
if (offset != 0 && ibuf.len >= offset) {
|
||||
if (check_bye(ibuf.data + offset))
|
||||
return -1;
|
||||
return STATUS_RESPONSE_BYE;
|
||||
}
|
||||
} while (ibuf.len < offset || (r = check_tag(ibuf.data + offset, ssn,
|
||||
tag)) == STATUS_RESPONSE_NONE);
|
||||
@ -820,6 +820,9 @@ response_idle(session *ssn, int tag)
|
||||
{
|
||||
regexp *re;
|
||||
|
||||
if (tag == -1)
|
||||
return -1;
|
||||
|
||||
re = &responses[DATA_RESPONSE_IDLE];
|
||||
|
||||
do {
|
||||
@ -838,7 +841,7 @@ response_idle(session *ssn, int tag)
|
||||
verbose("S (%d): %s", ssn->socket, ibuf.data);
|
||||
|
||||
if (check_bye(ibuf.data))
|
||||
return -1;
|
||||
return STATUS_RESPONSE_BYE;
|
||||
|
||||
} while (regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0));
|
||||
|
||||
|
@ -36,47 +36,50 @@ session_init(session *ssn)
|
||||
|
||||
ssn->server = NULL;
|
||||
ssn->port = NULL;
|
||||
ssn->ssl = NULL;
|
||||
ssn->username = NULL;
|
||||
ssn->password = NULL;
|
||||
ssn->socket = -1;
|
||||
#ifndef NO_SSLTLS
|
||||
ssn->ssl = NULL;
|
||||
ssn->sslsocket = NULL;
|
||||
#endif
|
||||
ssn->protocol = PROTOCOL_NONE;
|
||||
ssn->capabilities = CAPABILITY_NONE;
|
||||
ssn->ns.prefix = NULL;
|
||||
ssn->ns.delim = '\0';
|
||||
ssn->selected = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Remove session from sessions linked list.
|
||||
* Remove session from sessions linked list and free allocated memory.
|
||||
*/
|
||||
void
|
||||
session_destroy(session *ssn)
|
||||
{
|
||||
|
||||
if (!ssn)
|
||||
return;
|
||||
|
||||
sessions = list_remove(sessions, ssn);
|
||||
|
||||
session_free(ssn);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free session allocated memory.
|
||||
*/
|
||||
void
|
||||
session_free(session *ssn)
|
||||
{
|
||||
|
||||
if (ssn->server)
|
||||
xfree(ssn->server);
|
||||
if (ssn->port)
|
||||
xfree(ssn->port);
|
||||
if (ssn->ssl)
|
||||
xfree(ssn->ssl);
|
||||
if (ssn->username)
|
||||
xfree(ssn->username);
|
||||
if (ssn->password)
|
||||
xfree(ssn->password);
|
||||
if (ssn->ns.prefix)
|
||||
xfree(ssn->ns.prefix);
|
||||
if (ssn->selected)
|
||||
xfree(ssn->selected);
|
||||
xfree(ssn);
|
||||
|
||||
ssn = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,10 +11,12 @@
|
||||
typedef struct session {
|
||||
char *server; /* Server hostname. */
|
||||
char *port; /* Server port. */
|
||||
char *ssl; /* SSL protocol. */
|
||||
char *username; /* User name. */
|
||||
char *password; /* User password. */
|
||||
int socket; /* Socket. */
|
||||
#ifndef NO_SSLTLS
|
||||
SSL *ssl; /* SSL socket. */
|
||||
SSL *sslsocket; /* SSL socket. */
|
||||
#endif
|
||||
unsigned int protocol; /* IMAP protocol. Currently IMAP4rev1 and
|
||||
* IMAP4 are supported. */
|
||||
@ -23,6 +25,7 @@ typedef struct session {
|
||||
char *prefix; /* Namespace prefix. */
|
||||
char delim; /* Namespace delimiter. */
|
||||
} ns;
|
||||
char *selected;
|
||||
} session;
|
||||
|
||||
|
||||
@ -30,7 +33,6 @@ typedef struct session {
|
||||
session *session_new(void);
|
||||
void session_init(session *ssn);
|
||||
void session_destroy(session *ssn);
|
||||
void session_free(session *ssn);
|
||||
session *session_find(const char *server, const char *port, const char *user);
|
||||
|
||||
|
||||
|
64
src/socket.c
64
src/socket.c
@ -23,14 +23,13 @@
|
||||
* Connect to mail server.
|
||||
*/
|
||||
int
|
||||
open_connection(session *ssn, const char *server, const char *port,
|
||||
const char *protocol)
|
||||
open_connection(session *ssn)
|
||||
{
|
||||
struct addrinfo hints, *res, *ressave;
|
||||
int n, sockfd;
|
||||
|
||||
#ifdef NO_SSLTLS
|
||||
if (protocol) {
|
||||
if (ssn->ssl) {
|
||||
error("SSL not supported by this build\n");
|
||||
return -1;
|
||||
}
|
||||
@ -41,7 +40,7 @@ open_connection(session *ssn, const char *server, const char *port,
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
n = getaddrinfo(server, port, &hints, &res);
|
||||
n = getaddrinfo(ssn->server, ssn->port, &hints, &res);
|
||||
|
||||
if (n < 0) {
|
||||
error("gettaddrinfo; %s\n", gai_strerror(n));
|
||||
@ -70,15 +69,15 @@ open_connection(session *ssn, const char *server, const char *port,
|
||||
|
||||
if (sockfd == -1) {
|
||||
error("error while initiating connection to %s at port %s\n",
|
||||
server, port);
|
||||
ssn->server, ssn->port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssn->socket = sockfd;
|
||||
|
||||
#ifndef NO_SSLTLS
|
||||
if (protocol) {
|
||||
if (open_secure_connection(ssn, server, port, protocol) == -1) {
|
||||
if (ssn->ssl) {
|
||||
if (open_secure_connection(ssn) == -1) {
|
||||
close_connection(ssn);
|
||||
return -1;
|
||||
}
|
||||
@ -94,8 +93,7 @@ open_connection(session *ssn, const char *server, const char *port,
|
||||
* Initialize SSL/TLS connection.
|
||||
*/
|
||||
int
|
||||
open_secure_connection(session *ssn, const char *server, const char *port,
|
||||
const char *protocol)
|
||||
open_secure_connection(session *ssn)
|
||||
{
|
||||
int r, e;
|
||||
SSL_CTX *ctx;
|
||||
@ -103,28 +101,28 @@ open_secure_connection(session *ssn, const char *server, const char *port,
|
||||
|
||||
method = NULL;
|
||||
|
||||
if (!strncasecmp(protocol, "tls1", 4))
|
||||
method = TLSv1_client_method();
|
||||
else if (!strncasecmp(protocol, "ssl3", 4) ||
|
||||
!strncasecmp(protocol, "ssl2", 4))
|
||||
if (!strncasecmp(ssn->ssl, "ssl3", 4) ||
|
||||
!strncasecmp(ssn->ssl, "ssl2", 4))
|
||||
method = SSLv23_client_method();
|
||||
else
|
||||
method = TLSv1_client_method();
|
||||
|
||||
if (!(ctx = SSL_CTX_new(method)))
|
||||
goto fail;
|
||||
|
||||
if (!(ssn->ssl = SSL_new(ctx)))
|
||||
if (!(ssn->sslsocket = SSL_new(ctx)))
|
||||
goto fail;
|
||||
|
||||
SSL_set_fd(ssn->ssl, ssn->socket);
|
||||
SSL_set_fd(ssn->sslsocket, ssn->socket);
|
||||
|
||||
for (;;) {
|
||||
if ((r = SSL_connect(ssn->ssl)) > 0)
|
||||
if ((r = SSL_connect(ssn->sslsocket)) > 0)
|
||||
break;
|
||||
|
||||
switch (SSL_get_error(ssn->ssl, r)) {
|
||||
switch (SSL_get_error(ssn->sslsocket, r)) {
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
error("initiating SSL connection to %s; the "
|
||||
"connection has been closed cleanly\n", server);
|
||||
"connection has been closed cleanly\n", ssn->server);
|
||||
goto fail;
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
case SSL_ERROR_WANT_ACCEPT:
|
||||
@ -136,13 +134,13 @@ open_secure_connection(session *ssn, const char *server, const char *port,
|
||||
e = ERR_get_error();
|
||||
if (e == 0)
|
||||
error("initiating SSL connection to %s; EOF "
|
||||
"in violation of the protocol\n", server);
|
||||
"in violation of the protocol\n", ssn->server);
|
||||
else if (e == -1)
|
||||
error("initiating SSL connection to %s; %s\n",
|
||||
server, strerror(errno));
|
||||
ssn->server, strerror(errno));
|
||||
goto fail;
|
||||
case SSL_ERROR_SSL:
|
||||
error("initiating SSL connection to %s; %s\n", server,
|
||||
error("initiating SSL connection to %s; %s\n", ssn->server,
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto fail;
|
||||
default:
|
||||
@ -157,7 +155,7 @@ open_secure_connection(session *ssn, const char *server, const char *port,
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
ssn->ssl = NULL;
|
||||
ssn->sslsocket = NULL;
|
||||
SSL_CTX_free(ctx);
|
||||
|
||||
return -1;
|
||||
@ -198,10 +196,10 @@ int
|
||||
close_secure_connection(session *ssn)
|
||||
{
|
||||
|
||||
if (ssn->ssl) {
|
||||
SSL_shutdown(ssn->ssl);
|
||||
SSL_free(ssn->ssl);
|
||||
ssn->ssl = NULL;
|
||||
if (ssn->sslsocket) {
|
||||
SSL_shutdown(ssn->sslsocket);
|
||||
SSL_free(ssn->sslsocket);
|
||||
ssn->sslsocket = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -239,8 +237,8 @@ socket_read(session *ssn, char *buf, size_t len, long timeout, int timeoutfail)
|
||||
FD_SET(ssn->socket, &fds);
|
||||
|
||||
#ifndef NO_SSLTLS
|
||||
if (ssn->ssl) {
|
||||
if (SSL_pending(ssn->ssl) > 0 ||
|
||||
if (ssn->sslsocket) {
|
||||
if (SSL_pending(ssn->sslsocket) > 0 ||
|
||||
((s = select(ssn->socket + 1, &fds, NULL, NULL, tvp)) > 0 &&
|
||||
FD_ISSET(ssn->socket, &fds))) {
|
||||
r = socket_secure_read(ssn, buf, len);
|
||||
@ -291,12 +289,12 @@ socket_secure_read(session *ssn, char *buf, size_t len)
|
||||
int r, e;
|
||||
|
||||
for (;;) {
|
||||
r = (ssize_t) SSL_read(ssn->ssl, buf, len);
|
||||
r = (ssize_t) SSL_read(ssn->sslsocket, buf, len);
|
||||
|
||||
if (r > 0)
|
||||
break;
|
||||
|
||||
switch (SSL_get_error(ssn->ssl, r)) {
|
||||
switch (SSL_get_error(ssn->sslsocket, r)) {
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
error("reading data; the connection has been closed "
|
||||
"cleanly\n");
|
||||
@ -349,7 +347,7 @@ socket_write(session *ssn, const char *buf, size_t len)
|
||||
if ((s = select(ssn->socket + 1, NULL, &fds, NULL, NULL) > 0 &&
|
||||
FD_ISSET(ssn->socket, &fds))) {
|
||||
#ifndef NO_SSLTLS
|
||||
if (ssn->ssl) {
|
||||
if (ssn->sslsocket) {
|
||||
w = socket_secure_write(ssn, buf, len);
|
||||
|
||||
if (w <= 0)
|
||||
@ -402,12 +400,12 @@ socket_secure_write(session *ssn, const char *buf, size_t len)
|
||||
int w, e;
|
||||
|
||||
for (;;) {
|
||||
w = (ssize_t) SSL_write(ssn->ssl, buf, len);
|
||||
w = (ssize_t) SSL_write(ssn->sslsocket, buf, len);
|
||||
|
||||
if (w > 0)
|
||||
break;
|
||||
|
||||
switch (SSL_get_error(ssn->ssl, w)) {
|
||||
switch (SSL_get_error(ssn->sslsocket, w)) {
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
error("writing data; the connection has been closed "
|
||||
"cleanly\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user