]> git.sur5r.net Git - i3/i3status/blob - contrib/check_mail.py
14d2e82279b585c461d9932e652cd91302ba1ae6
[i3/i3status] / contrib / check_mail.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 # This script wraps i3status output and inject mail status, or just reports
5 # status on command line.  It is based on 'wrapper.py' script by Valentin
6 # Haenel, which could be found at:
7 # http://code.stapelberg.de/git/i3status/tree/contrib/wrapper.py
8 #
9 # To use it, ensure your ~/.i3status.conf contains this line:
10 #     output_format = "i3bar"
11 # in the 'general' section.
12 # Then, in your ~/.i3/config, use:
13 #     status_command i3status | path/to/check_mail.py ...
14 # In the 'bar' section.
15 #
16 # Or just run:
17 #     ./check_mail.py -1 ...
18 #
19 # Information on command line arguments (flags) may be obtained by running
20 #     ./check_mail.py -h
21 #
22 # © 2015 Dmitrij D. Czarkoff <czarkoff@gmail.com>
23 #
24 # Permission to use, copy, modify, and/or distribute this software for any
25 # purpose with or without fee is hereby granted, provided that the above
26 # copyright notice and this permission notice appear in all copies.
27 #
28 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
29 # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
30 # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
31 # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
32 # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
33 # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
34 # PERFORMANCE OF THIS SOFTWARE.
35
36 import argparse
37 import json
38 import os
39 import os.path
40 import sys
41
42 def print_line(message):
43     """ Non-buffered printing to stdout. """
44     sys.stdout.write(message + '\n')
45     sys.stdout.flush()
46
47 def read_line():
48     """ Interrupted respecting reader for stdin. """
49     # try reading a line, removing any extra whitespace
50     try:
51         line = sys.stdin.readline().strip()
52         # i3status sends EOF, or an empty line
53         if not line:
54             sys.exit(3)
55         return line
56     # exit on ctrl-c
57     except KeyboardInterrupt:
58         sys.exit()
59
60 def check_mail(label, nomail, ignore, colors):
61     """ Check mail in mailbox "label" and return report and color """
62     name = label
63     if not os.path.isabs(name):
64         name = os.path.join(os.environ['HOME'], name)
65
66     if not os.path.exists(name) or os.path.getsize(name) == 0:
67         return nomail, colors[0]
68
69     if os.path.isfile(name):
70         import mailbox
71
72         try:
73             mbox = mailbox.mbox(name, create = False)
74             messages = 0
75             for msg in mbox:
76                 if msg.get_flags() == '':
77                     messages += 1
78
79             if messages > 0:
80                 return '{0}:{1}'.format(os.path.basename(name),
81                         messages), colors[1]
82             else:
83                 return nomail, colors[0]
84
85         except:
86             pass
87
88     elif os.path.isdir(name):
89         report = ''
90         maildirs = 0
91
92         for subdir in os.listdir(name):
93             subdirpath = os.path.join(name, subdir)
94             if 'new' in os.listdir(subdirpath):
95                 maildirs += 1
96                 if subdir not in ignore:
97                     messages = len(os.listdir(os.path.join(subdirpath, 'new')))
98                     if messages > 0:
99                         report += ' {0}:{1}'.format(subdir, messages)
100
101         if maildirs > 0:
102             if len(report) > 0:
103                 return report[1:], colors[1]
104             else:
105                 return nomail, colors[0]
106
107     return '{0}: not a mailbox'.format(name), colors[2]
108
109 if __name__ == '__main__':
110     parser = argparse.ArgumentParser(description='Check mailboxes.')
111     parser.add_argument('mailbox', help='path to mailbox', type=str, nargs='*',
112             default=['/var/mail/{0}'.format(os.getlogin())])
113     parser.add_argument('-i', '--ignore', action='append', help='ignore named '
114             'mailboxes', type=str, dest='ignore', metavar='mailbox')
115     parser.add_argument('-1', '--once', help='check mailboxes, write results '
116             'to stdout and exit', action='store_true')
117     parser.add_argument('-0', '--nomail', help='text to print if no new mail '
118             'found', type=str, default='')
119     parser.add_argument('-g', '--good', help='color to use when there is no '
120             'new mail', type=str, default='#00FF00')
121     parser.add_argument('-d', '--degraded', help='color to use when there is '
122             'new mail', type=str, default='#FFFF00')
123     parser.add_argument('-b', '--bad', help='color to use when error was '
124             'detected', type=str, default='#FF0000')
125     parser.add_argument('-p', '--position', help='position of mail reports in '
126             'i3bar status', type=int, default=0)
127     args = parser.parse_args()
128
129     colors = [args.good, args.degraded, args.bad]
130
131     if args.once:
132         for name in args.mailbox:
133             report, color = check_mail(name, args.nomail, args.ignore, colors)
134             sys.stderr.write(report + '\n')
135         exit(0)
136
137     # Skip the first line which contains the version header.
138     print_line(read_line())
139
140     # The second line contains the start of the infinite array.
141     print_line(read_line())
142
143     while True:
144         line, prefix = read_line(), ''
145         # ignore comma at start of lines
146         if line.startswith(','):
147             line, prefix = line[1:], ','
148
149         j = json.loads(line)
150         # insert information into the start of the json
151         i = args.position
152         for name in args.mailbox:
153             report, color = check_mail(name, args.nomail, args.ignore, colors)
154             j.insert(i, {
155                     'name' : 'mail',
156                     'instance' : name,
157                     'full_text' : report,
158                     'color' : color
159                         })
160             i += 1
161         # and echo back new encoded json
162         print_line(prefix+json.dumps(j))