Merge lp:~black-perl/mailman/fix-mailman into lp:mailman

Proposed by Ankush Sharma
Status: Merged
Approved by: Barry Warsaw
Approved revision: 7302
Merged at revision: 7304
Proposed branch: lp:~black-perl/mailman/fix-mailman
Merge into: lp:mailman
Diff against target: 32 lines (+10/-1)
2 files modified
src/mailman/app/membership.py (+1/-1)
src/mailman/rest/tests/test_membership.py (+9/-0)
To merge this branch: bzr merge lp:~black-perl/mailman/fix-mailman
Reviewer Review Type Date Requested Status
Barry Warsaw Needs Fixing
Review via email: mp+251709@code.launchpad.net

Description of the change

Discussed here https://mail.python.org/pipermail/mailman-developers/2015-March/024474.html about the bug and its fix.
Added test to call mailman REST api using case sensitive email address in 'test_try_to_join_a_list_twice' method.

To post a comment you must log in.
Revision history for this message
Barry Warsaw (barry) wrote :

I think you've done a great job in finding the root cause. I have just a couple of inlined comments, but I am happy to fix those myself when I merge to trunk.

review: Approve
Revision history for this message
Barry Warsaw (barry) :
Revision history for this message
Barry Warsaw (barry) wrote :

Ah, the fix isn't right after all. The problem is that the call to mlist.subscribe() after breaking out of the loop can subscribe the original lower case address, but it should always subscribe the case preserved address. I have to think about this.

review: Needs Fixing
Revision history for this message
Barry Warsaw (barry) wrote :

What this means is that people cannot subscribe two email addresses to a mailing list that differ only in case. In some sense this conflicts with the model, since the case-different email addresses are considered different address objects, but I still think given the stated policy of case-preserving case-insensitive addresses, this will be acceptable.

It will still probably be possible to link two addresses to the user which differ only in case, but since these can't both be subscribed to the same mailing list (with the same role), I suppose we'll have to accept this oddity.

It's also possible to subscribe a user with a preferred address that differs in case with another address object linked to the user. This is consistent with the existing semantics.

Revision history for this message
Barry Warsaw (barry) wrote :

I'm not sure how much of your original branch survived, but I gave you credit for finding the bug. Thanks! You might take a look at r7304 for details. This was a tricky and fun one.

Revision history for this message
Ankush Sharma (black-perl) wrote :

Thank you Barry for your time. I am glad you appreciated the bug find. I will surely take a look.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/mailman/app/membership.py'
--- src/mailman/app/membership.py 2015-01-05 01:22:39 +0000
+++ src/mailman/app/membership.py 2015-03-04 09:46:29 +0000
@@ -98,7 +98,7 @@
98 else:98 else:
99 # The user exists and is linked to the address.99 # The user exists and is linked to the address.
100 for address in user.addresses:100 for address in user.addresses:
101 if address.email == email:101 if address.email == email.lower():
102 break102 break
103 else:103 else:
104 raise AssertionError(104 raise AssertionError(
105105
=== modified file 'src/mailman/rest/tests/test_membership.py'
--- src/mailman/rest/tests/test_membership.py 2015-01-05 01:40:47 +0000
+++ src/mailman/rest/tests/test_membership.py 2015-03-04 09:46:29 +0000
@@ -98,6 +98,15 @@
98 self.assertEqual(cm.exception.code, 409)98 self.assertEqual(cm.exception.code, 409)
99 self.assertEqual(cm.exception.reason, b'Member already subscribed')99 self.assertEqual(cm.exception.reason, b'Member already subscribed')
100100
101 # Member subscription using case sensitive email
102 with self.assertRaises(HTTPError) as cm:
103 call_api('http://localhost:9001/3.0/members', {
104 'list_id': 'test.example.com',
105 'subscriber': 'ANNE@example.com',
106 })
107 self.assertEqual(cm.exception.code, 409)
108 self.assertEqual(cm.exception.reason, b'Member already subscribed')
109
101 def test_join_with_invalid_delivery_mode(self):110 def test_join_with_invalid_delivery_mode(self):
102 with self.assertRaises(HTTPError) as cm:111 with self.assertRaises(HTTPError) as cm:
103 call_api('http://localhost:9001/3.0/members', {112 call_api('http://localhost:9001/3.0/members', {