diff --git a/kibicara/kibicara_mda.py b/kibicara/kibicara_mda.py index 9461860..ad7a29f 100644 --- a/kibicara/kibicara_mda.py +++ b/kibicara/kibicara_mda.py @@ -3,6 +3,8 @@ # SPDX-License-Identifier: 0BSD import email.parser +from email.policy import default +import email.message import sys import re import requests @@ -10,43 +12,102 @@ from logging import getLogger from kibicara.model import Hood from kibicara.platforms.email.model import Email import argparse +from asyncio import run +from fastapi import status +from ormantic import NoMatch -async def main(): +async def async_main(mail=None, hood_name=None): logger = getLogger(__name__) # the MDA passes the recipient address as command line argument parser = argparse.ArgumentParser() - parser.add_argument("recipient_address") - args = parser.parse_args() + if hood_name is None: + parser.add_argument("recipient_address") + args = parser.parse_args() + # extract hood name from the envelope recipient address + hood_name = args.recipient_address.split('@')[0].lower() - # read mail from STDIN - mailbytes = bytes(sys.stdin.read()) + if mail is None: + # read mail from STDIN + mail = bytes(sys.stdin.read(), encoding='ascii') + # parse plaintext to email.EmailMessage object + mail = email.parser.BytesParser(policy=default).parsebytes(mail) + else: + mail = email.parser.Parser(policy=default).parsestr(mail) - # parse plaintext to email.EmailMessage object - myparser = email.parser.BytesParser() - mail = myparser.parsebytes(mailbytes) + assert type(mail) == email.message.EmailMessage # extract relevant data from mail - for part in mail.walk(): - try: - text = part.get_body(('plain',)) - if not text: - text = re.sub(r'<[^>]*>', '', part.get_body(('html',))) - except Exception: - logger.info("No Body in this message part", exc_info=True) - if not text: - logger.error('No suitable message body') + body = mail.get_body(preferencelist=('plain', 'html')) + if body['content-type'].subtype == 'plain': + text = str(body.get_content()) + elif body['content-type'].subtype == 'html': + text = re.sub(r'<[^>]*>', '', body.get_content()) + + try: + text = str(text) + except UnboundLocalError: + print('No suitable message body') + exit(1) + try: + hood = await Hood.objects.get(name=hood_name) + except NoMatch: + print('No hood with this name') exit(1) - # extract hood name from the envelope recipient address - hood_name = args.recipient_address.split('@')[0].lower() - hood = await Hood.objects.get(name=hood_name) email_row = await Email.objects.get(hood=hood) body = { 'text': text, 'author': mail.get_unixfrom(), 'secret': email_row.secret, } - requests.post( - 'http://localhost:8000/api/hoods/%d/email/messages/' % (hood.id), json=body + response = requests.post( + 'http://localhost:8000/api/hoods/%d/email/messages/' % hood.id, json=body ) + print("Request sent:") + if response.status_code == status.HTTP_201_CREATED: + exit(0) + elif response.status_code == status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS: + print("Message was't accepted: " + text) + elif response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY: + print("Malformed request: " + str(response.json())) + elif response.status_code == status.HTTP_401_UNAUTHORIZED: + logger.error('Wrong API secret. kibicara_mda seems to be misconfigured') + else: + print(str(response.status_code)) + exit(1) + + +def main(): + run(async_main()) + + +if __name__.endswith('kibicara_mda'): + mail = """From test@example.com Tue Jun 16 15:33:19 2020 +Return-path: +Envelope-to: hood@localhost +Delivery-date: Tue, 16 Jun 2020 15:33:19 +0200 +Received: from [23.143.35.123] (helo=example.com) + by example.com with smtp (Exim 4.89) + (envelope-from ) + id 1jlC1e-0005ro-PL + for hood@localhost; Tue, 16 Jun 2020 15:33:19 +0200 +Message-ID: +Date: Tue, 16 Jun 2020 06:53:19 -0700 +Reply-To: "Test" +From: "Test" +User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1.17) Gecko/20080914 Thunderbird/2.0.0.17 +MIME-Version: 1.0 +To: +Subject: Chat: test +Content-Type: multipart/mixed; boundary="AqNPlAX243a8sip3B7kXv8UKD8wuti" + + +--AqNPlAX243a8sip3B7kXv8UKD8wuti +Content-Type: text/plain; charset=utf-8 + +test + +--AqNPlAX243a8sip3B7kXv8UKD8wuti-- + """ + run(async_main(mail=mail, hood_name='hood')) diff --git a/kibicara/platforms/email/bot.py b/kibicara/platforms/email/bot.py index 539bdd6..426e746 100644 --- a/kibicara/platforms/email/bot.py +++ b/kibicara/platforms/email/bot.py @@ -24,6 +24,7 @@ class EmailBot(Censor): """ Loop which waits for new messages and sends emails to all subscribers. """ while True: message = await self.receive() + logger.info("Received Email from %s: %s" % (message.author, message.text)) for subscriber in EmailSubscribers.objects.filter(hood=self.hood.id): token = to_token(email=subscriber.email, hood=self.hood.id) unsubscribe_link = (