我正在尝试为一些自定义的Django电子邮件后端编写单元测试,并针对“真正的”smtp服务器进行测试,我试图通过运行来使用Python的内置smtpd调试服务器:
python -m smtpd -n -c DebuggingServer localhost:1025
我的unittest基本上看起来像:
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,
)
当我运行它时,smtpd进程正确输出电子邮件内容。
但是,当我尝试捕获它时,我可以在我的单元测试中确认它,我什么也得不到。我已经尝试使用subprocess
包来启动进程并通过管道读取输出,但它从不接收任何输出。
我以为我错误地使用了子进程,所以作为最后的手段,我尝试使用以下命令启动进程:
python -m smtpd -n -c DebuggingServer localhost:1025 > /tmp/smtpd.log
并读取日志文件。但是,即使这样,也不会将任何输出写入文件。
这里发生了什么?
答案 0 :(得分:3)
我遇到了同样的问题,花了2天时间试图找出发生了什么。我试过跑两个
python -m smtpd -n -c DebuggingServer localhost:1025
和
python -m smtpd -n -c DebuggingServer localhost:1025 > mail.log
来自我与subprocess
的一次集成测试,但它没有用。在通过REPL进行实验时,我注意到subprocess
为我们打开的管道中的第一个读取挂起。我杀了之后,下一次读取实际上会返回数据。所以我开始调查流中的内容。但是因为我在2个小时内没有运气,所以我最终在SMTPServer
周围滚动自己的包装器,写入文件,然后让自己运转起来。
这是包装类(process_message
是smtpd.SMTPServer
模块可以运行的smtpd
子类所需的抽象方法:
# 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)
我用
运行它python -m smtpd -n -c test_smtpd.SMTPTestServer localhost:1025
虽然这不能直接回答你的问题,但这是一个简单的解决方法,所以我希望这会有所帮助。
答案 1 :(得分:1)
我注意到了相同的症状 - 对我来说,它有助于将-u
参数传递给Python解释器,如:
python -u -m smtpd -n -c DebuggingServer localhost:1025
强制stdin,stdout和stderr完全无缓冲。在重要的系统上,还将stdin,stdout和stderr置于二进制模式。
答案 2 :(得分:0)
根据this answer,输出缓冲在以下时间打开:
进程STDOUT被重定向到终端
以外的其他东西
在这种情况下,建议的解决方案是:
stdbuf -oL python -m smtpd -n -c DebuggingServer localhost:1025 > mail.log
答案 3 :(得分:0)
在使用 Flask 时,我为 app.logger 设置了一个类似的 SMPTHandler。
我发现 HasSensitivityClassification = Confidential
的输出转到 Starting Step #0
Step #0: Pulling image: mirror.gcr.io/library/golang
Step #0: Using default tag: latest
Step #0: Error response from daemon: manifest for mirror.gcr.io/library/golang:latest not found: manifest unknown: Failed to fetch "latest" from request "/v2/library/golang/manifests/latest".
...
Step #0: Error response from daemon: manifest for mirror.gcr.io/library/golang:latest not found: manifest unknown: Failed to fetch "latest" from request "/v2/library/golang/manifests/latest".
ERROR: failed to pull because we ran out of retries.
ERROR
ERROR: build step 0 "mirror.gcr.io/library/golang" failed: error pulling build step 0 "mirror.gcr.io/library/golang": generic::unknown: retry budget exhausted (10 attempts): step exited with non-zero status: 1
(&2),而不是 python -m smptd
(&1)。虽然可能有更优雅的解决方案,但这对我有用:
python -m smtpd -n -c DebuggingServer 127.0.0.1:1025 2>&1 >> smtp_error.log
该命令将 stderr
发送到 stdout
,然后将所有输出记录到 smpt_error.log。