experimental mail transport

This commit is contained in:
j3d1 2023-11-23 23:17:20 +01:00
parent e43d4837c3
commit 191c8d822b
4 changed files with 115 additions and 17 deletions

View file

@ -1,9 +1,11 @@
#!/usr/bin/env python3
import asyncio
import logging
import os
from abc import ABCMeta
import uvicorn
from aiosmtpd.controller import Controller, UnixSocketController
from aiosmtpd.controller import Controller, UnixSocketController, BaseController, UnixSocketMixin
from aiosmtpd.lmtp import LMTP
@ -47,17 +49,39 @@ class LTMPController(Controller):
return LMTP(self.handler)
class UnixSocketLMTPController(UnixSocketController):
class BaseAsyncController(BaseController, metaclass=ABCMeta):
def __init__(
self,
handler,
loop,
**SMTP_parameters,
):
super().__init__(
handler,
loop,
**SMTP_parameters,
)
def serve(self):
return self._create_server()
class UnixSocketLMTPController(UnixSocketMixin, BaseAsyncController):
def factory(self):
return LMTP(self.handler)
def _trigger_server(self): # pragma: no-unixsock
# Prevent confusion on which _trigger_server() to invoke.
# Or so LGTM.com claimed
UnixSocketMixin._trigger_server(self)
class UvicornServer(uvicorn.Server):
def install_signal_handlers(self):
pass
async def web():
async def web(loop):
log_config = uvicorn.config.LOGGING_CONFIG
log_config["handlers"]["default"] = {"class": "logging.FileHandler", "filename": "web.log", "formatter": "default"}
log_config["handlers"]["access"] = {"class": "logging.FileHandler", "filename": "web-access.log",
@ -67,8 +91,10 @@ async def web():
await server.serve()
async def tcp():
log = logging.getLogger('test')
async def tcp(loop):
log = logging.getLogger('test.log')
log.addHandler(logging.FileHandler('test.log'))
log.setLevel(logging.DEBUG)
log.info("Starting TCP server")
server = await asyncio.start_unix_server(handle_echo, path='test.sock')
@ -80,11 +106,20 @@ async def tcp():
log.info("TCP done")
async def lmtp():
log = logging.getLogger('lmtp')
async def lmtp(loop):
log = logging.getLogger('mail.log')
log.addHandler(logging.FileHandler('mail.log'))
log.setLevel(logging.DEBUG)
log.info("Starting LMTP server")
cont = UnixSocketLMTPController(ExampleHandler(), unix_socket='lmtp.sock')
cont.start()
server = await UnixSocketLMTPController(ExampleHandler(), unix_socket='lmtp.sock', loop=loop).serve()
addrs = ', '.join(str(sock.getsockname()) for sock in server.sockets)
log.info(f'Serving on {addrs}')
os.chmod('lmtp.sock', 0o775)
async with server:
await server.serve_forever()
log.info("LMTP done")
@ -104,18 +139,18 @@ def main():
import sdnotify
import signal
import setproctitle
import os
setproctitle.setproctitle("c3lf-sys3")
logging.basicConfig(filename='server.log', level=logging.DEBUG, encoding='utf-8')
logging.basicConfig(filename='test.log', level=logging.DEBUG, encoding='utf-8')
logging.basicConfig(filename='lmtp.log', level=logging.DEBUG, encoding='utf-8')
log = logging.getLogger()
log = logging.getLogger('server.log')
log.addHandler(logging.FileHandler('server.log'))
log.setLevel(logging.DEBUG)
log.info("Starting server")
loop = asyncio.get_event_loop()
loop.add_signal_handler(signal.SIGTERM, lambda: asyncio.create_task(shutdown(signal.SIGTERM, loop)))
loop.add_signal_handler(signal.SIGINT, lambda: asyncio.create_task(shutdown(signal.SIGINT, loop)))
loop.create_task(web())
loop.create_task(tcp())
loop.create_task(lmtp())
loop.create_task(web(loop))
loop.create_task(tcp(loop))
loop.create_task(lmtp(loop))
n = sdnotify.SystemdNotifier()
n.notify("READY=1")
log.info("Server ready")
@ -123,8 +158,13 @@ def main():
loop.run_forever()
finally:
loop.close()
os.remove("lmtp.sock")
os.remove("test.sock")
os.remove("web.sock")
logging.info("Server stopped")
logging.shutdown()
if __name__ == '__main__':
main()

View file

@ -8,6 +8,7 @@ c3lf-nodes:
git_branch: master
git_repo: <git_repo_url>
db_password: <db_password>
mail_domain: <mail_domain>
main_email: <main_email>
legacy_api_user: <legacy_api_user>
legacy_api_password: <legacy_api_password>

View file

@ -274,4 +274,11 @@
service:
name: c3lf-sys3
state: started
enabled: yes
enabled: yes
- name: configure postfix
template:
src: templates/postfix.cf.j2
dest: /etc/postfix/main.cf
notify:
- restart postfix

View file

@ -0,0 +1,50 @@
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# Debian specific: Specifying a file name will cause the first
# line of that file to be used as the name. The Debian default
# is /etc/mailname.
#myorigin = /etc/mailname
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
# appending .domain is the MUA's job.
append_dot_mydomain = no
readme_directory = no
# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 3.6 on
# fresh installs.
compatibility_level = 3.6
# TLS parameters
smtp_use_tls = yes
smtp_force_tls = yes
smtpd_use_tls = yes
smtpd_tls_cert_file=/etc/letsencrypt/live/{{ web_domain }}/fullchain.pem;
smtpd_tls_key_file=/etc/letsencrypt/live/{{ web_domain }}/privkey.pem;
smtpd_tls_security_level=may
smtp_tls_CApath=/etc/ssl/certs
smtp_tls_security_level=may
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = polaris.c3lf.de
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = $myhostname, polaris.c3lf.de, localhost.c3lf.de, , localhost, {{ mail_domain }}
#relayhost = firefly.lab.or.it
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
maillog_file = /var/log/mail.log
virtual_transport=lmtp:unix:/var/www/c3lf-sys3/lmtp.sock