makeplane/plane · error · AuthenticationException
5025
5025
Error message
SMTP_NOT_CONFIGURED
What it means
Raised in MagicCodeProvider.__init__ (magic_code.py:58) when EMAIL_HOST is falsy. EMAIL_HOST is read from instance config with an env fallback; an empty value means no SMTP server is configured, so magic-code emails cannot be delivered. Code 5025, payload {email}.
Source
Thrown at apps/api/plane/authentication/provider/credentials/magic_code.py:58
)
@staticmethod
def _verify_attempts_key(token_key):
return f"{token_key}:verify_attempts"
def __init__(self, request, key, code=None, callback=None):
(EMAIL_HOST, ENABLE_MAGIC_LINK_LOGIN) = get_configuration_value(
[
{"key": "EMAIL_HOST", "default": os.environ.get("EMAIL_HOST")},
{
"key": "ENABLE_MAGIC_LINK_LOGIN",
"default": os.environ.get("ENABLE_MAGIC_LINK_LOGIN", "1"),
},
]
)
if not (EMAIL_HOST):
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["SMTP_NOT_CONFIGURED"],
error_message="SMTP_NOT_CONFIGURED",
payload={"email": str(key)},
)
if ENABLE_MAGIC_LINK_LOGIN == "0":
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["MAGIC_LINK_LOGIN_DISABLED"],
error_message="MAGIC_LINK_LOGIN_DISABLED",
payload={"email": str(key)},
)
super().__init__(request=request, provider=self.provider, callback=callback)
self.key = key
self.code = code
def initiate(self):
## Generate a random tokenView on GitHub (pinned to 1c8a60f858)
Solutions
- Set EMAIL_HOST (and related SMTP creds: EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_PORT, EMAIL_USE_TLS) in instance config/env.
- If SMTP is intentionally unavailable, hide/disable the magic-code UI and guide users to the configured auth methods.
- Restart/reload the API after changing SMTP config so get_configuration_value picks up the new value.
Example fix
# before: EMAIL_HOST unset -> magic-code init -> 5025 # EMAIL_HOST=smtp.example.com # EMAIL_PORT=587 # EMAIL_USE_TLS=1 # after: SMTP configured, magic-code tokens are emailed
Defensive patterns
Strategy: validation
Validate before calling
from plane.license.utils.instance_value import get_configuration_value
import os
def smtp_configured() -> bool:
(host,) = get_configuration_value([{'key': 'EMAIL_HOST', 'default': os.environ.get('EMAIL_HOST')}])
return bool(host) Try / catch
try:
MagicCodeProvider(request, key=email)
except AuthenticationException as e:
if e.error_code == 5025:
hide_magic_code_ui(); offer_alternative_auth()
else:
raise Prevention
- Only expose magic-code in the UI when EMAIL_HOST is set.
- Validate the full SMTP config (host, port, user, password, TLS) at deploy time.
When it happens
Trigger: Constructing the MagicCodeProvider (initiate or verify) resolves EMAIL_HOST via get_configuration_value. If it is empty/None, AuthenticationException is raised before any code is generated or sent. Hit by calling the magic-code request or verify endpoint on an instance without SMTP.
Common situations: Fresh/self-hosted deploy without EMAIL_HOST set; SMTP migrated away and config not updated; instance intended for SSO-only but the UI still exposes magic-code.
Related errors
AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12).
Data as JSON: /api/errors/2edf131496c443b3.
Report an issue: GitHub.