This document describes all configuration options for django-login-email.
These settings should be configured in your Django settings.py.
Type: str
Required: ✅ Yes
Default: N/A (Django required setting)
Purpose: Used for AES encryption of email tokens
Requirements:
- MUST be at least 32 characters long (only first 32 characters are used)
- MUST be kept secret and not committed to version control
- MUST be unique per environment (dev/staging/prod)
- MUST remain constant (changing it invalidates all existing tokens)
Example:
# settings.py
SECRET_KEY = "your-secret-key-here-at-least-32-chars-long-1234567890"Security Warning: If SECRET_KEY is less than 32 characters, token encryption will be weak. Django's default key generator produces 50 characters.
Required: ✅ Yes (Django settings for email)
Settings:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' # Default
EMAIL_HOST = 'smtp.example.com' # SMTP server
EMAIL_PORT = 587 # Usually 587 (TLS) or 465 (SSL)
EMAIL_USE_TLS = True # Recommended
EMAIL_HOST_USER = 'your-email@example.com'
EMAIL_HOST_PASSWORD = 'your-password' # Use environment variableDevelopment Configuration:
# For local development with MailHog
EMAIL_HOST = 'localhost'
EMAIL_PORT = 1025
EMAIL_HOST_USER = 'user'
EMAIL_HOST_PASSWORD = ''Testing Configuration:
# For unit tests
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'Production Best Practices:
- Store
EMAIL_HOST_PASSWORDin environment variable - Use TLS/SSL encryption
- Consider using a transactional email service (SendGrid, Mailgun, AWS SES)
Required: ✅ Yes (must include package)
Example:
INSTALLED_APPS = [
# Django defaults
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
# This package
'django_login_email',
# Your apps
'yourapp',
]Note: Order matters - django_login_email should come before your apps so you can override templates.
These settings are configured on your view classes.
Type: Type[EmailLoginInfo]
Required: ✅ Yes
Default: None (must be set)
Purpose: Class to configure login email content and sending
Example:
from django_login_email import email as e
class MyLoginInfo(e.EmailLoginInfo):
system_name = "MyApp"
def __init__(self):
super().__init__()
self.from_email = "noreply@myapp.com"
self.url = "https://myapp.com/account/verify?token="
class LoginView(EmailLoginView):
login_info_class = MyLoginInfoCustomizable Attributes in EmailLoginInfo:
system_name: Your application name (shown in email)from_email: Sender email addressurl: Verification URL (must point to yourEmailVerifyView)subject: Email subject linewelcome_text: Text before the login linklogin_message: Template for the link (string.Template)
Type: Type[EmailRegisterInfo]
Required: ✅ Yes
Default: None (must be set)
Purpose: Class to configure registration email content
Example:
class MyRegisterInfo(e.EmailRegisterInfo):
system_name = "MyApp"
def __init__(self):
super().__init__()
self.from_email = "noreply@myapp.com"
self.url = "https://myapp.com/account/verify?token="
class LoginView(EmailLoginView):
register_info_class = MyRegisterInfoType: TimeLimit
Required: ❌ No
Default: LoginTimeLimit() (10 minutes)
Purpose: Configure rate limiting for email sending
Example:
from django_login_email.email import TimeLimit
class LoginView(EmailLoginView):
tl = TimeLimit(minutes=15) # 15 minute rate limitHow it works:
- User can only request a new email once every
minutesminutes - Timer starts when email is sent
- Timer resets when user successfully logs in
- Same email cannot be sent multiple times within the window
Recommended Values:
- Development: 1-5 minutes (for testing)
- Production: 10-15 minutes (balance security and UX)
- High-security: 30-60 minutes
Type: str
Required: ❌ No
Default: "login_email/login.html"
Purpose: Template for login form page
Example:
class LoginView(EmailLoginView):
template_name = "myapp/login.html"Type: str
Required: ❌ No
Default: "login_email/error.html"
Purpose: Template for error messages
Example:
class LoginView(EmailLoginView):
error_template = "myapp/error.html"Template Context:
error: Error message string
Type: str
Required: ❌ No
Default: "login_email/success.html"
Purpose: Template shown after email is sent
Example:
class LoginView(EmailLoginView):
success_template = "myapp/check_email.html"Template Context:
form: Submitted form with email address
Type: Type[Form]
Required: ❌ No
Default: LoginForm
Purpose: Form class for email input
Example (custom validation):
from django import forms
class CustomLoginForm(forms.Form):
email = forms.EmailField()
def clean_email(self):
email = self.cleaned_data['email']
# Custom validation: only allow company emails
if not email.endswith('@mycompany.com'):
raise forms.ValidationError("Only company emails allowed")
return email
class LoginView(EmailLoginView):
form_class = CustomLoginFormType: TimeLimit
Required: ❌ No
Default: LoginTimeLimit() (10 minutes)
Purpose: Configure token expiration time
Example:
class VerifyView(EmailVerifyView):
tl = TimeLimit(minutes=30) # Tokens valid for 30 minutesIMPORTANT: This MUST match the tl setting in your EmailLoginView, otherwise token validation will fail.
Type: str
Required: ❌ No
Default: "login_email/error.html"
Purpose: Template for token verification errors
Type: Method returning str
Required: ✅ Yes
Default: Returns "login_email:home" (you must override this)
Purpose: URL to redirect to after successful login
Example:
from django.urls import reverse
class VerifyView(EmailVerifyView):
def get_success_url(self):
return reverse("dashboard") # Your app's main pageType: str
Required: ❌ No
Default: "login_email:login"
Purpose: URL to redirect to after logout
Example:
class LogoutView(EmailLogoutView):
login_url = "myapp:login" # Or just "login" if no namespaceThe email body is generated using Python's string.Template. To customize:
import string
class MyLoginInfo(EmailLoginInfo):
def __init__(self):
super().__init__()
self.welcome_text = "Hello! Welcome to MyApp.<br>"
self.login_message = string.Template(
'<a href="$url$token" style="color: blue;">Click here to login</a>'
)Available Variables:
$url: Base verification URL$token: Encrypted token
WARNING: Only use this for debugging!
class DebugLoginView(EmailLoginView):
def check_could_send(self, email) -> bool:
return True # ALWAYS allow sendingThis bypasses the time limit check.
Override methods from IPBanUtils:
class MyLoginView(EmailLoginView):
def ban_ip(self, ip: str, reason: str):
# Custom logic: send notification email
send_admin_email(f"IP banned: {ip} - {reason}")
super().ban_ip(ip, reason)By default, new users are created with username = email. To customize:
from django_login_email.email import EmailVerifyMixin
class MyVerifyView(EmailVerifyView):
def verify_token(self, token_v: str):
# Call parent to get user
user = super().verify_token(token_v)
# Customize new users
if user.date_joined == user.last_login: # Newly created
user.first_name = user.email.split('@')[0]
user.save()
return user# settings/dev.py
DEBUG = True
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # Print to console
# Short rate limit for testing
from django_login_email.email import TimeLimit
LOGIN_TIME_LIMIT = TimeLimit(minutes=1)# settings/test.py
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'# settings/prod.py
DEBUG = False
EMAIL_USE_TLS = True
EMAIL_HOST = os.getenv('EMAIL_HOST')
EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD')
# Production rate limit
from django_login_email.email import TimeLimit
LOGIN_TIME_LIMIT = TimeLimit(minutes=15)Create a management command to validate settings:
# yourapp/management/commands/check_email_login.py
from django.core.management.base import BaseCommand
from django.conf import settings
class Command(BaseCommand):
def handle(self, *args, **options):
# Check SECRET_KEY length
if len(settings.SECRET_KEY) < 32:
self.stdout.write(self.style.WARNING(
'SECRET_KEY is less than 32 characters'
))
# Check email settings
required = ['EMAIL_HOST', 'EMAIL_HOST_USER', 'EMAIL_PORT']
for setting in required:
if not hasattr(settings, setting):
self.stdout.write(self.style.ERROR(
f'Missing setting: {setting}'
))
self.stdout.write(self.style.SUCCESS('Configuration OK'))# settings.py
INSTALLED_APPS = ['django_login_email', ...]
SECRET_KEY = 'your-secret-key-here-min-32-chars-long-abc123'
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# views.py
from django_login_email import views, email
LoginInfo, RegisterInfo = email.get_info_class("MyApp")
class LoginView(views.EmailLoginView):
login_info_class = LoginInfo
register_info_class = RegisterInfo
class VerifyView(views.EmailVerifyView):
def get_success_url(self):
return '/'# settings.py
import os
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'apikey'
EMAIL_HOST_PASSWORD = os.getenv('SENDGRID_API_KEY')
# views.py
from django_login_email import views, email
class ProductionLoginInfo(email.EmailLoginInfo):
system_name = "MyApp"
def __init__(self):
super().__init__()
self.from_email = "noreply@myapp.com"
self.url = "https://myapp.com/account/verify?token="
class ProductionRegisterInfo(email.EmailRegisterInfo):
system_name = "MyApp"
def __init__(self):
super().__init__()
self.from_email = "noreply@myapp.com"
self.url = "https://myapp.com/account/verify?token="
class LoginView(views.EmailLoginView):
login_info_class = ProductionLoginInfo
register_info_class = ProductionRegisterInfo
tl = email.TimeLimit(minutes=15)- Check EMAIL_BACKEND is SMTP in production
- Verify EMAIL_HOST_PASSWORD is correct
- Check SMTP server logs
- Test with Django shell:
from django.core.mail import send_mail send_mail('Test', 'Body', 'from@example.com', ['to@example.com'])
- Ensure
tlsettings match between LoginView and VerifyView - Check SECRET_KEY hasn't changed
- Verify token hasn't expired
- Check for clock skew if using multiple servers
- Adjust
tl.minutesto a higher value - Check EmailRecord table for stale entries
- Consider implementing cleanup for old records
- See Extension Points for customization options
- See API Specification for detailed API reference