From eca2255f56f85b3c8c60bfa42822bf013ed08d18 Mon Sep 17 00:00:00 2001 From: chrisbroderick Date: Thu, 8 Sep 2022 10:05:09 +0100 Subject: [PATCH] Test for filename using diaretics --- helpdesk/email.py | 10 +++++----- helpdesk/tests/test_get_email.py | 16 +++++++++++++++- helpdesk/tests/utils.py | 27 +++++++++++++++++++++------ 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/helpdesk/email.py b/helpdesk/email.py index 7c83f7db..7e0de522 100644 --- a/helpdesk/email.py +++ b/helpdesk/email.py @@ -621,7 +621,7 @@ def extract_part_data( if name: name = email.utils.collapse_rfc2231_value(name) part_body = None - part_full_body=None + part_full_body = None if part.get_content_maintype() == 'text' and name is None: if part.get_content_subtype() == 'plain': part_body = part.get_payload(decode=True) @@ -629,7 +629,7 @@ def extract_part_data( if part['Content-Transfer-Encoding'] == '8bit' and part.get_content_charset() == 'utf-8': part_body = part_body.decode('unicode_escape') part_body = decodeUnknown(part.get_content_charset(), part_body) - # have to use django_settings here so overwritting it works in tests + # have to use django_settings here so overwriting it works in tests # the default value is False anyway if ticket_id is None and getattr(django_settings, 'HELPDESK_FULL_FIRST_MESSAGE_FROM_EMAIL', False): # first message in thread, we save full body to avoid @@ -674,12 +674,12 @@ def extract_part_data( else: if not name: ext = mimetypes.guess_extension(part.get_content_type()) - name = "part-%i%s" % (counter, ext) + name = f"part-{counter}{ext}" else: - name = ("part-%i_" % counter) + name + name = f"part-{counter}_{name}" files.append(SimpleUploadedFile(name, part.get_payload(decode=True), mimetypes.guess_type(name)[0])) - logger.debug("Found MIME attachment %s" % name) + logger.debug("Found MIME attachment %s", name) return part_body, part_full_body def object_from_message(message: str, diff --git a/helpdesk/tests/test_get_email.py b/helpdesk/tests/test_get_email.py index df59fe80..14f8398e 100644 --- a/helpdesk/tests/test_get_email.py +++ b/helpdesk/tests/test_get_email.py @@ -19,7 +19,9 @@ from tempfile import mkdtemp from unittest import mock from helpdesk.tests import utils from helpdesk.exceptions import DeleteIgnoredTicketException, IgnoreTicketException -from helpdesk.email import object_from_message +from helpdesk.email import object_from_message, extract_part_data +from django.core.files.uploadedfile import SimpleUploadedFile +import typing THIS_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -158,6 +160,18 @@ class GetEmailCommonTests(TestCase): with self.assertRaises(IgnoreTicketException): object_from_message(message.as_string(), self.queue_public, self.logger); + def test_utf8_filename_attachment(self): + """ + Tests if an attachment correctly sent with a UTF8 filename in disposition is extracted correctly + """ + filename = "TeléfonoMañana.txt" + part = utils.generate_file_mime_part(locale="es_ES", filename=filename) + files: typing.List[SimpleUploadedFile] = [] + extract_part_data(part, counter=1, ticket_id="tst1", files=files, logger=self.logger) + sent_file: SimpleUploadedFile = files[0] + # The extractor prepends a part identifier so compare the ending + self.assertTrue(sent_file.name.endswith(filename), f"Filename extracted does not match: {sent_file.name}") + class GetEmailParametricTemplate(object): """TestCase that checks basic email functionality across methods and socks configs.""" diff --git a/helpdesk/tests/utils.py b/helpdesk/tests/utils.py index 3ae7f843..38ddcd53 100644 --- a/helpdesk/tests/utils.py +++ b/helpdesk/tests/utils.py @@ -144,7 +144,7 @@ def generate_file_mime_part(locale: str="en_US",filename: str = None) -> Message """ :param locale: change this to generate locale specific file name and attachment content - :param filename: pass a file name if you want t ospecify a specific name otherwise a random name will be generated + :param filename: pass a file name if you want to specify a specific name otherwise a random name will be generated """ part = MIMEBase('application', 'octet-stream') part.set_payload(get_fake("text", locale=locale, min_length=1024)) @@ -158,7 +158,7 @@ def generate_image_mime_part(locale: str="en_US",imagename: str = None) -> Messa """ :param locale: change this to generate locale specific file name and attachment content - :param filename: pass a file name if you want t ospecify a specific name otherwise a random name will be generated + :param filename: pass a file name if you want to specify a specific name otherwise a random name will be generated """ part = MIMEImage(generate_random_image(image_format="JPEG")) part.set_payload(get_fake("text", locale=locale, min_length=1024)) @@ -168,7 +168,22 @@ def generate_image_mime_part(locale: str="en_US",imagename: str = None) -> Messa part.add_header('Content-Disposition', "attachment; filename= %s" % imagename) return part -def add_email_headers(message: Message, locale: str="en_US", +def generate_email_list(address_cnt: int = 3, + locale: str="en_US", + use_short_email: bool=False + ) -> str: + """ + Generates a list of email addresses formatted for email headers on a Mime part + + :param address_cnt: the number of email addresses to string together + :param locale: change this to generate locale specific "real names" and subject + :param use_short_email: produces a email address without "real name" if True + + """ + email_address_list = [generate_email_address(locale, use_short_email=use_short_email)[0] for _ in range(0, address_cnt)] + return ",".join(email_address_list) + +def add_simple_email_headers(message: Message, locale: str="en_US", use_short_email: bool=False ) -> typing.Tuple[typing.Tuple[str, str], typing.Tuple[str, str]]: """ @@ -228,7 +243,7 @@ def generate_multipart_email(locale: str="en_US", msg = MIMEMultipart() for part_type in type_list: msg.append(generate_mime_part(locale=locale, part_type=part_type, use_short_email=use_short_email)) - from_meta, to_meta = add_email_headers(msg, locale=locale, use_short_email=use_short_email) + from_meta, to_meta = add_simple_email_headers(msg, locale=locale, use_short_email=use_short_email) return msg, from_meta, to_meta def generate_text_email(locale: str="en_US", @@ -239,7 +254,7 @@ def generate_text_email(locale: str="en_US", """ body = get_fake("text", locale=locale, min_length=1024) msg = MIMEText(body) - from_meta, to_meta = add_email_headers(msg, locale=locale, use_short_email=use_short_email) + from_meta, to_meta = add_simple_email_headers(msg, locale=locale, use_short_email=use_short_email) return msg, from_meta, to_meta def generate_html_email(locale: str="en_US", @@ -250,5 +265,5 @@ def generate_html_email(locale: str="en_US", """ body = get_fake_html(locale=locale) msg = MIMEText(body) - from_meta, to_meta = add_email_headers(msg, locale=locale, use_short_email=use_short_email) + from_meta, to_meta = add_simple_email_headers(msg, locale=locale, use_short_email=use_short_email) return msg, from_meta, to_meta