为什么Django的send_mail在测试期间不起作用?

时间:2013-06-18 14:22:38

标签: python django email

我有一个应用程序可以导入许多用户电子邮件地址并为其创建帐户。为了让他们设置自己的密码,我尝试使用django的PasswordResetForm(在django.contrib.auth.forms中)。一旦创建了用户帐户,就会调用密码重置:

def reset_password(person):
    form = PasswordResetForm({'email': person.email})
    if form.is_valid():
        form.save(from_email='myname@myserver.com')

我没有进行任何进一步的测试,而是包括执行此操作的单元测试:

import password_reset_module
class TestPasswordReset(TestCase):
     def setUp(self):
         p = Person(email='test@test.com')
     def test_send(self):
         password_reset_module.reset_password(p)

没有断言,现在我只想通过监控运行的控制台来查看是否有邮件发送:

python -m smtpd -n -c DebuggingServer localhost:1025

保存表单会调用django的send_mail。运行测试用例时,send_mail方法返回1.但是,控制台中不会显示任何邮件。奇怪的是从django的交互式shell调用send_mail:

python manage.py shell

工作正常。邮件显示在控制台中。在浏览器中单击忘记密码链接也会导致发送邮件。

我也尝试过基于文件的电子邮件后端无济于事。 当前settings.py电子邮件设置:

EMAIL_USE_TLS = False
EMAIL_HOST = 'localhost'
DEFAULT_FROM_EMAIL = 'myname@myserver.com'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_PORT = 1025

现在想知道我在调用密码重置时是否遗漏了某些内容,或者手头是否存在邮件服务器配置问题?

4 个答案:

答案 0 :(得分:4)

您的配置被否决了

在“电子邮件服务”部分, Django testing documentation说:

  

Django的测试运行器自动重定向所有   Django发送电子邮件到虚拟发件箱。 [...]   在测试运行期间,每个外发电子邮件都会保存在   django.core.mail.outbox。   这是所有EmailMessage个实例的简单列表   已被发送。

咦?

Django测试运行器实际上会为您配置一个不同的电子邮件后端(称为locmem)。 如果您只想进行单元测试,这非常方便 (没有与实际的电子邮件服务器集成),但是 如果你不了解它会非常令人惊讶。

(我没有使用Django测试运行器manage.py test,  但无论如何它都会发生,大概是因为我有  已安装pytest-django,它会神奇地修改我的py.test。)

如果要覆盖覆盖并使用电子邮件配置 在settings模块中给出,您需要重新设置的是 设置电子邮件后端,例如像这样:

@django.test.utils.override_settings(
    EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend')
def test_send_email_with_real_SMTP(self):
   ...

答案 1 :(得分:3)

根据我的理解,您在测试设备时正在运行以下命令。

python -m smtpd -n -c DebuggingServer localhost:1025

此命令启动一个“哑”的SMTP服务器,它接收您的电子邮件并在终端上显示它们。尝试在没有设置此DebuggingServer的情况下运行您的站点,并查看邮件是否已发送。

以下是对docs page

的引用

答案 2 :(得分:2)

尝试将其转换为适当的单元测试可能是值得的,当然您可以将其作为自动测试套件的一部分运行。对于单元测试,可能最简单的方法来检查邮件是否已发送(并在需要时验证邮件的内容)是使用内置电子邮件后端内置的Django - 您只需使用此框中的outbox属性即可获得发送邮件列表:

https://docs.djangoproject.com/en/dev/topics/email/#in-memory-backend

这样做的好处是不需要任何基础结构设置来支持测试电子邮件发送,这使得断言电子邮件的内容变得非常简单,这也应该使测试快速(与实际将电子邮件发送到SMTP相比)服务器)。

希望这有帮助。

答案 3 :(得分:0)

您可以使用 pytest-django 的 mailoutbox 夹具:

<块引用>

一个干净的电子邮件发件箱,Django 生成的电子邮件将发送到该发件箱。

示例

from django.core import mail

def test_mail(mailoutbox):
    mail.send_mail('subject', 'body', 'from@example.com', ['to@example.com'])
    assert len(mailoutbox) == 1
    m = mailoutbox[0]
    assert m.subject == 'subject'
    assert m.body == 'body'
    assert m.from_email == 'from@example.com'
    assert list(m.to) == ['to@example.com']
相关问题