$ cat /posts/django-email-sending-smtp-configuration-and-email-templates.md

Django Email Sending: SMTP Configuration and Email Templates

drwxr-xr-x2026-01-235 min0 views
Django Email Sending: SMTP Configuration and Email Templates

Email communication enables applications to send notifications, confirmations, password resets, newsletters, and transactional messages keeping users informed and engaged. Django's email framework provides comprehensive infrastructure for sending emails through SMTP servers supporting simple text emails, HTML emails with styling, attachments, bulk mailing, and email templates. This system integrates seamlessly with Django's authentication system for password resets, user registration confirmations, and notification workflows. This comprehensive guide explores Django 6.0 email capabilities including configuring SMTP settings for Gmail, SendGrid, and custom servers, sending simple emails with send_mail function, creating HTML emails with EmailMessage class, using email templates for consistent formatting, attaching files and inline images, sending bulk emails efficiently, handling email errors and failures, implementing email backends for development and testing, and best practices for email deliverability. Mastering email sending enables building professional applications with reliable communication channels from account notifications to marketing campaigns.

SMTP Configuration

SMTP configuration establishes connection parameters for email servers including hostname, port, authentication credentials, and security settings. Django supports various email backends including SMTP for production, console for development, file-based for testing, and third-party services like SendGrid or AWS SES. Proper SMTP configuration ensures reliable email delivery while development backends facilitate testing without sending real emails.

pythonsmtp_configuration.py
# settings.py - SMTP Configuration

# Gmail SMTP settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'your-app-password'  # Use app-specific password
DEFAULT_FROM_EMAIL = '[email protected]'
SERVER_EMAIL = '[email protected]'

# SendGrid configuration
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'apikey'
EMAIL_HOST_PASSWORD = 'your-sendgrid-api-key'

# Amazon SES configuration
EMAIL_HOST = 'email-smtp.us-east-1.amazonaws.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-ses-smtp-username'
EMAIL_HOST_PASSWORD = 'your-ses-smtp-password'

# Custom SMTP server
EMAIL_HOST = 'smtp.yourserver.com'
EMAIL_PORT = 465  # SSL port
EMAIL_USE_SSL = True
EMAIL_HOST_USER = 'your-username'
EMAIL_HOST_PASSWORD = 'your-password'

# Development: Console backend (prints to console)
if DEBUG:
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

# Testing: File backend (saves to files)
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/tmp/app-emails'

# Dummy backend (discards emails)
EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'

# Email timeout settings
EMAIL_TIMEOUT = 10  # seconds

# Environment variables (recommended for production)
import os

EMAIL_HOST = os.getenv('EMAIL_HOST', 'smtp.gmail.com')
EMAIL_PORT = int(os.getenv('EMAIL_PORT', 587))
EMAIL_USE_TLS = os.getenv('EMAIL_USE_TLS', 'True') == 'True'
EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD')
DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', '[email protected]')
For Gmail, generate an app-specific password instead of using your account password. Enable 2-factor authentication first, then create an app password in your Google Account security settings.

Sending Simple Emails

Django provides send_mail function for simple email sending accepting subject, message, sender, and recipient list. For advanced features including HTML content, attachments, and custom headers, use EmailMessage class offering complete control over email construction. Both approaches handle connection management, error handling, and SMTP protocol communication automatically.

pythonsending_emails.py
# Simple email with send_mail
from django.core.mail import send_mail
from django.conf import settings

def send_welcome_email(user):
    subject = 'Welcome to Our Platform'
    message = f'Hi {user.username},\n\nThank you for registering!'
    from_email = settings.DEFAULT_FROM_EMAIL
    recipient_list = [user.email]
    
    send_mail(
        subject,
        message,
        from_email,
        recipient_list,
        fail_silently=False,  # Raise exception on error
    )

# Send multiple emails with send_mass_mail
from django.core.mail import send_mass_mail

def send_bulk_notifications(users):
    messages = []
    for user in users:
        message = (
            f'Notification for {user.username}',
            f'Hi {user.username}, you have a new notification.',
            settings.DEFAULT_FROM_EMAIL,
            [user.email]
        )
        messages.append(message)
    
    send_mass_mail(messages, fail_silently=False)

# Advanced email with EmailMessage
from django.core.mail import EmailMessage

def send_custom_email(to_email, subject, body):
    email = EmailMessage(
        subject=subject,
        body=body,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[to_email],
        bcc=['[email protected]'],  # Blind carbon copy
        reply_to=['[email protected]'],  # Reply-to address
        headers={'Message-ID': 'unique-id'},  # Custom headers
    )
    email.send()

# HTML email
def send_html_email(user):
    subject = 'Welcome'
    html_message = f'''
    <html>
      <body>
        <h1>Welcome {user.username}!</h1>
        <p>Thank you for <strong>registering</strong>.</p>
      </body>
    </html>
    '''
    plain_message = f'Welcome {user.username}! Thank you for registering.'
    
    from django.core.mail import send_mail
    send_mail(
        subject,
        plain_message,
        settings.DEFAULT_FROM_EMAIL,
        [user.email],
        html_message=html_message,
    )

# Alternative: EmailMultiAlternatives
from django.core.mail import EmailMultiAlternatives

def send_multipart_email(user):
    subject = 'Welcome'
    text_content = f'Welcome {user.username}!'
    html_content = f'<h1>Welcome {user.username}!</h1>'
    
    email = EmailMultiAlternatives(
        subject,
        text_content,
        settings.DEFAULT_FROM_EMAIL,
        [user.email]
    )
    email.attach_alternative(html_content, "text/html")
    email.send()

# Send email with error handling
import logging
logger = logging.getLogger(__name__)

def safe_send_email(subject, message, recipient):
    try:
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [recipient],
            fail_silently=False,
        )
        logger.info(f'Email sent to {recipient}')
        return True
    except Exception as e:
        logger.error(f'Failed to send email to {recipient}: {str(e)}')
        return False

Email Templates

Email templates separate content from code enabling consistent formatting, easy updates, and designer-friendly email management. Django templates work for emails supporting variables, filters, and template inheritance. Using render_to_string function renders templates to strings suitable for email bodies. Template-based emails maintain professional appearance across email clients while allowing dynamic content insertion.

pythonemail_templates.py
# Email templates
# templates/emails/welcome_email.txt
"""
Hi {{ user.username }},

Welcome to {{ site_name }}!

Your account has been created successfully.

Username: {{ user.username }}
Email: {{ user.email }}

Please verify your email by clicking the link below:
{{ verification_link }}

Best regards,
The {{ site_name }} Team
"""

# templates/emails/welcome_email.html
"""
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; }
        .header { background: #007bff; color: white; padding: 20px; text-align: center; }
        .content { padding: 20px; }
        .button { background: #28a745; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; display: inline-block; }
    </style>
</head>
<body>
    <div class="header">
        <h1>Welcome to {{ site_name }}</h1>
    </div>
    <div class="content">
        <p>Hi {{ user.username }},</p>
        <p>Your account has been created successfully!</p>
        <p><strong>Username:</strong> {{ user.username }}</p>
        <p><strong>Email:</strong> {{ user.email }}</p>
        <p>
            <a href="{{ verification_link }}" class="button">Verify Your Email</a>
        </p>
        <p>Best regards,<br>The {{ site_name }} Team</p>
    </div>
</body>
</html>
"""

# Using email templates
from django.template.loader import render_to_string
from django.core.mail import EmailMultiAlternatives
from django.conf import settings

def send_welcome_email_template(user, verification_link):
    context = {
        'user': user,
        'site_name': 'My Platform',
        'verification_link': verification_link
    }
    
    # Render templates
    text_content = render_to_string('emails/welcome_email.txt', context)
    html_content = render_to_string('emails/welcome_email.html', context)
    
    # Create email
    email = EmailMultiAlternatives(
        subject='Welcome to My Platform',
        body=text_content,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[user.email]
    )
    email.attach_alternative(html_content, "text/html")
    email.send()

# Reusable email function
def send_template_email(template_name, context, subject, to_email):
    """
    Generic function to send template-based emails
    """
    text_content = render_to_string(f'emails/{template_name}.txt', context)
    html_content = render_to_string(f'emails/{template_name}.html', context)
    
    email = EmailMultiAlternatives(
        subject=subject,
        body=text_content,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[to_email]
    )
    email.attach_alternative(html_content, "text/html")
    email.send()

# Usage
context = {'user': user, 'order_number': '12345', 'total': 99.99}
send_template_email(
    'order_confirmation',
    context,
    'Order Confirmation',
    user.email
)

# Email with inline images
from django.core.mail import EmailMessage
from django.conf import settings
import os

def send_email_with_logo(user):
    email = EmailMessage(
        'Welcome',
        '<h1>Welcome!</h1><img src="cid:logo">',
        settings.DEFAULT_FROM_EMAIL,
        [user.email]
    )
    email.content_subtype = 'html'
    
    # Attach inline image
    logo_path = os.path.join(settings.BASE_DIR, 'static/images/logo.png')
    with open(logo_path, 'rb') as f:
        email.attach('logo.png', f.read(), 'image/png')
    
    email.send()

Email Attachments

Email attachments enable sending files like PDFs, images, or documents alongside email messages. Django's EmailMessage class provides attach and attach_file methods for including file data or file paths. Attachments support various file types with automatic MIME type detection ensuring proper handling across email clients.

pythonemail_attachments.py
# Email with file attachment
from django.core.mail import EmailMessage
from django.conf import settings

def send_invoice_email(user, invoice_pdf_path):
    email = EmailMessage(
        subject='Your Invoice',
        body='Please find your invoice attached.',
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[user.email]
    )
    
    # Attach file from path
    email.attach_file(invoice_pdf_path)
    email.send()

# Attach generated content
from io import BytesIO
from reportlab.pdfgen import canvas

def send_generated_pdf(user):
    # Generate PDF in memory
    buffer = BytesIO()
    p = canvas.Canvas(buffer)
    p.drawString(100, 750, f"Report for {user.username}")
    p.showPage()
    p.save()
    
    # Create email
    email = EmailMessage(
        'Your Report',
        'Please find your report attached.',
        settings.DEFAULT_FROM_EMAIL,
        [user.email]
    )
    
    # Attach PDF from buffer
    email.attach('report.pdf', buffer.getvalue(), 'application/pdf')
    email.send()

# Multiple attachments
def send_email_with_multiple_files(user, file_paths):
    email = EmailMessage(
        'Your Documents',
        'Please find your documents attached.',
        settings.DEFAULT_FROM_EMAIL,
        [user.email]
    )
    
    for file_path in file_paths:
        email.attach_file(file_path)
    
    email.send()

# Attach Django file field
from .models import Document

def send_document_email(user, document_id):
    document = Document.objects.get(pk=document_id)
    
    email = EmailMessage(
        f'Document: {document.title}',
        f'Please find {document.title} attached.',
        settings.DEFAULT_FROM_EMAIL,
        [user.email]
    )
    
    # Attach file from model FileField
    email.attach_file(document.file.path)
    email.send()

Email Best Practices

  1. Use environment variables: Store SMTP credentials in environment variables never committing passwords to version control
  2. Provide text alternatives: Always include plain text versions of HTML emails for email clients not supporting HTML
  3. Queue emails asynchronously: Use Celery for sending emails asynchronously preventing request timeouts and improving user experience
  4. Handle failures gracefully: Implement error handling and retry logic for failed email sending attempts
  5. Use email templates: Separate email content into templates enabling consistent formatting and easy updates
  6. Test thoroughly: Use console or file backends in development testing email functionality without sending real emails

Conclusion

Django's email framework provides comprehensive infrastructure for sending emails through SMTP servers supporting various email service providers. SMTP configuration establishes connection parameters enabling email delivery through Gmail, SendGrid, AWS SES, or custom servers. Simple emails use send_mail function while EmailMessage class offers advanced features including HTML content, attachments, and custom headers. Email templates separate content from code enabling consistent professional formatting with dynamic content insertion through Django template system. Attachments support sending files alongside messages from file paths, generated content, or model FileField instances. HTML emails with inline CSS provide rich formatting while plain text alternatives ensure compatibility across email clients. Following best practices including environment variable credentials, text alternatives, asynchronous sending, error handling, template usage, and thorough testing ensures reliable email delivery. Understanding Django email capabilities enables building professional applications with robust communication channels supporting transactional emails, notifications, and marketing campaigns throughout Django 6.0 development.

$ cat /comments/ (0)

new_comment.sh

// Email hidden from public

>_

$ cat /comments/

// No comments found. Be the first!

[session] guest@{codershandbook}[timestamp] 2026

Navigation

Connect

Subscribe

// 2026 {Coders Handbook}. EOF.