Test for filename using diaretics

This commit is contained in:
chrisbroderick 2022-09-08 10:05:09 +01:00
parent 357241e269
commit eca2255f56
3 changed files with 41 additions and 12 deletions

View File

@ -621,7 +621,7 @@ def extract_part_data(
if name: if name:
name = email.utils.collapse_rfc2231_value(name) name = email.utils.collapse_rfc2231_value(name)
part_body = None 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_maintype() == 'text' and name is None:
if part.get_content_subtype() == 'plain': if part.get_content_subtype() == 'plain':
part_body = part.get_payload(decode=True) 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': if part['Content-Transfer-Encoding'] == '8bit' and part.get_content_charset() == 'utf-8':
part_body = part_body.decode('unicode_escape') part_body = part_body.decode('unicode_escape')
part_body = decodeUnknown(part.get_content_charset(), part_body) 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 # the default value is False anyway
if ticket_id is None and getattr(django_settings, 'HELPDESK_FULL_FIRST_MESSAGE_FROM_EMAIL', False): 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 # first message in thread, we save full body to avoid
@ -674,12 +674,12 @@ def extract_part_data(
else: else:
if not name: if not name:
ext = mimetypes.guess_extension(part.get_content_type()) ext = mimetypes.guess_extension(part.get_content_type())
name = "part-%i%s" % (counter, ext) name = f"part-{counter}{ext}"
else: 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])) 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 return part_body, part_full_body
def object_from_message(message: str, def object_from_message(message: str,

View File

@ -19,7 +19,9 @@ from tempfile import mkdtemp
from unittest import mock from unittest import mock
from helpdesk.tests import utils from helpdesk.tests import utils
from helpdesk.exceptions import DeleteIgnoredTicketException, IgnoreTicketException 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__)) THIS_DIR = os.path.dirname(os.path.abspath(__file__))
@ -158,6 +160,18 @@ class GetEmailCommonTests(TestCase):
with self.assertRaises(IgnoreTicketException): with self.assertRaises(IgnoreTicketException):
object_from_message(message.as_string(), self.queue_public, self.logger); 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): class GetEmailParametricTemplate(object):
"""TestCase that checks basic email functionality across methods and socks configs.""" """TestCase that checks basic email functionality across methods and socks configs."""

View File

@ -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 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 = MIMEBase('application', 'octet-stream')
part.set_payload(get_fake("text", locale=locale, min_length=1024)) 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 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 = MIMEImage(generate_random_image(image_format="JPEG"))
part.set_payload(get_fake("text", locale=locale, min_length=1024)) 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) part.add_header('Content-Disposition', "attachment; filename= %s" % imagename)
return part 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 use_short_email: bool=False
) -> typing.Tuple[typing.Tuple[str, str], typing.Tuple[str, str]]: ) -> typing.Tuple[typing.Tuple[str, str], typing.Tuple[str, str]]:
""" """
@ -228,7 +243,7 @@ def generate_multipart_email(locale: str="en_US",
msg = MIMEMultipart() msg = MIMEMultipart()
for part_type in type_list: for part_type in type_list:
msg.append(generate_mime_part(locale=locale, part_type=part_type, use_short_email=use_short_email)) 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 return msg, from_meta, to_meta
def generate_text_email(locale: str="en_US", 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) body = get_fake("text", locale=locale, min_length=1024)
msg = MIMEText(body) 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 return msg, from_meta, to_meta
def generate_html_email(locale: str="en_US", 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) body = get_fake_html(locale=locale)
msg = MIMEText(body) 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 return msg, from_meta, to_meta