python 47 lines · 1 tab

Django email with HTML templates

Priya Sharma Jan 2026
1 tab
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.conf import settings


def send_welcome_email(user):
    """Send welcome email with HTML template."""
    context = {
        'user': user,
        'site_url': settings.SITE_URL,
    }

    # Render both plain text and HTML
    text_content = render_to_string('emails/welcome.txt', context)
    html_content = render_to_string('emails/welcome.html', context)

    email = EmailMultiAlternatives(
        subject='Welcome to our platform!',
        body=text_content,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[user.email],
    )

    email.attach_alternative(html_content, 'text/html')
    email.send()


def send_bulk_newsletter(subscriber_list, subject, template_name, context):
    """Send newsletter to multiple subscribers efficiently."""
    html_content = render_to_string(f'emails/{template_name}.html', context)
    text_content = render_to_string(f'emails/{template_name}.txt', context)

    emails = []
    for subscriber in subscriber_list:
        email = EmailMultiAlternatives(
            subject=subject,
            body=text_content,
            from_email=settings.DEFAULT_FROM_EMAIL,
            to=[subscriber.email],
        )
        email.attach_alternative(html_content, 'text/html')
        emails.append(email)

    # Send all at once
    from django.core.mail import get_connection
    connection = get_connection()
    connection.send_messages(emails)
1 file · python Explain with highlit

I send HTML emails using Django templates for consistent branding. The EmailMultiAlternatives class supports both plain text and HTML versions. I render templates with render_to_string and context data. For transactional emails, I queue them via Celery to avoid blocking requests. I use inline CSS because many email clients strip <style> tags. Testing email templates across clients (Gmail, Outlook) is crucial. I track email opens with pixel tracking when needed. This keeps emails maintainable and reusable across the application.


Related snips

Share this code

Here's the card — post it anywhere.

Django email with HTML templates — share card
Link copied