# Copyright (C) 2020 by Maike <maike@systemli.org> # Copyright (C) 2020 by Cathy Hu <cathy.hu@fau.de> # Copyright (C) 2020, 2023 by Thomas Lindner <tom@dl6tom.de> # Copyright (C) 2020 by Martin Rey <martin.rey@mailbox.org> # # SPDX-License-Identifier: 0BSD from argparse import ArgumentParser from asyncio import run as asyncio_run from email.parser import BytesParser from email.policy import default from email.utils import parseaddr from logging import getLogger from re import sub from sys import stdin from fastapi import status from ormantic import NoMatch from pytoml import load from requests import post from kibicara.config import config from kibicara.platforms.email.model import Email, EmailSubscriber logger = getLogger(__name__) class Main: def __init__(self): parser = ArgumentParser() parser.add_argument( "-f", "--config", dest="configfile", default="/etc/kibicara.conf", help="path to config file", ) # the MDA passes the recipient address as command line argument parser.add_argument("recipient") args = parser.parse_args() try: with open(args.configfile) as configfile: config.update(load(configfile)) except FileNotFoundError: # run with default config pass # extract email from the recipient email_name = args.recipient.lower() asyncio_run(self.__run(email_name)) async def __run(self, email_name): try: email = await Email.get(name=email_name) except NoMatch: logger.error("No recipient with this name") exit(1) # read mail from STDIN and parse to EmailMessage object message = BytesParser(policy=default).parsebytes(stdin.buffer.read()) sender = "" if message.get("sender"): sender = message.get("sender") elif message.get("from"): sender = message.get("from") else: logger.error("No Sender of From header") exit(1) sender = parseaddr(sender)[1] if not sender: logger.error("Could not parse sender") exit(1) maybe_subscriber = await EmailSubscriber.filter(email=sender).all() if len(maybe_subscriber) != 1 or maybe_subscriber[0].hood.id != email.hood.id: logger.error("Not a subscriber") exit(1) # extract relevant data from mail text = sub( r"<[^>]*>", "", message.get_body(preferencelist=("plain", "html")).get_content(), ) response = post( "{0}/api/hoods/{1}/email/messages/".format( config["root_url"], email.hood.pk ), json={"text": text, "secret": email.secret}, ) if response.status_code == status.HTTP_201_CREATED: exit(0) elif response.status_code == status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS: logger.error("Message was't accepted: {0}".format(text)) elif response.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY: logger.error("Malformed request: {0}".format(response.json())) elif response.status_code == status.HTTP_401_UNAUTHORIZED: logger.error("Wrong API secret. kibicara_mda seems to be misconfigured") else: logger.error( "REST-API failed with response status {0}".format(response.status_code) ) exit(1)