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:
parent
81d6648e8c
commit
2df2d8a4fc
4 changed files with 50 additions and 15 deletions
|
|
@ -642,8 +642,12 @@ class Message(models.Model):
|
||||||
if they are encoded as such.
|
if they are encoded as such.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
settings = utils.get_settings()
|
||||||
|
|
||||||
if self.encoded:
|
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')
|
return self.body.encode('utf-8')
|
||||||
|
|
||||||
def set_body(self, body):
|
def set_body(self, body):
|
||||||
|
|
@ -654,10 +658,16 @@ class Message(models.Model):
|
||||||
no fields existed for storing arbitrary bytes.
|
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')
|
body = body.encode('utf-8')
|
||||||
|
|
||||||
self.encoded = True
|
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):
|
def get_email_object(self):
|
||||||
"""Returns an `email.message.Message` instance representing the
|
"""Returns an `email.message.Message` instance representing the
|
||||||
|
|
@ -726,18 +736,24 @@ class MessageAttachment(models.Model):
|
||||||
return super(MessageAttachment, self).delete(*args, **kwargs)
|
return super(MessageAttachment, self).delete(*args, **kwargs)
|
||||||
|
|
||||||
def _get_rehydrated_headers(self):
|
def _get_rehydrated_headers(self):
|
||||||
|
settings = utils.get_settings()
|
||||||
|
|
||||||
headers = self.headers
|
headers = self.headers
|
||||||
if headers is None:
|
if headers is None:
|
||||||
return EmailMessage()
|
return EmailMessage()
|
||||||
if sys.version_info < (3, 0):
|
if not six.PY3:
|
||||||
try:
|
headers = headers.encode(settings['default_charset'], 'replace')
|
||||||
headers = headers.encode('utf-8')
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
headers = unicode(headers, 'utf-8').encode('utf-8')
|
|
||||||
return email.message_from_string(headers)
|
return email.message_from_string(headers)
|
||||||
|
|
||||||
def _set_dehydrated_headers(self, email_object):
|
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):
|
def __delitem__(self, name):
|
||||||
rehydrated = self._get_rehydrated_headers()
|
rehydrated = self._get_rehydrated_headers()
|
||||||
|
|
@ -745,7 +761,16 @@ class MessageAttachment(models.Model):
|
||||||
self._set_dehydrated_headers(rehydrated)
|
self._set_dehydrated_headers(rehydrated)
|
||||||
|
|
||||||
def __setitem__(self, name, value):
|
def __setitem__(self, name, value):
|
||||||
|
settings = utils.get_settings()
|
||||||
|
|
||||||
rehydrated = self._get_rehydrated_headers()
|
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
|
rehydrated[name] = value
|
||||||
self._set_dehydrated_headers(rehydrated)
|
self._set_dehydrated_headers(rehydrated)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,12 @@ import sys
|
||||||
import mock
|
import mock
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from django.core.mail import EmailMessage
|
||||||
from django_mailbox.models import Mailbox, Message
|
from django_mailbox.models import Mailbox, Message
|
||||||
from django_mailbox.utils import convert_header_to_unicode
|
from django_mailbox.utils import convert_header_to_unicode
|
||||||
from django_mailbox.tests.base import EmailMessageTestCase
|
from django_mailbox.tests.base import EmailMessageTestCase
|
||||||
|
from django.test.utils import override_settings
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.core.mail import EmailMessage
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['TestProcessEmail']
|
__all__ = ['TestProcessEmail']
|
||||||
|
|
@ -88,7 +89,7 @@ class TestProcessEmail(EmailMessageTestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_message_with_not_decoded_attachment_header(self):
|
def test_message_with_not_decoded_attachment_header(self):
|
||||||
if sys.version_info > (3, 0):
|
if not six.PY3:
|
||||||
self.skipTest(
|
self.skipTest(
|
||||||
"This test is only relevant on Python 2.x."
|
"This test is only relevant on Python 2.x."
|
||||||
)
|
)
|
||||||
|
|
@ -145,14 +146,17 @@ class TestProcessEmail(EmailMessageTestCase):
|
||||||
u'odpowied\u017a Burmistrza.jpg'
|
u'odpowied\u017a Burmistrza.jpg'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
DJANGO_MAILBOX_DEFAULT_CHARSET='iso8859-2'
|
||||||
|
)
|
||||||
def test_message_with_utf_headers_in_attachments(self):
|
def test_message_with_utf_headers_in_attachments(self):
|
||||||
email_object = self._get_email_object(
|
email_object = self._get_email_object(
|
||||||
'message_with_utf8_headers_in_attachment.eml',
|
'message_with_iso8859-2_attachment_filename.eml',
|
||||||
)
|
)
|
||||||
mailbox = Mailbox.objects.create()
|
mailbox = Mailbox.objects.create()
|
||||||
msg = mailbox.process_incoming_message(email_object)
|
msg = mailbox.process_incoming_message(email_object)
|
||||||
|
|
||||||
expected_count = 2
|
expected_count = 1
|
||||||
actual_count = msg.attachments.count()
|
actual_count = msg.attachments.count()
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|
@ -160,7 +164,13 @@ class TestProcessEmail(EmailMessageTestCase):
|
||||||
actual_count,
|
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):
|
def test_message_get_text_body(self):
|
||||||
message = self._get_email_object('multipart_text.eml')
|
message = self._get_email_object('multipart_text.eml')
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ def get_settings():
|
||||||
),
|
),
|
||||||
'default_charset': getattr(
|
'default_charset': getattr(
|
||||||
settings,
|
settings,
|
||||||
'DJANGO_MAILBOX_default_charset',
|
'DJANGO_MAILBOX_DEFAULT_CHARSET',
|
||||||
'iso8859-1',
|
'iso8859-1',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue