You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by gc...@apache.org on 2025/02/04 18:56:01 UTC
(allura) 01/02: [#8574] adding aiosmtpd to replace smtpd package
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 <gu...@slashdotmedia.com>
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