我需要测试我的Django应用程序发送的电子邮件内容是否正确。我不想依赖外部系统(例如临时的gmail帐户),因为我不是在测试实际的电子邮件服务... 我想把这些邮件存储在本地文件夹中,作为它们被发送的一部分。有什么提示可以实现吗?
Django测试框架提供了一些内置的助手来帮助您进行测试电子邮件服务。
文档中的示例(简短版本):
from django.core import mail
from django.test import TestCase
class EmailTest(TestCase):
def test_send_email(self):
mail.send_mail('Subject here', 'Here is the message.',
'from@example.com', ['to@example.com'],
fail_silently=False)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].subject, 'Subject here')
send_mail
时,它并不实用。 - santiagobasultosend_mail
函数的函数,因此无法访问mail
,你该如何处理? - Mattsend_mail
时,您仍然可以访问mail.outbox
。 - pymarcomail.outbox[0].body
会显示发送的电子邮件,即使send_mail
在其他地方执行也是如此。 - Robprint
语句在终端中查看生成的电子邮件(例如 print("Mailbox\n", mail.outbox[0].message(), "\n", "_" * 80)
),这可以放置在任何 assert
语句之前或之后。self.assertEqual(len(mail.outbox), 1)
- Staccato如果你对单元测试感兴趣,最好的解决方案是使用Django提供的内存后端。
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
以将其用作py.test fixture为例
@pytest.fixture(autouse=True)
def email_backend_setup(self, settings):
settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
在每个测试中,mail.outbox
会被重置为服务器状态,因此测试之间没有副作用。
在每个测试中,mail.outbox
会被重置为服务器状态,因此测试之间没有副作用。
from django.core import mail
def test_send(self):
mail.send_mail('subject', 'body.', 'from@example.com', ['to@example.com'])
assert len(mail.outbox) == 1
def test_send_again(self):
mail.send_mail('subject', 'body.', 'from@example.com', ['to@example.com'])
assert len(mail.outbox) == 1
为什么不通过继承smtpd.SMTPServer
和threading.Thread
来创建自己的简单SMTP服务器:
class TestingSMTPServer(smtpd.SMTPServer, threading.Thread):
def __init__(self, port=25):
smtpd.SMTPServer.__init__(
self,
('localhost', port),
('localhost', port),
decode_data=False
)
threading.Thread.__init__(self)
def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
self.received_peer = peer
self.received_mailfrom = mailfrom
self.received_rcpttos = rcpttos
self.received_data = data
def run(self):
asyncore.loop()
每当您的SMTP服务器接收到邮件请求时,都会调用process_message函数,您可以在其中执行任何操作。
在测试代码中,可以这样做:
smtp_server = TestingSMTPServer()
smtp_server.start()
do_thing_that_would_send_a_mail()
smtp_server.close()
self.assertIn(b'hello', smtp_server.received_data)
请记住通过调用smtp_server.close()
来关闭(close)asyncore.dispatcher
以结束asyncore循环(停止服务器监听)。
filebased.EmailBackend
的简单设置。这会呈现一个列表视图,链接到各个日志文件,它们具有方便的时间戳文件名。在列表中点击链接会在浏览器中显示该消息(原始)。
设置
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
EMAIL_FILE_PATH = f"{MEDIA_ROOT}/email_out"
视图
import os
from django.conf import settings
from django.shortcuts import render
def mailcheck(request):
path = f"{settings.MEDIA_ROOT}/email_out"
mail_list = os.listdir(path)
return render(request, "mailcheck.html", context={"mail_list": mail_list})
模板
{% if mail_list %}
<ul>
{% for msg in mail_list %}
<li>
<a href="{{ MEDIA_URL }}email_out/{{msg}}">{{ msg }}</a>
</li>
{% endfor %}
</ul>
{% else %}
No messages found.
{% endif %}
urls
path("mailcheck/", view=mailcheck, name="mailcheck"),
如果你有一个可用的TomCat服务器或其他Servlet引擎,那么一个不错的方法是使用"Post Hoc"。它是一个小型服务器,对应用程序而言就像SMTP服务器一样,但它包括一个用户界面,允许您查看和检查已发送的电子邮件消息。它是开源的,可以免费使用。
在这里找到它:Post Hoc GitHub 网站
查看博客文章:PostHoc: 测试发送电子邮件的应用程序