Тестирование отправки электронной почты в Django

Мне нужно проверить, что мое приложение Django отправляет электронные письма с правильным содержанием. Я не хочу полагаться на внешние системы (например, на специальную учетную запись gmail), так как Я не тестирую настоящую службу электронной почты...

Я хотел бы, возможно, хранить электронные письма локально, в папке, когда они отправляются. Любой совет о том, как этого добиться?


person RadiantHex    schedule 16.09.2010    source источник
comment
Модераторы: пожалуйста, заблокируйте этот вопрос. В ответы добавляется много спама, предлагающего смехотворно сложные решения только для продвижения внешних сервисов.   -  person nemesisdesign    schedule 18.02.2018


Ответы (9)


Вы можете использовать файловый сервер для отправки электронных писем, который является очень удобное решение для разработки и тестирования; электронные письма не отправляются, а сохраняются в папке, которую вы можете указать!

person Bernhard Vallant    schedule 16.09.2010
comment
Дополнительная информация о бэкэндах электронной почты: docs.djangoproject.com/en/dev /topics/email/#email-backends. Иногда достаточно даже простого консольного бэкенда. - person Jeewes; 14.05.2014
comment
Но есть ли способ получить доступ к сгенерированному электронному письму во время (автоматического) тестирования? - person Overdrivr; 03.01.2019

Платформа тестирования Django имеет несколько встроенных помощников, которые помогут вам в тестировании e -почтовый сервис.

Пример из документов (короткая версия):

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.',
            '[email protected]', ['[email protected]'],
            fail_silently=False)
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].subject, 'Subject here')
person Davor Lucic    schedule 16.09.2010
comment
+1 Хороший ответ. Но мне это бесполезно для сложных случаев, когда send_mail нельзя использовать. - person santiagobasulto; 08.02.2013
comment
Точнее документ находится здесь: docs.djangoproject.com/ ru/1.8/topics/email/#in-memory-backend - person nimiq; 30.11.2015
comment
Как бы вы это сделали, если бы вы тестировали функцию, которая вызывает send_mail, и поэтому вы не можете получить доступ к mail? - person Matt; 18.06.2017
comment
@MatthewDrill вы все еще можете получить доступ к mail.outbox, когда send_mail вызывается в другой функции. - person pymarco; 16.11.2017
comment
@pymarco Если вы импортируете почту из ядра, mail.outbox[0].body покажет вам отправленное письмо, даже если send_mail выполняется в другом месте. - person Rob; 16.11.2018
comment
Это отлично работает даже при массовой рассылке с использованием send_messages, здесь: docs .djangoproject.com/en/2.1/topics/email/ - person Manel Clos; 06.03.2019

Если вы занимаетесь модульным тестированием, лучшим решением будет использование Серверная часть в памяти, предоставленная 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.', '[email protected]', ['[email protected]'])
    assert len(mail.outbox) == 1

def test_send_again(self):
    mail.send_mail('subject', 'body.', '[email protected]', ['[email protected]'])
    assert len(mail.outbox) == 1
person kiril    schedule 25.04.2016

Для любого проекта, не требующего отправки вложений, я использую django-mailer, который имеет преимущество того, что все исходящие электронные письма попадают в очередь до тех пор, пока я не инициирую их отправку, и даже после того, как они были отправлены, они затем регистрируются — все это видно в панели администратора, что позволяет легко быстро проверить, какой код вы отправляете по электронной почте пытаясь выстрелить в межтрубки.

person Steve Jalim    schedule 16.09.2010
comment
В дополнение к этому, объекты Message, созданные django-mailer, означают, что вы также можете использовать их (и проверять их содержимое) в модульных тестах (я знаю, что в наборе тестов для фиктивного почтового ящика есть поддержка исходящих почтовых ящиков, но использование django-mailer не не отправлять почту, если ее не отправит команда управления, что означает, что вы не можете использовать этот объект почтового ящика) - person Steve Jalim; 16.09.2010
comment
Обновление, старое из моего первоначального ответа: github.com/SmileyChris/django-mailer-2 тоже поддерживает вложения - person Steve Jalim; 05.05.2013

У Django также есть встроенная в память электронная почта. Дополнительные сведения см. в документации в разделе бэкэнд в памяти. . Это присутствует в Django 1.6, не уверен, что он присутствует в чем-то более раннем.

person Josh K    schedule 26.06.2014

Исправление SMTPLib для целей тестирования может помочь протестировать отправку почты, не отправляя ее.

person pyfunc    schedule 16.09.2010

Соединив несколько частей вместе, вот простая установка, основанная на 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"),
person shacker    schedule 18.05.2019

Почему бы не создать свой собственный действительно простой 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)

Просто не забудьте close() asyncore.dispatcher, вызвав smtp_server.close(), чтобы завершить асинхронный цикл (остановить прослушивание сервером).

person frogcoder    schedule 18.09.2016

Если у вас есть доступный сервер TomCat или другой механизм сервлетов, хорошим подходом является "Post Hoc", который представляет собой небольшой сервер, который выглядит для приложения точно так же, как SMTP-сервер, но включает пользовательский интерфейс, который позволяет вам просматривать и проверить сообщения электронной почты, которые были отправлены. Он с открытым исходным кодом и находится в свободном доступе.

Найдите его по адресу: Post Hoc Site GitHub

См. сообщение в блоге: PostHoc: тестирование приложений которые отправляют электронную почту

person AgilePro    schedule 24.07.2017