Browse Source

Add imapdomo, an "imapfilter app"

Alois Mahdal 8 years ago
parent
commit
7969e42214

+ 2
- 0
.gitignore View File

@@ -4,6 +4,8 @@
4 4
 */gittum/private.gitconfig
5 5
 */vim/bundle/private/*
6 6
 dotfiles/imapfilter/private
7
+dotfiles/imapdomo/private
8
+dotfiles/imapdomo/certificates
7 9
 dotfiles/moc/cache/
8 10
 dotfiles/moc/equalizer
9 11
 dotfiles/moc/last_directory

+ 149
- 0
dotfiles/imapdomo/common.lua View File

@@ -0,0 +1,149 @@
1
+os = require "os"
2
+socket = require "socket"
3
+
4
+
5
+------------------------------------------------------------------------------
6
+-- config and handling                                                      --
7
+------------------------------------------------------------------------------
8
+
9
+function shortname()
10
+    --
11
+    -- Short hostname
12
+    --
13
+    local long = socket.dns.gethostname()
14
+    return string.gmatch(long, '[^.]+')()
15
+end
16
+
17
+function file_exists(name)
18
+    --
19
+    -- True if file *name* exists
20
+    --
21
+    local f=io.open(name,"r")
22
+    if f~=nil then io.close(f) return true else return false end
23
+end
24
+
25
+function init_host()
26
+    --
27
+    -- Look for action handler in basepaths; do first one
28
+    --
29
+    local init = imapdomo.dirs.host .. "/init.lua"
30
+    if file_exists(init) then
31
+        dofile(init)
32
+        return
33
+    end
34
+end
35
+
36
+function handle(action, basepaths)
37
+    --
38
+    -- Look for action handler in basepaths; do first one
39
+    --
40
+    local valid = {
41
+        newmail = true,
42
+        rewind = true,
43
+        cleanup = true
44
+    }
45
+    if not valid[action] then
46
+        error("invalid action: " .. action)
47
+        return nil
48
+    end
49
+    init_host()
50
+    for k,v in ipairs({imapdomo.dirs.host, imapdomo.dirs.default}) do
51
+        attempt = v .. "/handlers/" .. action .. ".lua"
52
+        if file_exists(attempt) then
53
+            dofile(attempt)
54
+            return
55
+        end
56
+    end
57
+end
58
+
59
+
60
+------------------------------------------------------------------------------
61
+-- mail getters                                                             --
62
+------------------------------------------------------------------------------
63
+
64
+function get_queue(acct, mbox)
65
+    --
66
+    -- Get queue from *mbox* from *acct* or nil (no messages)
67
+    --
68
+    -- If mbox is not specified, "FILTER_QUEUE" is used
69
+    --
70
+    mbox = mbox or "FILTER_QUEUE"
71
+    local exist, unread, unseen, uidnext = acct[mbox]:check_status()
72
+    if exist > 0 then
73
+        return acct[mbox]:select_all()
74
+    end
75
+    return nil
76
+end
77
+
78
+function _notifirc1(subj, from, body)
79
+    --
80
+    -- notify about message using (pre-configured) notifirc
81
+    --
82
+    local fd = assert(io.popen('notifirc -c mail -f - "message preview:"', "w"))
83
+    local fmt = "> %s\n> %s\n> BODY: %s"
84
+    fd:write(fmt:format(subj, from, body))
85
+    fd:close()
86
+end
87
+
88
+function notifirc_all(seq)
89
+    --
90
+    -- Send notifications about all messages in *seq*
91
+    --
92
+    for _, mesg in ipairs(seq) do
93
+        mbox, uid = table.unpack(mesg)
94
+        subj = mbox[uid]:fetch_field('Subject')
95
+        from = mbox[uid]:fetch_field('From')
96
+        body = mbox[uid]:fetch_body()
97
+        _notifirc1(subj, from, body)
98
+    end
99
+end
100
+
101
+function _partinf_compare(a, b)
102
+    if not type(a) == type(b) then
103
+        return false
104
+    end
105
+    if type(a) == 'number' then
106
+        return a == b
107
+    elseif type(a) == 'string' then
108
+        return a:lower() == b:lower()
109
+    end
110
+end
111
+
112
+function has_part_like(query, structure)
113
+    --
114
+    -- True if structure has MIME part matching *query*
115
+    --
116
+    if structure == nil then
117
+        return false
118
+    end
119
+    for partid, partinf in pairs(structure) do
120
+        local part_answer = true
121
+        -- check all query parts
122
+        for qkey, qvalue in pairs(query) do
123
+            value = partinf[qkey]
124
+            if not _partinf_compare(value, qvalue) then
125
+                part_answer = false
126
+                break
127
+            end
128
+        end
129
+        if part_answer then
130
+            return true
131
+        end
132
+    end
133
+    return false
134
+end
135
+
136
+function filter_part_like(query, seq)
137
+    --
138
+    -- Run MIME part query on *seq* sequence of messages
139
+    --
140
+    result = Set {}
141
+    for _, mesg in ipairs(seq) do
142
+        mbox, uid = table.unpack(mesg)
143
+        structure = mbox[uid]:fetch_structure()
144
+        if has_part_like(query, structure) then
145
+            table.insert(result, mesg)
146
+        end
147
+    end
148
+    return result
149
+end

+ 1
- 0
dotfiles/imapdomo/host View File

@@ -0,0 +1 @@
1
+../../external/dotfiles/imapdomo/host

+ 13
- 0
dotfiles/imapdomo/main.lua View File

@@ -0,0 +1,13 @@
1
+
2
+dofile ".imapdomo/common.lua"
3
+
4
+imapdomo = {
5
+    action = os.getenv("IMAPDOMO_ACTION"),
6
+    dirs = {
7
+        main = os.getenv("HOME") .. "/.imapdomo",
8
+        host = os.getenv("HOME") .. "/.imapdomo/host/" .. shortname(),
9
+        defhost = os.getenv("HOME") .. "/.imapdomo/default",
10
+    }
11
+}
12
+
13
+handle(imapdomo.action)

+ 4
- 0
dotfiles/imapdomo/private/README View File

@@ -0,0 +1,4 @@
1
+Keep here only files that are never to leave the particular
2
+machine ie. never to be backed up or synchronized.
3
+
4
+This folder should be auto-ignored by all such tools.

+ 56
- 0
dotfiles/imapdomo/utils/imapdomo View File

@@ -0,0 +1,56 @@
1
+#!/bin/bash
2
+
3
+. "$(shellfu-get path)" || exit 3
4
+
5
+shellfu import pretty
6
+
7
+SHELLFU_DEBUG=${SHELLFU_DEBUG:-true}
8
+
9
+usage() {
10
+    mkusage "newmail" \
11
+            "rewind" \
12
+            "cleanup" \
13
+         -- "newmail - check for and file new mail" \
14
+            "rewind - re-add messages from FILTER_FAIL back" \
15
+            "       to FILTER_QUEUE" \
16
+            "cleanup - delete or archive old messages"
17
+}
18
+
19
+mkcmd() {
20
+    #
21
+    # Compose imapfilter command
22
+    #
23
+    echo -n "IMAPDOMO_ACTION=$Action"
24
+    echo -n "  IMAPFILTER_HOME=$CfgDir"
25
+    echo -n "  imapfilter"
26
+    if $Debug
27
+    then
28
+        mkdir -p "$LogDir"
29
+        echo -n "  -d $LogDir/debug.log"
30
+    fi
31
+    echo -n "  -c $CfgDir/main.lua"
32
+}
33
+
34
+main() {
35
+    local Action    # what to do
36
+    local Debug     # true if debugging
37
+    local cmd       # imapfilter command
38
+    local CfgDir    # config directory
39
+    local LogDir    # config directory
40
+    CfgDir="$HOME/.imapdomo"
41
+    LogDir="$HOME/.cache/imapdomo/logs"
42
+    Debug=false
43
+    while true; do case $1 in
44
+        -d) Debug=true; SHELLFU_DEBUG=true; shift ;;
45
+        -*) usage ;;
46
+        *)  break ;;
47
+    esac done
48
+    Action="$1"; shift
49
+    grep -qw "$Action" <<< "newmail|rewind|cleanup" || usage
50
+    cmd=$(mkcmd)
51
+    debug -v cmd
52
+    bash -n <<<"$cmd" || die
53
+    eval "$cmd"
54
+}
55
+
56
+main "$@"