This is an automated email from the ASF dual-hosted git repository. gcruz pushed a commit to branch gc/8574 in repository https://gitbox.apache.org/repos/asf/allura.git
commit f928228c5edd017993ea18d9eb0afb097fcd3fa9 Author: Guillermo Cruz <[email protected]> AuthorDate: Fri Jan 31 12:17:00 2025 -0700 [#8574] adding aiosmtpd to replace smtpd package --- Allura/allura/command/smtp_server.py | 59 +++++++++++++++++++--------- Allura/docs/getting_started/installation.rst | 2 +- AlluraTest/alluratest/smtp_debug.py | 27 ++++++++++--- docker-compose.yml | 2 +- requirements.in | 1 + 5 files changed, 64 insertions(+), 27 deletions(-) diff --git a/Allura/allura/command/smtp_server.py b/Allura/allura/command/smtp_server.py index a8fe44b65..3a1b07e42 100644 --- a/Allura/allura/command/smtp_server.py +++ b/Allura/allura/command/smtp_server.py @@ -15,19 +15,27 @@ # specific language governing permissions and limitations # under the License. -import smtpd -import asyncore - import faulthandler import tg from paste.script import command import allura.tasks from allura.command import base +from allura.command.base import EmptyClass, Command from allura.lib import helpers as h - from paste.deploy.converters import asint +from aiosmtpd.controller import Controller +import asyncio +from tg.wsgiapp import RequestLocals + +async def start_server(loop): + handler = MailServer() + hostname = tg.config.get('forgemail.host', '0.0.0.0') + port = asint(tg.config.get('forgemail.port', 8825)) + controller = Controller(handler, hostname=hostname, port=port) + controller.start() + class SMTPServerCommand(base.Command): min_args = 1 @@ -38,25 +46,38 @@ class SMTPServerCommand(base.Command): parser.add_option('-c', '--context', dest='context', help=('The context of the message (path to the project' ' and/or tool')) - + def command(self): faulthandler.enable() self.basic_setup() - MailServer((tg.config.get('forgemail.host', '0.0.0.0'), - asint(tg.config.get('forgemail.port', 8825))), - None) - asyncore.loop() - - -class MailServer(smtpd.SMTPServer): - - def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): + loop = asyncio.get_event_loop() + task = loop.create_task(start_server(loop=loop)) + try: + loop.run_forever() + except KeyboardInterrupt: + task.cancel() + finally: + loop.close() + +class MailServer: + async def handle_DATA(self, server, session, envelope): try: + peer = session.peer + mailfrom = envelope.mail_from + rcpttos = envelope.rcpt_tos + data = envelope.content base.log.info('Msg Received from %s for %s', mailfrom, rcpttos) base.log.info(' (%d bytes)', len(data)) - task = allura.tasks.mail_tasks.route_email.post( - peer=peer, mailfrom=mailfrom, rcpttos=rcpttos, - data=h.really_unicode(data)) + tgl = RequestLocals() + tgl.tmpl_context = EmptyClass() + tgl.app_globals = tg.app_globals + tg.request_local.context._push_object(tgl) + task = allura.tasks.mail_tasks.route_email.post(peer=peer, mailfrom=mailfrom, rcpttos=rcpttos, + data=h.really_unicode(data)) base.log.info(f'Msg passed along as task {task._id}') - except Exception: - base.log.exception('Error handling msg') + except Exception as error: + base.log.exception(f'Error handling msg - {error}') + return '500 Could not process your message' + + return '250 OK' + diff --git a/Allura/docs/getting_started/installation.rst b/Allura/docs/getting_started/installation.rst index fddfa16f2..972b58055 100644 --- a/Allura/docs/getting_started/installation.rst +++ b/Allura/docs/getting_started/installation.rst @@ -341,7 +341,7 @@ your :file:`development.ini` (8826 by default). .. code-block:: bash - python -u -m smtpd -n -c DebuggingServer localhost:8826 + python -u -m aiosmtpd -n -c alluratest.smtp_debug.BetterDebuggingServer -l 0.0.0.0:8826 -d This will create a new debugging server that discards messages and prints them to stdout. diff --git a/AlluraTest/alluratest/smtp_debug.py b/AlluraTest/alluratest/smtp_debug.py index 377754bed..20db4fc32 100644 --- a/AlluraTest/alluratest/smtp_debug.py +++ b/AlluraTest/alluratest/smtp_debug.py @@ -15,11 +15,26 @@ # specific language governing permissions and limitations # under the License. -from smtpd import DebuggingServer +import tg +from aiosmtpd.handlers import Debugging, Sink +from aiosmtpd.controller import Controller +from io import StringIO +from paste.deploy.converters import asint +class BetterDebuggingServer: + + def process_message(self, server, session, envelope): + stream = StringIO() + handler = Debugging(stream) # throws away the email + hostname = tg.config.get('forgemail.host', '0.0.0.0') + port = asint(tg.config.get('forgemail.port', 8825)) + controller = Controller(handler, hostname=hostname, port=port) + controller.start() -class BetterDebuggingServer(DebuggingServer): - - def process_message(self, peer, mailfrom, rcpttos, data, **kwargs): - print('TO: ' + ', '.join(rcpttos)) - super().process_message(peer, mailfrom, rcpttos, data) + async def handle_DATA(self, server, session, envelope): + try: + rcpttos = envelope.rcpt_tos + print('TO: ' + ', '.join(rcpttos)) + except Exception as error: + return f'500 Could not process your message. Error {error}' + return '250 OK' \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index b4d2e3a4d..b0c0c28c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,7 +64,7 @@ services: environment: *env volumes_from: - web - command: python -u -m smtpd -n -c alluratest.smtp_debug.BetterDebuggingServer 0.0.0.0:8826 + command: python -u -m aiosmtpd -n -c alluratest.smtp_debug.BetterDebuggingServer -l 0.0.0.0:8826 -d expose: - "8826" diff --git a/requirements.in b/requirements.in index a4407483d..fe7387b7a 100644 --- a/requirements.in +++ b/requirements.in @@ -60,6 +60,7 @@ pytest pytest-xdist pytest-sugar docutils +aiosmtpd # deployment gunicorn
