Observed since 20 Oct, 17:03 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Allows you to skip entering your email after registering via EVE SSO
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.
placeholder_email_replaced signal when a user's placeholder is
replaced with a real address — downstream plugins (OIDC providers, audit
logs, welcome flows) can react without polling.is_placeholder_email() and get_placeholder_users() helpers so
callers can classify addresses without re-implementing the domain check.PlaceholderEmailFilter for the Django admin user list.en source + ru catalogue.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",
]
Configure these in local.py (or your equivalent settings file).
AA_SKIP_EMAIL_DOMAINDomain used for placeholder addresses.
strno-email.invalidAA_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_LIMITDefault limit for how many users are processed per run by the management command and the Celery task.
int5000AA_SKIP_EMAIL_LIMIT = 5000
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>
The plugin provides a Django management command to fill missing emails.
python manage.py fill_missing_emails
python manage.py fill_missing_emails --limit 5000
python manage.py fill_missing_emails --dry-run --limit 50
[!CAUTION] This will replace existing emails.
python manage.py fill_missing_emails --overwrite
Safer if some users have real emails and you only want to regenerate placeholders.
python manage.py fill_missing_emails --overwrite --only-placeholders
The plugin includes a Celery task named:
aa_skip_email.fill_missing_emailsTo run it periodically, add a schedule entry in local.py using CELERYBEAT_SCHEDULE.
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,
}
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,
}
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.
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)
placeholder_email_replacedSent 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:
--overwrite --only-placeholders).Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.4.1 | 18 Oct 2026 | 1 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitLab
| Contributor | Contributions |
|---|---|
| Boris Talovikov | 68 |
Default-branch author identities; GitLab commit counts exclude merge commits.
Public sponsor counts have not been collected. These signals belong to the repository owner.
gitlab · 4 observations shown. Missing days are unknown.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-23 | 1 | 2026-10-23T18:50:39.1465401Z |
| 2026-10-22 | 1 | 2026-10-22T18:50:22.0750435Z |
| 2026-10-21 | 1 | 2026-10-21T18:49:59.0992854Z |
| 2026-10-20 | 1 | 2026-10-20T18:49:40.3461886Z |
Observed since 20 Oct, 17:03 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:b0efdf554c180c6c99e2e02fa803814b1674291ed72e5a116d640e4b12c05c47