| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 | 
------------------------------------------------------------------------------
-- 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
 |