测试不使用电子邮件服务器发送电子邮件

我有一个 Django 应用程序可以发送电子邮件。生产服务器有一个电子邮件服务器,但我的本地盒子没有。我希望能够测试发送电子邮件本地。有没有什么办法可以让 django 不通过电子邮件服务器发送它,而只是打印到一个文件或控制台?

52701 次浏览

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

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.

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.

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='me@example.com')
self.assertEqual(len(mail.outbox), 1)
self.assertEqual(mail.outbox[0].to, ['me@example.com'])
...#etc

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

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 = 'your_email@example.com'

On top of your email setttings..All emails will be diverted to 'your_email@example.com'

Happy coding...

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.', 'messanger@localhost.com',['any@email.com'], 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.