![]()
AA Skip Email
Allows you to skip entering your email after registering via EVE SSO
AA Skip Email (aa_skip_email)
A small Alliance Auth plugin that lets you skip collecting real email addresses
during EVE SSO registration by automatically generating a placeholder User.email.
This is useful for integrations (e.g., OIDC clients) that expect email to be present.
Features
- Creates a placeholder email for newly created users during SSO registration.
- Includes a one-off Django management command to backfill missing emails.
- Includes a Celery task suitable for periodic execution to keep data consistent.
- Emits a
placeholder_email_replacedsignal when a user's placeholder is replaced with a real address — downstream plugins (OIDC providers, audit logs, welcome flows) can react without polling. - Exposes
is_placeholder_email()andget_placeholder_users()helpers so callers can classify addresses without re-implementing the domain check. - Ships a
PlaceholderEmailFilterfor the Django admin user list. - Translated user-visible strings (admin filter, command output,
AppConfig name) — currently
ensource +rucatalogue.
Requirements
- Python >= 3.12 (tested on 3.12 and 3.13)
- Alliance Auth >= 4.0, < 6 (tested against the latest AA 4.x and AA 5.x)
Installation
Install the plugin into the same Python environment as Alliance Auth (pip/uv/poetry-whatever you use).
pip install aa-skip-email
Add the app to INSTALLED_APPS (typically in local.py):
INSTALLED_APPS += [
...
"aa_skip_email",
...
]
Add the authentication backend to AUTHENTICATION_BACKENDS.
[!IMPORTANT] This plugin replaces Alliance Auth’s default
allianceauth.authentication.backends.StateBackendbehavior. UpdateAUTHENTICATION_BACKENDSso thatSkipEmailBackendis used instead of the original AA StateBackend.
Example:
AUTHENTICATION_BACKENDS = [
# Replace the original AA StateBackend with this plugin backend
"aa_skip_email.authentication.backends.SkipEmailBackend",
# Keep the rest of your original backends
"django.contrib.auth.backends.ModelBackend",
]
<hr />
Configuration
Configure these in local.py (or your equivalent settings file).
AA_SKIP_EMAIL_DOMAIN
Domain used for placeholder addresses.
- Type:
str - Default:
no-email.invalid
AA_SKIP_EMAIL_DOMAIN = "no-email.invalid"
Using a domain under .invalid helps avoid accidentally generating addresses at a real domain.
The plugin validates this setting at process start and raises
ImproperlyConfigured if the value is empty, contains @ or whitespace,
or has no . (single-label "domain"). This catches misconfigurations
before the first SSO registration attempt.
AA_SKIP_EMAIL_LIMIT
Default limit for how many users are processed per run by the management command and the Celery task.
- Type:
int - Default:
5000
AA_SKIP_EMAIL_LIMIT = 5000
<hr />
How placeholder emails are generated
A placeholder email is generated from the user’s username (sanitized to a conservative character set) and a unique suffix (typically the user id; otherwise a UUID). The local-part is kept within 64 characters.
Resulting format is similar to:
<sanitized-username>-<id-or-uuid>@<AA_SKIP_EMAIL_DOMAIN>
<hr />
One-off backfill (management command)
The plugin provides a Django management command to fill missing emails.
Fill missing emails (default)
python manage.py fill_missing_emails
Limit number of users
python manage.py fill_missing_emails --limit 5000
Dry-run (no writes)
python manage.py fill_missing_emails --dry-run --limit 50
Overwrite emails for all users
[!CAUTION] This will replace existing emails.
python manage.py fill_missing_emails --overwrite
Overwrite only existing placeholders
Safer if some users have real emails and you only want to regenerate placeholders.
python manage.py fill_missing_emails --overwrite --only-placeholders
<hr />
Scheduler (Celery Beat)
The plugin includes a Celery task named:
aa_skip_email.fill_missing_emails
To run it periodically, add a schedule entry in local.py using CELERYBEAT_SCHEDULE.
Example: run every 6 hours
from celery.schedules import crontab
CELERYBEAT_SCHEDULE["aa_skip_email_fill_missing_emails"] = {
"task": "aa_skip_email.fill_missing_emails",
"schedule": crontab(minute=0, hour="*/6"),
# Optional: helps spread load across instances in some AA deployments
"apply_offset": True,
}
Example: run daily at 04:15
from celery.schedules import crontab
CELERYBEAT_SCHEDULE["aa_skip_email_fill_missing_emails"] = {
"task": "aa_skip_email.fill_missing_emails",
"schedule": crontab(minute=15, hour=4),
"apply_offset": True,
}
<hr />
Public API for downstream plugins
is_placeholder_email(email)
from aa_skip_email import is_placeholder_email
if is_placeholder_email(user.email):
... # treat as unverified / non-routable
Centralised classifier — returns True for any address produced by
this plugin (case-insensitive domain match, anchored to the domain
part). Falsy values (None, "") return False.
get_placeholder_users()
from aa_skip_email.helpers import get_placeholder_users
count = get_placeholder_users().count()
ORM-side analogue of is_placeholder_email. Returns a queryset of
all users whose email is a plugin-generated placeholder. Useful
for admin reports, audit dashboards, or batch follow-up.
Admin filter
Add PlaceholderEmailFilter to AA's existing UserAdmin.list_filter
to surface a "Placeholder / Real / Blank" sidebar in the admin user
list. The plugin does not re-register the User model so AA's
custom UserAdmin remains intact:
# in your local.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from aa_skip_email.admin import PlaceholderEmailFilter
User = get_user_model()
UserAdmin = admin.site._registry[User].__class__
UserAdmin.list_filter = (*UserAdmin.list_filter, PlaceholderEmailFilter)
Signal placeholder_email_replaced
Sent when User.email transitions from a plugin-generated placeholder
to a real address. Useful for OIDC providers that flip
email_verified=true on the ID token, audit logs, welcome emails, etc.
from django.dispatch import receiver
from aa_skip_email.signals import placeholder_email_replaced
@receiver(placeholder_email_replaced, dispatch_uid="my_app.email_verified")
def on_email_replaced(sender, user, old_email, new_email, **kwargs):
...
The signal does not fire on:
- Initial fill of a blank/NULL email (placeholder is the new value).
- Placeholder rewritten as another placeholder (
--overwrite --only-placeholders). - Real email replaced with another real email.
See also
No reviews yet...
Python Requirements
- allianceauth<6,>=4.0
Required Python packages to be installed and other Python requirement.
App Dependencies
Required apps:
-
Used by apps:
-
Dependencies to other apps registered in this app directory.
Classifiers
- Development Status :: 4 - Beta
- Environment :: Web Environment
- Framework :: Django
- Framework :: Django :: 4.2
- Framework :: Django :: 5.2
- Intended Audience :: Developers
- License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
- Operating System :: OS Independent
- Programming Language :: Python :: 3 :: Only
- Programming Language :: Python :: 3.12
- Programming Language :: Python :: 3.13
- Topic :: Internet :: WWW/HTTP
- Topic :: Internet :: WWW/HTTP :: Site Management
Version
0.4.0
License
GPLv3+
Homepage
https://gitlab.com/zima-corp/aa-skip-email
PyPI
https://pypi.org/project/aa-skip-email/
Last updated
1 day, 19 hours ago
First published
2 years, 1 month ago
Category
Plugin Apps
Rating
-Authors
Boris Talovikov
Maintainers
Boris Blade Artrald
Please login to see more options.