]> git.decadent.org.uk Git - ion3.git/blob - utils/ion-statusd/statusd_mail.lua
e332dbc7b1e51d201b403972f78879c5b9a13ef0
[ion3.git] / utils / ion-statusd / statusd_mail.lua
1 --
2 -- ion/mod_statusbar/ion-statusd/statusd_mail.lua
3 -- 
4 -- Copyright (c) Tuomo Valkonen 2004-2008.
5 --
6 -- See the included file LICENSE for details.
7 --
8
9 -- The keyword for this monitor
10 local mon = "mail"
11
12 local defaults={
13     update_interval=10*1000,
14     retry_interval=60*10*1000,
15     mbox = os.getenv("MAIL"),
16     files = {}
17 }
18
19 local settings=table.join(statusd.get_config(mon), defaults)
20
21 local function TR(s, ...)
22     return string.format(statusd.gettext(s), unpack(arg))
23 end
24
25 local function check_spool()
26     if not settings.mbox then
27         statusd.warn(TR("MAIL environment variable not set "..
28                         "and no spool given."))
29     end
30 end
31
32 if not settings.files["spool"] then
33     check_spool()
34     settings.files["spool"] = settings.mbox
35 elseif not(settings.files["spool"] == mbox) then
36     statusd.warn(TR("%s.mbox does not match %s.files['spool']; using %s.mbox",
37                     mon, mon, mon))
38     check_spool()
39     settings.files["spool"] = settings.mbox
40 end
41
42 local function calcmail(fname)
43     local f, err=io.open(fname, 'r')
44     local total, read, old=0, 0, 0
45     local had_blank=true
46     local in_headers=false
47     local had_status=false
48     
49     if not f then
50         statusd.warn(err)
51         return
52     end
53
54     for l in f:lines() do
55         if had_blank and string.find(l, '^From ') then
56             total=total+1
57             had_status=false
58             in_headers=true
59             had_blank=false
60         else
61             had_blank=false
62             if l=="" then
63                 if in_headers then
64                     in_headers=false
65                 end
66                 had_blank=true
67             elseif in_headers and not had_status then
68                 local st, en, stat=string.find(l, '^Status:(.*)')
69                 if stat then
70                     had_status=true
71                     if string.find(l, 'R') then
72                         read=read+1
73                     end
74                     if string.find(l, 'O') then
75                         old=old+1
76                     end
77                 end
78             end
79         end
80     end
81     
82     f:close()
83     
84     return total, total-read, total-old
85 end
86
87
88 local mail_timer
89 local mail_timestamps = {}
90 function init_timestamps ()
91     for key, val in pairs(settings.files) do
92         mail_timestamps[key]=-2.0
93     end
94 end
95 init_timestamps()
96
97 local function update_mail()
98     local failed
99     for key, mbox in pairs(settings.files) do
100         if not mbox then
101             error(TR(key.." not set"))
102         end
103     
104         local old_tm=mail_timestamps[key]
105         mail_timestamps[key]=statusd.last_modified(mbox)
106     
107         if mail_timestamps[key]>old_tm then
108             local mail_total, mail_unread, mail_new=calcmail(mbox)
109             if failed == nil then
110                 failed = not mail_total
111             else
112                 failed = failed and (not mail_total)
113             end
114         
115             if key == "spool" then
116                 meter=mon
117             else
118                 meter=mon.."_"..key
119             end
120             if mail_total then
121                 statusd.inform(meter.."_new", tostring(mail_new))
122                 statusd.inform(meter.."_unread", tostring(mail_unread))
123                 statusd.inform(meter.."_total", tostring(mail_total))
124
125                 if mail_new>0 then
126                     statusd.inform(meter.."_new_hint", "important")
127                 else
128                     statusd.inform(meter.."_new_hint", "normal")
129                 end
130         
131                 if mail_unread>0 then
132                     statusd.inform(meter.."_unread_hint", "important")
133                 else
134                     statusd.inform(meter.."_unread_hint", "normal")
135                 end
136             end
137         end
138     end
139
140     if failed then
141         statusd.warn(TR("Disabling mail monitor for %d seconds.",
142                         settings.retry_interval/1000))
143         init_timestamps()
144         mail_timer:set(settings.retry_interval, update_mail)
145         return
146     end
147    
148     mail_timer:set(settings.update_interval, update_mail)
149 end
150
151 mail_timer=statusd.create_timer()
152 update_mail()
153