如何捕获 Python smtp 调试服务器的输出

Cer*_*rin 6 python email django

我正在尝试为一些自定义 Django 电子邮件后端编写单元测试,并针对“真正的”smtp 服务器对其进行测试,我正在尝试通过运行以下命令来使用 Python 的内置 smtpd 调试服务器:

python -m smtpd -n -c DebuggingServer localhost:1025
Run Code Online (Sandbox Code Playgroud)

我的单元测试基本上如下所示:

class Tests(TestCase):

    @override_settings(EMAIL_BACKEND='mycustombackend')
    @override_settings(EMAIL_HOST='localhost')
    @override_settings(EMAIL_PORT='1025')
    def test_backend(self):
        from django.core import mail
        mail.send_mail(
                subject='Subject here',
                message='Here is the message.',
                from_email='from@example.com',
                recipient_list=['to@example.com'],
                fail_silently=False,
            )
Run Code Online (Sandbox Code Playgroud)

当我运行它时,smtpd 进程正确输出电子邮件内容。

然而,当我尝试捕获它以便在单元测试中确认它时,我什么也没得到。我尝试过使用subprocess包来启动进程并通过管道读取输出,但它从未收到任何输出。

我认为我错误地使用了子进程,因此作为最后的手段,我尝试使用以下命令启动该进程:

python -m smtpd -n -c DebuggingServer localhost:1025 > /tmp/smtpd.log
Run Code Online (Sandbox Code Playgroud)

并读取日志文件。然而,即使如此,也不会将任何输出写入该文件。

这里发生了什么?

小智 3

我遇到了同样的问题,花了两天时间试图弄清楚发生了什么。我尝试同时运行

python -m smtpd -n -c DebuggingServer localhost:1025
Run Code Online (Sandbox Code Playgroud)

python -m smtpd -n -c DebuggingServer localhost:1025 > mail.log
Run Code Online (Sandbox Code Playgroud)

来自我的一项集成测试subprocess,但它不起作用。在通过 REPL 进行实验时,我注意到首先从挂起为我们打开的管道中读取数据subprocess。在我杀掉它之后,下一次读取实际上返回了数据。所以我开始调查流中的内容。但由于我在 2 小时内没有运气,所以我最终将自己的包装器写入SMTPServer文件,然后开始运行。

这是包装类(是的子类可由模块运行process_message所需的抽象方法):smtpd.SMTPServersmtpd

# test_smtpd.py

import smtpd

SMTP_DUMPFILE = '/tmp/mail.log'

class SMTPTestServer(smtpd.SMTPServer):
    def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
        with open(SMTP_DUMPFILE, 'w') as f:
            f.write(data)
Run Code Online (Sandbox Code Playgroud)

我运行它

python -m smtpd -n -c test_smtpd.SMTPTestServer localhost:1025
Run Code Online (Sandbox Code Playgroud)

虽然这并不能直接回答您的问题,但这是一个简单的解决方法,所以我希望这会有所帮助。