Necesito probar que mi aplicación Django envía correos electrónicos con el contenido correcto. No quiero depender de sistemas externos (como una cuenta de Gmail ad-hoc ), ya que no estoy probando el servicio de correo electrónico real ...
Me gustaría, tal vez, almacenar los correos electrónicos localmente, dentro de una carpeta a medida que se envían. ¿Algún consejo sobre cómo lograrlo?
Respuestas:
Puede utilizar un backend de archivos para enviar correos electrónicos, que es una solución muy útil para el desarrollo y las pruebas; los correos electrónicos no se envían, sino que se almacenan en una carpeta que puede especificar.
fuente
El marco de prueba de Django tiene algunos ayudantes integrados para ayudarlo a probar el servicio de correo electrónico .
Ejemplo de documentos (versión corta):
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')
fuente
send_mail
no se puede usar.mail
?mail.outbox
cuandosend_mail
se llama en otra función.mail.outbox[0].body
le mostrará el correo electrónico enviado incluso sisend_mail
se realiza en otro lugar.Si le gustan las pruebas unitarias, la mejor solución es usar el backend en memoria provisto por django.
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
Tome el caso de usarlo como un accesorio de py.test
@pytest.fixture(autouse=True) def email_backend_setup(self, settings): settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
En cada prueba,
mail.outbox
se reinicia con el servidor, por lo que no hay efectos secundarios entre pruebas.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
fuente
Usar MailHog
Además, tiene un componente llamado Jim , MailHog Chaos Monkey , que le permite probar el envío de correos electrónicos con varios problemas:
Lea más sobre esto aquí .
(A diferencia del mailcatcher original, que me falló al enviar correos electrónicos con emoji, codificado en UTF-8 y NO FUE realmente arreglado en la versión actual, MailHog simplemente funciona).
fuente
Para cualquier proyecto que no requiera el envío de archivos adjuntos, uso django-mailer , que tiene la ventaja de que todos los correos electrónicos salientes terminan en una cola hasta que active su envío, e incluso después de que se hayan enviado, se registran. todo lo cual es visible en el Administrador, lo que facilita la verificación rápida de lo que el código de correo electrónico está tratando de enviar a los intertubos.
fuente
Django también tiene un backend de correo electrónico en memoria. Más detalles en los documentos en Backend en memoria . Esto está presente en Django 1.6, no estoy seguro de si está presente en algo anterior.
fuente
Parchear SMTPLib con fines de prueba puede ayudar a probar el envío de correos electrónicos sin enviarlos.
fuente
Uniendo algunas de las piezas aquí juntas, aquí hay una configuración sencilla basada en
filebased.EmailBackend
. Esto genera una vista de lista que enlaza con los archivos de registro individuales, que tienen nombres de archivo convenientemente marcados con la hora. Al hacer clic en un enlace de la lista, se muestra ese mensaje en el navegador (sin formato):Configuraciones
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend" EMAIL_FILE_PATH = f"{MEDIA_ROOT}/email_out"
Ver
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})
Modelo
{% 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 %}
urls
path("mailcheck/", view=mailcheck, name="mailcheck"),
fuente
¿Por qué no iniciar su propio servidor SMTP realmente simple heredando de
smtpd.SMTPServer
ythreading.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()
Se llama a process_message cada vez que su servidor SMTP recibe una solicitud de correo, puede hacer lo que quiera allí.
En el código de prueba, haga algo como esto:
smtp_server = TestingSMTPServer() smtp_server.start() do_thing_that_would_send_a_mail() smtp_server.close() self.assertIn(b'hello', smtp_server.received_data)
Sólo recuerde que
close()
elasyncore.dispatcher
llamandosmtp_server.close()
a terminar el bucle asyncore (detener el servidor de la escucha).fuente
Si tiene un servidor TomCat disponible u otro motor de servlet, entonces un buen enfoque es "Post Hoc", que es un servidor pequeño que se ve en la aplicación exactamente como un servidor SMTP, pero incluye una interfaz de usuario que le permite ver y inspeccionar los mensajes de correo electrónico que se enviaron. Es de código abierto y está disponible gratuitamente.
Encuéntrelo en: Sitio Post Hoc GitHub
Vea la publicación del blog: PostHoc: Probar aplicaciones que envían correo electrónico
fuente