From be07fdff6cd6f7024b87d48a418b9ee61d61281a Mon Sep 17 00:00:00 2001 From: Bruno Tikami Date: Tue, 16 Feb 2016 17:10:13 -0200 Subject: [PATCH] UPDATED: Finished moving Message-Id field from to model. --- helpdesk/management/commands/get_email.py | 51 ++++++++--- ...re_message_id_field_into_followup_model.py | 24 ++++++ helpdesk/models.py | 27 +----- helpdesk/tests/test_ticket_submission.py | 86 ++++++++++--------- helpdesk/views/staff.py | 1 + 5 files changed, 111 insertions(+), 78 deletions(-) create mode 100644 helpdesk/migrations/0013_store_message_id_field_into_followup_model.py diff --git a/helpdesk/management/commands/get_email.py b/helpdesk/management/commands/get_email.py index d442b17b..3fb48516 100644 --- a/helpdesk/management/commands/get_email.py +++ b/helpdesk/management/commands/get_email.py @@ -168,9 +168,25 @@ def decode_mail_headers(string): decoded = decode_header(string) return u' '.join([unicode(msg, charset or 'utf-8') for msg, charset in decoded]) +def create_ticket_cc(ticket, cc_list): + + # Local import to deal with non-defined / circular reference problem + from helpdesk.views.staff import User, subscribe_to_ticket_updates + + for cced_email in cc_list: + + user = None + + try: + user = User.objects.get(email=cced_email) + except User.DoesNotExist: + pass + + ticket_cc = subscribe_to_ticket_updates(ticket=ticket, user=user, email=cced_email) + def create_object_from_email_message(message, ticket_id, payload, files, quiet): - ticket, new = None, False + ticket, followup, new = None, None, False now = timezone.now() queue = payload['queue'] @@ -178,24 +194,28 @@ def create_object_from_email_message(message, ticket_id, payload, files, quiet): message_id = message.get('Message-Id') in_reply_to = message.get('In-Reply-To') + cc_list = message.get('Cc') + + if in_reply_to is not None: + followup = FollowUp.objects.get(message_id=in_reply_to) + ticket = followup.ticket - query_set = Ticket.objects.filter(Q(id=ticket_id)|Q(submitter_email_id=message_id)) - if query_set.count() == 0: - ticket = None - new = True else: - t = query_set.first() + try: + t = Ticket.objects.get(id=ticket_id) + new = False + except Ticket.DoesNotExist: + ticket = None # New issue, create a new instance if ticket is None: t = Ticket.objects.create( - title=payload['subject'], - queue=queue, - submitter_email=sender_email, - submitter_email_id=message_id, - created=now, - description=payload['body'], - priority=payload['priority'], + title = payload['subject'], + queue = queue, + submitter_email = sender_email, + created = now, + description = payload['body'], + priority = payload['priority'], ) t.save() @@ -213,6 +233,7 @@ def create_object_from_email_message(message, ticket_id, payload, files, quiet): date = now, public = True, comment = payload['body'], + message_id = message_id, ) if t.status == Ticket.REOPENED_STATUS: @@ -242,6 +263,9 @@ def create_object_from_email_message(message, ticket_id, payload, files, quiet): context = safe_template_context(t) + if cc_list is not None: + create_ticket_cc(t, cc_list.split(',')) + if new: if sender_email: @@ -302,6 +326,7 @@ def create_object_from_email_message(message, ticket_id, payload, files, quiet): return t + def object_from_message(message, queue, quiet): # 'message' must be an RFC822 formatted message. diff --git a/helpdesk/migrations/0013_store_message_id_field_into_followup_model.py b/helpdesk/migrations/0013_store_message_id_field_into_followup_model.py new file mode 100644 index 00000000..2c1106c7 --- /dev/null +++ b/helpdesk/migrations/0013_store_message_id_field_into_followup_model.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.1 on 2016-02-16 18:13 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('helpdesk', '0012_add_submitter_email_id_field_to_ticket'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticket', + name='submitter_email_id', + ), + migrations.AddField( + model_name='followup', + name='message_id', + field=models.CharField(blank=True, editable=False, help_text="The Message ID of the submitter's email.", max_length=256, null=True, verbose_name='E-Mail ID'), + ), + ] diff --git a/helpdesk/models.py b/helpdesk/models.py index 009ad88f..12bb8b74 100644 --- a/helpdesk/models.py +++ b/helpdesk/models.py @@ -558,29 +558,7 @@ class Ticket(models.Model): def get_absolute_url(self): return ('helpdesk_view', (self.id,)) - get_absolute_url = models.permalink(get_absolute_url) - - def process_rfc_2822_data(self): - - if len(self.rfc_2822_items) > 0: - cc_list = self.rfc_2822_items.get('rfc_2822_cc', []) - - for cced_email in cc_list: - - user = None - - user_model = get_user_model() - - try: - user = user_model.objects.get(email=cced_email) - except user_model.DoesNotExist: - pass - - # Local import to deal with non-defined / circular reference problem - from .views import staff - - ticket_cc = staff.subscribe_to_ticket_updates(ticket=self, user=user, email=cced_email) - + get_absolute_url = models.permalink(get_absolute_url) def save(self, *args, **kwargs): if not self.id: @@ -594,9 +572,6 @@ class Ticket(models.Model): super(Ticket, self).save(*args, **kwargs) - # Process RFC 2822 fields, if any - self.process_rfc_2822_data() - class FollowUpManager(models.Manager): def private_followups(self): diff --git a/helpdesk/tests/test_ticket_submission.py b/helpdesk/tests/test_ticket_submission.py index e33b3f89..cc4c9ad5 100644 --- a/helpdesk/tests/test_ticket_submission.py +++ b/helpdesk/tests/test_ticket_submission.py @@ -2,14 +2,14 @@ import email import uuid -from helpdesk.models import Queue, CustomField, Ticket, TicketCC +from helpdesk.models import Queue, CustomField, FollowUp, Ticket, TicketCC from django.test import TestCase from django.core import mail from django.core.exceptions import ObjectDoesNotExist from django.test.client import Client from django.core.urlresolvers import reverse -from helpdesk.management.commands.get_email import ticket_from_message +from helpdesk.management.commands.get_email import object_from_message try: # python 3 from urllib.parse import urlparse @@ -57,7 +57,7 @@ class TicketBasicsTestCase(TestCase): submitter_email = 'foo@bar.py' msg.__setitem__('Message-ID', message_id) - msg.__setitem__('subject', self.ticket_data['title']) + msg.__setitem__('Subject', self.ticket_data['title']) msg.__setitem__('From', submitter_email) msg.__setitem__('To', self.queue_public.email_address) msg.__setitem__('Content-Type', 'text/plain;') @@ -65,12 +65,15 @@ class TicketBasicsTestCase(TestCase): email_count = len(mail.outbox) - ticket_from_message(str(msg), self.queue_public, quiet=True) - ticket = Ticket.objects.get(title=self.ticket_data['title'], submitter_email_id=message_id) + object_from_message(str(msg), self.queue_public, quiet=True) + + followup = FollowUp.objects.get(message_id=message_id) + ticket = Ticket.objects.get(id=followup.ticket.id) self.assertEqual(ticket.ticket_for_url, "q1-%s" % ticket.id) - # As we have created an Ticket from an email, we notify the sender (+1) and the new and update queues (+2) + # As we have created an Ticket from an email, we notify the sender (+1) + # and the new and update queues (+2) self.assertEqual(email_count + 1 + 2, len(mail.outbox)) @@ -81,29 +84,35 @@ class TicketBasicsTestCase(TestCase): "rfc_2822_cc" field when creating a instance. """ + msg = email.message.Message() + message_id = uuid.uuid4().hex + submitter_email = 'foo@bar.py' + cc_list = ['bravo@example.net', 'charlie@foobar.com'] - email_data = { - 'Message-ID': message_id, - 'cc': ['bravo@example.net', 'charlie@foobar.com'], - } - - # Regular ticket from email creation process - self.ticket_data = { - 'title': 'Test Ticket', - 'description': 'Some Test Ticket', - 'rfc_2822_cc': email_data.get('cc', []) - } + msg.__setitem__('Message-ID', message_id) + msg.__setitem__('Subject', self.ticket_data['title']) + msg.__setitem__('From', submitter_email) + msg.__setitem__('To', self.queue_public.email_address) + msg.__setitem__('Cc', ','.join(cc_list)) + msg.__setitem__('Content-Type', 'text/plain;') + msg.set_payload(self.ticket_data['description']) email_count = len(mail.outbox) - ticket_data = dict(queue=self.queue_public, **self.ticket_data) - ticket = Ticket.objects.create(**ticket_data) + + object_from_message(str(msg), self.queue_public, quiet=True) + + followup = FollowUp.objects.get(message_id=message_id) + ticket = Ticket.objects.get(id=followup.ticket.id) self.assertEqual(ticket.ticket_for_url, "q1-%s" % ticket.id) - self.assertEqual(email_count, len(mail.outbox)) + + # As we have created an Ticket from an email, we notify the sender (+1) + # and the new and update queues (+2) + self.assertEqual(email_count + 1 + 2, len(mail.outbox)) + # Ensure that is created - for cc_email in email_data.get('cc', []): - + for cc_email in cc_list: ticket_cc = TicketCC.objects.get(ticket=ticket, email=cc_email) self.assertTrue(ticket_cc.ticket, ticket) self.assertTrue(ticket_cc.email, cc_email) @@ -115,29 +124,28 @@ class TicketBasicsTestCase(TestCase): "rfc_2822_cc" field is provided when creating a instance. """ + msg = email.message.Message() + message_id = uuid.uuid4().hex + submitter_email = 'foo@bar.py' + cc_list = ['null@example', 'invalid@foobar'] - email_data = { - 'Message-ID': message_id, - 'cc': ['null@example', 'invalid@foobar'], - } - - # Regular ticket from email creation process - self.ticket_data = { - 'title': 'Test Ticket', - 'description': 'Some Test Ticket', - 'rfc_2822_cc': email_data.get('cc', []) - } + msg.__setitem__('Message-ID', message_id) + msg.__setitem__('Subject', self.ticket_data['title']) + msg.__setitem__('From', submitter_email) + msg.__setitem__('To', self.queue_public.email_address) + msg.__setitem__('Cc', ','.join(cc_list)) + msg.__setitem__('Content-Type', 'text/plain;') + msg.set_payload(self.ticket_data['description']) email_count = len(mail.outbox) - ticket_data = dict(queue=self.queue_public, **self.ticket_data) - ticket = Ticket.objects.create(**ticket_data) - self.assertEqual(ticket.ticket_for_url, "q1-%s" % ticket.id) - self.assertEqual(email_count, len(mail.outbox)) - # Ensure that is created - for cc_email in email_data.get('cc', []): + object_from_message(str(msg), self.queue_public, quiet=True) + ticket = Ticket.objects.get(title=self.ticket_data['title']) + + # Ensure that is created but the email field is not set + for cc_email in cc_list: self.assertEquals(0, TicketCC.objects.filter(ticket=ticket, email=cc_email).count()) def test_create_ticket_public(self): diff --git a/helpdesk/views/staff.py b/helpdesk/views/staff.py index 3aaac599..50186293 100644 --- a/helpdesk/views/staff.py +++ b/helpdesk/views/staff.py @@ -346,6 +346,7 @@ def subscribe_to_ticket_updates(ticket, user=None, email=''): except ValidationError: email = '' + ticketcc = TicketCC() ticketcc.ticket = ticket ticketcc.user = user