1
0
Fork 1
mirror of https://github.com/coddingtonbear/django-mailbox.git synced 2026-07-10 06:48:19 +02:00

[#130] Fix handling of single-byte filenames in attachment headers; among other unicode handling fixes.

This commit is contained in:
Adam Coddington 2017-03-05 21:31:22 -08:00
parent 81d6648e8c
commit 2df2d8a4fc
4 changed files with 50 additions and 15 deletions

View file

@ -642,8 +642,12 @@ class Message(models.Model):
if they are encoded as such.
"""
settings = utils.get_settings()
if self.encoded:
return base64.b64decode(self.body.encode('ascii'))
return base64.b64decode(
self.body.encode(settings['default_charset'], 'replace')
)
return self.body.encode('utf-8')
def set_body(self, body):
@ -654,10 +658,16 @@ class Message(models.Model):
no fields existed for storing arbitrary bytes.
"""
if six.PY3:
settings = utils.get_settings()
if six.PY3 and isinstance(body, six.text_type):
body = body.encode('utf-8')
self.encoded = True
self.body = base64.b64encode(body).decode('ascii')
self.body = base64.b64encode(body).decode(
settings['default_charset'],
'replace',
)
def get_email_object(self):
"""Returns an `email.message.Message` instance representing the
@ -726,18 +736,24 @@ class MessageAttachment(models.Model):
return super(MessageAttachment, self).delete(*args, **kwargs)
def _get_rehydrated_headers(self):
settings = utils.get_settings()
headers = self.headers
if headers is None:
return EmailMessage()
if sys.version_info < (3, 0):
try:
headers = headers.encode('utf-8')
except UnicodeDecodeError:
headers = unicode(headers, 'utf-8').encode('utf-8')
if not six.PY3:
headers = headers.encode(settings['default_charset'], 'replace')
return email.message_from_string(headers)
def _set_dehydrated_headers(self, email_object):
self.headers = email_object.as_string()
settings = utils.get_settings()
headers = email_object.as_string()
if isinstance(headers, six.binary_type):
headers = headers.decode(settings['default_charset'], 'replace')
self.headers = headers
def __delitem__(self, name):
rehydrated = self._get_rehydrated_headers()
@ -745,7 +761,16 @@ class MessageAttachment(models.Model):
self._set_dehydrated_headers(rehydrated)
def __setitem__(self, name, value):
settings = utils.get_settings()
rehydrated = self._get_rehydrated_headers()
if isinstance(value, six.binary_type):
# Ensure that no values in the bytestring cannot be encoded
# in the default charset
value = value.decode(
settings['default_charset'],
'replace'
).encode(settings['default_charset'], 'replace')
rehydrated[name] = value
self._set_dehydrated_headers(rehydrated)

View file

@ -4,11 +4,12 @@ import sys
import mock
import six
from django.core.mail import EmailMessage
from django_mailbox.models import Mailbox, Message
from django_mailbox.utils import convert_header_to_unicode
from django_mailbox.tests.base import EmailMessageTestCase
from django.test.utils import override_settings
from django.utils.encoding import force_text
from django.core.mail import EmailMessage
__all__ = ['TestProcessEmail']
@ -88,7 +89,7 @@ class TestProcessEmail(EmailMessageTestCase):
)
def test_message_with_not_decoded_attachment_header(self):
if sys.version_info > (3, 0):
if not six.PY3:
self.skipTest(
"This test is only relevant on Python 2.x."
)
@ -145,14 +146,17 @@ class TestProcessEmail(EmailMessageTestCase):
u'odpowied\u017a Burmistrza.jpg'
)
@override_settings(
DJANGO_MAILBOX_DEFAULT_CHARSET='iso8859-2'
)
def test_message_with_utf_headers_in_attachments(self):
email_object = self._get_email_object(
'message_with_utf8_headers_in_attachment.eml',
'message_with_iso8859-2_attachment_filename.eml',
)
mailbox = Mailbox.objects.create()
msg = mailbox.process_incoming_message(email_object)
expected_count = 2
expected_count = 1
actual_count = msg.attachments.count()
self.assertEqual(
@ -160,7 +164,13 @@ class TestProcessEmail(EmailMessageTestCase):
actual_count,
)
# TODO: Verify filenames
expected_filename = (
u'Odp. na wniosek o udost\u0119pnienie '
u'inf. publicznej.jpg'
)
actual_filename = msg.attachments.all()[0].get_filename()
self.assertEqual(expected_filename, actual_filename)
def test_message_get_text_body(self):
message = self._get_email_object('multipart_text.eml')

View file

@ -56,7 +56,7 @@ def get_settings():
),
'default_charset': getattr(
settings,
'DJANGO_MAILBOX_default_charset',
'DJANGO_MAILBOX_DEFAULT_CHARSET',
'iso8859-1',
)
}