summaryrefslogtreecommitdiffstats
path: root/modules/mail.py
blob: f4014560f2181557f493c59558714551522daf9f (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
# Fedora Developer Shell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Authors: Luke Macken <lmacken@redhat.com>
#
import re
import os
import gzip
import stat
import email
import urllib2
import logging

from os.path import join, exists, dirname, isdir
from mailbox import UnixMailbox
from datetime import datetime, timedelta

from base.vars import DEVSHELL_DIR
from base.module import Module

log = logging.getLogger(__name__)

class Mail(Module):
    """ A module for searching/viewing mailing lists """

    url = 'https://www.redhat.com/archives/%s/%s'

    def search(self, mailinglist, text):
        """ <list> <text>. Search specific mailing list for given text """
        now = datetime.now()
        while True:
            fetch = True
            filename = now.strftime("%Y-%B") + '.txt.gz'
            try:
                f = urllib2.urlopen(self.url % (mailinglist, filename))
            except urllib2.HTTPError:
                break
            local = join(DEVSHELL_DIR, mailinglist, filename)

            # Don't fetch the mbox if we already have a good local copy
            if exists(local):
                info = os.stat(local)
                if info[stat.ST_SIZE] == int(f.headers.get('Content-Length')):
                    fetch = False
                    log.debug("Using local mbox: %s" % local)
            if fetch:
                if not exists(dirname(local)):
                    os.makedirs(dirname(local))
                mbox = file(local, 'w')
                log.debug("Downloading %s" % local)
                mbox.write(f.read())
                mbox.close()
                f.close()

            self.__search_mbox(local, text)

            # Go back in time
            now = now - timedelta(days=31)

    def __search_mbox(self, mboxfile, text):
        """
            Search a compressed mbox for any specified keywords
        """
        num = 0
        statinfo = os.stat(mboxfile)
        gzmbox = gzip.open(mboxfile)
        mbox = UnixMailbox(gzmbox, email.message_from_file)
        while True:
            msg = mbox.next()
            if not msg: break
            num += 1
            fields = [msg['From'], msg['Subject']] + self.__body(msg)
            for field in fields:
                if re.search(text, field, re.IGNORECASE):
                    id = "%s.%s" % (statinfo[stat.ST_INO], num)
                    print "[%s] %s %s" % (id, msg['From'], msg['Subject'])
                    break
        gzmbox.close()

    def __body(self, msg):
        """
            Recursively gather multipart message bodies
        """
        body = []
        if msg.is_multipart():
            for payload in msg.get_payload():
                for part in payload.walk():
                    body += self.__body(part)
        else:
            body = [msg.get_payload()]
        return body

    def show(self, id):
        """ Show a message with a given ID """
        inode, msgnum = map(int, id.split('.'))
        olddir = os.getcwd()
        os.chdir(DEVSHELL_DIR)
        mboxfile = None
        for dir in filter(isdir, os.listdir('.')):
            for file in os.listdir(dir):
                statinfo = os.stat(join(dir, file))
                if statinfo[stat.ST_INO] == inode:
                    mboxfile = join(dir, file)
                    break
            if mboxfile: break
        if mboxfile:
            gzmbox = gzip.open(mboxfile)
            mbox = UnixMailbox(gzmbox, email.message_from_file)
            num = 0
            while num != msgnum:
                msg = mbox.next()
                num += 1
            self.__print_msg(msg)
        else:
            log.error("Cannot find message %s" % id)
        os.chdir(olddir)

    def __print_msg(self, msg):
        log.info("From: %s" % msg['From'])
        log.info("To: %s" % msg['To'])
        log.info("Subject: %s" % msg['Subject'])
        log.info('\n'.join(self.__body(msg)))

__all__ = ['Mail']