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) setmetatable(Account, Account._mt)
_imap = {}
setmetatable(_imap, { __mode = "v" })
Account._mt.__call = function (self, arg) Account._mt.__call = function (self, arg)
_check_required(arg.server, 'string') _check_required(arg.server, 'string')
_check_required(arg.username, 'string') _check_required(arg.username, 'string')
@ -37,7 +41,9 @@ Account._mt.__call = function (self, arg)
object._mt.__gc = object._logout_user object._mt.__gc = object._logout_user
setmetatable(object, object._mt) setmetatable(object, object._mt)
object:_login_user() table.insert(_imap, object)
object._login_user(object)
return object return object
end end
@ -45,15 +51,22 @@ end
function Account._check_connection(self) function Account._check_connection(self)
if not self._account.session then 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 end
return true
end end
function Account._check_result(self, request, result) function Account._check_result(self, request, result)
if result == nil then if result == nil then
self._account.session = nil self._account.session = nil
self._account.selected = 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
end end
@ -70,8 +83,9 @@ function Account._login_user(self)
self._account.password) self._account.password)
self._check_result(self, 'login', r) self._check_result(self, 'login', r)
if r == false then if r == false then
error('failed to authenticate to ' .. self._string .. '.', 0) error('authentication to ' .. self._string .. ' failed.', 0)
end end
if not r then return false end
self._account.session = s self._account.session = s
self._account.selected = nil self._account.selected = nil
@ -80,7 +94,7 @@ function Account._login_user(self)
end end
function Account._logout_user(self) 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) local r = ifcore.logout(self._account.session)
self._check_result(self, 'logout', r) self._check_result(self, 'logout', r)
if r == false then return false end if r == false then return false end
@ -116,7 +130,7 @@ function Account.list_all(self, folder, mbox)
end end
if mbox == nil then 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, '', local r, mailboxes, folders = ifcore.list(self._account.session, '',
folder .. mbox) folder .. mbox)
self._check_result(self, 'list', r) self._check_result(self, 'list', r)
@ -151,7 +165,7 @@ function Account.list_subscribed(self, folder, mbox)
end end
if mbox == nil then 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, '', local r, mailboxes, folders = ifcore.lsub(self._account.session, '',
folder .. mbox) folder .. mbox)
self._check_result(self, 'lsub', r) self._check_result(self, 'lsub', r)
@ -174,7 +188,7 @@ end
function Account.create_mailbox(self, name) function Account.create_mailbox(self, name)
_check_required(name, 'string') _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) local r = ifcore.create(self._account.session, name)
self._check_result(self, 'create', r) self._check_result(self, 'create', r)
if r == false then return false end if r == false then return false end
@ -189,7 +203,7 @@ end
function Account.delete_mailbox(self, name) function Account.delete_mailbox(self, name)
_check_required(name, 'string') _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) local r = ifcore.delete(self._account.session, name)
self._check_result(self, 'delete', r) self._check_result(self, 'delete', r)
if r == false then return false end if r == false then return false end
@ -205,7 +219,7 @@ function Account.rename_mailbox(self, oldname, newname)
_check_required(oldname, 'string') _check_required(oldname, 'string')
_check_required(newname, '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) local r = ifcore.rename(self._account.session, oldname, newname)
self._check_result(self, 'rename', r) self._check_result(self, 'rename', r)
if r == false then return false end if r == false then return false end
@ -221,7 +235,7 @@ end
function Account.subscribe_mailbox(self, name) function Account.subscribe_mailbox(self, name)
_check_required(name, 'string') _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) local r = ifcore.subscribe(self._account.session, name)
self._check_result(self, 'subscribe', r) self._check_result(self, 'subscribe', r)
if r == false then return false end if r == false then return false end
@ -236,7 +250,7 @@ end
function Account.unsubscribe_mailbox(self, name) function Account.unsubscribe_mailbox(self, name)
_check_required(name, 'string') _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) local r = ifcore.unsubscribe(self._account.session, name)
self._check_result(self, 'unsubscribe', r) self._check_result(self, 'unsubscribe', r)
if r == false then return false end 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 nochdir == nil then nochdir = false end
if noclose == nil then noclose = false end if noclose == nil then noclose = false end
ifsys.daemon(nochdir, noclose) ifsys.daemon(nochdir, noclose)
_daemon = true
repeat repeat
for _, account in pairs(_imap) do
if not account._account.session then
account:_login_user(account)
end
end
commands() commands()
collectgarbage()
until ifsys.sleep(interval) ~= 0 until ifsys.sleep(interval) ~= 0
end end

View File

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