summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mailman/app/bounces.py5
-rw-r--r--src/mailman/app/moderator.py4
-rw-r--r--src/mailman/archiving/mailarchive.py2
-rw-r--r--src/mailman/archiving/mhonarc.py2
-rw-r--r--src/mailman/archiving/prototype.py2
-rw-r--r--src/mailman/commands/docs/unshunt.rst2
-rw-r--r--src/mailman/commands/eml_membership.py2
-rw-r--r--src/mailman/email/message.py44
-rw-r--r--src/mailman/email/tests/test_message.py35
-rw-r--r--src/mailman/model/bounce.py5
-rw-r--r--src/mailman/model/messagestore.py2
-rw-r--r--src/mailman/rules/implicit_dest.py2
-rw-r--r--src/mailman/utilities/email.py2
13 files changed, 68 insertions, 41 deletions
diff --git a/src/mailman/app/bounces.py b/src/mailman/app/bounces.py
index 101d96f2a..89fff9beb 100644
--- a/src/mailman/app/bounces.py
+++ b/src/mailman/app/bounces.py
@@ -200,10 +200,13 @@ def send_probe(member, msg):
optionsurl=member.options_url,
owneraddr=mlist.owner_address,
)
+ message_id = msg['message-id']
+ if not isinstance(message_id, unicode):
+ message_id = message_id.decode("ascii")
pendable = _ProbePendable(
# We can only pend unicodes.
member_id=member.member_id.hex,
- message_id=msg['message-id'],
+ message_id=message_id,
)
token = getUtility(IPendings).add(pendable)
mailbox, domain_parts = split_email(mlist.bounces_address)
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py
index 78332b84a..2fba8c4ac 100644
--- a/src/mailman/app/moderator.py
+++ b/src/mailman/app/moderator.py
@@ -87,8 +87,8 @@ def hold_message(mlist, msg, msgdata=None, reason=None):
message_id = msg.get('message-id')
if message_id is None:
msg['Message-ID'] = message_id = unicode(make_msgid())
- assert isinstance(message_id, unicode), (
- 'Message-ID is not a unicode: %s' % message_id)
+ if not isinstance(message_id, unicode):
+ message_id = message_id.decode("ascii")
getUtility(IMessageStore).add(msg)
# Prepare the message metadata with some extra information needed only by
# the moderation interface.
diff --git a/src/mailman/archiving/mailarchive.py b/src/mailman/archiving/mailarchive.py
index 421d65cbd..120ed6865 100644
--- a/src/mailman/archiving/mailarchive.py
+++ b/src/mailman/archiving/mailarchive.py
@@ -68,6 +68,8 @@ class MailArchive:
message_id_hash = msg.get('x-message-id-hash')
if message_id_hash is None:
return None
+ if not isinstance(message_id_hash, unicode):
+ message_id_hash = message_id_hash.decode("ascii")
return urljoin(self.base_url, message_id_hash)
def archive_message(self, mlist, msg):
diff --git a/src/mailman/archiving/mhonarc.py b/src/mailman/archiving/mhonarc.py
index 4606925e0..815ab0855 100644
--- a/src/mailman/archiving/mhonarc.py
+++ b/src/mailman/archiving/mhonarc.py
@@ -73,6 +73,8 @@ class MHonArc:
message_id_hash = msg.get('x-message-id-hash')
if message_id_hash is None:
return None
+ if not isinstance(message_id_hash, unicode):
+ message_id_hash = message_id_hash.decode("ascii")
return urljoin(self.list_url(mlist), message_id_hash)
def archive_message(self, mlist, msg):
diff --git a/src/mailman/archiving/prototype.py b/src/mailman/archiving/prototype.py
index 153c44b69..54dc30c89 100644
--- a/src/mailman/archiving/prototype.py
+++ b/src/mailman/archiving/prototype.py
@@ -68,6 +68,8 @@ class Prototype:
message_id_hash = msg.get('x-message-id-hash')
if message_id_hash is None:
return None
+ if not isinstance(message_id_hash, unicode):
+ message_id_hash = message_id_hash.decode("ascii")
return urljoin(Prototype.list_url(mlist), message_id_hash)
@staticmethod
diff --git a/src/mailman/commands/docs/unshunt.rst b/src/mailman/commands/docs/unshunt.rst
index 93d89f001..9532ae029 100644
--- a/src/mailman/commands/docs/unshunt.rst
+++ b/src/mailman/commands/docs/unshunt.rst
@@ -83,7 +83,7 @@ queue.
2
>>> sorted(item.msg['message-id'] for item in items)
- [u'<badgers>', u'<crow>']
+ ['<badgers>', '<crow>']
Return to the original queue
diff --git a/src/mailman/commands/eml_membership.py b/src/mailman/commands/eml_membership.py
index 617807783..542e6fd4d 100644
--- a/src/mailman/commands/eml_membership.py
+++ b/src/mailman/commands/eml_membership.py
@@ -72,6 +72,8 @@ used.
print(_('$self.name: No valid address found to subscribe'),
file=results)
return ContinueProcessing.no
+ if not isinstance(address, unicode):
+ address = address.decode("ascii")
# Have we already seen one join request from this user during the
# processing of this email?
joins = getattr(results, 'joins', set())
diff --git a/src/mailman/email/message.py b/src/mailman/email/message.py
index f3a44e63c..21bdfd30d 100644
--- a/src/mailman/email/message.py
+++ b/src/mailman/email/message.py
@@ -53,29 +53,6 @@ class Message(email.message.Message):
self.__version__ = VERSION
email.message.Message.__init__(self)
- def __getitem__(self, key):
- # Ensure that header values are unicodes.
- value = email.message.Message.__getitem__(self, key)
- if isinstance(value, str):
- return unicode(value, 'ascii')
- return value
-
- def get(self, name, failobj=None):
- # Ensure that header values are unicodes.
- value = email.message.Message.get(self, name, failobj)
- if isinstance(value, str):
- return unicode(value, 'ascii')
- return value
-
- def get_all(self, name, failobj=None):
- # Ensure all header values are unicodes.
- missing = object()
- all_values = email.message.Message.get_all(self, name, missing)
- if all_values is missing:
- return failobj
- return [(unicode(value, 'ascii') if isinstance(value, str) else value)
- for value in all_values]
-
# BAW: For debugging w/ bin/dumpdb. Apparently pprint uses repr.
def __repr__(self):
return self.__str__()
@@ -144,18 +121,15 @@ class Message(email.message.Message):
field_values = self.get_all(header, [])
senders.extend(address.lower() for (display_name, address)
in email.utils.getaddresses(field_values))
- # Filter out None and the empty string.
- return [sender for sender in senders if sender]
-
- def get_filename(self, failobj=None):
- """Some MUA have bugs in RFC2231 filename encoding and cause
- Mailman to stop delivery in Scrubber.py (called from ToDigest.py).
- """
- try:
- filename = email.message.Message.get_filename(self, failobj)
- return filename
- except (UnicodeError, LookupError, ValueError):
- return failobj
+ # Filter out None and the empty string, and convert to unicode.
+ clean_senders = []
+ for sender in senders:
+ if not sender:
+ continue
+ if not isinstance(sender, unicode):
+ sender = sender.decode("ascii")
+ clean_senders.append(sender)
+ return clean_senders
diff --git a/src/mailman/email/tests/test_message.py b/src/mailman/email/tests/test_message.py
index e281c0d06..54519fa6b 100644
--- a/src/mailman/email/tests/test_message.py
+++ b/src/mailman/email/tests/test_message.py
@@ -26,9 +26,10 @@ __all__ = [
import unittest
+from email.parser import FeedParser
from mailman.app.lifecycle import create_list
-from mailman.email.message import UserNotification
+from mailman.email.message import UserNotification, Message
from mailman.testing.helpers import get_queue_messages
from mailman.testing.layers import ConfigLayer
@@ -58,3 +59,35 @@ class TestMessage(unittest.TestCase):
self.assertEqual(len(messages), 1)
self.assertEqual(messages[0].msg.get_all('precedence'),
['omg wtf bbq'])
+
+
+
+class TestMessageSubclass(unittest.TestCase):
+
+ def test_i18n_filenames(self):
+ parser = FeedParser(_factory=Message)
+ parser.feed(b"""Message-ID: <blah@example.com>
+Content-Type: multipart/mixed; boundary="------------050607040206050605060208"
+
+This is a multi-part message in MIME format.
+--------------050607040206050605060208
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: quoted-printable
+
+Test message containing an attachment with an accented filename
+
+--------------050607040206050605060208
+Content-Disposition: attachment;
+ filename*=UTF-8''d%C3%A9jeuner.txt
+
+Test content
+--------------050607040206050605060208--
+""")
+ msg = parser.close()
+ attachment = msg.get_payload()[1]
+ try:
+ filename = attachment.get_filename()
+ except TypeError, e:
+ raise
+ self.fail(e)
+ self.assertEqual(filename, u"d\xe9jeuner.txt")
diff --git a/src/mailman/model/bounce.py b/src/mailman/model/bounce.py
index cd658052d..c2f22eee9 100644
--- a/src/mailman/model/bounce.py
+++ b/src/mailman/model/bounce.py
@@ -57,7 +57,10 @@ class BounceEvent(Model):
self.list_id = list_id
self.email = email
self.timestamp = now()
- self.message_id = msg['message-id']
+ msgid = msg['message-id']
+ if not isinstance(msgid, unicode):
+ msgid = msgid.decode("ascii")
+ self.message_id = msgid
self.context = (BounceContext.normal if context is None else context)
self.processed = False
diff --git a/src/mailman/model/messagestore.py b/src/mailman/model/messagestore.py
index 19fa8133f..41c2ad8d8 100644
--- a/src/mailman/model/messagestore.py
+++ b/src/mailman/model/messagestore.py
@@ -58,6 +58,8 @@ class MessageStore:
raise ValueError('Exactly one Message-ID header required')
# Calculate and insert the X-Message-ID-Hash.
message_id = message_ids[0]
+ if not isinstance(message_id, unicode):
+ message_id = message_id.decode("ascii")
# Complain if the Message-ID already exists in the storage.
existing = store.query(Message).filter(
Message.message_id == message_id).first()
diff --git a/src/mailman/rules/implicit_dest.py b/src/mailman/rules/implicit_dest.py
index 8bfb0d2e0..507701ef6 100644
--- a/src/mailman/rules/implicit_dest.py
+++ b/src/mailman/rules/implicit_dest.py
@@ -73,6 +73,8 @@ class ImplicitDestination:
recipients = set()
for header in ('to', 'cc', 'resent-to', 'resent-cc'):
for fullname, address in getaddresses(msg.get_all(header, [])):
+ if not isinstance(address, unicode):
+ address = address.decode("ascii")
address = address.lower()
if address in aliases:
return False
diff --git a/src/mailman/utilities/email.py b/src/mailman/utilities/email.py
index 7025ddb89..91c8246af 100644
--- a/src/mailman/utilities/email.py
+++ b/src/mailman/utilities/email.py
@@ -62,6 +62,8 @@ def add_message_hash(msg):
message_id = msg.get('message-id')
if message_id is None:
return
+ if not isinstance(message_id, unicode):
+ message_id = message_id.decode("ascii")
# The angle brackets are not part of the Message-ID. See RFC 2822
# and http://wiki.list.org/display/DEV/Stable+URLs
if message_id.startswith('<') and message_id.endswith('>'):