问题
Any tips on testing email sending? Other than maybe creating a gmail account, especially for receiving those emails?
I would like to, maybe, store the emails locally, within a folder as they are sent.
回答1:
You can use a file backend for sending emails which is a very handy solution for development and testing; emails are not sent but stored in a folder you can specify!
回答2:
Django test framework has some built in helpers to aid you with testing e-mail service.
Example from docs (short version):
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:
If you are into unit-testing the best solution is to use the In-memory backend provided by django.
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
Take the case of use it as a py.test fixture
@pytest.fixture(autouse=True)
def email_backend_setup(self, settings):
settings.EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
In each test, the mail.outbox
is reset with the server, so there are no side effects between tests.
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
回答4:
Use MailHog
Inspired by MailCatcher, easier to install.
Built with Go - MailHog runs without installation on multiple platforms.
Also, it has a component called Jim, the MailHog Chaos Monkey, which enables you to test sending emails with various problems happening:
What can Jim do?
- Reject connections
- Rate limit connections
- Reject authentication
- Reject senders
- Reject recipients
Read more about it here.
(Unlike original mailcatcher, which failed on me when sending emails with emoji, encoded in UTF-8 and it WASN'T really fixed in the current release, MailHog just works.)
回答5:
For any project that doesn't require sending attachments, I use django-mailer, which has the benefit of all outbound emails ending up in a queue until I trigger their sending, and even after they've been sent, they are then logged - all of which is visible in the Admin, making it easy to quickly check what you emailing code is trying to fire off into the intertubes.
回答6:
Django also has an in-memory email backend. More details in the docs under In-memory backend. This is present in Django 1.6 not sure if it's present in anything earlier.
回答7:
Patching SMTPLib for testing purposes can help test sending mails without sending them.
- http://www.psychicorigami.com/2007/09/20/monkey-patching-pythons-smtp-lib-for-unit-testing/
回答8:
Using the file backend works well, but I find it a little a cumbersome to poke around the filesystem to look at emails. You could use mailcatcher, https://github.com/sj26/mailcatcher, to capture emails and display them in a web UI.
To use mailcatcher with Django you'll need to add something like the following to your settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = '127.0.0.1'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_PORT = 1025
EMAIL_USE_TLS = False
回答9:
Why not start your own really simple SMTP Server by inherit from smtpd.SMTPServer and 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 is called whenever your SMTP Server receive a mail request, you can do whatever you want there.
In the testing code, do something like this:
smtp_server = TestingSMTPServer()
smtp_server.start()
do_thing_that_would_send_a_mail()
smtp_server.close()
self.assertIn(b'hello', smtp_server.received_data)
Just remember to close() the asyncore.dispatcher by calling smtp_server.close()
to end the asyncore loop(stop the server from listening).
回答10:
If you have a TomCat server available, or other servlet engine, then a nice approach is "Post Hoc" which is a small server that looks to the application exactly like a SMTP server, but it includes a user interface that allows you to view and inspect the email messages that were sent. It is open source and freely available.
Find it at: Post Hoc GitHub Site
See the blog post: PostHoc: Testing Apps that Send Email
回答11:
https://websocket.email provides a simple way to test email sending with minimal setup (you don't even need an account).
回答12:
Tying a few of the pieces here together, here's a straightforward setup based on filebased.EmailBackend
. This renders a list view linking to the individual log files, which have conveniently timestamped filenames. Clicking a link in the list displays that message in the browser (raw):
Settings
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
EMAIL_FILE_PATH = f"{MEDIA_ROOT}/email_out"
View
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})
Template
{% 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"),
回答13:
Use Maildump.
https://github.com/ThiefMaster/maildump
MailDump is a python-based clone of the awesome MailCatcher tool. Its purpose is to provide developers a way to let applications send emails without actual emails being sent to anyone. Additionally lazy developers might prefer this over a real SMTP server simply for the sake of it being much easier and faster to set up.
However it requires Python 2.
回答14:
My solution is write content to a html file. This way can help you see how email look like. I leave it here htmlfilebased.EmailBackend.
Other tip: You can use django email template editor which can help you edit your email template with zero inline css.
来源:https://stackoverflow.com/questions/3728528/testing-email-sending