django/django · error · InvalidMailer
MAILERS[{alias!r}]: OPTIONS must define 'host'.
Error message
MAILERS[{alias!r}]: OPTIONS must define 'host'. What it means
Raised by the MAILERS-based SMTP email backend (alias is not None) when host is None after construction. It is an InvalidMailer error, message prefixed with MAILERS[<alias>]:. Unlike the deprecated path which falls back to settings.EMAIL_HOST, the MAILERS path requires an explicit 'host' in OPTIONS because the new system intentionally has no implicit default host. The check is at smtp.py:85-86.
Source
Thrown at django/core/mail/backends/smtp.py:86
)
if self.use_ssl and self.use_tls:
raise ValueError(
"EMAIL_USE_TLS/EMAIL_USE_SSL are mutually exclusive, so "
"only set one of those settings to True."
)
return
self.host = host
self.port = port
self.username = username
self.password = password
self.use_tls = use_tls if use_tls is not None else False
self.use_ssl = use_ssl if use_ssl is not None else False
self.timeout = timeout
self.ssl_keyfile = ssl_keyfile
self.ssl_certfile = ssl_certfile
if self.host is None:
raise InvalidMailer("OPTIONS must define 'host'.", alias=self.alias)
if self.use_ssl and self.use_tls:
raise InvalidMailer(
"The 'use_ssl' and 'use_tls' OPTIONS are incompatible. "
"Set at most one of them to True.",
alias=self.alias,
)
if self.port is None:
if self.use_ssl:
self.port = 465
elif self.use_tls:
self.port = 587
else:
self.port = 25
@property
def connection_class(self):
return smtplib.SMTP_SSL if self.use_ssl else smtplib.SMTP
View on GitHub (pinned to ae25a40be0)
Solutions
- Add 'host' to the alias OPTIONS, e.g. OPTIONS: {'host': 'smtp.example.com', 'port': 587}.
- Validate at startup: `assert 'host' in MAILERS['transactional']['OPTIONS'], 'host required'`.
- Keep port and credentials consistent in the same OPTIONS dict.
Example fix
# before
MAILERS = {
"default": {
"BACKEND": "django.core.mail.backends.smtp.EmailBackend",
"OPTIONS": {"port": 587, "username": "u", "password": "p"},
},
}
# after
MAILERS = {
"default": {
"BACKEND": "django.core.mail.backends.smtp.EmailBackend",
"OPTIONS": {
"host": "smtp.example.com",
"port": 587,
"username": "u",
"password": "p",
"use_tls": True,
},
},
} Defensive patterns
Strategy: validation
Validate before calling
from django.conf import settings
def validate_smtp_mailers_have_host():
for alias, cfg in getattr(settings, "MAILERS", {}).items():
if cfg.get("BACKEND") == "django.core.mail.backends.smtp.EmailBackend":
if not cfg.get("OPTIONS", {}).get("host"):
raise ImproperlyConfigured(
f"MAILERS[{alias!r}] SMTP backend requires OPTIONS['host']"
) Type guard
def is_valid_smtp_mailer(cfg: dict) -> bool:
return (
cfg.get("BACKEND") == "django.core.mail.backends.smtp.EmailBackend"
and isinstance(cfg.get("OPTIONS"), dict)
and isinstance(cfg["OPTIONS"].get("host"), str)
and bool(cfg["OPTIONS"]["host"])
) Try / catch
from django.core.mail import InvalidMailer
from django.core import mail
try:
mail.mailers["default"]
except InvalidMailer as e:
if "OPTIONS must define 'host'" in str(e):
raise SystemExit("Add OPTIONS['host'] to the SMTP MAILERS alias.")
raise Prevention
- Always include 'host' in every SMTP alias OPTIONS.
- Centralize mailer construction in a helper that asserts host is present.
- Add a startup check that all SMTP aliases define host, port, and TLS mode.
When it happens
Trigger: Defining a MAILERS alias with BACKEND 'django.core.mail.backends.smtp.EmailBackend' whose OPTIONS omits 'host', then accessing mailers[<alias>] or sending with using=<alias>.
Common situations: Migrating from EMAIL_HOST to MAILERS and forgetting to copy host into OPTIONS; aliasing a copy of the default config and stripping the host; typo 'Host' vs 'host' (the option is lowercase).
Related errors
- MAILERS[{alias!r}]: The 'use_ssl' and 'use_tls' OPTIONS are
- get_connection(backend, ...) is not supported with MAILERS.
- MAILERS[{alias!r}]: Unknown options {kwarg_names}.
- MAILERS[{alias!r}]: OPTIONS must define 'file_path'.
- MAILERS[{alias!r}]: 'file_path' is not a directory: {self.fi
AI-assisted analysis of django/django@ae25a40be0 (2026-08-06).
Data as JSON: /api/errors/7741330a3df692ef.
Report an issue: GitHub.