def process_attachments(followup, attached_files): max_email_attachment_size = getattr(settings, 'HELPDESK_MAX_EMAIL_ATTACHMENT_SIZE', 512000) attachments = [] for attached in attached_files: if attached.size: filename = smart_text(attached.name) att = Attachment( followup=followup, file=attached, filename=filename, mime_type=attached.content_type or mimetypes.guess_type(filename, strict=False)[0] or 'application/octet-stream', size=attached.size, ) att.save() if attached.size < max_email_attachment_size: # Only files smaller than 512kb (or as defined in # settings.HELPDESK_MAX_EMAIL_ATTACHMENT_SIZE) are sent via email. attachments.append([filename, att.file]) return attachments
def _attach_files_to_follow_up(self, followup): attachments = [] if self.cleaned_data['attachment']: import mimetypes attachment = self.cleaned_data['attachment'] filename = attachment.name.replace(' ', '_') att = Attachment( followup=followup, filename=filename, mime_type=mimetypes.guess_type(filename)[0] or 'application/octet-stream', size=attachment.size, ) att.file.save(attachment.name, attachment, save=False) att.save() if attachment.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. try: attachments.append([att.filename, att.file]) except NotImplementedError: pass return attachments
def reply_ticket(request, ticket_id): """reply ticket to the client""" if not (request.user.is_authenticated() and request.user.is_active and (request.user.is_staff)): return HttpResponseRedirect('%s?next=%s' % (reverse('staff/login'), request.path)) ticket = get_object_or_404(Ticket, id=ticket_id) if request.method == 'POST': title = request.POST.get('title', '') comment = request.POST.get('comment', '') new_status = int(request.POST.get('new_status', ticket.status)) if not all([title, comment]): return render(request, 'helpdesk/reply_ticket.html', { 'ticket': ticket, }) #save models f = FollowUp(public=True, ticket=ticket, date=timezone.now(), comment=comment, user=request.user) f.title = 'Email:{}'.format(title) if new_status != ticket.status: ticket.status = new_status ticket.save() f.new_status = new_status f.save() #save attachment files = [] if request.FILES: import mimetypes for file in request.FILES.getlist('attachment'): print(dir(file)) filename = file.name a = Attachment( followup=f, filename=filename, mime_type=mimetypes.guess_type(filename)[0] or 'application/octet-stream', size=file.size, ) a.file.save(filename, file, save=False) a.save() files.append([a.filename, a.file]) if new_status in [Ticket.RESOLVED_STATUS, Ticket.CLOSED_STATUS]: if new_status == Ticket.RESOLVED_STATUS: ticket.resolution = comment ticket.save() #send email send_reply_email(files=files, subject=title, body=comment, recipients=[ticket.submitter_email], sender=ticket.queue.from_address, fail_silently=True) return HttpResponseRedirect(ticket.get_absolute_url()) return render(request, 'helpdesk/reply_ticket.html', { 'ticket': ticket, })
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 == 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) 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 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 == 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') print files for file in files: print file if file['content']: filename = file['filename'].encode('ascii', 'replace').replace(' ', '_') print filename filename = re.sub('[^a-zA-Z0-9._-]+', '', filename) print 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 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'], ) if q.default_owner and not t.assigned_to: t.assigned_to = q.default_owner 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 t.assigned_to and \ t.assigned_to.usersettings.settings.get('email_on_ticket_assign', False) and \ t.assigned_to.email and \ t.assigned_to.email not in messages_sent_to: send_templated_mail( 'assigned_owner', context, recipients=t.assigned_to.email, sender=q.from_address, fail_silently=True, files=files, ) messages_sent_to.append(t.assigned_to.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 update_ticket(request, ticket_id, public=False): if not (public or (request.user.is_authenticated() and request.user.is_active and (request.user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE))): return HttpResponseForbidden(_('Sorry, you need to login to do that.')) ticket = get_object_or_404(Ticket, id=ticket_id) comment = request.POST.get('comment', '') new_status = int(request.POST.get('new_status', ticket.status)) title = request.POST.get('title', '') public = request.POST.get('public', False) owner = int(request.POST.get('owner', None)) priority = int(request.POST.get('priority', ticket.priority)) due_year = int(request.POST.get('due_date_year')) due_month = int(request.POST.get('due_date_month')) due_day = int(request.POST.get('due_date_day')) due_date = datetime( due_year, due_month, due_day) if due_year and due_month and due_day else ticket.due_date tags = request.POST.get('tags', '') # We need to allow the 'ticket' and 'queue' contexts to be applied to the # comment. from django.template import loader, Context context = safe_template_context(ticket) # this line sometimes creates problems if code is sent as a comment. # if comment contains some django code, like "why does {% if bla %} crash", # then the following line will give us a crash, since django expects {% if %} # to be closed with an {% endif %} tag. comment = loader.get_template_from_string(comment).render(Context(context)) if owner is None and ticket.assigned_to: owner = ticket.assigned_to.id f = FollowUp(ticket=ticket, date=datetime.now(), comment=comment) if request.user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE: f.user = request.user f.public = public reassigned = False if owner is not None: if owner != 0 and ( (ticket.assigned_to and owner != ticket.assigned_to.id) or not ticket.assigned_to): new_user = User.objects.get(id=owner) f.title = _('Assigned to %(username)s') % { 'username': new_user.username, } ticket.assigned_to = new_user reassigned = True # user changed owner to 'unassign' elif owner == 0 and ticket.assigned_to is not None: f.title = _('Unassigned') ticket.assigned_to = None if new_status != ticket.status: ticket.status = new_status ticket.save() f.new_status = new_status if f.title: f.title += ' and %s' % ticket.get_status_display() else: f.title = '%s' % ticket.get_status_display() if not f.title: if f.comment: f.title = _('Comment') else: f.title = _('Updated') f.save() files = [] if request.FILES: import mimetypes, os for file in request.FILES.getlist('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.file.path) if title != ticket.title: c = TicketChange( followup=f, field=_('Title'), old_value=ticket.title, new_value=title, ) c.save() ticket.title = title if priority != ticket.priority: c = TicketChange( followup=f, field=_('Priority'), old_value=ticket.priority, new_value=priority, ) c.save() ticket.priority = priority if due_date != ticket.due_date: c = TicketChange( followup=f, field=_('Due on'), old_value=ticket.due_date, new_value=due_date, ) if helpdesk_settings.HELPDESK_UPDATE_CALENDAR: from helpdesk import calendars calendars.update_calendar(request, search_date=ticket.due_date) c.save() ticket.due_date = due_date if HAS_TAGGING_SUPPORT: if tags != ticket.tags: c = TicketChange( followup=f, field=_('Tags'), old_value=ticket.tags, new_value=tags, ) c.save() ticket.tags = tags if HAS_TAGGIT_SUPPORT: old_tags = [tag.name for tag in ticket.tags.all()] old_tags.sort() new_tags = tags.replace(' ', '').strip(',').split(',') new_tags.sort() if new_tags != old_tags: c = TicketChange( followup=f, field=_('Tags'), old_value=', '.join(old_tags), new_value=', '.join(new_tags), ) c.save() ticket.tags.set(*new_tags) if new_status in [Ticket.RESOLVED_STATUS, Ticket.CLOSED_STATUS]: ticket.resolution = comment messages_sent_to = [] # ticket might have changed above, so we re-instantiate context with the # (possibly) updated ticket. context = safe_template_context(ticket) context.update( resolution=ticket.resolution, comment=f.comment, ) if ticket.submitter_email and public and ( f.comment or (f.new_status in (Ticket.RESOLVED_STATUS, Ticket.CLOSED_STATUS))): if f.new_status == Ticket.RESOLVED_STATUS: template = 'resolved_submitter' elif f.new_status == Ticket.CLOSED_STATUS: template = 'closed_submitter' else: template = 'updated_submitter' send_templated_mail( template, context, recipients=ticket.submitter_email, sender=ticket.queue.from_address, fail_silently=True, files=files, ) 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( template, context, recipients=cc.email_address, sender=ticket.queue.from_address, fail_silently=True, ) messages_sent_to.append(cc.email_address) if ticket.assigned_to and request.user != ticket.assigned_to and ticket.assigned_to.email and ticket.assigned_to.email not in messages_sent_to: # We only send e-mails to staff members if the ticket is updated by # another user. The actual template varies, depending on what has been # changed. if reassigned: template_staff = 'assigned_owner' elif f.new_status == Ticket.RESOLVED_STATUS: template_staff = 'resolved_owner' elif f.new_status == Ticket.CLOSED_STATUS: template_staff = 'closed_owner' else: template_staff = 'updated_owner' if (not reassigned or (reassigned and ticket.assigned_to.usersettings.settings.get( 'email_on_ticket_assign', False))) or ( not reassigned and ticket.assigned_to.usersettings.settings.get( 'email_on_ticket_change', False)): send_templated_mail( template_staff, context, recipients=ticket.assigned_to.email, sender=ticket.queue.from_address, fail_silently=True, files=files, ) messages_sent_to.append(ticket.assigned_to.email) if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to: if reassigned: template_cc = 'assigned_cc' elif f.new_status == Ticket.RESOLVED_STATUS: template_cc = 'resolved_cc' elif f.new_status == Ticket.CLOSED_STATUS: template_cc = 'closed_cc' else: template_cc = 'updated_cc' send_templated_mail( template_cc, context, recipients=ticket.queue.updated_ticket_cc, sender=ticket.queue.from_address, fail_silently=True, files=files, ) ticket.save() if request.user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE: return HttpResponseRedirect(ticket.get_absolute_url()) else: return HttpResponseRedirect(ticket.ticket_url)
def update_ticket(request, ticket_id, public=False): if not (public or (request.user.is_authenticated() and request.user.is_active and request.user.is_staff)): return HttpResponseForbidden(_('Sorry, you need to login to do that.')) ticket = get_object_or_404(Ticket, id=ticket_id) comment = request.POST.get('comment', '') new_status = int(request.POST.get('new_status', ticket.status)) title = request.POST.get('title', ticket.title) public = request.POST.get('public', public) owner = int(request.POST.get('owner', 0)) priority = int(request.POST.get('priority', ticket.priority)) tags = request.POST.get('tags', '') if public: ticket.notify_owner = True else: ticket.notify_owner = False # We need to allow the 'ticket' and 'queue' contexts to be applied to the # comment. from django.template import loader, Context context = safe_template_context(ticket) comment = loader.get_template_from_string(comment).render(Context(context)) if owner is None and ticket.assigned_to: owner = ticket.assigned_to.id f = FollowUp(ticket=ticket, date=datetime.now(), comment=comment) if request.user.is_authenticated(): f.user = request.user f.public = public reassigned = False if owner is not None: if owner != 0 and ( (ticket.assigned_to and owner != ticket.assigned_to.id) or not ticket.assigned_to): new_user = User.objects.get(id=owner) f.title = _('Assigned to %(username)s') % { 'username': new_user.username, } ticket.assigned_to = new_user reassigned = True elif owner == 0 and ticket.assigned_to is not None: f.title = _('Unassigned') ticket.assigned_to = None if new_status != ticket.status: ticket.status = new_status ticket.save() f.new_status = new_status if f.title: f.title += ' and %s' % ticket.get_status_display() else: f.title = '%s' % ticket.get_status_display() if not f.title: if f.comment: f.title = _('Comment') else: f.title = _('Updated') f.save() files = [] if request.FILES: import mimetypes, os for file in request.FILES.getlist('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.file.path) if title != ticket.title: c = TicketChange( followup=f, field=_('Title'), old_value=ticket.title, new_value=title, ) c.save() ticket.title = title if priority != ticket.priority: c = TicketChange( followup=f, field=_('Priority'), old_value=ticket.priority, new_value=priority, ) c.save() ticket.priority = priority if HAS_TAG_SUPPORT: if tags != ticket.tags: c = TicketChange( followup=f, field=_('Tags'), old_value=ticket.tags, new_value=tags, ) c.save() ticket.tags = tags if f.new_status == Ticket.RESOLVED_STATUS: ticket.resolution = comment messages_sent_to = [] context.update( resolution=ticket.resolution, comment=f.comment, ) if ticket.submitter_email and public and ( f.comment or (f.new_status in (Ticket.RESOLVED_STATUS, Ticket.CLOSED_STATUS))): if f.new_status == Ticket.RESOLVED_STATUS: template = 'resolved_owner' elif f.new_status == Ticket.CLOSED_STATUS: template = 'closed_owner' else: template = 'updated_owner' send_templated_mail( template, context, recipients=ticket.submitter_email, sender=ticket.queue.from_address, fail_silently=True, files=files, ) 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( template, context, recipients=cc.email_address, sender=ticket.queue.from_address, fail_silently=True, ) messages_sent_to.append(cc.email_address) if ticket.assigned_to and request.user.account != ticket.assigned_to and ticket.assigned_to.email and ticket.assigned_to.email not in messages_sent_to: # We only send e-mails to staff members if the ticket is updated by # another user. The actual template varies, depending on what has been # changed. if reassigned: template_staff = 'assigned_to' elif f.new_status == Ticket.RESOLVED_STATUS: template_staff = 'resolved_asigned_to' elif f.new_status == Ticket.CLOSED_STATUS: template_staff = 'closed_assigned_to' else: template_staff = 'updated_assigned_to' if (not reassigned or (reassigned and ticket.assigned_to.usersettings.settings.get( 'email_on_ticket_assign', False))) or ( not reassigned and ticket.assigned_to.usersettings.settings.get( 'email_on_ticket_change', False)): send_templated_mail( template_staff, context, recipients=ticket.assigned_to.email, sender=ticket.queue.from_address, fail_silently=True, files=files, ) messages_sent_to.append(ticket.assigned_to.email) if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to: if reassigned: template_cc = 'assigned_cc' elif f.new_status == Ticket.RESOLVED_STATUS: template_cc = 'resolved_cc' elif f.new_status == Ticket.CLOSED_STATUS: template_cc = 'closed_cc' else: template_cc = 'updated_cc' send_templated_mail( template_cc, context, recipients=ticket.queue.updated_ticket_cc, sender=ticket.queue.from_address, fail_silently=True, files=files, ) ticket.save() if request.user.is_staff: return HttpResponseRedirect(ticket.get_absolute_url()) else: return HttpResponseRedirect(ticket.ticket_url)
def followup_edit(request): id = request.POST.get("id") item = None if request.method == 'POST': if id: model = FollowUp.objects.get(id=id) form = FollowUpForm(request.POST, instance=model) if not (request.user.account.has_perm('helpdesk.change_followup')): messages.error( request, _(u'У вас нет прав на редактирование комментариев к заявке' ), extra_tags='alert-danger') return HttpResponseRedirect(request.path) else: form = FollowUpForm(request.POST, request.FILES) if not (request.user.account.has_perm('helpdesk.add_followup')): messages.error( request, _(u'У вас нет прав на добавление комментариев к заявке'), extra_tags='alert-danger') return HttpResponseRedirect(request.path) if form.is_valid(): model = form.save(commit=False) model.save() followup_type = form.cleaned_data.get('followup_type') if followup_type == 'comment': if not id: model.title = _(u'Добавлен комментарий от %(USER)s ') % { 'USER': request.user.account } elif followup_type == 'files': if not id: model.title = _(u'Добавлен файл от %(USER)s ') % { 'USER': request.user.account } files = [] if request.FILES: import mimetypes, os for file in request.FILES.getlist('file'): filename = file.name.replace(' ', '_') a = Attachment( followup=model, 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.file.path) elif followup_type == 'new_status': model.title = _(u'Статус заявки изменён %(USER)s ') % { 'USER': request.user.account } if model.new_status != model.ticket: model.ticket.status = model.new_status if model.new_status in [3, 4]: model.ticket.resolution = model.comment model.ticket.save() log('EDIT', request.user, model.ticket) model.systemuser = request.user.account model.save() from django.template import loader, Context log('EDIT', request.user, model) if id else log( 'CREATE', request.user, model) messages.success(request, _(u'Комментарий успешно сохранён.'), extra_tags='alert-success') return {'form': form, 'status': True} else: messages.error(request, _(u'При сохранении комментария возникли ошибки.'), extra_tags='alert-danger') if form._errors: for k, v in form._errors.items(): messages.error(request, '%s=>%s' % (k, ','.join(v)), extra_tags='alert-danger') return {'form': form, 'status': False} else: id = request.GET.get("id") ticket_id = request.GET.get("ticket_id") followup_type = request.GET.get("followup_type") or 'comment' new_status = request.GET.get("new_status") if not (request.user.account.has_perm('helpdesk.add_followup')): messages.error(request, _(u'У вас нет прав на создание комментариев.'), extra_tags='alert-danger') return {} if id: item = FollowUp.objects.get(id=id) form = FollowUpForm(instance=item) else: if new_status: form = FollowUpForm( initial={ 'ticket': Ticket.objects.get(id=ticket_id), 'followup_type': followup_type, 'new_status': 2 }) else: form = FollowUpForm( initial={ 'ticket': Ticket.objects.get(id=ticket_id), 'followup_type': followup_type }) return {'form': form, 'status': False}
def save(self, user): """ Writes and returns a Ticket() object """ q = self.cleaned_data['queue'] t = Ticket( title=self.cleaned_data['title'], submitter_email=self.cleaned_data['submitter_email'], created=datetime.now(), status=Ticket.OPEN_STATUS, queue=q, description=self.cleaned_data['description'], priority=self.cleaned_data['priority'], due_date=self.cleaned_data['due_date'], ) if HAS_TAGGING_SUPPORT: t.tags = self.cleaned_data['tags'] if self.cleaned_data['assigned_to']: try: u = self.cleaned_data['assigned_to'] t.assigned_to = u except User.DoesNotExist: t.assigned_to = None t.save() if HAS_TAGGIT_SUPPORT: t.tags.set(*self.cleaned_data['tags']) for field, value in self.cleaned_data.items(): if field.startswith('custom_'): field_name = field.replace('custom_', '') customfield = CustomField.objects.get(name=field_name) cfv = TicketCustomFieldValue(ticket=t, field=customfield, value=value) cfv.save() f = FollowUp( ticket=t, title=_('Ticket Opened'), date=datetime.now(), public=True, comment=self.cleaned_data['description'] if helpdesk_settings.HELPDESK_INCLUDE_DESCRIPTION_IN_FOLLOWUP else None, user=user, ) if self.cleaned_data['assigned_to']: f.title = _('Ticket Opened & Assigned to %(name)s') % { 'name': t.get_assigned_to } 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.file.path) context = safe_template_context(t) context['comment'] = f.comment messages_sent_to = [] if t.submitter_email: 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 t.assigned_to and t.assigned_to != user and getattr( t.assigned_to.usersettings.settings, 'email_on_ticket_assign', False ) and t.assigned_to.email and t.assigned_to.email not in messages_sent_to: send_templated_mail( 'assigned_owner', context, recipients=t.assigned_to.email, sender=q.from_address, fail_silently=True, files=files, ) messages_sent_to.append(t.assigned_to.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 update_ticket(request, ticket_id, public=False): ticket = get_object_or_404(Ticket, id=ticket_id,owner=request.user) comment = request.POST.get('comment', '') new_status = int(request.POST.get('new_status', ticket.status)) title = request.POST.get('title', ticket.title) #public = request.POST.get('public', public) public=True owner = ticket.owner #priority = int(request.POST.get('priority', ticket.priority)) tags = request.POST.get('tags', '') # We need to allow the 'ticket' and 'queue' contexts to be applied to the # comment. from django.template import loader, Context context = safe_template_context(ticket) comment = loader.get_template_from_string(comment).render(Context(context)) #if owner is None and ticket.assigned_to: # owner = ticket.assigned_to.id f = FollowUp(ticket=ticket, date=datetime.now(), comment=comment) #if request.user.is_authenticated(): f.account = request.user.account f.public = True reassigned = False if new_status != ticket.status: ticket.status = new_status ticket.save() f.new_status = new_status if f.title: f.title += _(u'%(STATUS)s %(USER)s ') % {'USER': request.user.account, 'STATUS': ticket.get_status_display()} else: f.title = _(u'%(STATUS)s %(USER)s ') % {'USER': request.user.account, 'STATUS': ticket.get_status_display()} if not f.title: if f.comment: f.title = _(u'Добавлен комментарий от %(USER)s ') % {'USER': request.user.account} else: f.title = _(u'Обновлено %(USER)s ') % {'USER': request.user.account} f.save() files = [] if request.FILES: import mimetypes, os for file in request.FILES.getlist('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.file.path) if title != ticket.title: c = TicketChange( followup=f, field=_('Title'), old_value=ticket.title, new_value=title, ) c.save() ticket.title = title if HAS_TAG_SUPPORT: if tags != ticket.tags: c = TicketChange( followup=f, field=_('Tags'), old_value=ticket.tags, new_value=tags, ) c.save() ticket.tags = tags if f.new_status == Ticket.RESOLVED_STATUS: ticket.resolution = comment messages_sent_to = [] context.update( resolution=ticket.resolution, comment=f.comment, ) if ticket.submitter_email and public and (f.comment or (f.new_status in (Ticket.RESOLVED_STATUS, Ticket.CLOSED_STATUS))): if f.new_status == Ticket.RESOLVED_STATUS: template = 'resolved_owner' elif f.new_status == Ticket.CLOSED_STATUS: template = 'closed_owner' else: template = 'updated_owner' send_templated_mail( template, context, recipients=ticket.submitter_email, sender=ticket.queue.from_address, fail_silently=True, files=files, ) 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( template, context, recipients=cc.email_address, sender=ticket.queue.from_address, fail_silently=True, ) messages_sent_to.append(cc.email_address) if ticket.assigned_to and request.user != ticket.assigned_to and ticket.assigned_to.email and ticket.assigned_to.email not in messages_sent_to: # We only send e-mails to staff members if the ticket is updated by # another user. The actual template varies, depending on what has been # changed. if reassigned: template_staff = 'assigned_to' elif f.new_status == Ticket.RESOLVED_STATUS: template_staff = 'resolved_assigned_to' elif f.new_status == Ticket.CLOSED_STATUS: template_staff = 'closed_assigned_to' else: template_staff = 'updated_assigned_to' if (not reassigned or ( reassigned and ticket.assigned_to.usersettings.settings.get('email_on_ticket_assign', False))) or (not reassigned and ticket.assigned_to.usersettings.settings.get('email_on_ticket_change', False)): send_templated_mail( template_staff, context, recipients=ticket.assigned_to.email, sender=ticket.queue.from_address, fail_silently=True, files=files, ) messages_sent_to.append(ticket.assigned_to.email) if ticket.queue.updated_ticket_cc and ticket.queue.updated_ticket_cc not in messages_sent_to: if reassigned: template_cc = 'assigned_cc' elif f.new_status == Ticket.RESOLVED_STATUS: template_cc = 'resolved_cc' elif f.new_status == Ticket.CLOSED_STATUS: template_cc = 'closed_cc' else: template_cc = 'updated_cc' send_templated_mail( template_cc, context, recipients=ticket.queue.updated_ticket_cc, sender=ticket.queue.from_address, fail_silently=True, files=files, ) ticket.save() return HttpResponseRedirect(ticket.ticket_url)
def save(self, request=None): """ 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=datetime.now(), status=Ticket.OPEN_STATUS, queue=q, description=self.cleaned_data['body'], priority=self.cleaned_data['priority'], ) t.save() for field, value in self.cleaned_data.items(): if field.startswith('custom_'): field_name = field.replace('custom_', '') 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=datetime.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.file.path) context = { 'ticket': t, 'queue': q, 'site': Site.objects.get_current(), 'request': request } send_templated_mail( 'newticket_submitter', context, recipients=t.submitter_email, sender=q.from_address, fail_silently=True, files=files, ) who_to_notify = [] emails = "%s,%s" % (q.new_ticket_cc, q.updated_ticket_cc) for e in emails.split(','): email = e.strip(' ') if email and email != t.submitter_email and email not in who_to_notify: who_to_notify.append(email) if who_to_notify: send_templated_mail( 'newticket_cc', context, recipients=who_to_notify, sender=q.from_address, fail_silently=True, files=files, ) return t
def save(self, owner=None): """ Writes and returns a Ticket() object """ q = Queue.objects.get(id=int(self.cleaned_data['queue'])) t = Ticket(title=self.cleaned_data['title'], owner=owner, submitter_email=self.cleaned_data['submitter_email'], created=datetime.now(), status=Ticket.OPEN_STATUS, queue=q, description=self.cleaned_data['body'], priority=self.cleaned_data['priority'], account=owner.account) t.save() f = FollowUp(ticket=t, title=_('Ticket Opened Via Web'), date=datetime.now(), public=True, comment=self.cleaned_data['body'], account=owner.account) 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.file.path) context = { 'ticket': t, 'queue': q, } messages_sent_to = [] send_templated_mail( 'newticket_owner', 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, user): """ Writes and returns a Ticket() object """ q = self.cleaned_data['queue'] t = Ticket(title=self.cleaned_data['title'], submitter_email=self.cleaned_data['submitter_email'], account=self.cleaned_data['account'], created=datetime.now(), status=Ticket.OPEN_STATUS, queue=q, description=self.cleaned_data['body'], priority=self.cleaned_data['priority'], owner=self.cleaned_data['owner']) if HAS_TAG_SUPPORT: t.tags = self.cleaned_data['tags'] if self.cleaned_data['assigned_to']: try: t.assigned_to = self.cleaned_data['assigned_to'] except User.DoesNotExist: t.assigned_to = None t.save() f = FollowUp( ticket=t, title=_('Ticket Opened'), date=datetime.now(), public=False, comment=self.cleaned_data['body'], systemuser=user.account, ) if self.cleaned_data['assigned_to']: f.title = _('Ticket Opened & Assigned to %(name)s') % { 'name': t.get_assigned_to } 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.file.path) context = { 'ticket': t, 'queue': q, 'comment': f.comment, } messages_sent_to = [] if t.submitter_email: send_templated_mail( 'newticket_owner', context, recipients=t.submitter_email, sender=q.from_address, fail_silently=True, files=files, ) messages_sent_to.append(t.submitter_email) #FIX USERSETTINGS #======================================================================= # if t.assigned_to and t.assigned_to != user and getattr(t.assigned_to.usersettings.settings, 'email_on_ticket_assign', False) and t.assigned_to.email and t.assigned_to.email not in messages_sent_to: # send_templated_mail( # 'assigned_to', # context, # recipients=t.assigned_to.email, # sender=q.from_address, # fail_silently=True, # files=files, # ) # messages_sent_to.append(t.assigned_to.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