Ignore errors and retry later when in daemon mode

A persistent failure that could lead to a session not being able to be
recovered, or a failure during the login process (which is not covered
by the recovery function), would normally cause the process to
terminate.  This is expected when the configuration is run once, but not
desirable when running in daemon mode.

And thus just after the process has become a daemon, a session that
could not be restored, either because the connection to the server could
not be established or the login and its related negotiations failed, is
now disabled temporarily, and a recoqnection is attempted at the
beginning of the next daemon loop iteration.

There is one exception to that, and that is when there is an
authentication error, for example when a wrong username or password has
been supplied, and in this case the process terminates and a relevant
error is printed.
This commit is contained in:
Lefteris Chatzimparmpas 2012-02-29 20:24:32 +01:00
parent dba6d38403
commit 3690506986
3 changed files with 61 additions and 33 deletions

View File

@ -8,6 +8,10 @@ Account._mt = {}
setmetatable(Account, Account._mt)
_imap = {}
setmetatable(_imap, { __mode = "v" })
Account._mt.__call = function (self, arg)
_check_required(arg.server, 'string')
_check_required(arg.username, 'string')
@ -37,7 +41,9 @@ Account._mt.__call = function (self, arg)
object._mt.__gc = object._logout_user
setmetatable(object, object._mt)
object:_login_user()
table.insert(_imap, object)
object._login_user(object)
return object
end
@ -45,15 +51,22 @@ end
function Account._check_connection(self)
if not self._account.session then
error('not connected to ' .. self._string, 0)
if not _daemon then
error('not connected to ' .. self._string, 0)
else
return false
end
end
return true
end
function Account._check_result(self, request, result)
if result == nil then
self._account.session = nil
self._account.selected = nil
error(request .. ' request to ' .. self._string .. ' failed', 0)
if not _daemon then
error(request .. ' request to ' .. self._string .. ' failed', 0)
end
end
end
@ -70,8 +83,9 @@ function Account._login_user(self)
self._account.password)
self._check_result(self, 'login', r)
if r == false then
error('failed to authenticate to ' .. self._string .. '.', 0)
error('authentication to ' .. self._string .. ' failed.', 0)
end
if not r then return false end
self._account.session = s
self._account.selected = nil
@ -80,7 +94,7 @@ function Account._login_user(self)
end
function Account._logout_user(self)
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.logout(self._account.session)
self._check_result(self, 'logout', r)
if r == false then return false end
@ -116,7 +130,7 @@ function Account.list_all(self, folder, mbox)
end
if mbox == nil then mbox = '%' end
self._check_connection(self)
if not self._check_connection(self) then return end
local r, mailboxes, folders = ifcore.list(self._account.session, '',
folder .. mbox)
self._check_result(self, 'list', r)
@ -151,7 +165,7 @@ function Account.list_subscribed(self, folder, mbox)
end
if mbox == nil then mbox = '*' end
self._check_connection(self)
if not self._check_connection(self) then return end
local r, mailboxes, folders = ifcore.lsub(self._account.session, '',
folder .. mbox)
self._check_result(self, 'lsub', r)
@ -174,7 +188,7 @@ end
function Account.create_mailbox(self, name)
_check_required(name, 'string')
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.create(self._account.session, name)
self._check_result(self, 'create', r)
if r == false then return false end
@ -189,7 +203,7 @@ end
function Account.delete_mailbox(self, name)
_check_required(name, 'string')
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.delete(self._account.session, name)
self._check_result(self, 'delete', r)
if r == false then return false end
@ -205,7 +219,7 @@ function Account.rename_mailbox(self, oldname, newname)
_check_required(oldname, 'string')
_check_required(newname, 'string')
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.rename(self._account.session, oldname, newname)
self._check_result(self, 'rename', r)
if r == false then return false end
@ -221,7 +235,7 @@ end
function Account.subscribe_mailbox(self, name)
_check_required(name, 'string')
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.subscribe(self._account.session, name)
self._check_result(self, 'subscribe', r)
if r == false then return false end
@ -236,7 +250,7 @@ end
function Account.unsubscribe_mailbox(self, name)
_check_required(name, 'string')
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.unsubscribe(self._account.session, name)
self._check_result(self, 'unsubscribe', r)
if r == false then return false end

View File

@ -59,8 +59,15 @@ function become_daemon(interval, commands, nochdir, noclose)
if nochdir == nil then nochdir = false end
if noclose == nil then noclose = false end
ifsys.daemon(nochdir, noclose)
_daemon = true
repeat
for _, account in pairs(_imap) do
if not account._account.session then
account:_login_user(account)
end
end
commands()
collectgarbage()
until ifsys.sleep(interval) ~= 0
end

View File

@ -29,16 +29,23 @@ end
function Mailbox._check_connection(self)
if not self._account._account.session then
error('not connected to ' .. self._account._string, 0)
if not _daemon then
error('not connected to ' .. self._account._string, 0)
else
return false
end
end
return true
end
function Mailbox._check_result(self, request, result)
if result == nil then
self._account._account.session = nil
self._account._account.selected = nil
error(request .. ' request to ' .. self._account._string ..
' failed', 0)
if not _daemon then
error(request .. ' request to ' .. self._account._string ..
' failed', 0)
end
end
end
@ -57,7 +64,7 @@ function Mailbox._cached_select(self)
if self._account._account.selected == nil or
self._account._account.selected ~= self._mailbox then
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.select(self._account._account.session, self._mailbox)
self._check_result(self, 'select', r)
if r == false then return false end
@ -68,7 +75,7 @@ function Mailbox._cached_select(self)
end
function Mailbox._cached_close(self)
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.close(self._account._account.session)
self._check_result(self, 'close', r)
if r == false then return false end
@ -102,7 +109,7 @@ function Mailbox._send_query(self, criteria, charset)
end
end
self._check_connection(self)
if not self._check_connection(self) then return end
local r, results = ifcore.search(self._account._account.session, query,
charset)
self._check_result(self, 'search', r)
@ -134,7 +141,7 @@ function Mailbox._flag_messages(self, mode, flags, messages)
if n < j then
j = n
end
self._check_connection(self)
if not self._check_connection(self) then return end
r = ifcore.store(self._account._account.session, table.concat(m, ',',
i, j), mode, f)
self._check_result(self, 'store', r)
@ -161,7 +168,7 @@ function Mailbox._copy_messages(self, dest, messages)
if n < j then
j = n
end
self._check_connection(self)
if not self._check_connection(self) then return end
r = ifcore.copy(self._account._account.session,
table.concat(m, ',', i, j), dest._mailbox)
self._check_result(self, 'copy', r)
@ -180,7 +187,7 @@ function Mailbox._copy_messages(self, dest, messages)
end
end
self._check_connection(dest)
if not self._check_connection(dest) then return end
r = ifcore.append(dest._account._account.session, dest._mailbox,
mesgs[i], table.concat(fast[i]['flags'], ' '),
fast[i]['date'])
@ -199,7 +206,7 @@ function Mailbox._fetch_fast(self, messages)
local results = {}
for _, m in ipairs(messages) do
self._check_connection(self)
if not self._check_connection(self) then return end
local r, flags, date, size =
ifcore.fetchfast(self._account._account.session, tostring(m))
self._check_result(self, 'fetchfast', r)
@ -228,7 +235,7 @@ function Mailbox._fetch_flags(self, messages)
local results = {}
for _, m in ipairs(messages) do
self._check_connection(self)
if not self._check_connection(self) then return end
local r, flags = ifcore.fetchflags(self._account._account.session,
tostring(m))
self._check_result(self, 'fetchfast', r)
@ -258,7 +265,7 @@ function Mailbox._fetch_date(self, messages)
self[m]._date then
results[m] = self[m]._date
else
self._check_connection(self)
if not self._check_connection(self) then return end
local r, date = ifcore.fetchdate(self._account._account.session,
tostring(m))
self._check_result(self, 'fetchdate', r)
@ -286,7 +293,7 @@ function Mailbox._fetch_size(self, messages)
self[m]._size then
results[m] = self[m]._size
else
self._check_connection(self)
if not self._check_connection(self) then return end
local r, size = ifcore.fetchsize(self._account._account.session,
tostring(m))
self._check_result(self, 'fetchsize', r)
@ -314,7 +321,7 @@ function Mailbox._fetch_header(self, messages)
self[m]._header then
results[m] = self[m]._header
else
self._check_connection(self)
if not self._check_connection(self) then return end
local r, header = ifcore.fetchheader(self._account._account.session,
tostring(m))
self._check_result(self, 'fetchheader', r)
@ -342,7 +349,7 @@ function Mailbox._fetch_body(self, messages)
self[m]._body then
results[m] = self[m]._body
else
self._check_connection(self)
if not self._check_connection(self) then return end
local r, body = ifcore.fetchbody(self._account._account.session,
tostring(m))
self._check_result(self, 'fetchbody', r)
@ -396,7 +403,7 @@ function Mailbox._fetch_fields(self, fields, messages)
self[m]._fields[f] then
results[m] = results[m] .. self[m]._fields[f]
else
self._check_connection(self)
if not self._check_connection(self) then return end
local r, field =
ifcore.fetchfields(self._account._account.session,
tostring(m), f)
@ -429,7 +436,7 @@ function Mailbox._fetch_structure(self, messages)
self[m]._structure then
results[m] = self[m]._structure
else
self._check_connection(self)
if not self._check_connection(self) then return end
local r, structure =
ifcore.fetchstructure(self._account._account.session,
tostring(m))
@ -460,7 +467,7 @@ function Mailbox._fetch_parts(self, parts, message)
self[message]._parts[part] then
results[part] = self[message]._parts[part]
else
self._check_connection(self)
if not self._check_connection(self) then return end
local r, bodypart = ifcore.fetchpart(self._account._account.session,
tostring(message), part)
self._check_result(self, 'fetchpart', r)
@ -480,7 +487,7 @@ end
function Mailbox.check_status(self)
self._check_connection(self)
if not self._check_connection(self) then return end
local r, exist, recent, unseen, uidnext =
ifcore.status(self._account._account.session,self._mailbox)
self._check_result(self, 'status', r)
@ -768,7 +775,7 @@ function Mailbox.append_message(self, message, flags, date)
_check_optional(date, 'string')
if type(flags) == 'table' then flags = table.concat(flags, ' ') end
self._check_connection(self)
if not self._check_connection(self) then return end
r = ifcore.append(self._account._account.session, self._mailbox, message,
flags, date)
self._check_result(self, 'append', r)
@ -1033,7 +1040,7 @@ end
function Mailbox.enter_idle(self)
if self._cached_select(self) ~= true then return false end
self._check_connection(self)
if not self._check_connection(self) then return end
local r = ifcore.idle(self._account._account.session)
self._check_result(self, 'idle', r)
if r == false then return false end