AnyMail не отправляет электронное письмо в тесте Django, несмотря на то, что mail.outbox пуст? - PullRequest
0 голосов
/ 07 июня 2018

Я хотел бы написать модульный тест Django, который проверяет, что электронное письмо отправляется без фактической отправки (как описано в https://docs.djangoproject.com/en/2.0/topics/testing/tools/#email-services),), но также может быть настроено на отправку действительного электронного письма (для проверки его форматирования,и т. д.).

Прямо сейчас у меня есть «обычный» тест:

from django.test import TestCase, override_settings
from django.core import mail
from lucy_web.test_factories import FamilyFactory, UserFactory
from lucy_web.views.app_invite import send_activation_email


# @override_settings(EMAIL_BACKEND="anymail.backends.mailgun.EmailBackend")
class SendActivationEmailTestCase(TestCase):
    def test_send_activation_email(self):
        user = UserFactory(email='kurt@startwithlucy.com')
        family = FamilyFactory(employee_user=user)
        send_activation_email(user=user)

        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].recipients(), [user.email])
        self.assertIn(
            f"Your activation code is {family.activation_code}.",
            mail.outbox[0].body)

(В тесте используются factory_boy испытательные приборы для некоторыхмодели). Этот тест проходит успешно, но если я прокомментирую в декораторе override_settings, я получу сообщение об ошибке:

(venv) Kurts-MacBook-Pro-2:lucy-web kurtpeek$ python manage.py test lucy_web.tests.test_app_invite
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test_send_activation_email (lucy_web.tests.test_app_invite.SendActivationEmailTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/kurtpeek/Documents/Dev/lucy2/lucy-web/lucy_web/tests/test_app_invite.py", line 15, in test_send_activation_email
    self.assertEqual(len(mail.outbox), 1)
AssertionError: 0 != 1

----------------------------------------------------------------------
Ran 1 test in 0.787s

FAILED (failures=1)
Destroying test database for alias 'default'...

Поскольку mail.outbox пусто, я ожидаю, что получу реальное письмо, но я проверил свою входящую почту и ничего не получил.

Ради полноты, вот функция, которую я тестирую:

from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string


def send_activation_email(user):
    context = {
        'activation_code': user.family.activation_code,
        'page_title': 'Lucy Invitation',
        'company': user.family.package.company,
        'num_sessions': user.family.session_count,
        'domain': settings.EMAIL_IMAGE_DOMAIN}

    message_text = render_to_string('email/activation_code.txt', context)
    message_html = render_to_string('email/activation_code.html', context)

    email = EmailMultiAlternatives(
        subject='LUCY Invitation',
        body=message_text,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[user.email],
        reply_to=[settings.SUPPORT_EMAIL])
    email.attach_alternative(message_html, "text/html")
    email.send()

Чтобы увеличить путаницу, изДокументы AnyMail (http://anymail.readthedocs.io/en/stable/tips/test_backend/#testing-your-app), может показаться, что AnyMail также записывает электронные письма в outbox в тесте.

Может кто-то указать, что здесь происходит не так? Почему я тоже не получаю письмои ничего не видя в mail.outbox?

1 Ответ

0 голосов
/ 07 июня 2018

Anymail захватывает сообщения в исходящих, только если вы используете тест EmailBackend :

@override_settings(EMAIL_BACKEND="anymail.backends.test.EmailBackend")
#                                                  ^^^^
class SendActivationEmailTestCase(TestCase):
    ...

Это не относится к вашему случаю, потому что вы используете живой MailgunEmailBackend.Это действительно попытается отправить сообщение (при условии, что вы также правильно установили MAILGUN_API_KEY - и поскольку email.send() не выдало ошибку, вы, вероятно, делаете это).

Итак, вам нужно выяснить, почемукажется, что почта отправлена, но вы, похоже, не получаете ее.Лучшее место для начала диагностики любой проблемы с отправкой электронной почты - это журналы Mailgun: https://app.mailgun.com/app/logs/. (Обязательно выберите правильный домен для отправки из меню слева.)

  • Есливы видите событие Accepted and Delivered для вашего тестового сообщения, проблема в принимающей стороне.(Проверьте папку со спамом.)

  • Если вы видите события Accepted, Rejected или Fail, проблема заключается в Mailgun: Anymail удается отправить вашу электронную почту в Mailgun, но Mailgun отказываетсяили не в состоянии доставить его.Проверьте журнал событий для объяснения.(Письмо from_email, которое не соответствует проверенному домену отправителя, является вероятной причиной.)

  • Если вы даже не видите событие Accepted в логах Mailgun, то проблема в Python-сторона: сообщение даже не попадает в Mailgun.Вы можете узнать больше, проверив anymail_status , который Anymail прикрепляет к письму при его отправке:

    def send_activation_email(user):
        # ...
        email.send()
        print(email.anymail_status.status)  # should be {'queued'}
        print(email.anymail_status.esp_response.content)  # raw Mailgun API response
    

Если ничего из этого не показываетисточник проблемы, обновите ваш вопрос, включив в него необработанный ответ API Mailgun и любые соответствующие события из журналов Mailgun.

...