Reputation: 1004
I have an app that imports a number of user email addresses and creates accounts for them. To have them set their own password, I tried to use django's PasswordResetForm (in django.contrib.auth.forms). The password reset is called as soon as a user account has been created:
def reset_password(person):
form = PasswordResetForm({'email': person.email})
if form.is_valid():
form.save(from_email='[email protected]')
I haven't gotten any further with testing than including a unit test that does this:
import password_reset_module
class TestPasswordReset(TestCase):
def setUp(self):
p = Person(email='[email protected]')
def test_send(self):
password_reset_module.reset_password(p)
No assertions, right now I just want to see if there is mail sent at all by monitoring the console in which I run:
python -m smtpd -n -c DebuggingServer localhost:1025
Saving the form calls django's send_mail. When running the testcase, the send_mail method returns 1. However, no mails show up in the console. The strange thing is that calling send_mail from django's interactive shell:
python manage.py shell
works fine. Mail shows up in the console. Clicking the forgot my password link in a browser also result in sent mails.
I have also tried the file based email backend to no avail. Current settings.py email settings:
EMAIL_USE_TLS = False
EMAIL_HOST = 'localhost'
DEFAULT_FROM_EMAIL = '[email protected]'
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_PORT = 1025
Now wondering if I am missing something when calling the password reset, or is there a mailserver configuration issue at hands?
Upvotes: 7
Views: 3743
Reputation: 27855
You can use the mailoutbox fixture of pytest-django:
A clean email outbox to which Django-generated emails are sent.
Example
from django.core import mail
def test_mail(mailoutbox):
mail.send_mail('subject', 'body', '[email protected]', ['[email protected]'])
assert len(mailoutbox) == 1
m = mailoutbox[0]
assert m.subject == 'subject'
assert m.body == 'body'
assert m.from_email == '[email protected]'
assert list(m.to) == ['[email protected]']
Upvotes: 1
Reputation: 39336
In Section "Email Services", the Django testing documentation says:
Django's test runner automatically redirects all Django-sent email to a dummy outbox. [...] During test running, each outgoing email is saved in
django.core.mail.outbox
. This is a simple list of allEmailMessage
instances that have been sent.
Huh?
The Django test runner will actually configure a different email backend for you (called locmem). It is very convenient if you want to do unit-testing only (without integration with an actual email server), but very surprising if you don't know it.
(I am not using the Django test runner manage.py test
,
but it happens anyway, presumably because I have
pytest-django
installed which magically modifies my py.test
.)
If you want to override the overriding and use the email configuration
given in your settings
module, all you need to re-set is the
setting for the email backend, e.g. like this:
@django.test.utils.override_settings(
EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend')
def test_send_email_with_real_SMTP(self):
...
Upvotes: 17
Reputation: 3665
It is probably worthwhile trying to turn this into a proper unit test, which of course you can then run as part of your automated test suite. For unit testing, probably the easiest way to check whether the mail was sent (and verify the contents of the mail if required) is to use Django's built-in in memory email backend - you can simply use the outbox attribute on this to get a list of sent mails:
https://docs.djangoproject.com/en/dev/topics/email/#in-memory-backend
This has the advantage of not requiring any infrastructure setup to support testing email sending, makes it very simple to assert the contents of your email, and this should also make the tests fast (when compared to actually sending the emails to an SMTP server).
Hope this helps.
Upvotes: 4
Reputation: 34493
From what I understand, you are running the following command while testing the unit.
python -m smtpd -n -c DebuggingServer localhost:1025
This command starts up a "dumb" SMTP server that recieves your emails and displays them on the terminal. Try running your site without this DebuggingServer set up and see if the mails are sent.
Here is the reference to the docs page
Upvotes: 3