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

Reply via email to