From 37d56c4a4704c823ac6a4ef7c3de4c0232ceee64 Mon Sep 17 00:00:00 2001 From: Wes Lord Date: Tue, 17 Oct 2023 21:06:57 -0700 Subject: [PATCH] Update mail_debug command to use aiosmtpd smtpd deprecated by Python 3.6, removed in Python 3.12 --- .../management/commands/mail_debug.py | 22 ++++++++++--------- requirements-dev.txt | 1 + tests/management/commands/test_mail_debug.py | 4 ++-- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/django_extensions/management/commands/mail_debug.py b/django_extensions/management/commands/mail_debug.py index 7a8424dc4..c76007612 100644 --- a/django_extensions/management/commands/mail_debug.py +++ b/django_extensions/management/commands/mail_debug.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -import asyncore +import asyncio import sys +from aiosmtpd.controller import Controller from logging import getLogger -from smtpd import SMTPServer from typing import List from django.core.management.base import BaseCommand, CommandError @@ -12,14 +12,12 @@ logger = getLogger(__name__) -class ExtensionDebuggingServer(SMTPServer): - """Duplication of smtpd.DebuggingServer, but using logging instead of print.""" - - # Do something with the gathered message - def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): +class CustomHandler: + async def handle_DATA(self, server, session, envelope): """Output will be sent to the module logger at INFO level.""" + peer = session.peer inheaders = 1 - lines = data.split('\n') + lines = envelope.content.decode('utf8', errors='replace').splitlines() logger.info('---------- MESSAGE FOLLOWS ----------') for line in lines: # headers first @@ -28,6 +26,7 @@ def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): inheaders = 0 logger.info(line) logger.info('------------ END MESSAGE ------------') + return '250 OK' class Command(BaseCommand): @@ -78,8 +77,11 @@ def handle(self, addrport='', *args, **options): def inner_run(): quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C' print("Now accepting mail at %s:%s -- use %s to quit" % (addr, port, quit_command)) - ExtensionDebuggingServer((addr, port), None, decode_data=True) - asyncore.loop() + handler = CustomHandler() + controller = Controller(handler, hostname=addr, port=port) + controller.start() + loop = asyncio.get_event_loop() + loop.run_forever() try: inner_run() diff --git a/requirements-dev.txt b/requirements-dev.txt index cc9112252..08578babd 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,6 +8,7 @@ factory-boy requests pygments vobject +aiosmtpd types-pyOpenSSL types-PyYAML diff --git a/tests/management/commands/test_mail_debug.py b/tests/management/commands/test_mail_debug.py index c75dbede1..f723f52c5 100644 --- a/tests/management/commands/test_mail_debug.py +++ b/tests/management/commands/test_mail_debug.py @@ -4,6 +4,6 @@ def test_initialize_mail_server(): - with mock.patch('django_extensions.management.commands.mail_debug.asyncore.loop') as loop: + with mock.patch('django_extensions.management.commands.mail_debug.asyncio') as asyncio: call_command('mail_debug', '2525') - assert loop.called, 'asyncore.loop was not called' + assert asyncio.get_event_loop.called, 'asyncio.get_event_loop was not called'