Sending Emails in Django: A Complete Guide

Last updated 1 month, 2 weeks ago | 144 views 75     5

Tags:- Python Django

Email is an essential feature in modern web applications — for account activation, password resets, notifications, contact forms, and more. Django makes it easy to send emails using its built-in EmailMessage and send_mail functionalities.

In this article, we’ll cover:

  • Django email settings

  • Sending plain text and HTML emails

  • Sending attachments

  • Using console, SMTP, and third-party email services

  • Best practices and common errors


✅ Prerequisites

Before you start:

  • Django should be installed (pip install django)

  • A Django project should be initialized (django-admin startproject)


⚙️ Step 1: Configure Email Settings in settings.py

Start by adding the following to your settings.py. These are needed for SMTP-based sending (e.g., using Gmail).

# settings.py

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'               # For Gmail
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'    # Replace with your email
EMAIL_HOST_PASSWORD = 'your_app_password'   # Use App Passwords or SMTP credentials
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

Important: If using Gmail, enable “Less secure app access” or use App Passwords with 2FA enabled.


Step 2: Send a Simple Email

Django provides the send_mail() function.

from django.core.mail import send_mail

def send_simple_email():
    send_mail(
        subject='Welcome to Django!',
        message='Thank you for joining our site.',
        from_email='[email protected]',
        recipient_list=['[email protected]'],
        fail_silently=False,
    )

✅ Run this inside a view, signal, or shell (python manage.py shell).


Step 3: Send HTML Email

To send emails with rich formatting, pass the html_message argument:

def send_html_email():
    send_mail(
        subject='Your Receipt',
        message='This is a fallback text message.',
        from_email='[email protected]',
        recipient_list=['[email protected]'],
        html_message="""
        <h1>Thank You for Your Purchase</h1>
        <p>We appreciate your business.</p>
        """,
        fail_silently=False,
    )

Step 4: Send Emails with Attachments

Use the EmailMessage class for advanced usage:

from django.core.mail import EmailMessage

def send_email_with_attachment():
    email = EmailMessage(
        subject='Invoice Attached',
        body='Please find the invoice attached.',
        from_email='[email protected]',
        to=['[email protected]'],
    )
    email.attach_file('invoices/invoice.pdf')
    email.send()

Testing Locally with the Console Backend

To avoid sending real emails during development, use the console backend.

# settings.py
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

Django will print emails to the terminal:

python manage.py runserver

Visit the page that triggers email sending, and the content will appear in the terminal.


Using the File-Based Email Backend

You can write emails to a file during testing:

EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = BASE_DIR / 'sent_emails'

Check the sent_emails/ folder to inspect the emails.


Using Third-Party Services

For production, it’s better to use services like:

Provider Notes
SendGrid Free tier, great API
Mailgun Reliable and developer-friendly
Amazon SES Cost-effective and scalable
SMTP2GO Simple SMTP configuration

You can use their SMTP credentials directly in Django or integrate via APIs using packages like django-anymail.


Full Working View Example

Here’s a view that sends an email when visited:

# views.py

from django.core.mail import send_mail
from django.http import HttpResponse

def send_email_view(request):
    send_mail(
        'Hello from Django',
        'This is a test email sent from a Django view.',
        '[email protected]',
        ['[email protected]'],
        fail_silently=False,
    )
    return HttpResponse('Email sent successfully!')
# urls.py

from django.urls import path
from .views import send_email_view

urlpatterns = [
    path('send-email/', send_email_view),
]

Visit http://localhost:8000/send-email/ to test.


⚠️ Common Errors & Fixes

Error Cause Solution
SMTPAuthenticationError Wrong password or 2FA enabled Use App Password with Gmail
ConnectionRefusedError SMTP server not reachable Check EMAIL_HOST and EMAIL_PORT
Email not sending fail_silently=True Set to False to debug
Timeout Slow or blocked connection Check firewall or try a different provider
HTML not rendering Sent as plain text Use html_message or EmailMultiAlternatives

Tips & Best Practices

  • ✅ Use get_connection() for sending multiple emails in bulk efficiently

  • ✅ Always use fail_silently=False during development

  • ✅ Store sensitive credentials in environment variables or .env files

  • ✅ Use a separate email account for app-based messaging

  • ✅ Avoid hardcoding emails — use settings.DEFAULT_FROM_EMAIL


Summary

Feature Functionality
send_mail() Simple, quick emails
EmailMessage Attachments, headers, and more
html_message Send styled content
Console backend Development email output
SMTP backend Production delivery

Bonus: Send Templated HTML Email with Context

from django.template.loader import render_to_string
from django.core.mail import EmailMessage

def send_templated_email():
    context = {'username': 'Alice'}
    html_content = render_to_string('emails/welcome.html', context)
    email = EmailMessage(
        subject='Welcome!',
        body=html_content,
        from_email='[email protected]',
        to=['[email protected]']
    )
    email.content_subtype = 'html'
    email.send()