Installation¶
This guide will help you install and configure Django Email Learning in your Django project.
Prerequisites¶
Python 3.10 or higher
Django 5.0 or higher
A configured email backend (for sending course emails)
Installation Steps¶
Install the Package
Install Django Email Learning via pip:
pip install django-email-learning
If you want to use AI editing tools, install with the AI optional extra:
pip install 'django-email-learning[ai]'
Add to INSTALLED_APPS
Add ‘django_email_learning’ to your INSTALLED_APPS in settings.py:
INSTALLED_APPS = [ # ... your other apps 'django_email_learning', # ... more apps ]
Run Database Migrations
Create the necessary database tables:
python manage.py migrate django_email_learning
Configure URLs
Add Django Email Learning URLs to your project’s main urls.py:
from django.urls import path, include urlpatterns = [ # ... your other URL patterns path('email-learning/', include('django_email_learning.urls')), # ... more URL patterns ]
You can change
email-learning/to any URL path you prefer. This will make:Platform (Admin Interface): Available at
/email-learning/platform/Public Course Pages: Available at
/email-learning/public/organization/<org_id>/API Endpoints: Available under
/email-learning/api/
Access Control¶
Platform Access
The course management platform (/platform/) requires authentication and is accessible to:
Django superusers
Users assigned as Organization users (managed via Django admin panel)
Note
Since the platform views require authentication, ensure your Django project has authentication views configured. You can use Django’s built-in authentication views by including them in your URLconf. See Django’s authentication views documentation for setup instructions.
Public Access
Public course enrollment pages are accessible without authentication and are designed for learners to discover and enroll in courses.
Configuration¶
Django Email Learning requires specific configuration in your Django settings. Add a DJANGO_EMAIL_LEARNING dictionary to your settings.py:
Required Settings¶
SITE_BASE_URL
The base URL of your site, used to generate absolute URLs in emails and course links.
ENCRYPTION_SECRET_KEY
A secret key used for encrypting sensitive data. It should be a long, random string. This will be used for encrypting API keys and IMAP passwords. This key will be used for bidirectional encryption/decryption, so keep it secure.
Same as all other sensitive configurations, it’s a good practice to load this from an environment variable or a secure vault.
Important
Changing this key after data has been created will prevent access to previously encrypted data. Chaning requires re-encrypting all existing data with the new key.
JWT_SECRET_KEY
A dedicated secret key used for signing and verifying JSON Web Tokens (JWTs). It should be a long, random string, independent of Django’s SECRET_KEY and ENCRYPTION_SECRET_KEY.
Using a separate key ensures that a JWT secret compromise does not affect other parts of your application.
Same as all other sensitive configurations, it’s a good practice to load this from an environment variable or a secure vault.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
}
Optional Settings¶
FROM_EMAIL
The default email address for outgoing course emails. If not specified, falls back to Django’s DEFAULT_FROM_EMAIL setting.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'FROM_EMAIL': 'courses@yourdomain.com',
}
TERMS_OF_SERVICE_URL
Optional link to your terms of service. When provided, this link is displayed in the public enrollment dialog so learners can review your terms before submitting their email address.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'TERMS_OF_SERVICE_URL': 'https://yourdomain.com/terms',
}
QUIZ_DEFAULTS
Optional configuration for the initial default values shown in the quiz form when creating a new quiz.
All values are boolean.
LIMITED_ATTEMPTS: Sets the default state of the Limited Attempts switch. When enabled, learners only have 2 attempts to pass the quiz. When disabled, learners can retry as many times as needed.IS_BLOCKING: Sets the default state of the Blocking Quiz switch. When enabled, learners must pass the quiz to continue receiving course content. When disabled, the quiz is treated as practice and does not gate course progress.HAS_DEADLINE: Sets the default state of the quiz deadline switch. When enabled, new quizzes start with a deadline. When disabled, new quizzes default to having no deadline.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'QUIZ_DEFAULTS': {
'LIMITED_ATTEMPTS': True,
'IS_BLOCKING': True,
'HAS_DEADLINE': True,
},
}
SIDEBAR.CUSTOM_COMPONENT
Optional configuration for injecting a custom component in the platform sidebar.
SCRIPT_URL: URL of the JavaScript module that registers your custom element.STYLE_URL: Optional stylesheet URL for the component (useNoneif not needed).COMPONENT_TAG: HTML tag rendered in the sidebar.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'SIDEBAR': {
'CUSTOM_COMPONENT': {
'SCRIPT_URL': 'url/path-to-your-component.js',
'STYLE_URL': 'url/path-to-your-component.css',
'COMPONENT_TAG': '<your-component />',
}
},
}
LOGO
Optional configuration for branding assets in the platform header.
HORIZONTAL_LOCKUP: Used on mobile devices where the sidebar is not open by default and the logo is shown in the top navbar.VERTICAL_LOCKUP: Used for sidebar-oriented layouts.LIGHT_BACKGROUND: Logo URL/path for light backgrounds.DARK_BACKGROUND: Logo URL/path for dark backgrounds.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'LOGO': {
'HORIZONTAL_LOCKUP': {
'LIGHT_BACKGROUND': 'url/path-to-horizontal-logo-for-light-background.png',
'DARK_BACKGROUND': 'url/path-to-horizontal-logo-for-dark-background.png',
},
'VERTICAL_LOCKUP': {
'LIGHT_BACKGROUND': 'url/path-to-vertical-logo-for-light-background.png',
'DARK_BACKGROUND': 'url/path-to-vertical-logo-for-dark-background.png',
},
},
}
PRIVATE_FILE_STORAGE_LOCATION
The filesystem path where privately uploaded files will be stored. Unlike media files served via Django’s MEDIA_URL which are publicly accessible, files stored here are not served publicly. They are only accessible through an authenticated endpoint, ensuring that sensitive files (such as assignment submissions or certificates) are protected and only available to authorised users.
If not specified, a default location will be used.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'PRIVATE_FILE_STORAGE_LOCATION': '/path/to/private/storage/',
}
Note
Ensure the directory exists and that the Django process has read/write permissions for the specified path. Do not place this directory inside your web server’s publicly served document root, as doing so would defeat the purpose of private storage.
AI
Optional configuration for AI-powered text editing features.
Configure this only if you have an OpenAI account and want to use AI edit tools.
If you do not use AI features, you can omit
AIentirely.Install AI dependencies with
pip install 'django-email-learning[ai]'.Add
'django_email_learning.ai'toINSTALLED_APPSwhen using AI tools.
INSTALLED_APPS = [
# ... your other apps
'django_email_learning',
'django_email_learning.ai',
# ... more apps
]
Available keys:
OPENAI_API_KEY: OpenAI API key used for AI requests.TEXT_EDITING_MODEL: OpenAI model name used by text editing.
Currently supported built-in models are:
gpt-4o-minigpt-5-nanogpt-5-mini
from django_email_learning.ai.language_models import LanguageModel
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'AI': {
'OPENAI_API_KEY': os.environ.get('OPENAI_API_KEY'),
'TEXT_EDITING_MODEL': LanguageModel.GPT_4O_MINI.model_name,
},
}
See AI Configuration for full details.
AMP_ENABLED
Optional flag to enable AMP email rendering for supported clients.
By default, AMP email support is disabled. Enable it only after your sending domain is registered as a dynamic email sender with Google:
Register dynamic email with Google
If AMP is enabled, you must also add trusted AMP mail client origins to Django’s CSRF_TRUSTED_ORIGINS so AMP form submissions are accepted.
DJANGO_EMAIL_LEARNING = {
'SITE_BASE_URL': 'https://yourdomain.com',
'ENCRYPTION_SECRET_KEY': 'your-very-long-random-string',
'JWT_SECRET_KEY': 'another-very-long-random-string',
'AMP_ENABLED': True,
}
CSRF_TRUSTED_ORIGINS = [
'https://mail.google.com',
'https://playground.amp.dev', # ⚠️ Do not include this in production - it's only needed for testing with the AMP playground
# Add any other trusted AMP mail client origins you use
]
Note
Keep AMP disabled in environments where you have not completed sender registration and trusted-origin configuration.
Email Backend Configuration¶
Django Email Learning sends course content and notifications via email. Ensure your Django project has a properly configured email backend:
# Example SMTP configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-email@gmail.com'
EMAIL_HOST_PASSWORD = 'your-app-password'
DEFAULT_FROM_EMAIL = 'your-email@gmail.com'
Management Command Scheduling¶
To automate content delivery, schedule the deliver_contents management command to run at regular intervals (e.g., every 15-60 minutes) using a task scheduler like cron or Celery Beat.
See Management Commands for more details.