python 59 lines · 1 tab

Django email with attachments and templates

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


def send_invoice_email(order):
    """Send invoice with PDF attachment."""
    subject = f'Invoice #{order.id}'

    # Render email from template
    context = {'order': order, 'site_url': settings.SITE_URL}
    html_content = render_to_string('emails/invoice.html', context)
    text_content = render_to_string('emails/invoice.txt', context)

    email = EmailMultiAlternatives(
        subject=subject,
        body=text_content,
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[order.customer.email],
        cc=['accounting@example.com'],
        bcc=['archive@example.com'],
    )

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

    # Attach PDF file
    pdf_path = f'/tmp/invoice_{order.id}.pdf'
    if os.path.exists(pdf_path):
        email.attach_file(pdf_path, mimetype='application/pdf')

    # Attach in-memory file
    csv_data = generate_csv_data(order)
    email.attach('order_items.csv', csv_data, 'text/csv')

    email.send()


def send_bulk_newsletter(subscribers, subject, template_name):
    """Send newsletter to many subscribers efficiently."""
    messages = []

    for subscriber in subscribers:
        context = {'subscriber': subscriber}
        html_content = render_to_string(f'emails/{template_name}.html', context)

        msg = EmailMultiAlternatives(
            subject=subject,
            body='Newsletter',
            from_email=settings.DEFAULT_FROM_EMAIL,
            to=[subscriber.email],
        )
        msg.attach_alternative(html_content, 'text/html')
        messages.append(msg)

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

Django's email system supports attachments and HTML templates. I use EmailMessage for full control or EmailMultiAlternatives for HTML+text versions. For attachments, I use attach_file() or attach() methods. I render email content from templates for consistency. For bulk emails, I send in batches to avoid rate limits. I use Celery for async sending. I track bounces and unsubscribes for deliverability. SMTP settings go in environment variables. This enables rich, professional emails from Django apps.


Related snips

Share this code

Here's the card — post it anywhere.

Django email with attachments and templates — share card
Link copied