Мне нужно проверить, что мое приложение 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')
источник
send_mail
нельзя использовать.mail
?mail.outbox
когдаsend_mail
вызывается из другой функции.mail.outbox[0].body
вы увидите отправленное письмо, даже еслиsend_mail
оно было выполнено в другом месте.Если вы занимаетесь модульным тестированием, лучшим решением будет использовать бэкэнд In-memory, предоставляемый 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
источник
Используйте MailHog
Кроме того, у него есть компонент под названием Jim , MailHog Chaos Monkey , который позволяет вам тестировать отправку электронных писем с различными возникающими проблемами:
Подробнее об этом читайте здесь .
(В отличие от оригинального mailcatcher, который у меня не получился при отправке писем с эмодзи, закодированными в UTF-8, и он НЕ был исправлен в текущем выпуске, MailHog просто работает.)
источник
Для любого проекта, который не требует отправки вложений, я использую django-mailer , преимущество которого заключается в том, что все исходящие электронные письма оказываются в очереди, пока я не инициирую их отправку, и даже после того, как они были отправлены, они затем регистрируются - все это видно в админке, что упрощает быструю проверку того, что вы отправляете по электронной почте, код пытается запустить в интертубах.
источник
Django также имеет серверную часть электронной почты в памяти. Более подробная информация в документации в разделе Бэкэнд In-memory . Это присутствует в Django 1.6, не уверен, что это было раньше.
источник
Исправление SMTPLib в целях тестирования может помочь проверить отправку писем без их отправки.
источник
Связывая вместе несколько частей, вот простая установка, основанная на
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 %}
URL
path("mailcheck/", view=mailcheck, name="mailcheck"),
источник
Почему бы не запустить собственный действительно простой SMTP-сервер, унаследовав от
smtpd.SMTPServer
и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()
process_message вызывается всякий раз, когда ваш SMTP-сервер получает почтовый запрос, вы можете делать там все, что хотите.
В коде тестирования сделайте что-то вроде этого:
smtp_server = TestingSMTPServer() smtp_server.start() do_thing_that_would_send_a_mail() smtp_server.close() self.assertIn(b'hello', smtp_server.received_data)
Только не забудьте по телефону , чтобы закончить цикл asyncore (остановить сервер от прослушивания).
close()
asyncore.dispatcher
smtp_server.close()
источник
Если у вас есть сервер TomCat или другой механизм сервлетов, то хорошим подходом будет «Post Hoc», который представляет собой небольшой сервер, который выглядит для приложения точно так же, как SMTP-сервер, но включает пользовательский интерфейс, который позволяет вам просматривать и проверьте отправленные сообщения электронной почты. Это открытый исходный код и бесплатный доступ.
Найти его можно на сайте: Post Hoc GitHub
См. Сообщение в блоге: PostHoc: Тестирование приложений, отправляющих электронную почту
источник