handlers/decorate.py can throw AttributeError when messages are VERPed or personalized
Here's a traceback:
Feb 01 18:42:42 2018 (27222) Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman
/core/runner.py", line 173, in _one_iteration
self._process_one_file(msg, msgdata)
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/core/runner.py", line 266, in _process_one_file
keepqueued = self._dispose(mlist, msg, msgdata)
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/runners/outgoing.py", line 93, in _dispose
self._func(mlist, msg, msgdata)
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/mta/deliver.py", line 86, in deliver
refused = agent.deliver(mlist, msg, msgdata)
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/mta/base.py", line 163, in deliver
callback(mlist, message_copy, msgdata_copy)
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/mta/decorating.py", line 32, in decorate
decorator.process(mlist, msg, msgdata)
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/handlers/decorate.py", line 247, in process
process(mlist, msg, msgdata)
File "/usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/handlers/decorate.py", line 51, in process
(member.subscriber.display_name, member.subscriber.email))
AttributeError: 'User' object has no attribute 'email'
The issue is that while member.subscriber is usually an Address instance, it's sometimes a User instance.
I've fixed this with:
--- ../git/mailman/src/mailman/handlers/decorate.py 2017-01-04 19:52:22.617368870 +0000
+++ /usr/local/lib/python3.6/site-packages/mailman-3.2.0a1-py3.6.egg/mailman/handlers/decorate.py 2018-02-02 01:37:09.055692110 +0000
@@ -47,8 +47,13 @@
if member is not None:
# Calculate the extra personalization dictionary.
recipient = msgdata.get('recipient', member.address.original_email)
+ # member.subscriber can be a User instance or an Address instance.
+ if member._address is not None:
+ member_address = member._address.email
+ else:
+ member_address = member._user.preferred_address.email
d['member'] = formataddr(
- (member.subscriber.display_name, member.subscriber.email))
+ (member.subscriber.display_name, member_address))
d['user_email'] = recipient
d['user_delivered_to'] = member.address.original_email
d['user_language'] = member.preferred_language.description
I think this is good, but I'll work on tests and an MR