]> git.sur5r.net Git - i3/i3status/blob - contrib/check_mail.py
Added function to print content from file (#331)
[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 IOError, exception:
86             return '{0}: {1}'.format(name, exception.strerror), colors[2]
87
88         except:
89             pass
90
91     elif os.path.isdir(name):
92         report = ''
93         maildirs = 0
94
95         for subdir in os.listdir(name):
96             subdirpath = os.path.join(name, subdir)
97             if 'new' in os.listdir(subdirpath):
98                 maildirs += 1
99                 if subdir not in ignore:
100                     messages = len(os.listdir(os.path.join(subdirpath, 'new')))
101                     if messages > 0:
102                         report += ' {0}:{1}'.format(subdir, messages)
103
104         if maildirs > 0:
105             if len(report) > 0:
106                 return report[1:], colors[1]
107             else:
108                 return nomail, colors[0]
109
110     return '{0}: not a mailbox'.format(name), colors[2]
111
112 if __name__ == '__main__':
113     parser = argparse.ArgumentParser(description='Check mailboxes.')
114     parser.add_argument('mailbox', help='path to mailbox', type=str, nargs='*',
115             default=['/var/mail/{0}'.format(os.getlogin())])
116     parser.add_argument('-i', '--ignore', action='append', help='ignore named '
117             'mailboxes', type=str, dest='ignore', metavar='mailbox')
118     parser.add_argument('-1', '--once', help='check mailboxes, write results '
119             'to stdout and exit', action='store_true')
120     parser.add_argument('-0', '--nomail', help='text to print if no new mail '
121             'found', type=str, default='')
122     parser.add_argument('-g', '--good', help='color to use when there is no '
123             'new mail', type=str, default='#00FF00')
124     parser.add_argument('-d', '--degraded', help='color to use when there is '
125             'new mail', type=str, default='#FFFF00')
126     parser.add_argument('-b', '--bad', help='color to use when error was '
127             'detected', type=str, default='#FF0000')
128     parser.add_argument('-p', '--position', help='position of mail reports in '
129             'i3bar status', type=int, default=0)
130     args = parser.parse_args()
131
132     colors = [args.good, args.degraded, args.bad]
133
134     if args.once:
135         for name in args.mailbox:
136             report, color = check_mail(name, args.nomail, args.ignore, colors)
137             sys.stderr.write(report + '\n')
138         exit(0)
139
140     # Skip the first line which contains the version header.
141     print_line(read_line())
142
143     # The second line contains the start of the infinite array.
144     print_line(read_line())
145
146     while True:
147         line, prefix = read_line(), ''
148         # ignore comma at start of lines
149         if line.startswith(','):
150             line, prefix = line[1:], ','
151
152         j = json.loads(line)
153         # insert information into the start of the json
154         i = args.position
155         for name in args.mailbox:
156             report, color = check_mail(name, args.nomail, args.ignore, colors)
157             j.insert(i, {
158                     'name' : 'mail',
159                     'instance' : name,
160                     'full_text' : report,
161                     'color' : color
162                         })
163             i += 1
164         # and echo back new encoded json
165         print_line(prefix+json.dumps(j))