------------------------------------------------------------------------------ -- config and handling -- ------------------------------------------------------------------------------ function file_exists(name) -- -- True if file *name* exists -- local f = io.open(name,"r") if f ~= nil then io.close(f) return true else return false end end function do_if_exists(filename) -- -- Do file from home, if exists -- local file = os.getenv("IMAPFILTER_HOME") .. "/" .. filename if file_exists(file) then dofile(file) return end end function handle() -- -- Handle action if it's valid -- local action = os.getenv("IMAPDOMO_ACTION") local file = os.getenv("IMAPFILTER_HOME") .. "/handlers/" .. action .. ".lua" if file_exists(file) then do_if_exists("init.lua") dofile(file) else error("no handler for action: " .. action) return nil end end ------------------------------------------------------------------------------ -- mail getters -- ------------------------------------------------------------------------------ function get_queue(acct, mbox) -- -- Get queue from *mbox* from *acct* or nil (no messages) -- -- If mbox is not specified, "FILTER_QUEUE" is used -- mbox = mbox or "FILTER_QUEUE" local exist, unread, unseen, uidnext = acct[mbox]:check_status() if exist > 0 then return acct[mbox]:select_all() end return nil end function _notifirc1(subj, from, body) -- -- notify about message using (pre-configured) notifirc -- local fd = assert(io.popen('notifirc -c mail -f - "message preview:"', "w")) local fmt = "> %s\n> %s\n> BODY: %s" fd:write(fmt:format(subj, from, body)) fd:close() end function notifirc_all(seq) -- -- Send notifications about all messages in *seq* -- for _, mesg in ipairs(seq) do mbox, uid = table.unpack(mesg) subj = mbox[uid]:fetch_field('Subject') from = mbox[uid]:fetch_field('From') body = mbox[uid]:fetch_body() _notifirc1(subj, from, body) end end function hook_all(seq, hname, ...) -- -- Call hook hname for all messages in seq -- local hfile = os.getenv("IMAPFILTER_HOME") .. "/hooks/" .. hname local hargs = {...} local harg local hcmd = hfile local fmt = ' %q' if file_exists(hfile) then for _, harg in pairs(hargs) do hcmd = hcmd .. fmt:format(harg) end for _, mesg in ipairs(seq) do mbox, uid = table.unpack(mesg) subj = mbox[uid]:fetch_field('Subject') from = mbox[uid]:fetch_field('From') to = mbox[uid]:fetch_field('To') date = mbox[uid]:fetch_field('Date') body = mbox[uid]:fetch_body() _hook1(hcmd, subj, from, to, date, body) end else error("no such hook: " .. hname) return nil end end function _hook1(hcmd, subj, from, to, date, body) -- -- push message through hook script -- local fd = assert(io.popen(hcmd, "w")) local fmt = "subj=%s\nfrom=%s\nto=%s\ndate=%s\n%s" fd:write(fmt:format(subj, from, to, date, body)) fd:close() end function _partinf_compare(a, b) if not type(a) == type(b) then return false end if type(a) == 'number' then return a == b elseif type(a) == 'string' then return a:lower() == b:lower() end end function has_part_like(query, structure) -- -- True if structure has MIME part matching *query* -- if structure == nil then return false end for partid, partinf in pairs(structure) do local part_answer = true -- check all query parts for qkey, qvalue in pairs(query) do value = partinf[qkey] if not _partinf_compare(value, qvalue) then part_answer = false break end end if part_answer then return true end end return false end function save_header(mesg, name) -- -- Append header from *mesg* to file named *name* -- -- File will be placed under directory specified by IMAPDOMO_HEADERS -- environment variable. -- local dest = os.getenv("IMAPDOMO_HEADERS") .. '/' .. name local cmd = ('cat >>"%q"'):format(dest) mbox, uid = table.unpack(mesg) header = mbox[uid]:fetch_header() if pipe_to(cmd, header) == 0 then return true else return false end end function filter_header_saved(seq, name) -- -- Save headers from sequence -- -- Append header of each message in sequence *seq* to file names -- *name* and return new sequence with those messages where save was -- successful. -- result = Set {} for _, mesg in ipairs(seq) do if save_header(mesg, name) then table.insert(result, mesg) end end return result end function filter_part_like(query, seq) -- -- Run MIME part query on *seq* sequence of messages -- result = Set {} for _, mesg in ipairs(seq) do mbox, uid = table.unpack(mesg) structure = mbox[uid]:fetch_structure() if has_part_like(query, structure) then table.insert(result, mesg) end end return result end