Django에서 이메일 보내기 테스트 [닫기]


90

내 Django 애플리케이션이 올바른 콘텐츠가 포함 된 이메일을 보내는 지 테스트해야합니다. 실제 이메일 서비스를 테스트하는 것이 아니기 때문에 임시 Gmail 계정 과 같은 외부 시스템에 의존하고 싶지 않습니다.

이메일을 보낼 때 폴더 안에 로컬로 저장하고 싶습니다. 그것을 달성하는 방법에 대한 팁이 있습니까?


중재자 :이 질문을 잠그십시오. 답변에 스팸이 많이 추가되어 외부 서비스를 홍보하기 위해 엄청나게 복잡한 솔루션을 제안합니다.
nemesisdesign

답변:


43

개발 및 테스트를위한 매우 편리한 솔루션 인 이메일 전송에 파일 백엔드를 사용할 수 있습니다 . 이메일은 전송되지 않지만 지정할 수있는 폴더에 저장됩니다!


1
이메일 백엔드에 대한 추가 정보 : docs.djangoproject.com/en/dev/topics/email/#email-backends . 때로는 간단한 콘솔 백엔드만으로도 충분합니다.
Jeewes

1
그러나 (자동) 테스트 중에 생성 된 이메일에 액세스 할 수있는 방법이 있습니까?
Overdrivr

182

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')

3
+1 좋은 답변입니다. 하지만 사용할 send_mail수없는 복잡한 경우에는 유용 하지 않습니다.
santiagobasulto

3
더 정확하게 문서는 여기에 있습니다. docs.djangoproject.com/en/1.8/topics/email/#in-memory-backend
nimiq

2
send_mail을 호출하고 따라서 액세스 할 수없는 함수를 테스트하는 경우 어떻게해야 mail합니까?
Matt D

3
@MatthewDrill 은 다른 함수에서 호출 mail.outbox될 때 여전히 액세스 할 수 있습니다 send_mail.
pymarco

2
@pymarco 코어에서 메일을 가져 오면 다른 곳에서 수행 mail.outbox[0].body되더라도 보낸 이메일이 표시 send_mail됩니다.
Rob

17

단위 테스트에 참여하는 경우 가장 좋은 해결책은 django에서 제공 하는 In-memory 백엔드 를 사용하는 것 입니다.

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

8

MailHog 사용

MailCatcher에서 영감을 받아 설치가 더 쉽습니다.

Go로 구축-MailHog는 여러 플랫폼에 설치하지 않고 실행됩니다.


또한 Jim , MailHog Chaos Monkey 라는 구성 요소가있어 다양한 문제가 발생하는 이메일 전송을 테스트 할 수 있습니다.

Jim은 무엇을 할 수 있습니까?

  • 연결 거부
  • 속도 제한 연결
  • 인증 거부
  • 발신자 거부
  • 수신자 거부

여기에서 자세한 내용을 읽어보십시오 .


(이모 지로 이메일을 보낼 때 실패한 원래 mailcatcher와 달리 UTF-8로 인코딩되고 현재 릴리스에서 실제로 수정되지 않았으며 MailHog는 작동합니다.)


5

첨부 파일을 보낼 필요가없는 모든 프로젝트의 경우 django-mailer를 사용 합니다. 모든 아웃 바운드 이메일이 전송을 트리거 할 때까지 대기열에 포함되고 전송 된 후에도 기록됩니다. 이 모든 것이 관리자에 표시되므로 이메일로 보내는 코드가 인터 튜브로 발사하려는 내용을 빠르게 확인할 수 있습니다.


또한 django-mailer가 생성 한 Message 객체는 단위 테스트에서도 테스트 할 수 있고 내용을 검사 할 수 있음을 의미합니다 (테스트 스위트에 더미 사서함에 대한 아웃 바운드 사서함 지원이 있다는 것을 알고 있지만 django-mailer를 사용하면 그렇지 않습니다. ) 해당 사서함 개체를 사용할 수 없습니다 의미 't 보내기 메일 관리 명령을 전송하지 않는 한,
스티브 Jalim

업데이트, 내 원래 답변에서 나이 : github.com/SmileyChris/django-mailer-2 도 첨부 파일을 지원합니다
Steve Jalim 2013 년

4

Django에는 인 메모리 이메일 백엔드도 있습니다. In-memory backend 아래의 문서에 자세한 내용이 있습니다. 이것은 Django 1.6에 존재하며 이전에 존재하는지 확실하지 않습니다.



1

여기에 몇 가지 조각을 결합하여 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"),

0

smtpd.SMTPServerand 에서 상속하여 정말 간단한 SMTP 서버를 시작하는 것은 어떨까요 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.dispatchersmtp_server.close()


0

TomCat 서버를 사용할 수 있거나 다른 서블릿 엔진이있는 경우 좋은 접근 방식은 "Post Hoc"입니다. 이것은 SMTP 서버와 똑같이 애플리케이션을 바라 보는 작은 서버입니다. 전송 된 이메일 메시지를 검사하십시오. 오픈 소스이며 자유롭게 사용할 수 있습니다.

찾기 : Post Hoc GitHub 사이트

블로그 게시물 : PostHoc : 이메일을 보내는 앱 테스트를 참조하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.