2 # -*- coding: utf-8 -*-
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
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.
17 # ./check_mail.py -1 ...
19 # Information on command line arguments (flags) may be obtained by running
22 # © 2015 Dmitrij D. Czarkoff <czarkoff@gmail.com>
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.
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.
42 def print_line(message):
43 """ Non-buffered printing to stdout. """
44 sys.stdout.write(message + '\n')
48 """ Interrupted respecting reader for stdin. """
49 # try reading a line, removing any extra whitespace
51 line = sys.stdin.readline().strip()
52 # i3status sends EOF, or an empty line
57 except KeyboardInterrupt:
60 def check_mail(label, nomail, ignore, colors):
61 """ Check mail in mailbox "label" and return report and color """
63 if not os.path.isabs(name):
64 name = os.path.join(os.environ['HOME'], name)
66 if not os.path.exists(name) or os.path.getsize(name) == 0:
67 return nomail, colors[0]
69 if os.path.isfile(name):
73 mbox = mailbox.mbox(name, create = False)
76 if msg.get_flags() == '':
80 return '{0}:{1}'.format(os.path.basename(name),
83 return nomail, colors[0]
85 except IOError, exception:
86 return '{0}: {1}'.format(name, exception.strerror), colors[2]
91 elif os.path.isdir(name):
95 for subdir in os.listdir(name):
96 subdirpath = os.path.join(name, subdir)
97 if 'new' in os.listdir(subdirpath):
99 if subdir not in ignore:
100 messages = len(os.listdir(os.path.join(subdirpath, 'new')))
102 report += ' {0}:{1}'.format(subdir, messages)
106 return report[1:], colors[1]
108 return nomail, colors[0]
110 return '{0}: not a mailbox'.format(name), colors[2]
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()
132 colors = [args.good, args.degraded, args.bad]
135 for name in args.mailbox:
136 report, color = check_mail(name, args.nomail, args.ignore, colors)
137 sys.stderr.write(report + '\n')
140 # Skip the first line which contains the version header.
141 print_line(read_line())
143 # The second line contains the start of the infinite array.
144 print_line(read_line())
147 line, prefix = read_line(), ''
148 # ignore comma at start of lines
149 if line.startswith(','):
150 line, prefix = line[1:], ','
153 # insert information into the start of the json
155 for name in args.mailbox:
156 report, color = check_mail(name, args.nomail, args.ignore, colors)
160 'full_text' : report,
164 # and echo back new encoded json
165 print_line(prefix+json.dumps(j))