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?
The preferred way to write tests in Django is using the unittest module built-in to the Python standard library. This is covered in detail in the Writing and running tests document. You can also use any other Python test framework; Django provides an API and tools for that kind of integration.
Django's unit tests use a Python standard library module: unittest . This module defines tests using a class-based approach. When you run your tests, the default behavior of the test utility is to find all the test cases (that is, subclasses of unittest.
Testing is vital. Without properly testing your code, you will never know if the code works as it should, now or in the future when the codebase changes.
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):
...
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With