Django Email HTML Template Fix
In this tutorial, you'll learn about Django Email HTML Template Fix. We cover key concepts, practical examples, and best practices.
The Problem
Plain text emails look unprofessional. You need HTML emails with branding, styling, and clickable buttons, but Django's send_mail sends plain text by default.
Quick Fix
Wrong — plain text only
from django.core.mail import send_mail
send_mail(
'Welcome to DodaTech',
'Hi, thanks for signing up! Click the link to activate.',
'noreply@dodatech.com',
[user.email],
)
Output: Plain text email. No branding, no links, no formatting.
Correct — HTML email with template
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
def send_welcome_email(user):
subject = 'Welcome to DodaTech'
html_content = render_to_string('emails/welcome.html', {
'username': user.username,
'activate_url': f'https://dodatech.com/activate/{user.activation_key}/',
})
text_content = f"Hi {user.username}, welcome to DodaTech!"
msg = EmailMultiAlternatives(
subject, text_content,
'noreply@dodatech.com',
[user.email],
)
msg.attach_alternative(html_content, 'text/html')
msg.send()
HTML email template
<!-- templates/emails/welcome.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: Arial, sans-serif; background: #f4f4f4; padding: 20px; }
.container { max-width: 600px; margin: 0 auto; background: white; }
.header { background: #2563eb; color: white; padding: 20px; text-align: center; }
.content { padding: 30px; }
.button { display: inline-block; padding: 12px 24px; background: #2563eb;
color: white; text-decoration: none; border-radius: 4px; }
.footer { padding: 20px; color: #666; font-size: 12px; }
</style>
</head>
<body>
<div class="container">
<div class="header"><h1>Welcome to DodaTech</h1></div>
<div class="content">
<p>Hi {{ username }},</p>
<p>Thanks for signing up! Click the button below to activate your account:</p>
<p style="text-align: center;">
<a href="{{ activate_url }}" class="button">Activate Account</a>
</p>
</div>
<div class="footer">Built by DodaTech developers</div>
</div>
</body>
</html>
Inline CSS for email clients
# Install premailer: pip install premailer
from premailer import transform
html_content = render_to_string('emails/welcome.html', context)
html_content = transform(html_content) # Inlines CSS
Batch HTML emails
def send_newsletter(users):
from django.core.mail import get_connection
connection = get_connection()
messages = []
for user in users:
html = render_to_string('emails/newsletter.html', {'user': user})
text = f"Your newsletter content here"
msg = EmailMultiAlternatives(
'Monthly Newsletter', text,
'noreply@dodatech.com', [user.email],
)
msg.attach_alternative(html, 'text/html')
messages.append(msg)
connection.send_messages(messages) # Reuses SMTP connection
Prevention
- Always include a plain text fallback for email clients that don't render HTML.
- Use inline CSS (or premailer) for email client compatibility.
- Test emails with tools like Litmus or Mailtrap before sending to real users.
Common Mistakes with email html template
- Using
headandtailinstead of pattern matching, causing runtime errors on empty lists - Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
- Using
returnto exit a function early instead of wrapping a pure value in the monad
These mistakes appear frequently in real-world DJANGO code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.