mirror of
https://gitea.mueller.network/extern/django-helpdesk.git
synced 2024-11-22 16:03:19 +01:00
Fix #1054
This commit is contained in:
parent
0d810d6102
commit
b3edba3fc5
@ -478,7 +478,11 @@ def create_object_from_email_message(message, ticket_id, payload, files, logger)
|
|||||||
|
|
||||||
logger.info("[%s-%s] %s" % (ticket.queue.slug, ticket.id, ticket.title,))
|
logger.info("[%s-%s] %s" % (ticket.queue.slug, ticket.id, ticket.title,))
|
||||||
|
|
||||||
|
try:
|
||||||
attached = process_attachments(f, files)
|
attached = process_attachments(f, files)
|
||||||
|
except ValidationError as e:
|
||||||
|
logger.error(str(e))
|
||||||
|
else:
|
||||||
for att_file in attached:
|
for att_file in attached:
|
||||||
logger.info(
|
logger.info(
|
||||||
"Attachment '%s' (with size %s) successfully added to ticket from email.",
|
"Attachment '%s' (with size %s) successfully added to ticket from email.",
|
||||||
|
@ -7,6 +7,7 @@ forms.py - Definitions of newforms-based forms for creating and maintaining
|
|||||||
tickets.
|
tickets.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -33,6 +34,7 @@ from helpdesk.settings import (
|
|||||||
CUSTOMFIELD_TIME_FORMAT,
|
CUSTOMFIELD_TIME_FORMAT,
|
||||||
CUSTOMFIELD_TO_FIELD_DICT
|
CUSTOMFIELD_TO_FIELD_DICT
|
||||||
)
|
)
|
||||||
|
from helpdesk.validators import validate_file_extension
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
@ -243,6 +245,7 @@ class AbstractTicketForm(CustomFieldMixin, forms.Form):
|
|||||||
'Only file types such as plain text (.txt), '
|
'Only file types such as plain text (.txt), '
|
||||||
'a document (.pdf, .docx, or .odt), '
|
'a document (.pdf, .docx, or .odt), '
|
||||||
'or screenshot (.png or .jpg) may be uploaded.'),
|
'or screenshot (.png or .jpg) may be uploaded.'),
|
||||||
|
validators=[validate_file_extension]
|
||||||
)
|
)
|
||||||
|
|
||||||
class Media:
|
class Media:
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.core import mail
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
@ -36,7 +37,7 @@ unused_port = "49151"
|
|||||||
class GetEmailCommonTests(TestCase):
|
class GetEmailCommonTests(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.queue_public = Queue.objects.create()
|
self.queue_public = Queue.objects.create(title='Test', slug='test')
|
||||||
self.logger = logging.getLogger('helpdesk')
|
self.logger = logging.getLogger('helpdesk')
|
||||||
|
|
||||||
# tests correct syntax for command line option
|
# tests correct syntax for command line option
|
||||||
@ -147,7 +148,7 @@ class GetEmailCommonTests(TestCase):
|
|||||||
ignore = IgnoreEmail(name="Test Ignore", email_address=from_meta[1], keep_in_mailbox=False)
|
ignore = IgnoreEmail(name="Test Ignore", email_address=from_meta[1], keep_in_mailbox=False)
|
||||||
ignore.save()
|
ignore.save()
|
||||||
with self.assertRaises(DeleteIgnoredTicketException):
|
with self.assertRaises(DeleteIgnoredTicketException):
|
||||||
object_from_message(message.as_string(), self.queue_public, self.logger);
|
object_from_message(message.as_string(), self.queue_public, self.logger)
|
||||||
|
|
||||||
def test_will_not_delete_ignored_email(self):
|
def test_will_not_delete_ignored_email(self):
|
||||||
"""
|
"""
|
||||||
@ -158,7 +159,7 @@ class GetEmailCommonTests(TestCase):
|
|||||||
ignore = IgnoreEmail(name="Test Ignore", email_address=from_meta[1], keep_in_mailbox=True)
|
ignore = IgnoreEmail(name="Test Ignore", email_address=from_meta[1], keep_in_mailbox=True)
|
||||||
ignore.save()
|
ignore.save()
|
||||||
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):
|
def test_utf8_filename_attachment(self):
|
||||||
"""
|
"""
|
||||||
@ -172,6 +173,26 @@ class GetEmailCommonTests(TestCase):
|
|||||||
# The extractor prepends a part identifier so compare the ending
|
# 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}")
|
self.assertTrue(sent_file.name.endswith(filename), f"Filename extracted does not match: {sent_file.name}")
|
||||||
|
|
||||||
|
@override_settings(VALID_EXTENSIONS=['.png'])
|
||||||
|
def test_wrong_extension_attachment(self):
|
||||||
|
"""
|
||||||
|
Tests if an attachment with a wrong extension doesn't stop the email process
|
||||||
|
"""
|
||||||
|
message, _, _ = utils.generate_multipart_email(type_list=['plain', 'image'])
|
||||||
|
|
||||||
|
self.assertEqual(len(mail.outbox), 0)
|
||||||
|
|
||||||
|
with self.assertLogs(logger='helpdesk', level='ERROR') as cm:
|
||||||
|
object_from_message(message.as_string(), self.queue_public, self.logger)
|
||||||
|
|
||||||
|
self.assertIn(
|
||||||
|
"ERROR:helpdesk:{'file': ['Unsupported file extension: .jpg']}",
|
||||||
|
cm.output
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
|
self.assertEqual(f'[test-1] {message.get("subject")} (Opened)', mail.outbox[0].subject)
|
||||||
|
|
||||||
|
|
||||||
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."""
|
||||||
|
@ -161,7 +161,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 to specify 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", array_dims=(200, 200)))
|
||||||
part.set_payload(get_fake("text", locale=locale, min_length=1024))
|
part.set_payload(get_fake("text", locale=locale, min_length=1024))
|
||||||
encoders.encode_base64(part)
|
encoders.encode_base64(part)
|
||||||
if not imagename:
|
if not imagename:
|
||||||
@ -206,7 +206,7 @@ def add_simple_email_headers(message: Message, locale: str="en_US",
|
|||||||
def generate_mime_part(locale: str="en_US",
|
def generate_mime_part(locale: str="en_US",
|
||||||
part_type: str="plain",
|
part_type: str="plain",
|
||||||
use_short_email: bool=False
|
use_short_email: bool=False
|
||||||
) -> typing.Tuple[Message, typing.Tuple[str, str], typing.Tuple[str, str]]:
|
) -> typing.Optional[Message]:
|
||||||
"""
|
"""
|
||||||
Generates amime part of the sepecified type
|
Generates amime part of the sepecified type
|
||||||
|
|
||||||
@ -222,10 +222,8 @@ def generate_mime_part(locale: str="en_US",
|
|||||||
msg = MIMEText(body)
|
msg = MIMEText(body)
|
||||||
elif "file" == part_type:
|
elif "file" == part_type:
|
||||||
msg = generate_file_mime_part(locale=locale)
|
msg = generate_file_mime_part(locale=locale)
|
||||||
msg = MIMEText(body)
|
|
||||||
elif "image" == part_type:
|
elif "image" == part_type:
|
||||||
msg = generate_image_mime_part(locale=locale)
|
msg = generate_image_mime_part(locale=locale)
|
||||||
msg = MIMEText(body)
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Mime part not implemented: " + part_type)
|
raise Exception("Mime part not implemented: " + part_type)
|
||||||
return msg
|
return msg
|
||||||
@ -243,7 +241,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.attach(generate_mime_part(locale=locale, part_type=part_type, use_short_email=use_short_email))
|
||||||
from_meta, to_meta = add_simple_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
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
|
||||||
# TODO: can we use the builtin Django validator instead?
|
# TODO: can we use the builtin Django validator instead?
|
||||||
@ -32,4 +33,5 @@ def validate_file_extension(value):
|
|||||||
# should always allow that?
|
# should always allow that?
|
||||||
if not (ext.lower() == '' or ext.lower() == '.'):
|
if not (ext.lower() == '' or ext.lower() == '.'):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
'Unsupported file extension: %s.' % ext.lower())
|
_('Unsupported file extension: ') + ext.lower()
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user