Пример #1
0
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
Пример #2
0
    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
Пример #3
0
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,
    })
Пример #4
0
 def save(self, user):
     task = Task.objects.get(id=int(self.cleaned_data['task']))
     if self.cleaned_data['attachment']:
         import mimetypes
         file = self.cleaned_data['attachment']
         filename = file.name.replace(' ', '_')
         a = Attachment(
             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()
         task.attachments.add(a)
     task.save()
     return None
Пример #5
0
    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
Пример #6
0
def process_attachments(followup, attached_files):
    max_email_attachment_size = getattr(settings, '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.MAX_EMAIL_ATTACHMENT_SIZE) are sent via email.
                attachments.append([filename, att.file])

    return attachments
Пример #7
0
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 form_valid(self, form):
        old_ticket = form.instance
        ticket = form.save(commit=False)

        no_changes = all([
            not self.request.FILES,
            not self.request.POST['comment'],
            ticket.status == old_ticket.status,
            ticket.title == old_ticket.title,
            ticket.priority == int(old_ticket.priority),
            ticket.due_date == old_ticket.due_date,
            ticket.owner_id != old_ticket.owner_id
        ])

        if no_changes:
            self.object = old_ticket
            return HttpResponseRedirect(self.get_success_url())

        ticket.save()
        self.object = ticket

        followup = FollowUp(
            ticket_id=ticket.pk,
            date = timezone.now(),
            comment = self.request.POST['comment'],
            user_id = self.request.user.pk,
            public = self.request.POST['public'],
            title = ''
        )

        reassigned = False

        if ticket.owner_id != old_ticket.owner_id:
            followup.title = _('Asigned to %s' % User.objects.get(id=ticket.owner_id))
            reassigned = True

        if ticket.status != old_ticket.status:
            if followup.title != '':
                followup.title += ' and '
            followup.title += ticket.get_status_display()

        followup.save()

        files = []
        if self.request.FILES:
            import mimetypes, os
            for file in self.request.FILES.getlist('attachment'):
                filename = file.name.encode('ascii', 'ignore')
                a = Attachment(
                    followup_id=followup.pk,
                    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()

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

        if old_ticket.title != ticket.title:
            change = TicketChange(
                followup_id=followup.id,
                field=_('Title'),
                old_value = old_ticket.title,
                new_value = ticket.title
            )

        if old_ticket.priority != ticket.priority:
            change = TicketChange(
                followup_id=followup.id,
                field=_('Priority'),
                old_value = old_ticket.priority,
                new_value = ticket.priority
            )

        if old_ticket.due_date != ticket.due_date:
            change = TicketChange(
                followup_id=followup.id,
                field=_('Due on'),
                old_value = old_ticket.due_date,
                new_value = ticket.due_date
            )

        # 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.

        # get_template_from_string was removed in Django 1.8 http://django.readthedocs.org/en/1.8.x/ref/templates/upgrading.html
        try:
            from django.template import engines
            template_func = engines['django'].from_string
        except ImportError:  # occurs in django < 1.8
            template_func = loader.get_template_from_string

        # RemovedInDjango110Warning: render() must be called with a dict, not a Context.
        if VERSION < (1, 8):
            context = Context(context)

        comment = template_func(followup.comment).render(context)

        if ticket.status in [ Ticket.RESOLVED_STATUS, Ticket.CLOSED_STATUS ]:
            if ticket.status == Ticket.RESOLVED_STATUS or ticket.resolution is None:
                ticket.resolution = comment

        messages_sent_to = []
        if followup.public and (followup.comment or
            (followup.new_status in (Ticket.RESOLVED_STATUS, Ticket.CLOSED_STATUS))):

            if followup.new_status == Ticket.RESOLVED_STATUS:
                template = 'resolved_'
            elif followup.new_status == Ticket.CLOSED_STATUS:
                template = 'closed_'
            else:
                template = 'updated_'

            template_suffix = 'submitter'

            if ticket.submitter_email:
                send_templated_mail(
                    template + template_suffix,
                    context,
                    recipients=ticket.submitter_email,
                    sender=ticket.queue.from_address,
                    fail_silently=True,
                    files=files,
                    )
                messages_sent_to.append(ticket.submitter_email)

            template_suffix = 'cc'

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

        if old_ticket.assigned_to_id and self.request.user.pk != ticket.assigned_to_id \
            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 followup.new_status == Ticket.RESOLVED_STATUS:
                template_staff = 'resolved_owner'
            elif followup.new_status == Ticket.CLOSED_STATUS:
                template_staff = 'closed_owner'
            else:
                template_staff = 'updated_owner'

            if (not reassigned or \
                ( reassigned and old_ticket.assigned_to.usersettings.settings.get('email_on_ticket_assign', False))) \
                or (not reassigned and old_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 followup.new_status == Ticket.RESOLVED_STATUS:
                template_cc = 'resolved_cc'
            elif followup.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()

        # auto subscribe user if enabled
        if helpdesk_settings.HELPDESK_AUTO_SUBSCRIBE_ON_TICKET_RESPONSE:
            ticketcc_string, SHOW_SUBSCRIBE = return_ticketccstring_and_show_subscribe(self.request.user, ticket)
            if SHOW_SUBSCRIBE:
                subscribe_staff_member_to_ticket(ticket, self.request.user)

        return HttpResponseRedirect(self.get_success_url())
Пример #9
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 = datetime.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_', '')
                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 = 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
Пример #10
0
    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
Пример #11
0
    def save(self, user):
        """
        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"],
            due_date=self.cleaned_data["due_date"],
        )

        if HAS_TAG_SUPPORT:
            t.tags = self.cleaned_data["tags"]

        if self.cleaned_data["assigned_to"]:
            try:
                u = User.objects.get(id=self.cleaned_data["assigned_to"])
                t.assigned_to = u
            except User.DoesNotExist:
                t.assigned_to = None
        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"),
            date=datetime.now(),
            public=True,
            comment=self.cleaned_data["body"],
            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
Пример #12
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: ", "").strip()

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

    sender_name = parseaddr(sender)[0]
    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"^\[(?P<queue>[-A-Za-z0-9]+)-(?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 = 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 = datetime.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

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

    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 = datetime.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%s" % (t.queue.slug, t.id, t.title, update)).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
Пример #13
0
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)

    
Пример #14
0
def create_object_from_email_message(message, ticket_id, payload, files, quiet):

    ticket, previous_followup, new = None, None, False
    now = timezone.now()

    queue = payload['queue']
    sender_email = payload['sender_email']

    to_list = getaddresses(message.get_all('To', []))
    cc_list = getaddresses(message.get_all('Cc', []))

    message_id = message.get('Message-Id')
    in_reply_to = message.get('In-Reply-To')

    if in_reply_to is not None:
        try:
            queryset = FollowUp.objects.filter(message_id=in_reply_to).order_by('-date')
            if queryset.count() > 0:
                previous_followup = queryset.first()
                ticket = previous_followup.ticket
        except FollowUp.DoesNotExist:
            pass #play along. The header may be wrong

    if previous_followup is None and ticket_id is not None:
        try:
            ticket = Ticket.objects.get(id=ticket_id)
            new = False
        except Ticket.DoesNotExist:
            ticket = None

    # New issue, create a new <Ticket> instance
    if ticket is None:
        ticket = Ticket.objects.create(
            title = payload['subject'],
            queue = queue,
            submitter_email = sender_email,
            created = now,
            description = payload['body'],
            priority = payload['priority'],
        )
        ticket.save()

        new = True
        update = ''

    # Old issue being re-openned
    elif ticket.status == Ticket.CLOSED_STATUS:
        ticket.status = Ticket.REOPENED_STATUS
        ticket.save()

    f = FollowUp(
        ticket = ticket,
        title = _('E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}),
        date = now,
        public = True,
        comment = payload['body'],
        message_id = message_id,
    )

    if ticket.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" % (ticket.queue.slug, ticket.id, ticket.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(ticket)

    new_ticket_ccs = []
    new_ticket_ccs.append(create_ticket_cc(ticket, to_list))
    new_ticket_ccs.append(create_ticket_cc(ticket, cc_list))

    notification_template = None
    notifications_to_be_sent = [sender_email,]
    
    if queue.enable_notifications_on_email_events and len(notifications_to_be_sent):

        ticket_cc_list = TicketCC.objects.filter(ticket=ticket).all().values_list('email', flat=True)

        for email in ticket_cc_list : 
            notifications_to_be_sent.append(email)

    if new:

        notification_template = 'newticket_cc'

        if sender_email:
            send_templated_mail(
                'newticket_submitter',
                context,
                recipients=notifications_to_be_sent,
                sender=queue.from_address,
                fail_silently=True,
                extra_headers={'In-Reply-To': message_id},
                )

        if queue.new_ticket_cc:

            send_templated_mail(
                'newticket_cc',
                context,
                recipients=queue.new_ticket_cc,
                sender=queue.from_address,
                fail_silently=True,
                extra_headers={'In-Reply-To': message_id},
                )

        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,
                extra_headers={'In-Reply-To': message_id},
                )

    else:

        notification_template = 'updated_cc'

        context.update(comment=f.comment)

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

        if ticket.assigned_to:
            send_templated_mail(
                'updated_owner',
                context,
                recipients=ticket.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,
                )    

        if queue.enable_notifications_on_email_events:

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

    return ticket
Пример #15
0
  def form_valid(self, form):
    self.object = form.save(True)
    t = self.object
    q = t.queue
    for field, value in form.cleaned_data.items():
        if field.startswith('custom_'):
            field_name = field.replace('custom_', '', 1)
            customfields = CustomField.objects.filter(customfieldset__queue_id=form.cleaned_data['queue'])

            for customfield in customfields:
                if customfield.name == field_name:
                    cfv = TicketCustomFieldValue(ticket=t,
                                                 field=customfield,
                                                 value=value)
                    cfv.save()

                    cfs = CustomFieldSet(queue_id=q.pk,
                                        field=customfield)
                    cfs.save()

    f = FollowUp(
      ticket_id = t.pk,
      title = _('Ticket Opened'),
      date = timezone.now(),
      public = True,
      comment = form.cleaned_data['body'],
      user_id = t.assigned_to_id
    )
    if form.cleaned_data['assigned_to']:
        f.title = _('Ticket Opened & Assigned to %(name)s') % {
            'name': t.get_assigned_to
        }

    f.save()
    
    files = []
    if form.cleaned_data['attachment']:
        import mimetypes
        file = form.cleaned_data['attachment']
        filename = file.name.replace(' ', '_')
        a = Attachment(
            followup_id=f.pk,
            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.
            try:
                files.append([a.filename, a.file])
            except NotImplementedError:
                pass

    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 != self.request.user 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 HttpResponseRedirect(self.get_success_url())
Пример #16
0
def ticket_from_message(message, queue, quiet):
    is_cc = False
    update = None

    # '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: ", "").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

    # Check if we're being CC'ed, in which case we might not want to send emails or filter
    dest = decode_mail_headers(decodeUnknown(message.get_charset(), message.get('to', _('Unknown Sender'))))
    dest_email = parseaddr(dest)
    if (not helpdesk_settings.HELPDESK_EMAIL_CONFIRM_CC or helpdesk_settings.HELPDESK_FILTER_CC_ALTERNATE) \
    and dest_email[1] != queue.email_address:
        is_cc = True

    # If we want to filter CC'd messages to a seperate queue, do so
    # Try to filter to a queue based on gmail labels
    reset_queue = False
    if helpdesk_settings.HELPDESK_FILTER_LABEL_TO_QUEUE:
      match_info = re.match(r"^(.*?)\++(?P<label>.*?)@.*", dest_email[1])
      if match_info:
        try:
          new_queue = Queue.objects.get(slug=match_info.group('label').lower())
          if new_queue:
            logger.info(" ++ Matched label '%s' to queue '%s'" % (match_info.group('label').lower(), new_queue))
            queue = new_queue
            reset_queue = True
        except:
          logger.error(" !! Failed to match label '%s' to a queue, not moving message" % match_info.group('label').lower())

    # Check we want to filter CCs, but only if we have a queue and
    # a queue was not already modified because we matched a label
    if helpdesk_settings.HELPDESK_FILTER_CC_ALTERNATE and is_cc and queue.alternate_queue is not None \
    and not reset_queue:
        logger.info(" ++ We think this is CC'd")
        queue = queue.alternate_queue

    matchobj = re.match(r"^\[(?P<queue>[-A-Za-z0-9]+)-(?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':
                try:
                  body_plain = decodeUnknown(part.get_content_charset(), part.get_payload(decode=True))
                except: # We could get a unicode exception here, in which case, we really don't know anymore
                  body_plain = None
            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

    plain = html = False

    if body_plain:
        body = body_plain
        plain = True
    else:
        body = _('No plain-text email body available. Please see attachment email_html_body.html.')

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

    now = datetime.now()

    if ticket:
        try:
            t = Ticket.objects.get(id=ticket)
            new = False
        except Ticket.DoesNotExist:
            logger.debug("Didn't find a ticket with ID %s" % ticket)
            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:
        logger.debug("Creating new ticket for email")
        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:
        logger.debug("Reopening ticket")
        t.status = Ticket.REOPENED_STATUS
        t.save()

    f = FollowUp(
        ticket = t,
        title = _('E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}),
        date = datetime.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:
        logger.info(" [%s-%s] %s%s" % (t.queue.slug, t.id, t.title, update)).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:
                logger.info("    - %s" % filename)


    context = safe_template_context(t)

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

        if queue.new_ticket_cc and not is_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 and not is_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 and not is_cc:
            send_templated_mail(
                'updated_owner',
                context,
                recipients=t.assigned_to.email,
                sender=queue.from_address,
                fail_silently=True,
                )

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

    return t
Пример #17
0
    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 form_valid(self, form):
        form.instance.created = timezone.now()
        form.instance.status = Ticket.OPEN_STATUS
        self.object = form.save()
        t = self.object

        f = FollowUp(   ticket_id = t.id,
                        title = _('Ticket Opened'),
                        date = timezone.now(),
                        public = True,
                        comment = '',
                        user_id = t.assigned_to_id
        )

        if t.assigned_to_id:
            f.title = _('Ticket Opened & Assigned to %(name)s') % {
                'name': t.get_assigned_to.get_full_name()
            }

        f.save()

        files = []
        if form.cleaned_data.get('attachment'):
            import mimetypes
            file = form.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.
                try:
                    files.append([a.filename, a.file])
                except NotImplementedError:
                    pass

        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=t.queue.from_address,
                fail_silently=True,
                files=files,
                )
            messages_sent_to.append(t.submitter_email)

        #if t.assigned_to and t.assigned_to != user 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:
        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=t.queue.from_address,
                fail_silently=True,
                files=files,
                )
            messages_sent_to.append(t.assigned_to.email)

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

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

        return HttpResponseRedirect(self.get_success_url())
Пример #19
0
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 save(self):
        """
        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=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
Пример #21
0
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)
Пример #22
0
def ticket_from_message(message, queue, logger):
    # '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))
    for affix in STRIPPED_SUBJECT_STRINGS:
        subject = subject.replace(affix, "")
    subject = subject.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')
        logger.info("Matched tracking ID %s-%s" % (queue.slug, ticket))
    else:
        logger.info("No tracking ID matched.")
        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)))
                logger.debug("Discovered plain text MIME part")
            else:
                body_html = part.get_payload(decode=True)
                logger.debug("Discovered HTML MIME part")
        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()},
            )
            logger.debug("Found MIME attachment %s" % name)

        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
            logger.info("Found existing ticket with Tracking ID %s-%s" % (t.queue.slug, t.id))
        except Ticket.DoesNotExist:
            logger.info("Tracking ID %s-%s not associated with existing ticket. Creating new ticket." % (queue.slug, ticket))
            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
        logger.debug("Created new ticket %s-%s" % (t.queue.slug, t.id))

    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()
    logger.debug("Created new FollowUp for Ticket")

    if six.PY2:
        logger.info(("[%s-%s] %s" % (t.queue.slug, t.id, t.title,)).encode('ascii', 'replace'))
    elif six.PY3:
        logger.info("[%s-%s] %s" % (t.queue.slug, t.id, t.title,))

    for file in files:
        if file['content']:
            if six.PY2:
                filename = file['filename'].encode('ascii', 'replace').replace(' ', '_')
            elif six.PY3:
                filename = file['filename'].replace(' ', '_')
            filename = re.sub('[^a-zA-Z0-9._-]+', '', filename)
            logger.info("Found attachment '%s'" % 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()
            logger.info("Attachment '%s' successfully added to ticket." % 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
Пример #23
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'],
        )

        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
Пример #24
0
    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
Пример #25
0
    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
Пример #26
0
    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
Пример #27
0
    def save(self, user):
        """
        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 HAS_TAG_SUPPORT:
            t.tags = self.cleaned_data['tags']

        if self.cleaned_data['assigned_to']:
            try:
                u = User.objects.get(id=self.cleaned_data['assigned_to'])
                t.assigned_to = u
            except User.DoesNotExist:
                t.assigned_to = None
        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'),
                        date = timezone.now(),
                        public = True,
                        comment = self.cleaned_data['body'],
                        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 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
Пример #28
0
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} 
Пример #29
0
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', '')
    public = request.POST.get('public', False)
    owner = int(request.POST.get('owner', None))
    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_staff:
        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 = []

    # 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:
        return HttpResponseRedirect(ticket.get_absolute_url())
    else:
        return HttpResponseRedirect(ticket.ticket_url)
Пример #30
0
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}
Пример #31
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 == 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
Пример #32
0
    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