在Django中测试电子邮件发送[关闭]


90

我需要测试我的Django应用程序是否发送了具有正确内容的电子邮件。我不想依赖外部系统(例如临时gmail帐户),因为我没有测试实际的电子邮件服务...

我可能想在发送电子邮件时将电子邮件本地存储在一个文件夹中。关于如何实现的任何提示?


主持人:请锁定这个问题。答案中添加了很多垃圾邮件,提出了非常复杂的解决方案,以促进外部服务。
nemesisdesign

Answers:



182

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')

3
+1好答案。但是对于无法使用的复杂情况,我send_mail没有用。
santiagobasulto


2
如果您测试了一个调用send_mail从而无法访问的函数,该mail怎么办?
马特D

3
@MatthewDrill在另一个函数中被调用mail.outbox时仍可以访问send_mail
pymarco

2
@pymarco如果您从核心导入邮件,mail.outbox[0].body即使send_mail在其他地方执行了邮件发送,也会显示给您已发送的电子邮件。
罗布

17

如果您要进行单元测试,最好的解决方案是使用django提供的内存中后端

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

8

使用MailHog

受MailCatcher启发,易于安装。

使用Go构建-MailHog无需安装在多个平台上即可运行。


此外,它还有一个名为Jim的组件,MailHog Chaos Monkey,它使您能够测试正在发生的各种问题的电子邮件发送:

吉姆能做什么?

  • 拒绝连接
  • 限速连接
  • 拒绝身份验证
  • 拒绝发件人
  • 拒绝收件人

在此处了解更多信息。


(与原始mailcatcher不同,它在发送带有emoji表情的电子邮件时失败了,该电子邮件使用UTF-8编码,并且在当前版本中并未得到真正修复,MailHog可以正常工作。)


5

对于不需要发送附件的任何项目,我使用django-mailer,它的好处是所有出站电子邮件最终都排在队列中,直到我触发它们的发送,甚至在它们发送之后,也都将它们记录下来-所有这些内容都可以在Admin中看到,从而可以轻松快速地检查您通过电子邮件发送的代码试图插入管道的内容。


除此之外,django-mailer创建的Message对象意味着您也可以在单元测试中对它们进行处理(并检查其内容)(我知道虚拟套件在测试套件中具有出站邮箱支持,但是使用django-mailer却没有)除非管理命令发送邮件,否则不要发送邮件,这意味着您不能使用该邮箱对象)
Steve Jalim

更新,年龄从我原来的答复:github.com/SmileyChris/django-mailer-2不支持的附件,太
史蒂夫Jalim

4

Django也有一个内存中的电子邮件后端。内存后端下的文档中有更多详细信息。这在Django 1.6中存在,不确定是否在更早的版本中存在。



1

将此处的一些内容捆绑在一起,这是基于的简单设置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"),

0

为什么不通过继承自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()结束asyncore循环(停止从听音服务器)。


0

如果您有可用的TomCat服务器或其他Servlet引擎,则“ Post Hoc”是一种不错的方法,它是一种小型服务器,在外观上与SMTP服务器完全相同,但是它包含一个用户界面,可用于查看和检查已发送的电子邮件。它是开源的,免费提供。

在以下位置找到它:Post Hoc GitHub Site

请参阅博客文章: PostHoc:测试发送电子邮件的应用程序

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.