cc77338ff4
When user doesn't have permissions to access some file, he is better served by exact error message python recieved then by statement "not a mailbox".
166 lines
5.8 KiB
Python
Executable File
166 lines
5.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# This script wraps i3status output and inject mail status, or just reports
|
|
# status on command line. It is based on 'wrapper.py' script by Valentin
|
|
# Haenel, which could be found at:
|
|
# http://code.stapelberg.de/git/i3status/tree/contrib/wrapper.py
|
|
#
|
|
# To use it, ensure your ~/.i3status.conf contains this line:
|
|
# output_format = "i3bar"
|
|
# in the 'general' section.
|
|
# Then, in your ~/.i3/config, use:
|
|
# status_command i3status | path/to/check_mail.py ...
|
|
# In the 'bar' section.
|
|
#
|
|
# Or just run:
|
|
# ./check_mail.py -1 ...
|
|
#
|
|
# Information on command line arguments (flags) may be obtained by running
|
|
# ./check_mail.py -h
|
|
#
|
|
# © 2015 Dmitrij D. Czarkoff <czarkoff@gmail.com>
|
|
#
|
|
# Permission to use, copy, modify, and/or distribute this software for any
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
# copyright notice and this permission notice appear in all copies.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
# PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import os.path
|
|
import sys
|
|
|
|
def print_line(message):
|
|
""" Non-buffered printing to stdout. """
|
|
sys.stdout.write(message + '\n')
|
|
sys.stdout.flush()
|
|
|
|
def read_line():
|
|
""" Interrupted respecting reader for stdin. """
|
|
# try reading a line, removing any extra whitespace
|
|
try:
|
|
line = sys.stdin.readline().strip()
|
|
# i3status sends EOF, or an empty line
|
|
if not line:
|
|
sys.exit(3)
|
|
return line
|
|
# exit on ctrl-c
|
|
except KeyboardInterrupt:
|
|
sys.exit()
|
|
|
|
def check_mail(label, nomail, ignore, colors):
|
|
""" Check mail in mailbox "label" and return report and color """
|
|
name = label
|
|
if not os.path.isabs(name):
|
|
name = os.path.join(os.environ['HOME'], name)
|
|
|
|
if not os.path.exists(name) or os.path.getsize(name) == 0:
|
|
return nomail, colors[0]
|
|
|
|
if os.path.isfile(name):
|
|
import mailbox
|
|
|
|
try:
|
|
mbox = mailbox.mbox(name, create = False)
|
|
messages = 0
|
|
for msg in mbox:
|
|
if msg.get_flags() == '':
|
|
messages += 1
|
|
|
|
if messages > 0:
|
|
return '{0}:{1}'.format(os.path.basename(name),
|
|
messages), colors[1]
|
|
else:
|
|
return nomail, colors[0]
|
|
|
|
except IOError, exception:
|
|
return '{0}: {1}'.format(name, exception.strerror), colors[2]
|
|
|
|
except:
|
|
pass
|
|
|
|
elif os.path.isdir(name):
|
|
report = ''
|
|
maildirs = 0
|
|
|
|
for subdir in os.listdir(name):
|
|
subdirpath = os.path.join(name, subdir)
|
|
if 'new' in os.listdir(subdirpath):
|
|
maildirs += 1
|
|
if subdir not in ignore:
|
|
messages = len(os.listdir(os.path.join(subdirpath, 'new')))
|
|
if messages > 0:
|
|
report += ' {0}:{1}'.format(subdir, messages)
|
|
|
|
if maildirs > 0:
|
|
if len(report) > 0:
|
|
return report[1:], colors[1]
|
|
else:
|
|
return nomail, colors[0]
|
|
|
|
return '{0}: not a mailbox'.format(name), colors[2]
|
|
|
|
if __name__ == '__main__':
|
|
parser = argparse.ArgumentParser(description='Check mailboxes.')
|
|
parser.add_argument('mailbox', help='path to mailbox', type=str, nargs='*',
|
|
default=['/var/mail/{0}'.format(os.getlogin())])
|
|
parser.add_argument('-i', '--ignore', action='append', help='ignore named '
|
|
'mailboxes', type=str, dest='ignore', metavar='mailbox')
|
|
parser.add_argument('-1', '--once', help='check mailboxes, write results '
|
|
'to stdout and exit', action='store_true')
|
|
parser.add_argument('-0', '--nomail', help='text to print if no new mail '
|
|
'found', type=str, default='')
|
|
parser.add_argument('-g', '--good', help='color to use when there is no '
|
|
'new mail', type=str, default='#00FF00')
|
|
parser.add_argument('-d', '--degraded', help='color to use when there is '
|
|
'new mail', type=str, default='#FFFF00')
|
|
parser.add_argument('-b', '--bad', help='color to use when error was '
|
|
'detected', type=str, default='#FF0000')
|
|
parser.add_argument('-p', '--position', help='position of mail reports in '
|
|
'i3bar status', type=int, default=0)
|
|
args = parser.parse_args()
|
|
|
|
colors = [args.good, args.degraded, args.bad]
|
|
|
|
if args.once:
|
|
for name in args.mailbox:
|
|
report, color = check_mail(name, args.nomail, args.ignore, colors)
|
|
sys.stderr.write(report + '\n')
|
|
exit(0)
|
|
|
|
# Skip the first line which contains the version header.
|
|
print_line(read_line())
|
|
|
|
# The second line contains the start of the infinite array.
|
|
print_line(read_line())
|
|
|
|
while True:
|
|
line, prefix = read_line(), ''
|
|
# ignore comma at start of lines
|
|
if line.startswith(','):
|
|
line, prefix = line[1:], ','
|
|
|
|
j = json.loads(line)
|
|
# insert information into the start of the json
|
|
i = args.position
|
|
for name in args.mailbox:
|
|
report, color = check_mail(name, args.nomail, args.ignore, colors)
|
|
j.insert(i, {
|
|
'name' : 'mail',
|
|
'instance' : name,
|
|
'full_text' : report,
|
|
'color' : color
|
|
})
|
|
i += 1
|
|
# and echo back new encoded json
|
|
print_line(prefix+json.dumps(j))
|