gpg-lacre/lacre/daemon.py
Piotr F. Mieszkowski ddcef93abb Fix a bug introduced by refactoring, clean up code
- Fix certificate retrieval.

- Store recipients within MailOperation objects.

- Log more information.

- Fix some warnings.
2022-10-19 18:36:23 +00:00

89 lines
2.3 KiB
Python

"""Lacre Daemon, the Advanced Mail Filter message dispatcher."""
import logging
import lacre
import lacre.config as conf
import sys
from aiosmtpd.controller import Controller
import asyncio
# Mail status constants.
#
# These are the only values that our mail handler is allowed to return.
RESULT_OK = '250 OK'
RESULT_ERROR = '500 Could not process your message'
RESULT_NOT_IMPLEMENTED = '500 Not implemented yet'
# Load configuration and init logging, in this order. Only then can we load
# the last Lacre module, i.e. lacre.mailgate.
conf.load_config()
lacre.init_logging(conf.get_item("logging", "config"))
LOG = logging.getLogger(__name__)
import lacre.mailgate as gate
class MailEncryptionProxy:
"""A mail handler dispatching to appropriate mail operation."""
async def handle_DATA(self, server, session, envelope):
"""Accept a message and either encrypt it or forward as-is."""
# for now, just return an error because we're not ready to handle mail
for operation in gate.delivery_plan(envelope.rcpt_tos):
LOG.debug(f"Sending mail via {operation}")
new_message = operation.perform(envelope.content)
gate.send_msg(new_message, operation.recipients(), envelope.mail_from)
return RESULT_NOT_IMPLEMENTED
def _init_controller():
proxy = MailEncryptionProxy()
host, port = conf.daemon_params()
LOG.info(f"Initialising a mail Controller at {host}:{port}")
return Controller(proxy, hostname=host, port=port)
def _validate_config():
missing = conf.validate_config()
if missing:
params = ", ".join([_full_param_name(tup) for tup in missing])
LOG.error(f"Following mandatory parameters are missing: {params}")
sys.exit(lacre.EX_CONFIG)
def _full_param_name(tup):
return f"[{tup[0]}]{tup[1]}"
async def _sleep():
while True:
await asyncio.sleep(5)
def _main():
_validate_config()
controller = _init_controller()
LOG.info("Starting the daemon...")
# starts the controller in a new thread
controller.start()
# _this_ thread now continues operation, so it may be used to control key
# and certificate cache
try:
asyncio.run(_sleep())
except KeyboardInterrupt:
LOG.info("Finishing...")
controller.stop()
LOG.info("Done")
if __name__ == '__main__':
_main()