AnyMail не отправляет электронное письмо в тесте Django, несмотря на то, что mail.outbox пуст?
Я хотел бы написать модульный тест Django, который проверяет, что электронное письмо отправляется без фактической отправки (как описано в https://docs.djangoproject.com/en/2.0/topics/testing/tools/), но также может быть настроен на отправку фактического электронного письма (для проверки его форматирования и т. д.).
Прямо сейчас у меня есть "обычный" тест:
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/) может показаться, что AnyMail также перехватывает электронные письма в outbox
в тесте.
Кто-то может указать, что здесь происходит не так? Почему я не получаю электронную почту и не вижу ничего в mail.outbox
?
1 ответ
Anymail перехватывает сообщения только в папке "Исходящие", если вы используете тестовый EmailBackend:
@override_settings(EMAIL_BACKEND="anymail.backends.test.EmailBackend")
# ^^^^
class SendActivationEmailTestCase(TestCase):
...
Это не применимо в вашем случае, потому что вы используете LiveGun EmailBackend. Это действительно попытается отправить сообщение (при условии, что вы также правильно установили 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.