2008-02-06 05:36:07 +01:00
|
|
|
#!/usr/bin/python
|
|
|
|
"""
|
|
|
|
Jutda Helpdesk - A Django powered ticket tracker for small enterprise.
|
2008-01-15 06:18:54 +01:00
|
|
|
|
2008-02-06 05:36:07 +01:00
|
|
|
(c) Copyright 2008 Jutda. All Rights Reserved. See LICENSE for details.
|
2008-01-15 06:18:54 +01:00
|
|
|
|
2008-02-06 05:36:07 +01:00
|
|
|
scripts/get_email.py - Designed to be run from cron, this script checks the
|
2008-08-19 10:50:38 +02:00
|
|
|
POP and IMAP boxes defined for the queues within a
|
|
|
|
helpdesk, creating tickets from the new messages (or
|
2008-02-06 05:36:07 +01:00
|
|
|
adding to existing tickets if needed)
|
2008-01-15 06:18:54 +01:00
|
|
|
"""
|
2008-08-18 23:34:41 +02:00
|
|
|
|
|
|
|
import email
|
2008-01-07 21:22:13 +01:00
|
|
|
import imaplib
|
2008-08-18 23:34:41 +02:00
|
|
|
import mimetypes
|
|
|
|
import poplib
|
|
|
|
import re
|
2014-12-10 22:37:34 +01:00
|
|
|
import socket
|
2009-07-21 11:54:23 +02:00
|
|
|
|
2013-01-23 01:35:18 +01:00
|
|
|
from datetime import timedelta
|
2008-12-10 22:46:54 +01:00
|
|
|
from email.header import decode_header
|
2011-01-29 07:25:53 +01:00
|
|
|
from email.Utils import parseaddr, collapse_rfc2231_value
|
2009-07-21 11:54:23 +02:00
|
|
|
from optparse import make_option
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2014-01-29 13:08:33 +01:00
|
|
|
from email_reply_parser import EmailReplyParser
|
|
|
|
|
2008-08-13 23:42:57 +02:00
|
|
|
from django.core.files.base import ContentFile
|
2008-08-18 23:29:31 +02:00
|
|
|
from django.core.management.base import BaseCommand
|
2008-10-25 00:52:34 +02:00
|
|
|
from django.db.models import Q
|
2008-08-18 23:34:41 +02:00
|
|
|
from django.utils.translation import ugettext as _
|
2012-10-07 10:50:26 +02:00
|
|
|
from helpdesk import settings
|
2008-08-18 23:34:41 +02:00
|
|
|
|
2013-01-23 01:35:18 +01:00
|
|
|
try:
|
|
|
|
from django.utils import timezone
|
|
|
|
except ImportError:
|
|
|
|
from datetime import datetime as timezone
|
|
|
|
|
2011-11-09 16:37:37 +01:00
|
|
|
from helpdesk.lib import send_templated_mail, safe_template_context
|
2016-02-20 15:39:16 +01:00
|
|
|
from helpdesk.models import Queue, Ticket, TicketCC, FollowUp, Attachment, IgnoreEmail
|
2008-08-18 23:29:31 +02:00
|
|
|
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2008-08-18 23:29:31 +02:00
|
|
|
class Command(BaseCommand):
|
2009-07-21 11:54:23 +02:00
|
|
|
def __init__(self):
|
|
|
|
BaseCommand.__init__(self)
|
|
|
|
|
|
|
|
self.option_list += (
|
|
|
|
make_option(
|
|
|
|
'--quiet', '-q',
|
|
|
|
default=False,
|
|
|
|
action='store_true',
|
|
|
|
help='Hide details about each queue/message as they are processed'),
|
|
|
|
)
|
|
|
|
|
|
|
|
help = 'Process Jutda Helpdesk queues and process e-mails via POP3/IMAP as required, feeding them into the helpdesk.'
|
|
|
|
|
2008-08-18 23:29:31 +02:00
|
|
|
def handle(self, *args, **options):
|
2009-07-21 11:54:23 +02:00
|
|
|
quiet = options.get('quiet', False)
|
|
|
|
process_email(quiet=quiet)
|
2008-08-18 23:29:31 +02:00
|
|
|
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2009-07-21 11:54:23 +02:00
|
|
|
def process_email(quiet=False):
|
2008-08-19 10:50:38 +02:00
|
|
|
for q in Queue.objects.filter(
|
|
|
|
email_box_type__isnull=False,
|
|
|
|
allow_email_submission=True):
|
|
|
|
|
|
|
|
if not q.email_box_last_check:
|
2013-01-23 01:35:18 +01:00
|
|
|
q.email_box_last_check = timezone.now()-timedelta(minutes=30)
|
2008-08-19 10:50:38 +02:00
|
|
|
|
|
|
|
if not q.email_box_interval:
|
|
|
|
q.email_box_interval = 0
|
|
|
|
|
|
|
|
|
|
|
|
queue_time_delta = timedelta(minutes=q.email_box_interval)
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2013-01-23 01:35:18 +01:00
|
|
|
if (q.email_box_last_check + queue_time_delta) > timezone.now():
|
2008-01-07 21:22:13 +01:00
|
|
|
continue
|
2008-05-07 11:04:18 +02:00
|
|
|
|
2009-07-21 11:54:23 +02:00
|
|
|
process_queue(q, quiet=quiet)
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2013-01-23 01:35:18 +01:00
|
|
|
q.email_box_last_check = timezone.now()
|
2008-01-07 21:22:13 +01:00
|
|
|
q.save()
|
|
|
|
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2009-07-21 11:54:23 +02:00
|
|
|
def process_queue(q, quiet=False):
|
|
|
|
if not quiet:
|
|
|
|
print "Processing: %s" % q
|
2012-01-17 02:01:47 +01:00
|
|
|
|
2014-12-10 22:37:34 +01:00
|
|
|
if q.socks_proxy_type and q.socks_proxy_host and q.socks_proxy_port:
|
2014-12-11 00:44:47 +01:00
|
|
|
try:
|
|
|
|
import socks
|
|
|
|
except ImportError:
|
|
|
|
raise ImportError("Queue has been configured with proxy settings, but no socks library was installed. Try to install PySocks via pypi.")
|
|
|
|
|
2014-12-10 22:37:34 +01:00
|
|
|
proxy_type = {
|
|
|
|
'socks4': socks.SOCKS4,
|
|
|
|
'socks5': socks.SOCKS5,
|
|
|
|
}.get(q.socks_proxy_type)
|
|
|
|
|
|
|
|
socks.set_default_proxy(proxy_type=proxy_type, addr=q.socks_proxy_host, port=q.socks_proxy_port)
|
|
|
|
socket.socket = socks.socksocket
|
|
|
|
else:
|
|
|
|
socket.socket = socket._socketobject
|
|
|
|
|
2012-01-17 02:01:47 +01:00
|
|
|
email_box_type = settings.QUEUE_EMAIL_BOX_TYPE if settings.QUEUE_EMAIL_BOX_TYPE else q.email_box_type
|
|
|
|
|
|
|
|
if email_box_type == 'pop3':
|
2008-12-10 22:46:54 +01:00
|
|
|
|
2012-01-17 02:36:24 +01:00
|
|
|
if q.email_box_ssl or settings.QUEUE_EMAIL_BOX_SSL:
|
2008-08-20 03:57:41 +02:00
|
|
|
if not q.email_box_port: q.email_box_port = 995
|
2012-01-17 02:01:47 +01:00
|
|
|
server = poplib.POP3_SSL(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
|
2008-08-20 03:57:41 +02:00
|
|
|
else:
|
|
|
|
if not q.email_box_port: q.email_box_port = 110
|
2012-01-17 02:01:47 +01:00
|
|
|
server = poplib.POP3(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
|
2008-08-20 03:57:41 +02:00
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
server.getwelcome()
|
2012-01-17 02:01:47 +01:00
|
|
|
server.user(q.email_box_user or settings.QUEUE_EMAIL_BOX_USER)
|
|
|
|
server.pass_(q.email_box_pass or settings.QUEUE_EMAIL_BOX_PASSWORD)
|
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
|
|
|
|
messagesInfo = server.list()[1]
|
|
|
|
|
|
|
|
for msg in messagesInfo:
|
|
|
|
msgNum = msg.split(" ")[0]
|
|
|
|
msgSize = msg.split(" ")[1]
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
full_message = "\n".join(server.retr(msgNum)[1])
|
2016-02-16 18:49:40 +01:00
|
|
|
ticket = object_from_message(message=full_message, queue=q, quiet=quiet)
|
2008-12-10 22:46:54 +01:00
|
|
|
|
2008-10-25 00:52:34 +02:00
|
|
|
if ticket:
|
|
|
|
server.dele(msgNum)
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
server.quit()
|
|
|
|
|
2012-01-17 02:01:47 +01:00
|
|
|
elif email_box_type == 'imap':
|
2012-01-17 02:36:24 +01:00
|
|
|
if q.email_box_ssl or settings.QUEUE_EMAIL_BOX_SSL:
|
2008-08-20 03:57:41 +02:00
|
|
|
if not q.email_box_port: q.email_box_port = 993
|
2012-01-17 02:01:47 +01:00
|
|
|
server = imaplib.IMAP4_SSL(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
|
2008-08-20 03:57:41 +02:00
|
|
|
else:
|
|
|
|
if not q.email_box_port: q.email_box_port = 143
|
2012-01-17 02:01:47 +01:00
|
|
|
server = imaplib.IMAP4(q.email_box_host or settings.QUEUE_EMAIL_BOX_HOST, int(q.email_box_port))
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2012-01-17 02:01:47 +01:00
|
|
|
server.login(q.email_box_user or settings.QUEUE_EMAIL_BOX_USER, q.email_box_pass or settings.QUEUE_EMAIL_BOX_PASSWORD)
|
2008-05-07 11:04:18 +02:00
|
|
|
server.select(q.email_box_imap_folder)
|
2010-07-16 09:50:08 +02:00
|
|
|
|
|
|
|
status, data = server.search(None, 'NOT', 'DELETED')
|
|
|
|
if data:
|
2009-07-21 11:20:14 +02:00
|
|
|
msgnums = data[0].split()
|
|
|
|
for num in msgnums:
|
|
|
|
status, data = server.fetch(num, '(RFC822)')
|
2016-02-16 18:49:40 +01:00
|
|
|
ticket = object_from_message(message=data[0][1], queue=q, quiet=quiet)
|
2009-07-21 11:20:14 +02:00
|
|
|
if ticket:
|
|
|
|
server.store(num, '+FLAGS', '\\Deleted')
|
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
server.expunge()
|
|
|
|
server.close()
|
|
|
|
server.logout()
|
|
|
|
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2008-11-18 01:24:37 +01:00
|
|
|
def decodeUnknown(charset, string):
|
|
|
|
if not charset:
|
|
|
|
try:
|
2012-10-09 17:34:20 +02:00
|
|
|
return string.decode('utf-8','ignore')
|
2008-11-18 01:24:37 +01:00
|
|
|
except:
|
2012-10-09 17:34:20 +02:00
|
|
|
return string.decode('iso8859-1','ignore')
|
2011-02-02 09:02:39 +01:00
|
|
|
return unicode(string, charset)
|
2008-12-10 22:46:54 +01:00
|
|
|
|
|
|
|
def decode_mail_headers(string):
|
|
|
|
decoded = decode_header(string)
|
|
|
|
return u' '.join([unicode(msg, charset or 'utf-8') for msg, charset in decoded])
|
2008-11-18 01:24:37 +01:00
|
|
|
|
2016-02-16 20:10:13 +01:00
|
|
|
def create_ticket_cc(ticket, cc_list):
|
|
|
|
|
|
|
|
# Local import to deal with non-defined / circular reference problem
|
|
|
|
from helpdesk.views.staff import User, subscribe_to_ticket_updates
|
|
|
|
|
2016-02-20 20:35:17 +01:00
|
|
|
new_ticket_ccs = []
|
2016-02-16 20:10:13 +01:00
|
|
|
for cced_email in cc_list:
|
|
|
|
|
|
|
|
user = None
|
|
|
|
|
|
|
|
try:
|
|
|
|
user = User.objects.get(email=cced_email)
|
|
|
|
except User.DoesNotExist:
|
|
|
|
pass
|
|
|
|
|
|
|
|
ticket_cc = subscribe_to_ticket_updates(ticket=ticket, user=user, email=cced_email)
|
2016-02-20 20:35:17 +01:00
|
|
|
new_ticket_ccs.append(ticket_cc)
|
2016-02-16 20:10:13 +01:00
|
|
|
|
2016-02-20 20:35:17 +01:00
|
|
|
return new_ticket_ccs
|
2016-02-20 15:39:16 +01:00
|
|
|
|
2016-02-16 18:49:40 +01:00
|
|
|
def create_object_from_email_message(message, ticket_id, payload, files, quiet):
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2016-02-16 20:17:58 +01:00
|
|
|
ticket, previous_followup, new = None, None, False
|
2016-02-16 18:49:40 +01:00
|
|
|
now = timezone.now()
|
2008-10-25 00:52:34 +02:00
|
|
|
|
2016-02-16 18:49:40 +01:00
|
|
|
queue = payload['queue']
|
|
|
|
sender_email = payload['sender_email']
|
2009-01-19 10:40:14 +01:00
|
|
|
|
2016-02-16 18:49:40 +01:00
|
|
|
message_id = message.get('Message-Id')
|
|
|
|
in_reply_to = message.get('In-Reply-To')
|
2016-02-16 20:10:13 +01:00
|
|
|
cc_list = message.get('Cc')
|
|
|
|
|
|
|
|
if in_reply_to is not None:
|
2016-02-16 20:17:58 +01:00
|
|
|
try:
|
2016-02-19 16:01:39 +01:00
|
|
|
queryset = FollowUp.objects.filter(message_id=in_reply_to).order_by('-date')
|
|
|
|
if queryset.count() > 0:
|
|
|
|
previous_followup = queryset.first()
|
|
|
|
ticket = previous_followup.ticket
|
2016-02-16 20:17:58 +01:00
|
|
|
except FollowUp.DoesNotExist:
|
|
|
|
pass #play along. The header may be wrong
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2016-02-16 20:17:58 +01:00
|
|
|
if previous_followup is None and ticket_id is not None:
|
2016-02-16 20:10:13 +01:00
|
|
|
try:
|
2016-02-16 20:17:58 +01:00
|
|
|
ticket = Ticket.objects.get(id=ticket_id)
|
2016-02-16 20:10:13 +01:00
|
|
|
new = False
|
|
|
|
except Ticket.DoesNotExist:
|
|
|
|
ticket = None
|
2008-01-10 01:28:45 +01:00
|
|
|
|
2016-02-16 18:49:40 +01:00
|
|
|
# New issue, create a new <Ticket> instance
|
2016-02-15 19:16:28 +01:00
|
|
|
if ticket is None:
|
2016-02-16 20:17:58 +01:00
|
|
|
ticket = Ticket.objects.create(
|
2016-02-16 20:10:13 +01:00
|
|
|
title = payload['subject'],
|
|
|
|
queue = queue,
|
|
|
|
submitter_email = sender_email,
|
|
|
|
created = now,
|
|
|
|
description = payload['body'],
|
|
|
|
priority = payload['priority'],
|
2008-01-07 21:22:13 +01:00
|
|
|
)
|
2016-02-16 20:17:58 +01:00
|
|
|
ticket.save()
|
2016-02-16 18:49:40 +01:00
|
|
|
|
2008-02-08 01:19:58 +01:00
|
|
|
new = True
|
|
|
|
update = ''
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2016-02-16 18:49:40 +01:00
|
|
|
# Old issue being re-openned
|
2016-02-16 20:17:58 +01:00
|
|
|
elif ticket.status == Ticket.CLOSED_STATUS:
|
|
|
|
ticket.status = Ticket.REOPENED_STATUS
|
|
|
|
ticket.save()
|
2009-08-11 10:51:54 +02:00
|
|
|
|
2012-01-25 05:19:07 +01:00
|
|
|
f = FollowUp(
|
2016-02-16 20:17:58 +01:00
|
|
|
ticket = ticket,
|
2012-01-25 05:19:07 +01:00
|
|
|
title = _('E-Mail Received from %(sender_email)s' % {'sender_email': sender_email}),
|
2016-02-16 18:49:40 +01:00
|
|
|
date = now,
|
2012-01-25 05:19:07 +01:00
|
|
|
public = True,
|
2016-02-16 18:49:40 +01:00
|
|
|
comment = payload['body'],
|
2016-02-16 20:10:13 +01:00
|
|
|
message_id = message_id,
|
2012-01-25 05:19:07 +01:00
|
|
|
)
|
|
|
|
|
2016-02-16 20:17:58 +01:00
|
|
|
if ticket.status == Ticket.REOPENED_STATUS:
|
2012-01-25 05:19:07 +01:00
|
|
|
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:
|
2016-02-16 20:21:46 +01:00
|
|
|
print (" [%s-%s] %s" % (ticket.queue.slug, ticket.id, ticket.title,)).encode('ascii', 'replace')
|
2012-01-25 05:19:07 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2016-02-16 20:17:58 +01:00
|
|
|
context = safe_template_context(ticket)
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2016-02-20 20:35:17 +01:00
|
|
|
new_ticket_ccs = []
|
2016-02-16 20:10:13 +01:00
|
|
|
if cc_list is not None:
|
2016-02-20 20:35:17 +01:00
|
|
|
new_ticket_ccs = create_ticket_cc(ticket, cc_list.split(','))
|
2016-02-16 20:10:13 +01:00
|
|
|
|
2016-02-20 20:35:17 +01:00
|
|
|
notification_template = None
|
2016-02-20 15:39:16 +01:00
|
|
|
|
2008-02-08 01:19:58 +01:00
|
|
|
if new:
|
2008-02-06 00:35:40 +01:00
|
|
|
|
2016-02-20 20:35:17 +01:00
|
|
|
notification_template = 'newticket_cc'
|
|
|
|
|
2008-01-07 21:22:13 +01:00
|
|
|
if sender_email:
|
2008-08-19 10:50:38 +02:00
|
|
|
send_templated_mail(
|
|
|
|
'newticket_submitter',
|
|
|
|
context,
|
|
|
|
recipients=sender_email,
|
|
|
|
sender=queue.from_address,
|
|
|
|
fail_silently=True,
|
2016-02-16 18:49:40 +01:00
|
|
|
extra_headers={'In-Reply-To': message_id},
|
2008-08-19 10:50:38 +02:00
|
|
|
)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
if queue.new_ticket_cc:
|
2016-02-20 20:35:17 +01:00
|
|
|
|
2008-08-19 10:50:38 +02:00
|
|
|
send_templated_mail(
|
|
|
|
'newticket_cc',
|
|
|
|
context,
|
|
|
|
recipients=queue.new_ticket_cc,
|
|
|
|
sender=queue.from_address,
|
|
|
|
fail_silently=True,
|
2016-02-16 18:49:40 +01:00
|
|
|
extra_headers={'In-Reply-To': message_id},
|
2008-08-19 10:50:38 +02:00
|
|
|
)
|
|
|
|
|
2008-08-20 03:57:41 +02:00
|
|
|
if queue.updated_ticket_cc and queue.updated_ticket_cc != queue.new_ticket_cc:
|
2008-08-19 10:50:38 +02:00
|
|
|
send_templated_mail(
|
|
|
|
'newticket_cc',
|
|
|
|
context,
|
|
|
|
recipients=queue.updated_ticket_cc,
|
|
|
|
sender=queue.from_address,
|
|
|
|
fail_silently=True,
|
2016-02-16 18:49:40 +01:00
|
|
|
extra_headers={'In-Reply-To': message_id},
|
2008-08-19 10:50:38 +02:00
|
|
|
)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
else:
|
2016-02-20 20:35:17 +01:00
|
|
|
|
|
|
|
notification_template = 'updated_cc'
|
|
|
|
|
2012-01-25 05:19:07 +01:00
|
|
|
context.update(comment=f.comment)
|
|
|
|
|
2016-02-16 20:21:46 +01:00
|
|
|
if ticket.status == Ticket.REOPENED_STATUS:
|
2011-02-07 11:23:06 +01:00
|
|
|
update = _(' (Reopened)')
|
2009-08-11 10:51:54 +02:00
|
|
|
else:
|
|
|
|
update = _(' (Updated)')
|
2008-02-06 00:35:40 +01:00
|
|
|
|
2016-02-16 20:21:46 +01:00
|
|
|
if ticket.assigned_to:
|
2008-08-19 10:50:38 +02:00
|
|
|
send_templated_mail(
|
|
|
|
'updated_owner',
|
|
|
|
context,
|
2016-02-16 20:21:46 +01:00
|
|
|
recipients=ticket.assigned_to.email,
|
2008-08-19 10:50:38 +02:00
|
|
|
sender=queue.from_address,
|
|
|
|
fail_silently=True,
|
|
|
|
)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
if queue.updated_ticket_cc:
|
2008-08-19 10:50:38 +02:00
|
|
|
send_templated_mail(
|
|
|
|
'updated_cc',
|
|
|
|
context,
|
|
|
|
recipients=queue.updated_ticket_cc,
|
|
|
|
sender=queue.from_address,
|
|
|
|
fail_silently=True,
|
|
|
|
)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
2016-02-20 20:35:17 +01:00
|
|
|
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 len(notifications_to_be_sent):
|
|
|
|
|
|
|
|
send_templated_mail(
|
|
|
|
notification_template,
|
|
|
|
context,
|
|
|
|
recipients=notifications_to_be_sent,
|
|
|
|
sender=queue.from_address,
|
|
|
|
fail_silently=True,
|
|
|
|
extra_headers={'In-Reply-To': message_id},
|
|
|
|
)
|
|
|
|
|
2016-02-16 20:17:58 +01:00
|
|
|
return ticket
|
2008-10-25 00:52:34 +02:00
|
|
|
|
2016-02-16 20:10:13 +01:00
|
|
|
|
2016-02-16 18:49:40 +01:00
|
|
|
def object_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_id = matchobj.group('id')
|
|
|
|
else:
|
|
|
|
ticket_id = 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',
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
payload = {
|
|
|
|
'body': body,
|
|
|
|
'subject': subject,
|
|
|
|
'queue': queue,
|
|
|
|
'sender_email': sender_email,
|
|
|
|
'priority': priority,
|
|
|
|
'files': files,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return create_object_from_email_message(message, ticket_id, payload, files, quiet=quiet)
|
2008-08-19 10:50:38 +02:00
|
|
|
|
2008-01-07 21:22:13 +01:00
|
|
|
if __name__ == '__main__':
|
|
|
|
process_email()
|
2008-08-19 10:50:38 +02:00
|
|
|
|