我需要测试我的 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')
您可以使用文件后端发送电子邮件,这是一个非常方便的开发和测试解决方案;电子邮件不会发送,而是存储在您可以指定的文件夹中!
如果您要进行单元测试,最好的解决方案是使用django 提供的In-memory 后端。
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
以将其用作py.test夹具为例
@pytest.fixture(autouse=True)
def email_backend_setup(self, settings):
settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
在每次测试中,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
使用MailHog
受 MailCatcher 启发,更易于安装。
使用 Go 构建 - MailHog 无需安装即可在多个平台上运行。
此外,它还有一个名为Jim的组件,即MailHog Chaos Monkey,它使您能够测试发送电子邮件时出现的各种问题:
吉姆能做什么?
- 拒绝连接
- 速率限制连接
- 拒绝认证
- 拒绝发件人
- 拒绝收件人
在此处阅读更多相关信息。
(与原始的 mailcatcher 不同,它在发送带有表情符号的电子邮件时失败了,以 UTF-8 编码并且在当前版本中并没有真正修复,MailHog 可以正常工作。)
对于不需要发送附件的任何项目,我使用django-mailer,它的好处是所有出站电子邮件都排在队列中,直到我触发它们的发送,即使在它们发送之后,它们也会被记录 -所有这些都在 Admin 中可见,从而可以轻松快速地检查您通过电子邮件发送的代码试图向 intertubes 发射的内容。
Django 也有一个内存中的电子邮件后端。更多详细信息请参阅In-memory backend下的文档。这存在于 Django 1.6 中,不确定它是否存在于更早的版本中。
为测试目的修补 SMTPLib 有助于在不发送邮件的情况下测试发送邮件。
为什么不通过继承smtpd.SMTPServer
和启动您自己的非常简单的 SMTP 服务器threading.Thread
:
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)
只要记住close()
通过asyncore.dispatcher
调用smtp_server.close()
来结束异步循环(停止服务器监听)。
将这里的一些部分捆绑在一起,这是一个基于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 %}
网址
path("mailcheck/", view=mailcheck, name="mailcheck"),
如果您有可用的 TomCat 服务器或其他 servlet 引擎,那么一个不错的方法是“Post Hoc”,它是一个小型服务器,看起来与 SMTP 服务器完全一样,但它包含一个用户界面,允许您查看和检查已发送的电子邮件。它是开源的并且免费提供。
在以下位置找到它:Post Hoc GitHub 站点
请参阅博客文章: PostHoc:测试发送电子邮件的应用程序