[email] Fix email parsing in kibicara_mda

This commit is contained in:
maike 2020-07-13 03:58:14 +02:00 committed by dl6tom
parent b8113c59ae
commit 1bfa7b6a41
2 changed files with 84 additions and 22 deletions

View file

@ -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: <test@example.com>
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 <test@example.com>)
id 1jlC1e-0005ro-PL
for hood@localhost; Tue, 16 Jun 2020 15:33:19 +0200
Message-ID: <B5F50812.F55DFD8B@example.com>
Date: Tue, 16 Jun 2020 06:53:19 -0700
Reply-To: "Test" <test@example.com>
From: "Test" <test@example.com>
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: <hood@localhost>
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'))

View file

@ -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 = (