#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Endpoint for sending emails to the list via the UI"""
import plugins.server
import plugins.session
import email.message
import aiosmtplib
import fnmatch
import typing
import aiohttp.web


async def process(
    server: plugins.server.BaseServer, session: plugins.session.SessionObject, indata: dict,
) -> typing.Union[dict, aiohttp.web.Response]:

    if not server.config.ui.mailhost:
        return {"error": "This server has not been set up for sending email yet."}

    # Figure out outgoing MTA
    mailhost = server.config.ui.mailhost
    mailport = 25
    if ":" in mailhost:
        mailhost, _mailport = mailhost.split(":", 1)
        mailport = int(_mailport)

    # Figure out if recipient list is on allowed list
    to = indata.get("to", "")
    mldomain = to.strip("<>").split("@")[-1]
    allowed_to_send = False
    for allowed_domain in server.config.ui.sender_domains.split(" "):
        if fnmatch.fnmatch(mldomain, allowed_domain):
            allowed_to_send = True
            break
    if not allowed_to_send:
        return {"error": "Recipient mailing list is not an allowed recipient for emails via the web."}

    # If logged in and everything, prep for dispatch
    if session.credentials and session.credentials.authoritative:
        subject = indata.get("subject")
        body = indata.get("body")
        irt = indata.get("in-reply-to")
        references = indata.get("references")

        if to and subject and body:
            msg = email.message.EmailMessage()
            if irt:
                msg["in-reply-to"] = irt
            if references:
                msg["references"] = references
            msg["from"] = "%s <%s>" % (session.credentials.name, session.credentials.email)
            msg["to"] = to
            msg["subject"] = subject
            msg["X-Sender"] = "Apache Pony Mail Foal Composer v/0.1"
            msg.set_charset("utf-8")
            msg.set_content(body)
            await aiosmtplib.send(msg, hostname=mailhost, port=mailport)
            return {"okay": True, "message": "Message dispatched!"}
        else:
            return {"error": "You need to fill out both recipient, subject and text body."}
    else:
        return {"error": "You need to be logged in via an authoritative source to send emails."}


def register(server: plugins.server.BaseServer):
    return plugins.server.Endpoint(process)
