This repository has been archived by the owner on Feb 16, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
mailwatch.py
114 lines (95 loc) · 3.99 KB
/
mailwatch.py
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
# 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; either version 3 of the License, or
# (at your option) any later version.
#
# 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 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
from errbot import BotPlugin, botcmd
import logging
import sys
PY2 = sys.version_info[0] == 2
import imaplib
from email.header import decode_header, make_header
import email, email.utils
import datetime
log = logging.getLogger('errbot.plugins.mailwatch')
class MailWatch(BotPlugin):
""""Poll IMAP mailboxes and report new mails to specified chatrooms"""
min_err_version = '1.6.0'
_highest_uid = None # Highest UID we've encountered, so we know where we left off
def activate(self):
super(MailWatch, self).activate()
if self.config is not None and set(("INTERVAL", "ACCOUNTS")) <= set(self.config):
self._initial_poll = True
self.start_poller(self.config['INTERVAL'], self.runpolls)
else:
log.info("Not starting MailWatch poller, plugin not configured")
def get_configuration_template(self):
return {'INTERVAL': 60, 'ACCOUNTS': [{'HOSTNAME': 'domain.tld', 'MAILBOX': 'INBOX', 'USERNAME': 'username', 'PASSWORD': 'password', 'ROOM': 'roomid@conference.domain.tld', 'SSL': True}]}
def check_configuration(self, configuration):
for i,item in enumerate(configuration['ACCOUNTS']):
if 'MAILBOX' not in item:
configuration['ACCOUNTS'][i]['MAILBOX'] = 'INBOX'
def runpolls(self):
"""Polls all configured mailboxes"""
assert 'ACCOUNTS' in self.config
for account in self.config['ACCOUNTS']:
self.poll(account['HOSTNAME'], account['MAILBOX'], account['USERNAME'], account['PASSWORD'], account['ROOM'])
def poll(self, host, mailbox, user, passwd, room, ssl=True):
"""Poll an IMAP mailbox"""
log.info("Polling {0}@{1}".format(user, host))
if 'seen' not in self.shelf.keys():
seen = []
else:
seen = self.shelf['seen']
if ssl:
M = imaplib.IMAP4_SSL(host)
else:
M = imaplib.IMAP4(host)
log.debug("IMAP LOGIN")
code,message = M.login(user, passwd)
log.debug("{0}: {1}".format(code, message))
log.debug("IMAP SELECT: {0}".format(mailbox))
M.select(mailbox)
log.debug("{0}: {1}".format(code, message))
log.debug("IMAP SEARCH")
if self._highest_uid is None:
search = '(SENTSINCE {})'.format((datetime.datetime.now() + datetime.timedelta(weeks=-1)).strftime('%d-%b-%Y'))
else:
search = '(UID {}:*)'.format(self._highest_uid)
typ, data = M.search(None, search)
log.debug("{0}: {1}".format(typ, data))
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822.HEADER)')
raw_mail = data[0][1]
# raw_message is a bytestring which must be decoded to make it usable
mail = email.message_from_string(raw_mail.decode("utf-8", "ignore"))
if mail.get('Message-ID') not in seen:
log.debug("New message: {0}".format(mail.get('Message-ID')))
seen.append(mail.get('Message-ID'))
message = 'New email arrived'
for hdrname in ['From','To','Cc','Subject']:
value = mail.get(hdrname) or None
if value:
if PY2:
pairs = decode_header(value)
hdrvalue = ' '.join([ unicode(t[0], t[1] or 'ASCII') for t in pairs ])
message += "\n\t{}: {}".format(hdrname, hdrvalue)
else:
hi = make_header(decode_header(value))
message += "\n\t{}: {}".format(hdrname, str(hi))
self.send(room, message, message_type='groupchat')
else:
log.debug("Seen message: {0}".format(mail.get('Message-ID')))
self._highest_uid = num.decode('ascii')
M.close()
M.logout()
self.shelf['seen'] = seen
self.shelf.sync()