2011-03-06 06:58:58 -05:00
|
|
|
-- The Mailbox class represents a mailbox that resides in an IMAP account.
|
|
|
|
|
|
|
|
Mailbox = {}
|
|
|
|
|
|
|
|
Mailbox._mt = {}
|
|
|
|
setmetatable(Mailbox, Mailbox._mt)
|
|
|
|
|
|
|
|
|
|
|
|
Mailbox._mt.__call = function (self, account, mailbox)
|
|
|
|
local object = {}
|
|
|
|
|
|
|
|
object._type = 'mailbox'
|
2012-02-14 16:13:15 -05:00
|
|
|
object._account = account
|
|
|
|
object._mailbox = mailbox
|
2012-02-22 12:55:38 -05:00
|
|
|
object._string = account._account.username .. '@' ..
|
|
|
|
account._account.server .. '/' .. mailbox
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
for key, value in pairs(Mailbox) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if type(value) == 'function' then object[key] = value end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
object._mt = {}
|
|
|
|
object._mt.__index = object._attach_message
|
|
|
|
setmetatable(object, object._mt)
|
|
|
|
|
|
|
|
return object
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2012-02-22 02:18:38 -05:00
|
|
|
function Mailbox._check_connection(self)
|
|
|
|
if not self._account._account.session then
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not _daemon then
|
|
|
|
error('not connected to ' .. self._account._string, 0)
|
|
|
|
else
|
|
|
|
return false
|
|
|
|
end
|
2012-02-22 02:18:38 -05:00
|
|
|
end
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
return true
|
2012-02-22 02:18:38 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._check_result(self, request, result)
|
|
|
|
if result == nil then
|
|
|
|
self._account._account.session = nil
|
|
|
|
self._account._account.selected = nil
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not _daemon then
|
|
|
|
error(request .. ' request to ' .. self._account._string ..
|
|
|
|
' failed', 0)
|
|
|
|
end
|
2012-02-22 02:18:38 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2011-03-06 06:58:58 -05:00
|
|
|
function Mailbox._attach_message(self, uid)
|
2012-02-22 02:18:38 -05:00
|
|
|
self[uid] = Message(self._account, self, uid)
|
2011-03-06 06:58:58 -05:00
|
|
|
return self[uid]
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._detach_message(self, uid)
|
|
|
|
self[uid] = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2011-04-04 17:48:23 -04:00
|
|
|
function Mailbox._cached_select(self)
|
2012-02-20 19:01:16 -05:00
|
|
|
if self._account._account.selected == nil or
|
|
|
|
self._account._account.selected ~= self._mailbox then
|
2012-02-22 02:18:38 -05:00
|
|
|
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r = ifcore.select(self._account._account.session, self._mailbox)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'select', r)
|
|
|
|
if r == false then return false end
|
|
|
|
|
|
|
|
self._account._account.selected = self._mailbox
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
2012-02-22 02:18:38 -05:00
|
|
|
return true
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
2011-04-04 17:48:23 -04:00
|
|
|
function Mailbox._cached_close(self)
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r = ifcore.close(self._account._account.session)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'close', r)
|
|
|
|
if r == false then return false end
|
|
|
|
|
|
|
|
self._account._account.selected = nil
|
|
|
|
|
|
|
|
return true
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox._send_query(self, criteria, charset)
|
|
|
|
_check_optional(criteria, { 'string', 'table' })
|
|
|
|
_check_optional(charset, 'string')
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if self._cached_select(self) ~= true then return {} end
|
|
|
|
|
2011-03-06 06:58:58 -05:00
|
|
|
local query
|
2012-02-11 16:55:03 -05:00
|
|
|
if criteria == nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
query = 'ALL'
|
2012-02-11 16:55:03 -05:00
|
|
|
elseif type(criteria) == 'string' then
|
2011-03-06 06:58:58 -05:00
|
|
|
query = 'ALL ' .. criteria
|
|
|
|
else
|
|
|
|
query = _make_query(criteria)
|
|
|
|
end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if charset == nil then
|
2012-02-14 16:13:15 -05:00
|
|
|
if type(options.charset) == 'string' then
|
2011-03-06 06:58:58 -05:00
|
|
|
charset = options.charset
|
|
|
|
else
|
|
|
|
charset = ''
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, results = ifcore.search(self._account._account.session, query,
|
|
|
|
charset)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'search', r)
|
|
|
|
if r == false then return false end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
|
|
|
if results == nil then return {} end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local t = {}
|
|
|
|
for n in string.gmatch(results, '%d+') do
|
|
|
|
table.insert(t, { self, tonumber(n) })
|
|
|
|
end
|
|
|
|
|
|
|
|
return t
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox._flag_messages(self, mode, flags, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local f = ''
|
2012-02-14 16:13:15 -05:00
|
|
|
if #flags ~= 0 then f = table.concat(flags, ' ') end
|
2011-03-06 06:58:58 -05:00
|
|
|
local m = _make_range(messages)
|
|
|
|
local n = #m
|
|
|
|
local r = false
|
|
|
|
for i = 1, n, 50 do
|
|
|
|
j = i + 49
|
2012-02-11 16:55:03 -05:00
|
|
|
if n < j then
|
2011-03-06 06:58:58 -05:00
|
|
|
j = n
|
|
|
|
end
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
r = ifcore.store(self._account._account.session, table.concat(m, ',',
|
|
|
|
i, j), mode, f)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'store', r)
|
|
|
|
if r == false then break end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
2012-02-22 02:18:38 -05:00
|
|
|
return true
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox._copy_messages(self, dest, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local r = false
|
2012-02-20 19:01:16 -05:00
|
|
|
if self._account._account.session == dest._account._account.session then
|
2012-02-14 16:13:15 -05:00
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local m = _make_range(messages)
|
|
|
|
local n = #m
|
|
|
|
for i = 1, n, 50 do
|
|
|
|
j = i + 49
|
2012-02-11 16:55:03 -05:00
|
|
|
if n < j then
|
2011-03-06 06:58:58 -05:00
|
|
|
j = n
|
|
|
|
end
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
r = ifcore.copy(self._account._account.session,
|
|
|
|
table.concat(m, ',', i, j), dest._mailbox)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'copy', r)
|
|
|
|
if r == false then break end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
else
|
|
|
|
local fast = self._fetch_fast(self, messages)
|
|
|
|
local mesgs = self._fetch_message(self, messages)
|
|
|
|
|
|
|
|
for i in pairs(fast) do
|
|
|
|
for k, v in ipairs(fast[i]['flags']) do
|
2012-02-11 16:55:03 -05:00
|
|
|
if string.lower(v) == '\\recent' then
|
2011-03-06 06:58:58 -05:00
|
|
|
table.remove(fast[i]['flags'], k)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(dest) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
r = ifcore.append(dest._account._account.session, dest._mailbox,
|
|
|
|
mesgs[i], table.concat(fast[i]['flags'], ' '),
|
2012-02-14 16:13:15 -05:00
|
|
|
fast[i]['date'])
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(dest, 'append', r)
|
|
|
|
if r == false then break end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-22 02:18:38 -05:00
|
|
|
return true
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox._fetch_fast(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, flags, date, size =
|
|
|
|
ifcore.fetchfast(self._account._account.session, tostring(m))
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchfast', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if flags ~= nil and date ~= nil and size ~= nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
local f = {}
|
|
|
|
for s in string.gmatch(flags, '%S+') do
|
|
|
|
table.insert(f, s)
|
|
|
|
end
|
|
|
|
results[m] = {}
|
|
|
|
results[m]['flags'] = f
|
|
|
|
results[m]['date'] = date
|
|
|
|
results[m]['size'] = size
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_flags(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, flags = ifcore.fetchflags(self._account._account.session,
|
|
|
|
tostring(m))
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchfast', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if flags ~= nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
local f = {}
|
|
|
|
for s in string.gmatch(flags, '%S+') do
|
|
|
|
table.insert(f, s)
|
|
|
|
end
|
|
|
|
results[m] = f
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_date(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true and
|
2012-02-11 16:55:03 -05:00
|
|
|
self[m]._date then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = self[m]._date
|
|
|
|
else
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, date = ifcore.fetchdate(self._account._account.session,
|
2012-02-14 16:13:15 -05:00
|
|
|
tostring(m))
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchdate', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if date ~= nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = date
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true then self[m]._date = date end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_size(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true and
|
2012-02-11 16:55:03 -05:00
|
|
|
self[m]._size then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = self[m]._size
|
|
|
|
else
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, size = ifcore.fetchsize(self._account._account.session,
|
2012-02-14 16:13:15 -05:00
|
|
|
tostring(m))
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchsize', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if size ~= nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = tonumber(size)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true then self[m]._size = tonumber(size) end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_header(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true and
|
2012-02-11 16:55:03 -05:00
|
|
|
self[m]._header then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = self[m]._header
|
|
|
|
else
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, header = ifcore.fetchheader(self._account._account.session,
|
2012-02-14 16:13:15 -05:00
|
|
|
tostring(m))
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchheader', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if header ~= nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = header
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true then self[m]._header = header end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_body(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true and
|
2012-02-11 16:55:03 -05:00
|
|
|
self[m]._body then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = self[m]._body
|
|
|
|
else
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, body = ifcore.fetchbody(self._account._account.session,
|
2012-02-14 16:13:15 -05:00
|
|
|
tostring(m))
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchbody', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if body ~= nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = body
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true then self[m]._body = body end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_message(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local header = self._fetch_header(self, messages)
|
|
|
|
local body = self._fetch_body(self, messages)
|
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
2012-02-11 16:55:03 -05:00
|
|
|
if header[m] == nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = nil
|
2012-02-11 16:55:03 -05:00
|
|
|
elseif body[m] == nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = header[m]
|
|
|
|
else
|
|
|
|
results[m] = header[m] .. body[m]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-20 18:11:28 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
|
|
|
|
2011-03-06 06:58:58 -05:00
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox._fetch_fields(self, fields, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
|
|
|
results[m] = ''
|
|
|
|
for _, f in ipairs(fields) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true and
|
2012-02-11 16:55:03 -05:00
|
|
|
self[m]._fields[f] then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = results[m] .. self[m]._fields[f]
|
|
|
|
else
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, field =
|
|
|
|
ifcore.fetchfields(self._account._account.session,
|
|
|
|
tostring(m), f)
|
2012-02-22 02:18:38 -05:00
|
|
|
|
|
|
|
self._check_result(self, 'fetchfields', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if field ~= nil then
|
2012-02-22 12:57:54 -05:00
|
|
|
field = string.gsub(field, '\r\n\r\n$', '\n')
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = results[m] .. field
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true then self[m]._fields[f] = field end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2012-02-22 12:57:54 -05:00
|
|
|
results[m] = string.gsub(results[m], '\n$', '')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_structure(self, messages)
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages or #messages == 0 then return end
|
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, m in ipairs(messages) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true and
|
2012-02-11 16:55:03 -05:00
|
|
|
self[m]._structure then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = self[m]._structure
|
|
|
|
else
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, structure =
|
|
|
|
ifcore.fetchstructure(self._account._account.session,
|
|
|
|
tostring(m))
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchstructure', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if structure ~= nil then
|
2012-02-14 16:13:15 -05:00
|
|
|
local parsed = _parse_structure({ ['s'] = structure,
|
|
|
|
['i'] = 1 })
|
2011-03-06 06:58:58 -05:00
|
|
|
results[m] = parsed
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true then self[m]._structure = parsed end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox._fetch_parts(self, parts, message)
|
2012-02-14 16:13:15 -05:00
|
|
|
if self._cached_select(self) ~= true then return end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
local results = {}
|
|
|
|
for _, part in ipairs(parts) do
|
|
|
|
results[part] = ''
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.cache == true and
|
2012-02-11 16:55:03 -05:00
|
|
|
self[message]._parts[part] then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[part] = self[message]._parts[part]
|
|
|
|
else
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r, bodypart = ifcore.fetchpart(self._account._account.session,
|
2012-02-14 16:13:15 -05:00
|
|
|
tostring(message), part)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'fetchpart', r)
|
|
|
|
if r == false then break end
|
|
|
|
|
2012-02-11 16:55:03 -05:00
|
|
|
if bodypart ~= nil then
|
2011-03-06 06:58:58 -05:00
|
|
|
results[part] = bodypart
|
|
|
|
self[message]._parts[part] = bodypart
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
|
|
|
return results
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.check_status(self)
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-14 16:13:15 -05:00
|
|
|
local r, exist, recent, unseen, uidnext =
|
2012-02-20 19:01:16 -05:00
|
|
|
ifcore.status(self._account._account.session,self._mailbox)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'status', r)
|
|
|
|
if r == false then return false end
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(exist .. ' messages, ' .. recent .. ' recent, ' .. unseen ..
|
|
|
|
' unseen, in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return exist, recent, unseen, uidnext
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.send_query(self, criteria, charset)
|
|
|
|
return Set(self._send_query(self, criteria, charset))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.select_all(self)
|
|
|
|
return self.send_query(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.add_flags(self, flags, messages)
|
|
|
|
_check_required(flags, 'table')
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'add', flags, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages flagged in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.remove_flags(self, flags, messages)
|
|
|
|
_check_required(flags, 'table')
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'remove', flags, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages flagged in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.replace_flags(self, flags, messages)
|
|
|
|
_check_required(flags, 'table')
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'replace', flags, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages flagged in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.mark_answered(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'add', { '\\Answered' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages marked answered in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.mark_deleted(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'add', { '\\Deleted' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages marked deleted in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.mark_draft(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'add', { '\\Draft' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages marked draft in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.mark_flagged(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'add', { '\\Flagged' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages marked flagged in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.mark_seen(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'add', { '\\Seen' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages marked seen in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.unmark_answered(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'remove', { '\\Answered' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages unmarked answered in ' .. self._string ..
|
|
|
|
'.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.unmark_deleted(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'remove', { '\\Deleted' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages unmarked deleted in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.unmark_draft(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'remove', { '\\Draft' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages unmarked draft in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.unmark_flagged(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'remove', { '\\Flagged' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages unmarked flagged in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.unmark_seen(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'remove', { '\\Seen' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages unmarked seen in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.delete_messages(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._flag_messages(self, 'add', { '\\Deleted' }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages deleted in ' .. self._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.copy_messages(self, dest, messages)
|
|
|
|
_check_required(dest, 'table')
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local r = self._copy_messages(self, dest, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print(#mesgs .. ' messages copied from ' .. self._string .. ' to ' ..
|
|
|
|
dest._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.move_messages(self, dest, messages)
|
|
|
|
_check_required(dest, 'table')
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
|
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local rc = self._copy_messages(self, dest, mesgs)
|
|
|
|
local rf = false
|
2012-02-11 16:55:03 -05:00
|
|
|
if rc == true then
|
2011-03-06 06:58:58 -05:00
|
|
|
rf = self._flag_messages(self, 'add', { '\\Deleted' }, mesgs)
|
|
|
|
end
|
2012-02-22 12:55:38 -05:00
|
|
|
if options.info == true and rc == true and rf == true then
|
|
|
|
print(#mesgs .. ' messages moved from ' .. self._string .. ' to ' ..
|
|
|
|
dest._string .. '.')
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return rc == true and rf == true
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.fetch_flags(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_flags(self, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_date(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_date(self, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_size(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_size(self, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_header(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_header(self, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_body(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_body(self, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_message(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_message(self, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_fields(self, fields, messages)
|
|
|
|
_check_required(fields, 'table')
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_fields(self, fields, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_structure(self, messages)
|
|
|
|
_check_required(messages, 'table')
|
|
|
|
return self._fetch_structure(self, _extract_messages(self, messages))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.fetch_parts(self, parts, message)
|
|
|
|
_check_required(parts, 'table')
|
|
|
|
_check_required(message, 'number')
|
|
|
|
return self._fetch_parts(self, parts, message)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2011-08-06 08:16:07 -04:00
|
|
|
function Mailbox.append_message(self, message, flags, date)
|
|
|
|
_check_required(message, 'string')
|
|
|
|
_check_optional(flags, { 'string', 'table' })
|
|
|
|
_check_optional(date, 'string')
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if type(flags) == 'table' then flags = table.concat(flags, ' ') end
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
r = ifcore.append(self._account._account.session, self._mailbox, message,
|
|
|
|
flags, date)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'append', r)
|
|
|
|
if r == false then return false end
|
|
|
|
|
2012-02-19 17:56:54 -05:00
|
|
|
if options.info == true and r == true then
|
2012-02-22 12:55:38 -05:00
|
|
|
print('Appended message of ' .. #message .. ' octets to ' ..
|
|
|
|
self._string .. '.')
|
2012-02-19 17:56:54 -05:00
|
|
|
end
|
2012-02-11 16:47:08 -05:00
|
|
|
|
2012-02-22 02:18:38 -05:00
|
|
|
return true
|
2011-08-06 08:16:07 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
2011-03-06 06:58:58 -05:00
|
|
|
function Mailbox.is_answered(self)
|
|
|
|
return self.send_query(self, 'ANSWERED')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_deleted(self)
|
|
|
|
return self.send_query(self, 'DELETED')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_draft(self)
|
|
|
|
return self.send_query(self, 'DRAFT')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_flagged(self)
|
|
|
|
return self.send_query(self, 'FLAGGED')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_new(self)
|
|
|
|
return self.send_query(self, 'NEW')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_old(self)
|
|
|
|
return self.send_query(self, 'OLD')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_recent(self)
|
|
|
|
return self.send_query(self, 'RECENT')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_seen(self)
|
|
|
|
return self.send_query(self, 'SEEN')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_unanswered(self)
|
|
|
|
return self.send_query(self, 'UNANSWERED')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_undeleted(self)
|
|
|
|
return self.send_query(self, 'UNDELETED')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_undraft(self)
|
|
|
|
return self.send_query(self, 'UNDRAFT')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_unflagged(self)
|
|
|
|
return self.send_query(self, 'UNFLAGGED')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_unseen(self)
|
|
|
|
return self.send_query(self, 'UNSEEN')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_larger(self, size)
|
|
|
|
_check_required(size, 'number')
|
|
|
|
return self.send_query(self, 'LARGER ' .. tostring(size))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_smaller(self, size)
|
|
|
|
_check_required(size, 'number')
|
|
|
|
return self.send_query(self, 'SMALLER ' .. tostring(size))
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.arrived_on(self, date)
|
|
|
|
_check_required(date, 'string')
|
|
|
|
return self.send_query(self, 'ON ' .. date)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.arrived_before(self, date)
|
|
|
|
_check_required(date, 'string')
|
|
|
|
return self.send_query(self, 'BEFORE ' .. date)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.arrived_since(self, date)
|
|
|
|
_check_required(date, 'string')
|
|
|
|
return self.send_query(self, 'SINCE ' .. date)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.sent_on(self, date)
|
|
|
|
_check_required(date, 'string')
|
|
|
|
return self.send_query(self, 'SENTON ' .. date)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.sent_before(self, date)
|
|
|
|
_check_required(date, 'string')
|
|
|
|
return self.send_query(self, 'SENTBEFORE ' .. date)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.sent_since(self, date)
|
|
|
|
_check_required(date, 'string')
|
|
|
|
return self.send_query(self, 'SENTSINCE ' .. date)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_newer(self, days)
|
|
|
|
_check_required(days, 'number')
|
|
|
|
return self.send_query(self, 'SINCE ' .. form_date(days))
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.is_older(self, days)
|
|
|
|
_check_required(days, 'number')
|
|
|
|
return self.send_query(self, 'BEFORE ' .. form_date(days))
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.has_flag(self, flag)
|
|
|
|
_check_required(flag, 'string')
|
|
|
|
return self.send_query(self, 'KEYWORD "' .. flag .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.contain_field(self, field, string)
|
|
|
|
_check_required(field, 'string')
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'HEADER ' .. field .. ' "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_bcc(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'BCC "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_cc(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'CC "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_from(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'FROM "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_subject(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'SUBJECT "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_to(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'TO "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_header(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'TEXT "' .. string .. '" NOT BODY "' ..
|
|
|
|
string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_body(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'BODY "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.contain_message(self, string)
|
|
|
|
_check_required(string, 'string')
|
|
|
|
return self.send_query(self, 'TEXT "' .. string .. '"')
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
function Mailbox.match_field(self, field, pattern, messages)
|
|
|
|
_check_required(field, 'string')
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages then messages = self._send_query(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local fields = self._fetch_fields(self, { field }, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if #mesgs == 0 or fields == nil then return Set({}) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local results = {}
|
|
|
|
for m, f in pairs(fields) do
|
2012-02-22 12:57:54 -05:00
|
|
|
if regex_search(pattern, (string.gsub(f, '^[^:]*: ?(.*)$', '%1'))) then
|
2011-03-06 06:58:58 -05:00
|
|
|
table.insert(results, {self, m})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return Set(results)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_bcc(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
return self.match_field(self, 'Bcc', pattern, messages)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_cc(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
return self.match_field(self, 'Cc', pattern, messages)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_from(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
return self.match_field(self, 'From', pattern, messages)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_subject(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
return self.match_field(self, 'Subject', pattern, messages)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_to(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
return self.match_field(self, 'To', pattern, messages)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_header(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages then messages = self._send_query(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local header = self._fetch_header(self, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if #mesgs == 0 or header == nil then return Set({}) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local results = {}
|
|
|
|
for m, h in pairs(header) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if regex_search(pattern, h) then table.insert(results, {self, m}) end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return Set(results)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_body(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages then messages = self._send_query(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local body = self._fetch_body(self, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if #mesgs == 0 or body == nil then return Set({}) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local results = {}
|
|
|
|
for m, b in pairs(body) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if regex_search(pattern, b) then table.insert(results, {self, m}) end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return Set(results)
|
|
|
|
end
|
|
|
|
|
|
|
|
function Mailbox.match_message(self, pattern, messages)
|
|
|
|
_check_required(pattern, 'string')
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
if not messages then messages = self._send_query(self) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local mesgs = _extract_messages(self, messages)
|
|
|
|
local full = self._fetch_message(self, mesgs)
|
2012-02-14 16:13:15 -05:00
|
|
|
if #mesgs == 0 or full == nil then return Set({}) end
|
2011-03-06 06:58:58 -05:00
|
|
|
local results = {}
|
|
|
|
for m, f in pairs(full) do
|
2012-02-14 16:13:15 -05:00
|
|
|
if regex_search(pattern, f) then table.insert(results, {self, m}) end
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
return Set(results)
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2012-02-14 16:13:15 -05:00
|
|
|
function Mailbox.enter_idle(self)
|
|
|
|
if self._cached_select(self) ~= true then return false end
|
2011-03-06 06:58:58 -05:00
|
|
|
|
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.
2012-02-29 14:24:32 -05:00
|
|
|
if not self._check_connection(self) then return end
|
2012-02-20 19:01:16 -05:00
|
|
|
local r = ifcore.idle(self._account._account.session)
|
2012-02-22 02:18:38 -05:00
|
|
|
self._check_result(self, 'idle', r)
|
|
|
|
if r == false then return false end
|
2012-02-11 16:47:08 -05:00
|
|
|
|
2012-02-20 18:11:28 -05:00
|
|
|
if options.close == true then self._cached_close(self) end
|
|
|
|
|
2012-02-22 02:18:38 -05:00
|
|
|
return true
|
2011-03-06 06:58:58 -05:00
|
|
|
end
|
|
|
|
|
2012-02-22 12:56:45 -05:00
|
|
|
|
|
|
|
Mailbox.open = _cached_select
|
2012-02-21 14:13:55 -05:00
|
|
|
Mailbox.close = _cached_close
|
2012-02-14 16:13:15 -05:00
|
|
|
|
2011-03-06 06:58:58 -05:00
|
|
|
Mailbox._mt.__index = function () end
|
|
|
|
Mailbox._mt.__newindex = function () end
|