summaryrefslogtreecommitdiff
path: root/contrib/check_mail.py
blob: ac23f77eee6024c5a7a60edf4853308cfa438833 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/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))