Example #1
0
def ticket_from_message(message, queue, quiet):
    # 'message' must be an RFC822 formatted message.
    msg = message
    message = email.message_from_string(msg.decode('utf-8'))
    subject = message.get('subject', _('Created from e-mail'))
    subject = decode_mail_headers(decodeUnknown(message.get_charset(), subject))
    subject = subject.replace("Re: ", "").replace("Fw: ", "").replace("RE: ", "").replace("FW: ", "").replace("Automatic reply: ", "").strip()

    sender = message.get('from', _('Unknown Sender'))
    sender = decode_mail_headers(decodeUnknown(message.get_charset(), sender))

    sender_email = parseaddr(sender)[1]

    body_plain, body_html = '', ''

    for ignore in IgnoreEmail.objects.filter(Q(queues=queue) | Q(queues__isnull=True)):
        if ignore.test(sender_email):
            if ignore.keep_in_mailbox:
                # By returning 'False' the message will be kept in the mailbox,
                # and the 'True' will cause the message to be deleted.
                return False
            return True

    matchobj = re.match(r'.*\['+re.escape(queue.slug)+r'-(?P<id>\d+)\]', subject)
    if matchobj:
        # This is a reply or forward.
        ticket = matchobj.group('id')
    else:
        ticket = None

    counter = 0
    files = []

    for part in message.walk():
        if part.get_content_maintype() == 'multipart':
            continue

        name = part.get_param("name")
        if name:
            name = collapse_rfc2231_value(name)

        if part.get_content_maintype() == 'text' and name is None:
            if part.get_content_subtype() == 'plain':
                body_plain = EmailReplyParser.parse_reply(decodeUnknown(part.get_content_charset(), part.get_payload(decode=True)))
            else:
                body_html = decodeUnknown(part.get_content_charset(), part.get_payload(decode=True))
                # make plain text more legible when viewing the ticket
                body_html, n = re.subn(r'[\r\n]+', r'', body_html)
                body_html, n = re.subn(r'\>\s+\<', r'><', body_html)
                body_html = body_html.replace("</h1>", "</h1>\n")
                body_html = body_html.replace("</h2>", "</h2>\n")
                body_html = body_html.replace("</h3>", "</h3>\n")
                body_html = body_html.replace("<p>", "\n<p>")
                body_html = body_html.replace("</p>", "</p>\n")
                body_html = body_html.replace("</div>", "</div>\n")
                body_html = body_html.replace("</tr>", "</tr>\n")
                body_html = body_html.replace("</td>", "</td> ")
                body_html = body_html.replace("<table>", "\n<table>")
                body_html = body_html.replace("</table>", "</table>\n")
                body_html = body_html.replace("<br />", "<br />\n")

                try:
                    # strip html tags
                    body_plain = striptags(body_html)
                except DjangoUnicodeDecodeError:
                    charset = chardet.detect(body_html)['encoding']
                    body_plain = striptags(str(body_html, charset))

                body_plain = unescape(body_plain)
        else:
            if not name:
                ext = mimetypes.guess_extension(part.get_content_type())
                name = "part-%i%s" % (counter, ext)

            files.append({
                'filename': name,
                'content': part.get_payload(decode=True),
                'type': part.get_content_type()},
                )

        counter += 1

    if body_plain:
        body = body_plain
        if body_html:
            body += '\n\n'
            body += _('***Note that HTML tags are stripped out. Please see attachment email_html_body.html for the full html content.')
    else:
        body = _('No plain-text email body available. Please see attachment email_html_body.html.')

    if body_html:
        files.append({
            'filename': _("email_html_body.html"),
            'content': body_html,
            'type': 'text/html',
        })

    now = timezone.now()

    if ticket:
        try:
            t = Ticket.objects.get(id=ticket)
            new = False
        except Ticket.DoesNotExist:
            ticket = None

    priority = 3

    smtp_priority = message.get('priority', '')
    smtp_importance = message.get('importance', '')

    high_priority_types = ('high', 'important', '1', 'urgent')

    if smtp_priority in high_priority_types or smtp_importance in high_priority_types:
        priority = 2

    if ticket is None:
        t = Ticket(
            title=subject,
            queue=queue,
            submitter_email=sender_email,
            created=now,
            description=body,
            priority=priority,
        )
        t.save()
        new = True
        #update = ''

    elif t.status == Ticket.CLOSED_STATUS:
        t.status = Ticket.REOPENED_STATUS
        t.save()

    f = FollowUp(
        ticket = t,
        title = _('E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}),
        date = timezone.now(),
        public = True,
        comment = body,
    )

    if t.status == Ticket.REOPENED_STATUS:
        f.new_status = Ticket.REOPENED_STATUS
        f.title = _('Ticket Re-Opened by E-Mail Received from %(sender_email)s' % {'sender_email': sender_email})

    f.save()

    if not quiet:
        print((" [%s-%s] %s" % (t.queue.slug, t.id, t.title,)).encode('ascii', 'replace'))

    for file in files:
        if file['content']:
            filename = file['filename'].replace(' ', '_')
            filename = re.sub(r'[^a-zA-Z0-9._-]+', '', filename)
            a = Attachment(
                followup=f,
                filename=filename,
                mime_type=file['type'],
                size=len(file['content']),
                )
            a.file.save(filename, ContentFile(file['content']), save=False)
            a.save()
            if not quiet:
                print("    - %s" % filename)

    context = safe_template_context(t)

    if new:

        if sender_email and not is_no_reply_address(sender_email):
            send_templated_mail(
                'newticket_submitter',
                context,
                recipients=sender_email,
                sender=queue.from_address,
                fail_silently=True,
                )

        if queue.new_ticket_cc:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=queue.new_ticket_cc,
                sender=queue.from_address,
                fail_silently=True,
                )

        if queue.updated_ticket_cc and queue.updated_ticket_cc != queue.new_ticket_cc:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=queue.updated_ticket_cc,
                sender=queue.from_address,
                fail_silently=True,
                )

    else:
        context.update(comment=f.comment)

        #if t.status == Ticket.REOPENED_STATUS:
        #    update = _(' (Reopened)')
        #else:
        #    update = _(' (Updated)')

        if t.assigned_to:
            send_templated_mail(
                'updated_owner',
                context,
                recipients=t.assigned_to.email,
                sender=queue.from_address,
                fail_silently=True,
                )

        if queue.updated_ticket_cc:
            send_templated_mail(
                'updated_cc',
                context,
                recipients=queue.updated_ticket_cc,
                sender=queue.from_address,
                fail_silently=True,
                )

    return t
Example #2
0
    def save(self):
        """
        Writes and returns a Ticket() object
        """

        q = Queue.objects.get(id=int(self.cleaned_data['queue']))

        t = Ticket(
            title=self.cleaned_data['title'],
            submitter_email=self.cleaned_data['submitter_email'],
            created=timezone.now(),
            status=Ticket.OPEN_STATUS,
            queue=q,
            description=self.cleaned_data['body'],
            priority=self.cleaned_data['priority'],
            due_date=self.cleaned_data['due_date'],
        )

        t.save()

        for field, value in self.cleaned_data.items():
            if field.startswith('custom_'):
                field_name = field.replace('custom_', '', 1)
                customfield = CustomField.objects.get(name=field_name)
                cfv = TicketCustomFieldValue(ticket=t,
                                             field=customfield,
                                             value=value)
                cfv.save()

        f = FollowUp(
            ticket=t,
            title=_('Ticket Opened Via Web'),
            date=timezone.now(),
            public=True,
            comment=self.cleaned_data['body'],
        )

        f.save()

        files = []
        if self.cleaned_data['attachment']:
            import mimetypes
            file = self.cleaned_data['attachment']
            filename = file.name.replace(' ', '_')
            a = Attachment(
                followup=f,
                filename=filename,
                mime_type=mimetypes.guess_type(filename)[0]
                or 'application/octet-stream',
                size=file.size,
            )
            a.file.save(file.name, file, save=False)
            a.save()

            if file.size < getattr(settings, 'MAX_EMAIL_ATTACHMENT_SIZE',
                                   512000):
                # Only files smaller than 512kb (or as defined in
                # settings.MAX_EMAIL_ATTACHMENT_SIZE) are sent via email.
                files.append([a.filename, a.file])

        context = safe_template_context(t)

        messages_sent_to = []

        send_templated_mail(
            'newticket_submitter',
            context,
            recipients=t.submitter_email,
            sender=q.from_address,
            fail_silently=True,
            files=files,
        )
        messages_sent_to.append(t.submitter_email)

        if q.new_ticket_cc and q.new_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=q.new_ticket_cc,
                sender=q.from_address,
                fail_silently=True,
                files=files,
            )
            messages_sent_to.append(q.new_ticket_cc)

        if q.updated_ticket_cc and q.updated_ticket_cc != q.new_ticket_cc and q.updated_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=q.updated_ticket_cc,
                sender=q.from_address,
                fail_silently=True,
                files=files,
            )

        return t
Example #3
0
    def save(self):
        """
        Writes and returns a Ticket() object
        """

        q = Queue.objects.get(id=int(self.cleaned_data['queue']))

        t = Ticket(
            title = self.cleaned_data['title'],
            submitter_email = self.cleaned_data['submitter_email'],
            created = timezone.now(),
            status = Ticket.OPEN_STATUS,
            queue = q,
            description = self.cleaned_data['body'],
            priority = self.cleaned_data['priority'],
            due_date = self.cleaned_data['due_date'],
            )

        t.save()

        for field, value in self.cleaned_data.items():
            if field.startswith('custom_'):
                field_name = field.replace('custom_', '', 1)
                customfield = CustomField.objects.get(name=field_name)
                cfv = TicketCustomFieldValue(ticket=t,
                            field=customfield,
                            value=value)
                cfv.save()

        f = FollowUp(
            ticket = t,
            title = _('Ticket Opened Via Web'),
            date = timezone.now(),
            public = True,
            comment = self.cleaned_data['body'],
            )

        f.save()

        files = []
        if self.cleaned_data['attachment']:
            import mimetypes
            file = self.cleaned_data['attachment']
            filename = file.name.replace(' ', '_')
            a = Attachment(
                followup=f,
                filename=filename,
                mime_type=mimetypes.guess_type(filename)[0] or 'application/octet-stream',
                size=file.size,
                )
            a.file.save(file.name, file, save=False)
            a.save()
            
            if file.size < getattr(settings, 'MAX_EMAIL_ATTACHMENT_SIZE', 512000):
                # Only files smaller than 512kb (or as defined in 
                # settings.MAX_EMAIL_ATTACHMENT_SIZE) are sent via email.
                files.append([a.filename, a.file])

        context = safe_template_context(t)

        messages_sent_to = []

        send_templated_mail(
            'newticket_submitter',
            context,
            recipients=t.submitter_email,
            sender=q.from_address,
            fail_silently=True,
            files=files,
            )
        messages_sent_to.append(t.submitter_email)

        if q.new_ticket_cc and q.new_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=q.new_ticket_cc,
                sender=q.from_address,
                fail_silently=True,
                files=files,
                )
            messages_sent_to.append(q.new_ticket_cc)

        if q.updated_ticket_cc and q.updated_ticket_cc != q.new_ticket_cc and q.updated_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=q.updated_ticket_cc,
                sender=q.from_address,
                fail_silently=True,
                files=files,
                )

        return t
def escalate_tickets(queues, verbose):
    """ Only include queues with escalation configured """
    queryset = Queue.objects.filter(escalate_days__isnull=False).exclude(
        escalate_days=0)
    if queues:
        queryset = queryset.filter(slug__in=queues)

    for q in queryset:
        last = date.today() - timedelta(days=q.escalate_days)
        today = date.today()
        workdate = last

        days = 0

        while workdate < today:
            if EscalationExclusion.objects.filter(date=workdate).count() == 0:
                days += 1
            workdate = workdate + timedelta(days=1)

        req_last_escl_date = date.today() - timedelta(days=days)

        if verbose:
            print("Processing: %s" % q)

        for t in q.ticket_set.filter(
                Q(status=Ticket.OPEN_STATUS)
                | Q(status=Ticket.REOPENED_STATUS)).exclude(priority=1).filter(
                    Q(on_hold__isnull=True)
                    | Q(on_hold=False)).filter(
                        Q(last_escalation__lte=req_last_escl_date)
                        | Q(last_escalation__isnull=True,
                            created__lte=req_last_escl_date)):

            t.last_escalation = timezone.now()
            t.priority -= 1
            t.save()

            context = safe_template_context(t)

            if t.submitter_email:
                send_templated_mail(
                    'escalated_submitter',
                    context,
                    recipients=t.submitter_email,
                    sender=t.queue.from_address,
                    fail_silently=True,
                )

            if t.queue.updated_ticket_cc:
                send_templated_mail(
                    'escalated_cc',
                    context,
                    recipients=t.queue.updated_ticket_cc,
                    sender=t.queue.from_address,
                    fail_silently=True,
                )

            if t.assigned_to:
                send_templated_mail(
                    'escalated_owner',
                    context,
                    recipients=t.assigned_to.email,
                    sender=t.queue.from_address,
                    fail_silently=True,
                )

            if verbose:
                print("  - Esclating %s from %s>%s" %
                      (t.ticket, t.priority + 1, t.priority))

            f = FollowUp(
                ticket=t,
                title='Ticket Escalated',
                date=timezone.now(),
                public=True,
                comment=_('Ticket escalated after %s days' % q.escalate_days),
            )
            f.save()

            tc = TicketChange(
                followup=f,
                field=_('Priority'),
                old_value=t.priority + 1,
                new_value=t.priority,
            )
            tc.save()
Example #5
0
def ticket_from_message(message, queue, quiet):
    # 'message' must be an RFC822 formatted message.
    msg = message
    message = email.message_from_string(msg)
    subject = message.get('subject', _('Created from e-mail'))
    subject = decode_mail_headers(decodeUnknown(message.get_charset(),
                                                subject))
    subject = subject.replace("Re: ", "").replace("Fw: ", "").replace(
        "RE: ", "").replace("FW: ", "").replace("Automatic reply: ",
                                                "").strip()

    sender = message.get('from', _('Unknown Sender'))
    sender = decode_mail_headers(decodeUnknown(message.get_charset(), sender))

    sender_email = parseaddr(sender)[1]

    body_plain, body_html = '', ''

    for ignore in IgnoreEmail.objects.filter(
            Q(queues=queue) | Q(queues__isnull=True)):
        if ignore.test(sender_email):
            if ignore.keep_in_mailbox:
                # By returning 'False' the message will be kept in the mailbox,
                # and the 'True' will cause the message to be deleted.
                return False
            return True

    matchobj = re.match(r".*\[" + queue.slug + "-(?P<id>\d+)\]", subject)
    if matchobj:
        # This is a reply or forward.
        ticket = matchobj.group('id')
    else:
        ticket = None

    counter = 0
    files = []

    for part in message.walk():
        if part.get_content_maintype() == 'multipart':
            continue

        name = part.get_param("name")
        if name:
            name = collapse_rfc2231_value(name)

        if part.get_content_maintype() == 'text' and name is None:
            if part.get_content_subtype() == 'plain':
                body_plain = EmailReplyParser.parse_reply(
                    decodeUnknown(part.get_content_charset(),
                                  part.get_payload(decode=True)))
            else:
                body_html = part.get_payload(decode=True)
                # make plain text more legible when viewing the ticket
                body_html, n = re.subn(r'[\r\n]+', r'', body_html)
                body_html, n = re.subn(r'\>\s+\<', r'><', body_html)
                body_html = body_html.replace("</h1>", "</h1>\n")
                body_html = body_html.replace("</h2>", "</h2>\n")
                body_html = body_html.replace("</h3>", "</h3>\n")
                body_html = body_html.replace("<p>", "\n<p>")
                body_html = body_html.replace("</p>", "</p>\n")
                body_html = body_html.replace("</div>", "</div>\n")
                body_html = body_html.replace("</tr>", "</tr>\n")
                body_html = body_html.replace("</td>", "</td> ")
                body_html = body_html.replace("<table>", "\n<table>")
                body_html = body_html.replace("</table>", "</table>\n")
                body_html = body_html.replace("<br />", "<br />\n")

                try:
                    # strip html tags
                    body_plain = striptags(body_html)
                except DjangoUnicodeDecodeError:
                    charset = chardet.detect(body_html)['encoding']
                    body_plain = striptags(str(body_html, charset))

                body_plain = unescape(body_plain)
        else:
            if not name:
                ext = mimetypes.guess_extension(part.get_content_type())
                name = "part-%i%s" % (counter, ext)

            files.append(
                {
                    'filename': name,
                    'content': part.get_payload(decode=True),
                    'type': part.get_content_type()
                }, )

        counter += 1

    if body_plain:
        body = body_plain
        if body_html:
            body += '\n\n'
            body += _(
                '***Note that HTML tags are stripped out. Please see attachment email_html_body.html for the full html content.'
            )
    else:
        body = _(
            'No plain-text email body available. Please see attachment email_html_body.html.'
        )

    if body_html:
        files.append({
            'filename': _("email_html_body.html"),
            'content': body_html,
            'type': 'text/html',
        })

    now = timezone.now()

    if ticket:
        try:
            t = Ticket.objects.get(id=ticket)
            new = False
        except Ticket.DoesNotExist:
            ticket = None

    priority = 3

    smtp_priority = message.get('priority', '')
    smtp_importance = message.get('importance', '')

    high_priority_types = ('high', 'important', '1', 'urgent')

    if smtp_priority in high_priority_types or smtp_importance in high_priority_types:
        priority = 2

    if ticket is None:
        t = Ticket(
            title=subject,
            queue=queue,
            submitter_email=sender_email,
            created=now,
            description=body,
            priority=priority,
        )
        t.save()
        new = True
        #update = ''

    elif t.status == Ticket.CLOSED_STATUS:
        t.status = Ticket.REOPENED_STATUS
        t.save()

    f = FollowUp(
        ticket=t,
        title=_('E-Mail Received from %(sender_email)s' %
                {'sender_email': sender_email}),
        date=timezone.now(),
        public=True,
        comment=body,
    )

    if t.status == Ticket.REOPENED_STATUS:
        f.new_status = Ticket.REOPENED_STATUS
        f.title = _(
            'Ticket Re-Opened by E-Mail Received from %(sender_email)s' %
            {'sender_email': sender_email})

    f.save()

    if not quiet:
        print((" [%s-%s] %s" % (
            t.queue.slug,
            t.id,
            t.title,
        )).encode('ascii', 'replace'))

    for file in files:
        if file['content']:
            filename = file['filename'].encode('ascii',
                                               'replace').replace(' ', '_')
            filename = re.sub('[^a-zA-Z0-9._-]+', '', filename)
            a = Attachment(
                followup=f,
                filename=filename,
                mime_type=file['type'],
                size=len(file['content']),
            )
            a.file.save(filename, ContentFile(file['content']), save=False)
            a.save()
            if not quiet:
                print("    - %s" % filename)

    context = safe_template_context(t)

    if new:

        if sender_email:
            send_templated_mail(
                'newticket_submitter',
                context,
                recipients=sender_email,
                sender=queue.from_address,
                fail_silently=True,
            )

        if queue.new_ticket_cc:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=queue.new_ticket_cc,
                sender=queue.from_address,
                fail_silently=True,
            )

        if queue.updated_ticket_cc and queue.updated_ticket_cc != queue.new_ticket_cc:
            send_templated_mail(
                'newticket_cc',
                context,
                recipients=queue.updated_ticket_cc,
                sender=queue.from_address,
                fail_silently=True,
            )

    else:
        context.update(comment=f.comment)

        #if t.status == Ticket.REOPENED_STATUS:
        #    update = _(' (Reopened)')
        #else:
        #    update = _(' (Updated)')

        if t.assigned_to:
            send_templated_mail(
                'updated_owner',
                context,
                recipients=t.assigned_to.email,
                sender=queue.from_address,
                fail_silently=True,
            )

        if queue.updated_ticket_cc:
            send_templated_mail(
                'updated_cc',
                context,
                recipients=queue.updated_ticket_cc,
                sender=queue.from_address,
                fail_silently=True,
            )

    return t
Example #6
0
    def api_public_resolve(self):
        try:
            ticket = Ticket.objects.get(id=self.request.POST.get('ticket', False))
        except Ticket.DoesNotExist:
            return api_return(STATUS_ERROR, "Invalid ticket ID")

        resolution = self.request.POST.get('resolution', None)

        if not resolution:
            return api_return(STATUS_ERROR, "Blank resolution")

        f = FollowUp(
            ticket=ticket,
            date=timezone.now(),
            comment=resolution,
            user=self.request.user,
            title='Resolved',
            public=True,
            )
        f.save()

        context = safe_template_context(ticket)
        context['resolution'] = f.comment

        subject = '%s %s (Resolved)' % (ticket.ticket, ticket.title)

        messages_sent_to = []

        if ticket.submitter_email:
            send_templated_mail(
                'resolved_submitter',
                context,
                recipients=ticket.submitter_email,
                sender=ticket.queue.from_address,
                fail_silently=True,
                )
            messages_sent_to.append(ticket.submitter_email)

            for cc in ticket.ticketcc_set.all():
                if cc.email_address not in messages_sent_to:
                    send_templated_mail(
                        'resolved_submitter',
                        context,
                        recipients=cc.email_address,
                        sender=ticket.queue.from_address,
                        fail_silently=True,
                        )
                    messages_sent_to.append(cc.email_address)

        if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'resolved_cc',
                context,
                recipients=ticket.queue.updated_ticket_cc,
                sender=ticket.queue.from_address,
                fail_silently=True,
                )
            messages_sent_to.append(ticket.queue.updated_ticket_cc)

        if ticket.assigned_to and self.request.user != ticket.assigned_to and getattr(ticket.assigned_to.usersettings.settings, 'email_on_ticket_apichange', False) and ticket.assigned_to.email and ticket.assigned_to.email not in messages_sent_to:
            send_templated_mail(
                'resolved_resolved',
                context,
                recipients=ticket.assigned_to.email,
                sender=ticket.queue.from_address,
                fail_silently=True,
                )

        ticket.resoltuion = f.comment
        ticket.status = Ticket.RESOLVED_STATUS

        ticket.save()

        return api_return(STATUS_OK)
Example #7
0
    def api_public_add_followup(self):
        try:
            ticket = Ticket.objects.get(id=self.request.POST.get('ticket', False))
        except Ticket.DoesNotExist:
            return api_return(STATUS_ERROR, "Invalid ticket ID")

        message = self.request.POST.get('message', None)
        public = self.request.POST.get('public', 'n')

        if public not in ['y', 'n']:
            return api_return(STATUS_ERROR, "Invalid 'public' flag")

        if not message:
            return api_return(STATUS_ERROR, "Blank message")

        f = FollowUp(
            ticket=ticket,
            date=timezone.now(),
            comment=message,
            user=self.request.user,
            title='Comment Added',
            )

        if public:
            f.public = True

        f.save()

        context = safe_template_context(ticket)
        context['comment'] = f.comment

        messages_sent_to = []

        if public and ticket.submitter_email:
            send_templated_mail(
                'updated_submitter',
                context,
                recipients=ticket.submitter_email,
                sender=ticket.queue.from_address,
                fail_silently=True,
                )
            messages_sent_to.append(ticket.submitter_email)

        if public:
            for cc in ticket.ticketcc_set.all():
                if cc.email_address not in messages_sent_to:
                    send_templated_mail(
                        'updated_submitter',
                        context,
                        recipients=cc.email_address,
                        sender=ticket.queue.from_address,
                        fail_silently=True,
                        )
                    messages_sent_to.append(cc.email_address)

        if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'updated_cc',
                context,
                recipients=ticket.queue.updated_ticket_cc,
                sender=ticket.queue.from_address,
                fail_silently=True,
                )
            messages_sent_to.append(ticket.queue.updated_ticket_cc)

        if (
            ticket.assigned_to and
            self.request.user != ticket.assigned_to and
            ticket.assigned_to.usersettings.settings.get('email_on_ticket_apichange', False) and
            ticket.assigned_to.email and
            ticket.assigned_to.email not in messages_sent_to
        ):
            send_templated_mail(
                'updated_owner',
                context,
                recipients=ticket.assigned_to.email,
                sender=ticket.queue.from_address,
                fail_silently=True,
            )

        ticket.save()

        return api_return(STATUS_OK)
Example #8
0
def escalate_tickets(queues, verbose):
    """ Only include queues with escalation configured """
    queryset = Queue.objects.filter(escalate_days__isnull=False).exclude(escalate_days=0)
    if queues:
        queryset = queryset.filter(slug__in=queues)

    for q in queryset:
        last = date.today() - timedelta(days=q.escalate_days)
        today = date.today()
        workdate = last

        days = 0

        while workdate < today:
            if EscalationExclusion.objects.filter(date=workdate).count() == 0:
                days += 1
            workdate = workdate + timedelta(days=1)

        req_last_escl_date = date.today() - timedelta(days=days)

        if verbose:
            print("Processing: %s" % q)

        for t in q.ticket_set.filter(
                  Q(status=Ticket.OPEN_STATUS)
                | Q(status=Ticket.REOPENED_STATUS)
            ).exclude(
                priority=1
            ).filter(
                  Q(on_hold__isnull=True)
                | Q(on_hold=False)
            ).filter(
                  Q(last_escalation__lte=req_last_escl_date)
                | Q(last_escalation__isnull=True, created__lte=req_last_escl_date)
            ):

            t.last_escalation = timezone.now()
            t.priority -= 1
            t.save()

            context = safe_template_context(t)

            if t.submitter_email:
                send_templated_mail(
                    'escalated_submitter',
                    context,
                    recipients=t.submitter_email,
                    sender=t.queue.from_address,
                    fail_silently=True,
                    )

            if t.queue.updated_ticket_cc:
                send_templated_mail(
                    'escalated_cc',
                    context,
                    recipients=t.queue.updated_ticket_cc,
                    sender=t.queue.from_address,
                    fail_silently=True,
                    )

            if t.assigned_to:
                send_templated_mail(
                    'escalated_owner',
                    context,
                    recipients=t.assigned_to.email,
                    sender=t.queue.from_address,
                    fail_silently=True,
                    )

            if verbose:
                print("  - Esclating %s from %s>%s" % (
                    t.ticket,
                    t.priority+1,
                    t.priority
                    ))

            f = FollowUp(
                ticket = t,
                title = 'Ticket Escalated',
                date=timezone.now(),
                public=True,
                comment=_('Ticket escalated after %s days' % q.escalate_days),
            )
            f.save()

            tc = TicketChange(
                followup = f,
                field = _('Priority'),
                old_value = t.priority + 1,
                new_value = t.priority,
            )
            tc.save()
Example #9
0
    def api_public_resolve(self):
        try:
            ticket = Ticket.objects.get(
                id=self.request.POST.get('ticket', False))
        except Ticket.DoesNotExist:
            return api_return(STATUS_ERROR, "Invalid ticket ID")

        resolution = self.request.POST.get('resolution', None)

        if not resolution:
            return api_return(STATUS_ERROR, "Blank resolution")

        f = FollowUp(
            ticket=ticket,
            date=timezone.now(),
            comment=resolution,
            user=self.request.user,
            title='Resolved',
            public=True,
        )
        f.save()

        context = safe_template_context(ticket)
        context['resolution'] = f.comment

        subject = '%s %s (Resolved)' % (ticket.ticket, ticket.title)

        messages_sent_to = []

        if ticket.submitter_email:
            send_templated_mail(
                'resolved_submitter',
                context,
                recipients=ticket.submitter_email,
                sender=ticket.queue.from_address,
                fail_silently=True,
            )
            messages_sent_to.append(ticket.submitter_email)

            for cc in ticket.ticketcc_set.all():
                if cc.email_address not in messages_sent_to:
                    send_templated_mail(
                        'resolved_submitter',
                        context,
                        recipients=cc.email_address,
                        sender=ticket.queue.from_address,
                        fail_silently=True,
                    )
                    messages_sent_to.append(cc.email_address)

        if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'resolved_cc',
                context,
                recipients=ticket.queue.updated_ticket_cc,
                sender=ticket.queue.from_address,
                fail_silently=True,
            )
            messages_sent_to.append(ticket.queue.updated_ticket_cc)

        if ticket.assigned_to and self.request.user != ticket.assigned_to and getattr(
                ticket.assigned_to.usersettings.settings,
                'email_on_ticket_apichange', False
        ) and ticket.assigned_to.email and ticket.assigned_to.email not in messages_sent_to:
            send_templated_mail(
                'resolved_resolved',
                context,
                recipients=ticket.assigned_to.email,
                sender=ticket.queue.from_address,
                fail_silently=True,
            )

        ticket.resoltuion = f.comment
        ticket.status = Ticket.RESOLVED_STATUS

        ticket.save()

        return api_return(STATUS_OK)
Example #10
0
    def api_public_add_followup(self):
        try:
            ticket = Ticket.objects.get(
                id=self.request.POST.get('ticket', False))
        except Ticket.DoesNotExist:
            return api_return(STATUS_ERROR, "Invalid ticket ID")

        message = self.request.POST.get('message', None)
        public = self.request.POST.get('public', 'n')

        if public not in ['y', 'n']:
            return api_return(STATUS_ERROR, "Invalid 'public' flag")

        if not message:
            return api_return(STATUS_ERROR, "Blank message")

        f = FollowUp(
            ticket=ticket,
            date=timezone.now(),
            comment=message,
            user=self.request.user,
            title='Comment Added',
        )

        if public:
            f.public = True

        f.save()

        context = safe_template_context(ticket)
        context['comment'] = f.comment

        messages_sent_to = []

        if public and ticket.submitter_email:
            send_templated_mail(
                'updated_submitter',
                context,
                recipients=ticket.submitter_email,
                sender=ticket.queue.from_address,
                fail_silently=True,
            )
            messages_sent_to.append(ticket.submitter_email)

        if public:
            for cc in ticket.ticketcc_set.all():
                if cc.email_address not in messages_sent_to:
                    send_templated_mail(
                        'updated_submitter',
                        context,
                        recipients=cc.email_address,
                        sender=ticket.queue.from_address,
                        fail_silently=True,
                    )
                    messages_sent_to.append(cc.email_address)

        if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to:
            send_templated_mail(
                'updated_cc',
                context,
                recipients=ticket.queue.updated_ticket_cc,
                sender=ticket.queue.from_address,
                fail_silently=True,
            )
            messages_sent_to.append(ticket.queue.updated_ticket_cc)

        if (ticket.assigned_to and self.request.user != ticket.assigned_to
                and ticket.assigned_to.usersettings.settings.get(
                    'email_on_ticket_apichange', False)
                and ticket.assigned_to.email
                and ticket.assigned_to.email not in messages_sent_to):
            send_templated_mail(
                'updated_owner',
                context,
                recipients=ticket.assigned_to.email,
                sender=ticket.queue.from_address,
                fail_silently=True,
            )

        ticket.save()

        return api_return(STATUS_OK)