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']
|