summaryrefslogtreecommitdiffstats
path: root/modules/mail.py
blob: 9a2532a9adedc2e5b74f956c2af28ceaf6b2e67c (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
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']