6 Commits

Author SHA1 Message Date
  Alois Mahdal c3137b8a70 Bump version 4 years ago
  Alois Mahdal b4ae749515 Revamp packaging to achieve more correct Lua style 4 years ago
  Alois Mahdal b58b69cc9e Remove unnecessary import 4 years ago
  Alois Mahdal c4dd99c13d Add support for hooks 5 years ago
  Alois Mahdal 7b272940d8 Remove unnecessary argument 5 years ago
  Alois Mahdal 7b0ad1ca2b Enable lock-related debugging 5 years ago
6 changed files with 96 additions and 38 deletions
  1. 2
    2
      mkit.ini
  2. 1
    1
      packaging/debian/install
  3. 1
    1
      packaging/template.spec
  4. 78
    29
      src/imapdomo.lua
  5. 12
    3
      src/imapdomo.skel
  6. 2
    2
      src/main.lua.skel

+ 2
- 2
mkit.ini View File

1
 [project]
1
 [project]
2
-    version     = 0.0.9
2
+    version     = 0.0.10
3
     name        = imapdomo
3
     name        = imapdomo
4
     pkgname     = imapdomo
4
     pkgname     = imapdomo
5
     maintainer  = Alois Mahdal <netvor+imapdomo@vornet.cz>
5
     maintainer  = Alois Mahdal <netvor+imapdomo@vornet.cz>
38
 
38
 
39
 [files]
39
 [files]
40
     bin     = src/imapdomo
40
     bin     = src/imapdomo
41
+    share   = src/imapdomo.lua
41
     share   = src/main.lua
42
     share   = src/main.lua
42
-    share   = src/common.lua
43
 
43
 
44
 #mkit version=0.0.34
44
 #mkit version=0.0.34

+ 1
- 1
packaging/debian/install View File

1
 /usr/bin/imapdomo
1
 /usr/bin/imapdomo
2
-/usr/share/imapdomo/common.lua
2
+/usr/share/imapdomo/imapdomo.lua
3
 /usr/share/imapdomo/main.lua
3
 /usr/share/imapdomo/main.lua

+ 1
- 1
packaging/template.spec View File

29
 %files
29
 %files
30
 %dir %{_datadir}/%{name}
30
 %dir %{_datadir}/%{name}
31
 %{_bindir}/%{name}
31
 %{_bindir}/%{name}
32
-%{_datadir}/%{name}/common.lua
32
+%{_datadir}/%{name}/imapdomo.lua
33
 %{_datadir}/%{name}/main.lua
33
 %{_datadir}/%{name}/main.lua
34
 
34
 
35
 %changelog
35
 %changelog

src/common.lua → src/imapdomo.lua View File

1
-os = require "os"
2
-
1
+local pkg = {}
3
 
2
 
4
 ------------------------------------------------------------------------------
3
 ------------------------------------------------------------------------------
5
 -- config and handling                                                      --
4
 -- config and handling                                                      --
6
 ------------------------------------------------------------------------------
5
 ------------------------------------------------------------------------------
7
 
6
 
8
-function file_exists(name)
7
+pkg.load_mailboxes = function()
8
+    --
9
+    -- Load mailboxes from $IMAPDOMO_CFGDIR/mailboxes.lua
10
+    --
11
+    local fname = os.getenv("IMAPDOMO_CFGDIR") .. '/mailboxes.lua'
12
+    assert(pkg.file_exists(fname))
13
+    return dofile(fname)
14
+end
15
+
16
+pkg.file_exists = function(name)
9
     --
17
     --
10
     -- True if file *name* exists
18
     -- True if file *name* exists
11
     --
19
     --
18
     end
26
     end
19
 end
27
 end
20
 
28
 
21
-function do_if_exists(filename)
29
+pkg.do_if_exists = function (filename)
22
     --
30
     --
23
     -- Do file from home, if exists
31
     -- Do file from home, if exists
24
     --
32
     --
25
     local file = os.getenv("IMAPFILTER_HOME") .. "/" .. filename
33
     local file = os.getenv("IMAPFILTER_HOME") .. "/" .. filename
26
-    if file_exists(file) then
34
+    if pkg.file_exists(file) then
27
         dofile(file)
35
         dofile(file)
28
         return
36
         return
29
     end
37
     end
30
 end
38
 end
31
 
39
 
32
-function handle()
40
+pkg.handle = function()
33
     --
41
     --
34
     -- Handle action if it's valid
42
     -- Handle action if it's valid
35
     --
43
     --
36
     local action = os.getenv("IMAPDOMO_ACTION")
44
     local action = os.getenv("IMAPDOMO_ACTION")
37
     local file = os.getenv("IMAPFILTER_HOME") .. "/handlers/" .. action .. ".lua"
45
     local file = os.getenv("IMAPFILTER_HOME") .. "/handlers/" .. action .. ".lua"
38
-    if file_exists(file) then
39
-        do_if_exists("init.lua")
46
+    if pkg.file_exists(file) then
47
+        pkg.do_if_exists("init.lua")
40
         dofile(file)
48
         dofile(file)
41
     else
49
     else
42
         error("no handler for action: " .. action)
50
         error("no handler for action: " .. action)
49
 -- mail getters                                                             --
57
 -- mail getters                                                             --
50
 ------------------------------------------------------------------------------
58
 ------------------------------------------------------------------------------
51
 
59
 
52
-function get_queue(acct, mbox)
60
+pkg.get_queue = function(acct, mbox)
53
     --
61
     --
54
     -- Get queue from *mbox* from *acct* or nil (no messages)
62
     -- Get queue from *mbox* from *acct* or nil (no messages)
55
     --
63
     --
56
     -- If mbox is not specified, "FILTER_QUEUE" is used
64
     -- If mbox is not specified, "FILTER_QUEUE" is used
57
     --
65
     --
58
     mbox = mbox or "FILTER_QUEUE"
66
     mbox = mbox or "FILTER_QUEUE"
59
-    local exist, unread, unseen, uidnext = acct[mbox]:check_status()
67
+    local exist = acct[mbox]:check_status()
60
     if exist > 0 then
68
     if exist > 0 then
61
         return acct[mbox]:select_all()
69
         return acct[mbox]:select_all()
62
     end
70
     end
63
     return nil
71
     return nil
64
 end
72
 end
65
 
73
 
66
-function _notifirc1(subj, from, body)
74
+pkg._notifirc1 = function(subj, from, body)
67
     --
75
     --
68
     -- notify about message using (pre-configured) notifirc
76
     -- notify about message using (pre-configured) notifirc
69
     --
77
     --
73
     fd:close()
81
     fd:close()
74
 end
82
 end
75
 
83
 
76
-function notifirc_all(seq)
84
+pkg.notifirc_all = function(seq)
77
     --
85
     --
78
     -- Send notifications about all messages in *seq*
86
     -- Send notifications about all messages in *seq*
79
     --
87
     --
80
     for _, mesg in ipairs(seq) do
88
     for _, mesg in ipairs(seq) do
89
+        local mbox, uid, subj, from, body
81
         mbox, uid = table.unpack(mesg)
90
         mbox, uid = table.unpack(mesg)
82
         subj = mbox[uid]:fetch_field('Subject')
91
         subj = mbox[uid]:fetch_field('Subject')
83
         from = mbox[uid]:fetch_field('From')
92
         from = mbox[uid]:fetch_field('From')
84
         body = mbox[uid]:fetch_body()
93
         body = mbox[uid]:fetch_body()
85
-        _notifirc1(subj, from, body)
94
+        pkg._notifirc1(subj, from, body)
86
     end
95
     end
87
 end
96
 end
88
 
97
 
89
-function _partinf_compare(a, b)
98
+pkg.hook_all = function(seq, hname, ...)
99
+    --
100
+    -- Call hook hname for all messages in seq
101
+    --
102
+    local hfile = os.getenv("IMAPFILTER_HOME") .. "/hooks/" .. hname
103
+    local hargs = {...}
104
+    local hcmd = hfile
105
+    local fmt = ' %q'
106
+    if pkg.file_exists(hfile) then
107
+        for _, harg in pairs(hargs) do
108
+            hcmd = hcmd .. fmt:format(harg)
109
+        end
110
+        for _, mesg in ipairs(seq) do
111
+            local mbox, uid, subj, body, from, to, date
112
+            mbox, uid = table.unpack(mesg)
113
+            subj = mbox[uid]:fetch_field('Subject')
114
+            from = mbox[uid]:fetch_field('From')
115
+            to = mbox[uid]:fetch_field('To')
116
+            date = mbox[uid]:fetch_field('Date')
117
+            body = mbox[uid]:fetch_body()
118
+            pkg._hook1(hcmd, subj, from, to, date, body)
119
+        end
120
+    else
121
+        error("no such hook: " .. hname)
122
+        return nil
123
+    end
124
+end
125
+
126
+pkg._hook1 = function(hcmd, subj, from, to, date, body)
127
+    --
128
+    -- push message through hook script
129
+    --
130
+    local fd = assert(io.popen(hcmd, "w"))
131
+    local fmt = "subj=%s\nfrom=%s\nto=%s\ndate=%s\n%s"
132
+    fd:write(fmt:format(subj, from, to, date, body))
133
+    fd:close()
134
+end
135
+
136
+pkg._partinf_compare = function(a, b)
90
     if not type(a) == type(b) then
137
     if not type(a) == type(b) then
91
         return false
138
         return false
92
     end
139
     end
97
     end
144
     end
98
 end
145
 end
99
 
146
 
100
-function has_part_like(query, structure)
147
+pkg.has_part_like = function(query, structure)
101
     --
148
     --
102
     -- True if structure has MIME part matching *query*
149
     -- True if structure has MIME part matching *query*
103
     --
150
     --
108
         local part_answer = true
155
         local part_answer = true
109
         -- check all query parts
156
         -- check all query parts
110
         for qkey, qvalue in pairs(query) do
157
         for qkey, qvalue in pairs(query) do
111
-            value = partinf[qkey]
112
-            if not _partinf_compare(value, qvalue) then
158
+            local value = partinf[qkey]
159
+            if not pkg._partinf_compare(value, qvalue) then
113
                 part_answer = false
160
                 part_answer = false
114
                 break
161
                 break
115
             end
162
             end
121
     return false
168
     return false
122
 end
169
 end
123
 
170
 
124
-function save_header(mesg, name)
171
+pkg.save_header = function(mesg, name)
125
     --
172
     --
126
     -- Append header from *mesg* to file named *name*
173
     -- Append header from *mesg* to file named *name*
127
     --
174
     --
130
     --
177
     --
131
     local dest = os.getenv("IMAPDOMO_HEADERS") .. '/' .. name
178
     local dest = os.getenv("IMAPDOMO_HEADERS") .. '/' .. name
132
     local cmd = ('cat >>"%q"'):format(dest)
179
     local cmd = ('cat >>"%q"'):format(dest)
133
-    mbox, uid = table.unpack(mesg)
134
-    header = mbox[uid]:fetch_header()
135
-    if pipe_to(cmd, header) == 0 then
180
+    local mbox, uid = table.unpack(mesg)
181
+    local header = mbox[uid]:fetch_header()
182
+    if pkg.pipe_to(cmd, header) == 0 then
136
         return true
183
         return true
137
     else
184
     else
138
         return false
185
         return false
139
     end
186
     end
140
 end
187
 end
141
 
188
 
142
-function filter_header_saved(seq, name)
189
+pkg.filter_header_saved = function(seq, name)
143
     --
190
     --
144
     -- Save headers from sequence
191
     -- Save headers from sequence
145
     --
192
     --
147
     -- *name* and return new sequence with those messages where save was
194
     -- *name* and return new sequence with those messages where save was
148
     -- successful.
195
     -- successful.
149
     --
196
     --
150
-    result = Set {}
197
+    local result = {}
151
     for _, mesg in ipairs(seq) do
198
     for _, mesg in ipairs(seq) do
152
-        if save_header(mesg, name) then
199
+        if pkg.save_header(mesg, name) then
153
             table.insert(result, mesg)
200
             table.insert(result, mesg)
154
         end
201
         end
155
     end
202
     end
156
     return result
203
     return result
157
 end
204
 end
158
 
205
 
159
-function filter_part_like(query, seq)
206
+pkg.filter_part_like = function(query, seq)
160
     --
207
     --
161
     -- Run MIME part query on *seq* sequence of messages
208
     -- Run MIME part query on *seq* sequence of messages
162
     --
209
     --
163
-    result = Set {}
210
+    local result = {}
164
     for _, mesg in ipairs(seq) do
211
     for _, mesg in ipairs(seq) do
165
-        mbox, uid = table.unpack(mesg)
166
-        structure = mbox[uid]:fetch_structure()
167
-        if has_part_like(query, structure) then
212
+        local mbox, uid = table.unpack(mesg)
213
+        local structure = mbox[uid]:fetch_structure()
214
+        if pkg.has_part_like(query, structure) then
168
             table.insert(result, mesg)
215
             table.insert(result, mesg)
169
         end
216
         end
170
     end
217
     end
171
     return result
218
     return result
172
 end
219
 end
220
+
221
+return pkg

+ 12
- 3
src/imapdomo.skel View File

24
        "configuration directory."                                             \
24
        "configuration directory."                                             \
25
        ""                                                                     \
25
        ""                                                                     \
26
        "See imapfilter_config(5)) for guide and API reference.  Few functions"\
26
        "See imapfilter_config(5)) for guide and API reference.  Few functions"\
27
-       "are also available in .imapdomo/common.lua"                           \
27
+       "are also available in .imapdomo/imapdomo.lua"                         \
28
        ""                                                                     \
28
        ""                                                                     \
29
        "NOTE: Be aware that it's your responsibility to ensure that filters"  \
29
        "NOTE: Be aware that it's your responsibility to ensure that filters"  \
30
        "don't cause performance problems. (Trust me, it's not so hard to"     \
30
        "don't cause performance problems. (Trust me, it's not so hard to"     \
46
     # Compose imapfilter command
46
     # Compose imapfilter command
47
     #
47
     #
48
     echo -n "IMAPDOMO_ACTION=$Action"
48
     echo -n "IMAPDOMO_ACTION=$Action"
49
+    echo -n "  LUA_PATH=$IMAPDOMO_HOME/?.lua"
50
+    echo -n "  IMAPDOMO_CFGDIR=$CfgDir"
49
     echo -n "  IMAPDOMO_HEADERS=$HeaderDir"
51
     echo -n "  IMAPDOMO_HEADERS=$HeaderDir"
50
     echo -n "  IMAPFILTER_HOME=$CfgDir"
52
     echo -n "  IMAPFILTER_HOME=$CfgDir"
51
     echo -n "  imapfilter"
53
     echo -n "  imapfilter"
76
     #
78
     #
77
     # List recognized handlers
79
     # List recognized handlers
78
     #
80
     #
79
-    find "$CfgDir/handlers" -name "*.lua" -printf "%f\n" \
81
+    find "$CfgDir/handlers" -name "*.lua" -printf '%f\n' \
80
       | sed 's/.lua$//'
82
       | sed 's/.lua$//'
81
 }
83
 }
82
 
84
 
84
     #
86
     #
85
     # Put the lockfile
87
     # Put the lockfile
86
     #
88
     #
89
+    debug -v NoLock
87
     $NoLock && return 0
90
     $NoLock && return 0
88
     date +"$$@%s" > "$IMAPDOMO_USER_CACHE/lock"
91
     date +"$$@%s" > "$IMAPDOMO_USER_CACHE/lock"
92
+    debug -f "$IMAPDOMO_USER_CACHE/lock"
89
 }
93
 }
90
 
94
 
91
 is_locked() {
95
 is_locked() {
95
     # True if lockfile exists. False if lockfile does not exist or locking
99
     # True if lockfile exists. False if lockfile does not exist or locking
96
     # is turned off.
100
     # is turned off.
97
     #
101
     #
102
+    debug -v NoLock
98
     $NoLock && return 1
103
     $NoLock && return 1
104
+    debug -f "$IMAPDOMO_USER_CACHE/lock"
99
     test -e "$IMAPDOMO_USER_CACHE/lock"
105
     test -e "$IMAPDOMO_USER_CACHE/lock"
100
 }
106
 }
101
 
107
 
103
     #
109
     #
104
     # Remove the lockfile
110
     # Remove the lockfile
105
     #
111
     #
112
+    debug -v NoLock
106
     $NoLock && return 0
113
     $NoLock && return 0
114
+    debug -f "$IMAPDOMO_USER_CACHE/lock"
107
     rm "$IMAPDOMO_USER_CACHE/lock"
115
     rm "$IMAPDOMO_USER_CACHE/lock"
108
 }
116
 }
109
 
117
 
166
     esac done
174
     esac done
167
     Action="$1"; shift
175
     Action="$1"; shift
168
     test -n "$Action" || usage -w "no action specified"
176
     test -n "$Action" || usage -w "no action specified"
177
+    test -f "$CfgDir/mailboxes.lua" || die "no mailboxes defined"
169
     debug -v Action CfgDir LogDir HeaderDir Debug CdTo NoLock
178
     debug -v Action CfgDir LogDir HeaderDir Debug CdTo NoLock
170
     is_locked && return 1
179
     is_locked && return 1
171
     lock
180
     lock
172
-    handle "$Action"; es=$?
181
+    handle; es=$?
173
     unlock
182
     unlock
174
     return $es
183
     return $es
175
 }
184
 }

+ 2
- 2
src/main.lua.skel View File

1
 #!/bin/lua
1
 #!/bin/lua
2
 
2
 
3
-dofile "__IMAPDOMO_SHARE__/common.lua"
3
+local imapdomo = require "imapdomo"
4
 
4
 
5
-handle()
5
+imapdomo.handle()