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
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 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()
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
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)
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)
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()
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)
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)