
Dear Steve, dear list
That's not true on the systems I've worked with most recently -- those will be recognized as duplicate addresses (...)
You are right. I am sorry for this confusion. Please let me correct my initial posting to this list from yesterday, saying:
(...) <markus.grandpre@uni-konstanz.de> and <Markus.Grandpre@uni-konstanz.de> are being recognized as separate identities.
That is not the case. Meanwhile I discovered an error with logging into Postorius when an account is associated with two semantically identical email addresses that differ in their formatting, e.g.,
<markus.grandpre@uni-konstanz.de>
and
<Markus.Grandpre@uni-konstanz.de>.
In this case, the user is unable to log in, and I observed the following error message in the log file:
(...) returned more than one EmailAddress -- it returned 2!
Here is the complete stack trace of this error:
ERROR 2025-02-10 14:29:55,599 211159 django.request Internal Server Error: /mailman3/accounts/login/ Traceback (most recent call last): File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 70, in view return self.dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/utils/decorators.py", line 43, in _wrapper return bound_method(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/views/decorators/debug.py", line 89, in sensitive_post_parameters_wrapper return view(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 149, in dispatch return super(LoginView, self).dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 77, in dispatch response = super(RedirectAuthenticatedUserMixin, self).dispatch( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 98, in dispatch return handler(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 105, in post response = self.form_valid(form) ^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 162, in form_valid return form.login(self.request, redirect_url=success_url) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/forms.py", line 196, in login ret = perform_login( ^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/utils.py", line 168, in perform_login response = adapter.pre_login(request, user, **hook_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/adapter.py", line 411, in pre_login if not has_verified_email(user, email): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/utils.py", line 130, in has_verified_email emailaddress = EmailAddress.objects.get_for_user(user, email) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/managers.py", line 54, in get_for_user ret = self.get(user=user, email__iexact=email) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 439, in get raise self.model.MultipleObjectsReturned( allauth.account.models.EmailAddress.MultipleObjectsReturned: get() returned more than one EmailAddress -- it returned 2! ERROR 2025-02-10 14:29:55,599 211159 django.request Internal Server Error: /mailman3/accounts/login/ Traceback (most recent call last): File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py", line 47, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/core/handlers/base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 70, in view return self.dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/utils/decorators.py", line 43, in _wrapper return bound_method(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/views/decorators/debug.py", line 89, in sensitive_post_parameters_wrapper return view(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 149, in dispatch return super(LoginView, self).dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 77, in dispatch response = super(RedirectAuthenticatedUserMixin, self).dispatch( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/views/generic/base.py", line 98, in dispatch return handler(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 105, in post response = self.form_valid(form) ^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/views.py", line 162, in form_valid return form.login(self.request, redirect_url=success_url) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/forms.py", line 196, in login ret = perform_login( ^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/utils.py", line 168, in perform_login response = adapter.pre_login(request, user, **hook_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/adapter.py", line 411, in pre_login if not has_verified_email(user, email): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/utils.py", line 130, in has_verified_email emailaddress = EmailAddress.objects.get_for_user(user, email) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/allauth/account/managers.py", line 54, in get_for_user ret = self.get(user=user, email__iexact=email) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/db/models/manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/django/db/models/query.py", line 439, in get raise self.model.MultipleObjectsReturned( allauth.account.models.EmailAddress.MultipleObjectsReturned: get() returned more than one EmailAddress -- it returned 2!
To resolve the issue, the only solution I found was to manually delete the second email address from the database:
mailman3web-prod=> select * from account_emailaddress where user_id = 93; id | email | verified | primary | user_id -----+---------------------------------+----------+---------+--------- 100 | Markus.Grandpre@uni-konstanz.de | t | t | 93 101 | markus.grandpre@uni-konstanz.de | t | f | 93 (2 rows) mailman3web-prod=> delete from account_emailaddress where id = 100; DELETE 1 mailman3web-prod=> select * from account_emailaddress where user_id = 93 ; id | email | verified | primary | user_id -----+---------------------------------+----------+---------+--------- 101 | markus.grandpre@uni-konstanz.de | t | f | 93 (1 row)
Could I have achieved the same deletion using the REST interface?
After the deletion login with <markus.grandpre@uni-konstanz.de> was possible again, and I set the remaining email address as 'primary' using Postorius.
I am not entirely sure how the duplicate email address came into the system. During the data migration from Mailman 2.1 to Mailman 3, an account was created for <markus.grandpre@uni-konstanz.de>. It is most likely that during registration, the user provided <Markus.Grandpre@uni-konstanz.de> as username or email address, which resulted in both variations of the semantically same email address being stored under the same account.
I apologize again for the incorrect information in my initial message to this list. I should have waited until I had a clearer understanding of this issue.
Best regards, Markus
Am 10.02.25 um 15:32 schrieb Stephen J. Turnbull:
Markus Grandpré writes:
We've encountered an issue with Postorius after migrating from Mailman 2.1. It appears that Postorius is treating email addresses with differing capitalization as distinct user accounts. For example, <markus.grandpre@uni-konstanz.de> and <Markus.Grandpre@uni-konstanz.de> are being recognized as separate identities.
That's not true on the systems I've worked with most recently -- those will be recognized as duplicate addresses, both at list import time and at login on Postorius. Those are versions Mailman 3.3.9 and 3.3.11, with corresponding Postorius. As far as I can tell the last case- sensitivity bugs were fixed as of Mailman 3.2.1 (released 2019-02-22). Postorius does not appear to have had any case sensitivity bugs (not surprising since Postorius just passes them through to Mailman).
I guess it's possible that this is a Debianism, or there was a temporary regression around 3.3.8.
Is there a known configuration option or method within Postorius (or Mailman 3 itself) to normalize or unify account identification, effectively treating email addresses as case-insensitive for account matching?
There is no such configuration option because Mailman has treated email addresses as case insensitive for quite a while. All I can recommend is an upgrade.
Steve
-- Markus Ludwig Grandpré Universität Konstanz Kommunikations-, Informations-, Medienzentrum (KIM) Abteilung IT-Dienste Forschung und Lehre, B803, Tel: ++49 7531 88 4342