Welcome to part 7 - the last in the series on how we dockerise Django projects at Webinative.
In this article, we will focus on handling emails in the development environment. As web application developers, we engineer apps that rely on emails for signing up, logging in, and sending OTPs, notifications and reminders.
Some teams use their SMTP provider (like SendGrid and MailJet) to test their emails. However, this approach is risky as someone might accidentally send test emails to actual customers.
We looked for solutions that separate development, testing and production environments without code changes. And we found Mailhog – a simple SMTP server that integrates with any Django app with mere configuration changes.
Let's dive in.
Let's define a new Mailhog service below the dockerise-django
section in the docker-compose.yml
file.
version: '3'
services:
dockerise-postgres:
# ...
dockerise-django:
# ...
dockerise-mailhog:
image: mailhog/mailhog
container_name: dockerise-mailhog
logging:
driver: 'none' # disable saving logs
ports:
- 8025:8025 # web ui
expose:
- 1025
volumes:
# ...
mailhog/mailhog
docker image.Let's define the basic settings required to interface with any SMTP server in our project's settings.py
file.
# Email settings
DEFAULT_FROM_EMAIL = os.getenv("DJANGO_DEFAULT_FROM_EMAIL", "webmaster@localhost")
EMAIL_HOST = os.getenv("DJANGO_EMAIL_HOST")
EMAIL_HOST_PASSWORD = os.getenv("DJANGO_EMAIL_HOST_PASSWORD")
EMAIL_HOST_USER = os.getenv("DJANGO_EMAIL_HOST_USER")
EMAIL_PORT = os.getenv("DJANGO_EMAIL_PORT")
EMAIL_USE_TLS = os.getenv("DJANGO_EMAIL_USE_TLS")
Next, add these ENV variables in the dockerise-django.env
file,
# DJANGO_DEFAULT_FROM_EMAIL=
DJANGO_EMAIL_HOST=dockerise-mailhog
# DJANGO_EMAIL_HOST_PASSWORD=
# DJANGO_EMAIL_HOST_USER=
DJANGO_EMAIL_PORT=1025
# DJANGO_EMAIL_USE_TLS=
Note: Mailhog, by default, does NOT require a username, password or TLS setting.
Let's provision the mailhog container by running,
docker-compose up -d
# verify the status of dockerise-mailhog service to be "running"
docker-compose ps
Access the Django shell using the command,
docker-compose exec dockerise-django ./manage.py shell
Once inside the Django shell, send a test email,
from django.core.mail import send_mail
send_mail('Test mail', 'Mail message goes here', None, ['[email protected]'])
Go to http://localhost:8025/ in your browser, and you should see the test mail we just sent.
Did you know?
You can configure Django to send you emails about unhandled exceptions (those resulting in HTTP 500 errors) with a complete stack trace. This error reporting is helpful in LIVE (or production) environments with DEBUG
set to False
.
Add these additional settings to your project.
# Error reporting through email
ADMINS = [
("Webservices", "[email protected]"),
]
SERVER_EMAIL = os.getenv("DJANGO_SERVER_EMAIL", "root@localhost")
ADMINS
- email addresses to whom the errors should be reported (TO addresses).SERVER_EMAIL
- email address of the server reporting the error (FROM address).Let us modify our view to raise an exception intentionally,
# core/views.py
def home(request):
if request.GET.get('trigger_500'):
1000 / 0 # raise an exception to test error-reporting
return render(request, "core/home.html")
Django reports errors through email only from environments with DEBUG
set to False
. Remove or comment the "DJANGO_DEBUG=True
" line in the dockerise-django.env
file.
Recreate the containers,
docker-compose up -d
Visit http://localhost:8000/?trigger_500=true. You should see a blank 500 error page, as shown below.
Switch to the Mailhog tab and refresh. You should see the error email.
Here we are at the end of this seven-part series.
In this article, we set up a mailhog SMTP service (container) and sent an email from Django programmatically. We also configured our Django app to send emails from production servers in case of 500 errors.
All changes described in this article have been committed to the GitHub branch "part_07/mailhog
" of this repository.
Like this article? Have a comment to share or a question to raise? Join our Discord server.