Models reference

May 27, 2026 · View on GitHub

This page enumerates every database-backed class shipped by dbmail, along with field types, semantics, and cross-references. For conceptual deep-dives see the architecture explanations (Track 4 in the docs roadmap).

Templates

MailCategory

Optional grouping label for MailTemplate. No behaviour, only admin filtering.

FieldTypeNotes
nameCharField(50)Unique within installation.
created, updatedauto timestamps

MailFromEmail

A reusable From: identity. Linked to MailTemplate.from_email.

FieldTypeNotes
nameCharField(100)Sender display name.
emailEmailFieldSender address.
credentialFK(MailFromEmailCredential, null)Optional SMTP credential.

If credential is set, the Sender opens a per-template SMTP connection using those settings instead of project-level EMAIL_HOST*. Useful for multi-tenant setups where different templates send via different mailboxes.

MailFromEmailCredential

SMTP credential. Stored as plaintext at rest — encrypted column lands in 3.1. See security model.

FieldTypeNotes
hostCharField(50)e.g. smtp.gmail.com
portPositiveIntegerField25 / 465 / 587
usernameCharField(50)optional
passwordCharField(128)optional, rendered via PasswordInput in admin
use_tlsBooleanField
fail_silentlyBooleanField

Admin restricted to superusers — staff cannot view or edit.

MailBcc

Global BCC list. Every send copies these addresses. Per-template BCC is on MailTemplate.bcc_email instead.

FieldTypeNotes
emailEmailFieldunique
is_activeBooleanField

MailBaseTemplate

Optional wrapper used by MailTemplate.base to share common HTML/header/footer across templates. The base body is concatenated with the per-template body before render.

FieldTypeNotes
nameCharField(50)unique
messageHTMLFieldDjango template, must contain {{content}} for the inner body. Superuser-only edit (SSTI surface).

MailTemplate

The central table. Every send dispatches against a MailTemplate.slug.

FieldTypeNotes
nameCharField(100)Display name.
subjectCharField(255)Django template, rendered against context. Superuser-only edit.
messageHTMLFieldBody. Same.
slugSlugField, uniquePublic identifier passed to send_db_mail("slug", ...).
categoryFK(MailCategory, null)
from_emailFK(MailFromEmail, null)Optional override of DEFAULT_FROM_EMAIL.
baseFK(MailBaseTemplate, null)Optional wrapper.
bcc_emailM2M(MailBcc)Per-template BCC.
intervalPositiveIntegerField, default 60Seconds before retry on failure (Celery default_retry_delay).
priorityIntegerField, choices=PRIORITY_STEPSHigh / Medium / Low / Deferred.
enable_logBooleanField, default TrueIf False, only failed sends are logged.
is_htmlBooleanField, default FalseDrives plain vs alternative MIME.
is_adminBooleanField, default FalseHide from regular send_db_mail callers; admin-only template.
is_activeBooleanField, default TrueIf False, send_db_mail returns None silently.
num_of_retriesPositiveIntegerField, default 1Sync-mode retry attempts.
created, updatedauto

Cache: per-slug, no TTL — invalidated by _clean_cache on save.

Logs / observability

MailLog

One row per send attempt (success or failure, depending on enable_log).

FieldTypeNotes
templateFK(MailTemplate)
is_sentBooleanField, db_indexTrue / False per attempt.
error_messageTextFieldTruncated traceback.
error_exceptionFK(MailLogException, null)Classification.
num_of_retriesPositiveIntegerField
log_idCharField(50), db_indexUUID-shaped per send (used by tracking pixel).
backendCharField, db_indexmail / sms / tts / push / bot.
providerCharField, db_indexIf a custom provider was used.
userFK(USER, null)If user= kwarg was passed (and stayed JSON-clean).
correlation_idCharField(64), db_index, nullOptional business key (order ID, request ID, OpenTelemetry trace ID). Pass as correlation_id= kwarg to any send_db_* function or as a POST field to /dbmail/api/.
createdauto

Indexes: MailLog(created), MailLog(template, is_sent) for operational queries.

MailLogEmail

Per-recipient row for each MailLog. One log → many emails (to / cc / bcc).

FieldTypeNotes
logFK(MailLog)cascade
emailCharFieldrecipient address
mail_typeCharField, choices=to/cc/bcc

MailLogTrack

Open-rate / read-receipt enrichment. Created when a recipient hits the tracking pixel URL.

FieldTypeNotes
mail_logFK(MailLog)cascade
counterPositiveIntegerFieldopen count
is_readBooleanField
ipGenericIPAddressFieldresolved via django-ipware
user_agentCharField
os, os_version, dist_name, dist_versionCharFieldpopulated by httpagentparser if installed
browser, browser_versionCharField
country_name, country_code, country_code3CharFieldpopulated by geoip2 if installed
city, region, postal_codeCharField
latitude, longitudeFloatField
area_code, dma_codeIntegerField
created, updatedauto

Indexes: MailLogTrack(mail_log, ip).

MailLogException

Classifier for repeated send failures. The admin lists all unique exception class names ever logged; flagging one as ignore=True makes the Sender suppress retries for that exception class.

FieldTypeNotes
nameCharField, uniquee.g. SMTPRecipientsRefused
ignoreBooleanField

Signals (DB-driven)

Signal

Connect a Django dispatch.Signal (post_save, pre_save, …) to a MailTemplate. Edited only by superusers (SSTI surface — rules is a template expression).

FieldTypeNotes
nameCharField(100)display
modelFK(ContentType)the model whose lifecycle fires the signal
signalCharField, choicespre_save, post_save, pre_delete, post_delete, m2m_changed
templateFK(MailTemplate)what to send
groupFK(MailGroup, null)optional BCC list
rulesTextFieldDjango template expression — must render to "True" for the send to fire
intervalPositiveIntegerField, default 0If > 0, dispatch is deferred (SignalDeferredDispatch).
receive_onceBooleanFieldIf True, dispatched at most once per (model, instance.pk).
update_modelBooleanFieldIf True, stamps mail_sent field on the instance after success.
is_activeBooleanField

SignalLog

Tracks (model, model_pk, signal) triples already fired (for receive_once enforcement).

SignalDeferredDispatch

Queue row for non-zero Signal.interval. The send_dbmail_deferred_signal management command drains rows whose eta <= now().

FieldTypeNotes
args, kwargs, paramsBinaryFieldlegacy pickle blobs (kept until 4.0 — opt-in via DB_MAILER_ALLOW_PICKLE_LEGACY)
args_json, kwargs_json, params_jsonJSONField, nullablenew dual-write target (pickle → JSON migration)
etaDateTimeField, db_indexwhen to dispatch
doneBooleanField, nullableNULL=pending, False=in-flight, True=done
createdauto

Index: (eta, done) for the cron drain query.

Groups / subscriptions

MailGroup

A named list of email / phone / push tokens. Resolved when recipient is a string with no @ or +.

FieldTypeNotes
nameCharField(100)
slugSlugField, uniquepassed as recipient
created, updatedauto

MailGroupEmail

Member of a MailGroup.

FieldTypeNotes
nameCharField(100)display
emailCharField, unique-per-groupaddress / phone / token
groupFK(MailGroup)cascade

MailSubscription

Per-user opt-in / opt-out for a backend. Honours quiet hours.

FieldTypeNotes
userFK(USER, null)nullable for guest subs
addressCharField, db_indexrecipient
backendCharField, db_indexmail / sms / push
start_hour, end_hourTimeFieldquiet-hours window — sends only inside
defer_at_allowed_hoursBooleanFieldif True, queue for later instead of dropping
is_enabledBooleanFielduser opt-out
is_checkedBooleanFieldconfirmation-link verified
created, updatedauto

Index: (address, backend).

ApiKeyUsageAudit

Persistent audit trail for every hit on /dbmail/api/. One row per request, written regardless of authentication outcome. The table is informational — it does not gate any request processing. Admin view is read-only.

FieldTypeNotes
api_keyFK(ApiKey, null, on_delete=PROTECT)Null when the key is missing or cannot be resolved (e.g. missing_api_key).
api_key_nameCharField(25)Copy of ApiKey.name at write time, retained if the FK is later deleted.
ipGenericIPAddressFieldResolved via django-ipware.
uaCharFieldUser-Agent header.
actionCharFieldOne of: kill_switch, missing_api_key, provider_blocked, rate_limit, hmac_invalid, invalid_key, bad_request, send.
successBooleanFieldTrue only for send.
detailCharField, nullFirst four characters of the raw key on authentication failures; slug on send.
createdauto

Retention and cleanup are the operator's responsibility. The bundled clean_dbmail_logs management command does not touch this table.

API

ApiKey

Public API endpoint authenticator. See api.md and security model.

FieldTypeNotes
nameCharField(25)display
api_keyCharField(32), uniquelegacy plaintext column (kept for 3.x, removed in 4.0)
password_hashCharField(255)Django make_password output (Argon2 / PBKDF2)
is_activeBooleanField
last_used_atDateTimeField, nullpopulated on every successful authentication
last_used_ipGenericIPAddressField, nullresolved via django-ipware
created, updatedauto

Admin actions: Rotate selected API keys (replaces the raw value

  • blanks the hash for re-hashing on next save), Revoke selected (toggles is_active=False).

Files

MailFile

Attachment for MailTemplate. Files are stored under MEDIA_ROOT via Django's FileField.

FieldTypeNotes
templateFK(MailTemplate)cascade
nameCharField(100)display
filenameFileField(upload_to=UPLOAD_TO)

Natural keys

Seven models ship a NaturalKeyManager and implement natural_key(): MailCategory, MailBaseTemplate, MailFromEmail, MailBcc, MailTemplate, MailLogException, and MailGroup.

This enables portable fixture exports that reference objects by a human-readable key instead of an auto-generated integer primary key:

python manage.py dumpdata dbmail \
    --natural-foreign \
    --natural-primary \
    --indent 2 \
    > fixtures/dbmail_templates.json

The resulting fixture can be loaded into any environment (staging, CI database, fresh production instance) without PK conflicts:

python manage.py loaddata fixtures/dbmail_templates.json

The natural key for each model is its unique human-readable field (e.g. slug for MailTemplate and MailGroup, name for MailCategory).

Cross-references