asawilliams
asawilliams

Reputation: 2938

Test sending email without email server

I have a Django application that sends an email. The production server has an email server but my local box does not. I would like to be able to test sending of email locally. Is there any way that I can have django not send it through the email server and just print out to a file or console?

Upvotes: 78

Views: 55104

Answers (6)

radtek
radtek

Reputation: 36300

This elaborates on the answer from Benjamin. One way that I test emails if I don't have a local email server like postfix, sendmail or exim installed is to run the python email server. You can run it on port 25 with sudo, or just use a port > 1024 (reserved ports):

python -m smtpd -n -c DebuggingServer localhost:1025
#sudo python -m smtpd -n -c DebuggingServer localhost:25

For testing with your current django app code, you can change settings.py temporarily to include this at the botom:

EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD = 'localhost', 1025, None, None

Now test out your emails, or you can do this in ./manage.py shell in another terminal window like so:

python manage.py shell

And paste in this code to send an email:

from django.core.mail import send_mail​
send_mail('Subject here', 'Here is the message.', '[email protected]',['[email protected]'], fail_silently=False)

No need to use any real emails since you will see everything in your terminal. You can dump it to the appropriate container like .html for further testing.

Upvotes: 13

Njogu Mbau
Njogu Mbau

Reputation: 446

There is a cool app for this by caktus https://github.com/caktus/django-email-bandit Just add this to your settings.py file:

EMAIL_BACKEND = 'bandit.backends.smtp.HijackSMTPBackend'
BANDIT_EMAIL = '[email protected]'

On top of your email setttings..All emails will be diverted to '[email protected]'

Happy coding...

Upvotes: 11

Benjamin Wohlwend
Benjamin Wohlwend

Reputation: 31838

Python has a little SMTP server built-in. You can start it in a second console with this command:

python -m smtpd -n -c DebuggingServer localhost:1025

This will simply print all the mails sent to localhost:1025 in the console.

You have to configure Django to use this server in your settings.py:

EMAIL_HOST = 'localhost'
EMAIL_PORT = 1025

Upvotes: 85

Julien Grenier
Julien Grenier

Reputation: 3394

If your tests extends from django.test.testcases.TestCase then nothing has to be done. Django will replace the EmailBackend to a "special" one. Then you can test what would had been sent like this :

def testMethodThatSendAEmail(self):
    ...
    from django.core import mail
    object.method_that_send_email(to='[email protected]')
    self.assertEqual(len(mail.outbox), 1)
    self.assertEqual(mail.outbox[0].to, ['[email protected]'])
    ...#etc

The outbox object is a special object that get injected into mail when python manage.py test is run.

Upvotes: 35

Matthew Schinckel
Matthew Schinckel

Reputation: 35629

You can configure your application to write emails out to temporary files instead of sending them (similar to Daniel Hepper's answer).

EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = 'tmp/email-messages/'

This saves each new message as a separate file. Useful if you are sending heaps of emails, and don't want to have to use the scrollback.

Upvotes: 42

Daniel Hepper
Daniel Hepper

Reputation: 29967

You can configure your application to use the Console Backend for sending e-mail. It writes e-mails to standard out instead of sending them.

Change your settings.py to include this line:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Don't forget to remove it for production.

Upvotes: 143

Related Questions