Manage transactional email templates from the Django admin — editable layouts, preview, and test send without deploys.
Project description
django-simple-email
Edit your transactional email templates from the Django admin. No redeploy. No template files. Just open the admin, change the copy, and send a test to see it live.
The problem it solves
Normally, changing the text in a transactional email means editing a file, committing, pushing, and waiting for a deploy. With django-simple-email, templates live in the database. Anyone with admin access can edit them, and a Preview + Send test button lets you confirm the result before it ever reaches a real user.
Install
pip install django-simple-email
Add to INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"django_simple_email",
]
Run migrations:
python manage.py migrate
That's it.
Core concepts
EmailLayout
A layout is a reusable envelope: a header and a footer that wrap the content of multiple templates. Define your brand header once — logo, colors, top bar — and reuse it across every email.
Layouts are optional. A template without a layout renders its body directly.
EmailTemplate
A template is the email itself: subject, HTML body, and an optional plain-text fallback. Both subject and html_body support Django template syntax, so you can use {{ variable }}, {% if %}, {% for %}, and everything else Django templates offer.
Each template stores a sample_context — a JSON object with example values. This is what Preview and Send test use, so you always have realistic data to work with.
Getting started
Step 1 — Create a layout
A layout wraps templates with a shared header and footer. It is optional — templates without a layout render their body directly.
Via the admin
Go to Email Layouts → Add. Write your header and footer as plain HTML. Both fields support Django template syntax.
<!-- header_html -->
<table width="600" style="margin:0 auto;font-family:Arial,sans-serif;">
<tr><td style="background:#1a1a2e;padding:24px;color:#fff;">
<strong>{{ company_name }}</strong>
</td></tr>
<tr><td style="padding:32px;">
<!-- footer_html -->
</td></tr>
<tr><td style="background:#f4f4f4;padding:16px;text-align:center;font-size:12px;color:#aaa;">
© {{ company_name }}
</td></tr>
</table>
Or using fixture
[
{
"model": "django_simple_email.emaillayout",
"pk": 1,
"fields": {
"name": "default",
"header_html": "<table width=\"600\" style=\"margin:0 auto\"><tr><td style=\"background:#1a1a2e;padding:24px;color:#fff\"><strong>{{ company_name }}</strong></td></tr><tr><td style=\"padding:32px\">",
"footer_html": "</td></tr><tr><td style=\"padding:16px;text-align:center;font-size:12px;color:#aaa\">© {{ company_name }}</td></tr></table>"
}
}
]
Step 2 — Create a template
Via the admin
Go to Email Templates → Add. The key fields:
| Field | Description |
|---|---|
| Name | Slug used in your code — e.g. welcome, password-reset |
| Subject default | Email subject. Supports {{ variables }} |
| HTML body | Email body. Supports full Django template syntax |
| Text body | Plain-text fallback (optional but recommended) |
| Layout | Layout to wrap this template (optional) |
| Sample context | JSON with example values — used by Preview and Send test |
Example sample context:
{
"name": "Ana Silva",
"company_name": "My App",
"cta_url": "https://example.com/dashboard"
}
Via fixture
[
{
"model": "django_simple_email.emailtemplate",
"pk": 1,
"fields": {
"name": "welcome",
"description": "Sent when a new user signs up",
"subject_default": "Welcome to {{ company_name }}, {{ name }}!",
"html_body": "<p>Hi <strong>{{ name }}</strong>, your account is ready.</p><p><a href=\"{{ cta_url }}\">Get started</a></p>",
"text_body": "Hi {{ name }},\n\nYour account is ready.\n\nGet started: {{ cta_url }}",
"layout": 1,
"sample_context": {
"name": "Ana Silva",
"company_name": "My App",
"cta_url": "https://example.com/dashboard"
}
}
}
]
Load it with:
python manage.py loaddata your_fixture.json
Step 3 — Send from your code
Call send_template_mail anywhere in your Django project — views, signals, Celery tasks, management commands:
from django_simple_email.sending import send_template_mail
send_template_mail(
template_name="welcome",
recipient_list=[user.email],
context={
"name": user.get_full_name(),
"company_name": "My App",
"cta_url": request.build_absolute_uri("/dashboard/"),
},
)
The context you pass is merged on top of the template's sample_context — you only need to pass the values that change per call.
Override the subject at call time
send_template_mail(
template_name="notification",
recipient_list=[user.email],
context={"message": "Your export is ready."},
subject="[Action required] Your export is ready",
)
Use a custom sender
send_template_mail(
template_name="welcome",
recipient_list=[user.email],
context={...},
from_email="onboarding@myapp.com",
)
Or call directly on a template instance
from django_simple_email.models import EmailTemplate
template = EmailTemplate.objects.get(name="welcome")
template.send_email(recipient_list=[user.email], context={"name": user.get_full_name()})
send_template_mail uses whatever EMAIL_BACKEND you have configured — no lock-in. It integrates natively with django-anymail: just install anymail, set your EMAIL_BACKEND, and emails will go through your chosen ESP (Mailgun, SendGrid, Postmark, Amazon SES, etc.) with no extra configuration.
Admin features
Templates list
The templates list shows a Preview HTML link and a Send test button per row, so you can check any template without opening it.
Change page
When editing a template, the Metadata section at the bottom has:
- Preview HTML — opens the fully rendered email (layout + body) in a new tab
- Send test — renders and sends the email to
DJANGO_SIMPLE_EMAIL_TEST_RECIPIENTimmediately, showing a success or error message inline
Settings
| Setting | Default | Description |
|---|---|---|
DJANGO_SIMPLE_EMAIL_TEST_RECIPIENT |
"test@test.com" |
Address used by the admin test-send button |
# settings.py
DJANGO_SIMPLE_EMAIL_TEST_RECIPIENT = "you@yourcompany.com"
Local development
Requirements
First-time setup
git clone https://github.com/GustavoRizzo/django-simple-email.git
cd django-simple-email
poetry install
poetry run task setup # migrate + create superuser
poetry run task load-fixtures # load sample layouts and templates
Running
poetry run task mailpit # Mailpit SMTP on :1025, web UI on :8025
poetry run task run-demo # Django on localhost:8000
Go to localhost:8000/admin and log in with the superuser you created.
The fixtures include a default layout and three templates (welcome, password-reset, notification), plus seasonal layout variants (Halloween, Christmas, New Year) with matching template variations — enough to explore the preview and test-send features right away.
Tests and linting
poetry run task test
poetry run task lint
poetry run task lint-fix
Releasing
poetry version patch # 0.1.0 → 0.1.1
poetry build
poetry publish
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_simple_email-0.1.2.tar.gz.
File metadata
- Download URL: django_simple_email-0.1.2.tar.gz
- Upload date:
- Size: 11.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.14.0 Linux/6.6.87.2-microsoft-standard-WSL2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5335240d7e9938ba5f3a73dad59a42219658f33c88c0d0f3bc2c75b78dbcc31c
|
|
| MD5 |
80d72993c597890c5f57b154a1386d5b
|
|
| BLAKE2b-256 |
8ffb0972821e0614e36b99b0cd349edac80faf59c14dad8dd49e4543cec10133
|
File details
Details for the file django_simple_email-0.1.2-py3-none-any.whl.
File metadata
- Download URL: django_simple_email-0.1.2-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.14.0 Linux/6.6.87.2-microsoft-standard-WSL2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79d9986de9b104d5c3b0433f909f0f26e15d2f453858384eefa4b33253c086dd
|
|
| MD5 |
5042320bb1f0064777dbc642f8389397
|
|
| BLAKE2b-256 |
33beb3874fc2a79ee7c14017e53840058e4274c7ab6649458e8088a69113d1f2
|