ticketfrei/active_bots/mailbot.py

115 lines
3.8 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
2018-03-24 15:26:35 +00:00
from config import config
import logging
import sendmail
import ssl
import datetime
import email
import imaplib
import report
2018-03-28 22:13:00 +00:00
from bot import Bot
2018-03-24 15:26:35 +00:00
logger = logging.getLogger(__name__)
2018-03-28 22:13:00 +00:00
class Mailbot(Bot):
"""
Bot which sends Mails if mentioned via twitter/mastodon, and tells
other bots that it received mails.
"""
2018-03-28 23:50:05 +00:00
def login(self, user):
# change to use mailbox of local system
mailinglist = user.get_mailinglist()
mailbox = imaplib.IMAP4_SSL(mailinglist)
context = ssl.create_default_context()
try:
2018-03-28 23:50:05 +00:00
mailbox.starttls(ssl_context=context)
except:
2018-03-24 15:26:35 +00:00
logger.error('StartTLS failed', exc_info=True)
try:
2018-03-28 23:50:05 +00:00
mailbox.login(config["mail"]["user"],
2018-03-24 15:26:35 +00:00
config["mail"]["passphrase"])
except imaplib.IMAP4.error:
2018-03-24 15:26:35 +00:00
logger.error("Login to mail server failed", exc_info=True)
try:
2018-03-24 15:26:35 +00:00
mailer = sendmail.Mailer()
mailer.send('', config['web']['contact'],
'Ticketfrei Crash Report',
attachment=config['logging']['logpath'])
except:
2018-03-24 15:26:35 +00:00
logger.error('Mail sending failed', exc_info=True)
2018-03-28 22:13:00 +00:00
def crawl(self, user):
"""
crawl for new mails.
:return: msgs: (list of report.Report objects)
"""
2018-03-28 23:50:05 +00:00
mailbox = self.login(user)
try:
2018-03-28 23:50:05 +00:00
rv, data = mailbox.select("Inbox")
except imaplib.IMAP4.abort:
2018-03-24 15:26:35 +00:00
logger.error("Crawling Mail failed", exc_info=True)
rv = False
msgs = []
if rv == 'OK':
2018-03-28 23:50:05 +00:00
rv, data = mailbox.search(None, "ALL")
if rv != 'OK':
return msgs
for num in data[0].split():
2018-03-28 23:50:05 +00:00
rv, data = mailbox.fetch(num, '(RFC822)')
if rv != 'OK':
2018-03-24 15:26:35 +00:00
logger.error("Couldn't fetch mail %s %s" % (rv, str(data)))
return msgs
msg = email.message_from_bytes(data[0][1])
2018-03-28 23:50:05 +00:00
# check if email was sent by the bot itself. Different solution?
if not user.get_mailinglist() in msg['From']:
# get a comparable date out of the email
date_tuple = email.utils.parsedate_tz(msg['Date'])
2018-03-24 15:26:35 +00:00
date_tuple = datetime.datetime.fromtimestamp(
email.utils.mktime_tz(date_tuple)
)
date = int((date_tuple -
datetime.datetime(1970, 1, 1)).total_seconds())
2018-03-28 23:50:05 +00:00
if date > user.get_seen_mail():
msgs.append(self.make_report(msg))
return msgs
2018-03-28 23:50:05 +00:00
def post(self, user, report):
"""
sends reports by other sources to a mailing list.
2018-03-28 23:50:05 +00:00
:param report: (report.Report object)
"""
2018-03-28 23:50:05 +00:00
mailinglist = self.login(user)
if report.source is not self:
mailer = sendmail.Mailer()
mailer.send(report.text, mailinglist,
"Warnung: Kontrolleure gesehen")
def make_report(self, msg):
"""
generates a report out of a mail
:param msg: email.parser.Message object
:return: post: report.Report object
"""
# get a comparable date out of the email
date_tuple = email.utils.parsedate_tz(msg['Date'])
2018-03-24 15:26:35 +00:00
date_tuple = datetime.datetime.fromtimestamp(
email.utils.mktime_tz(date_tuple)
)
date = (date_tuple - datetime.datetime(1970, 1, 1)).total_seconds()
author = msg.get("From") # get mail author from email header
# :todo take only the part before the @
text = msg.get_payload()
post = report.Report(author, "mail", text, None, date)
self.last_mail = date
return post