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
|
|
|
|
POP and IMAP boxes defined for the queues within a
|
|
|
|
helpdesk, creating tickets from the new messages (or
|
|
|
|
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
|
2008-01-07 21:22:13 +01:00
|
|
|
from datetime import datetime, timedelta
|
|
|
|
from email.Utils import parseaddr
|
|
|
|
|
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-08-18 23:34:41 +02:00
|
|
|
from django.utils.translation import ugettext as _
|
|
|
|
|
|
|
|
from helpdesk.lib import send_templated_mail
|
|
|
|
from helpdesk.models import Queue, Ticket, FollowUp, Attachment
|
2008-08-18 23:29:31 +02:00
|
|
|
|
|
|
|
class Command(BaseCommand):
|
|
|
|
def handle(self, *args, **options):
|
|
|
|
process_email()
|
|
|
|
|
2008-01-07 21:22:13 +01:00
|
|
|
def process_email():
|
2008-05-21 23:16:44 +02:00
|
|
|
for q in Queue.objects.filter(email_box_type__isnull=False, allow_email_submission=True):
|
2008-01-07 21:22:13 +01:00
|
|
|
if not q.email_box_last_check: q.email_box_last_check = datetime.now()-timedelta(minutes=30)
|
|
|
|
if not q.email_box_interval: q.email_box_interval = 0
|
|
|
|
|
|
|
|
if (q.email_box_last_check + timedelta(minutes=q.email_box_interval)) > datetime.now():
|
|
|
|
continue
|
2008-05-07 11:04:18 +02:00
|
|
|
|
|
|
|
process_queue(q)
|
2008-01-07 21:22:13 +01:00
|
|
|
|
|
|
|
q.email_box_last_check = datetime.now()
|
|
|
|
q.save()
|
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
def process_queue(q):
|
|
|
|
print "Processing: %s" % q
|
|
|
|
if q.email_box_type == 'pop3':
|
|
|
|
server = poplib.POP3(q.email_box_host)
|
|
|
|
server.getwelcome()
|
|
|
|
server.user(q.email_box_user)
|
|
|
|
server.pass_(q.email_box_pass)
|
|
|
|
|
|
|
|
messagesInfo = server.list()[1]
|
|
|
|
|
|
|
|
for msg in messagesInfo:
|
|
|
|
msgNum = msg.split(" ")[0]
|
|
|
|
msgSize = msg.split(" ")[1]
|
|
|
|
|
|
|
|
full_message = "\n".join(server.retr(msgNum)[1])
|
|
|
|
ticket_from_message(message=full_message, queue=q)
|
|
|
|
|
|
|
|
server.dele(msgNum)
|
|
|
|
server.quit()
|
|
|
|
|
|
|
|
elif q.email_box_type == 'imap':
|
|
|
|
if not q.email_box_port: q.email_box_port = 143
|
|
|
|
|
|
|
|
server = imaplib.IMAP4(q.email_box_host, q.email_box_port)
|
|
|
|
server.login(q.email_box_user, q.email_box_pass)
|
|
|
|
server.select(q.email_box_imap_folder)
|
|
|
|
status, data = server.search(None, 'ALL')
|
|
|
|
for num in data[0].split():
|
|
|
|
status, data = server.fetch(num, '(RFC822)')
|
|
|
|
ticket_from_message(message=data[0][1], queue=q)
|
|
|
|
server.store(num, '+FLAGS', '\\Deleted')
|
|
|
|
server.expunge()
|
|
|
|
server.close()
|
|
|
|
server.logout()
|
|
|
|
|
2008-01-07 21:22:13 +01:00
|
|
|
def ticket_from_message(message, queue):
|
|
|
|
# 'message' must be an RFC822 formatted message.
|
|
|
|
msg = message
|
|
|
|
message = email.message_from_string(msg)
|
2008-05-07 11:04:18 +02:00
|
|
|
subject = message.get('subject', _('Created from e-mail'))
|
2008-01-07 21:22:13 +01:00
|
|
|
subject = subject.replace("Re: ", "").replace("Fw: ", "").strip()
|
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
sender = message.get('from', _('Unknown Sender'))
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2008-05-07 11:04:18 +02:00
|
|
|
sender_email = parseaddr(sender)[1]
|
2008-02-08 01:19:58 +01:00
|
|
|
if sender_email.startswith('postmaster'):
|
|
|
|
sender_email = ''
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2008-02-06 00:35:40 +01:00
|
|
|
regex = re.compile("^\[[A-Za-z0-9]+-\d+\]")
|
2008-01-07 21:22:13 +01:00
|
|
|
if regex.match(subject):
|
|
|
|
# This is a reply or forward.
|
2008-02-06 00:35:40 +01:00
|
|
|
ticket = re.match(r"^\[(?P<queue>[A-Za-z0-9]+)-(?P<id>\d+)\]", subject).group('id')
|
2008-01-07 21:22:13 +01:00
|
|
|
else:
|
|
|
|
ticket = None
|
|
|
|
counter = 0
|
|
|
|
files = []
|
|
|
|
for part in message.walk():
|
2008-08-18 23:29:31 +02:00
|
|
|
if part.get_content_maintype() == 'multipart':
|
2008-01-07 21:22:13 +01:00
|
|
|
continue
|
|
|
|
|
|
|
|
name = part.get_param("name")
|
|
|
|
|
|
|
|
if part.get_content_maintype() == 'text' and name == None:
|
|
|
|
body = part.get_payload()
|
|
|
|
else:
|
2008-08-18 23:29:31 +02:00
|
|
|
if not name:
|
2008-01-07 21:22:13 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
now = datetime.now()
|
|
|
|
|
|
|
|
if ticket:
|
|
|
|
try:
|
|
|
|
t = Ticket.objects.get(id=ticket)
|
2008-02-08 01:19:58 +01:00
|
|
|
new = False
|
2008-08-18 23:29:31 +02:00
|
|
|
except Ticket.DoesNotExist:
|
2008-01-07 21:22:13 +01:00
|
|
|
ticket = None
|
|
|
|
|
2008-01-10 01:28:45 +01:00
|
|
|
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
|
|
|
|
|
2008-01-07 21:22:13 +01:00
|
|
|
if ticket == None:
|
|
|
|
t = Ticket(
|
|
|
|
title=subject,
|
|
|
|
queue=queue,
|
|
|
|
submitter_email=sender_email,
|
|
|
|
created=now,
|
|
|
|
description=body,
|
2008-01-10 01:28:45 +01:00
|
|
|
priority=priority,
|
2008-01-07 21:22:13 +01:00
|
|
|
)
|
|
|
|
t.save()
|
2008-02-08 01:19:58 +01:00
|
|
|
new = True
|
|
|
|
update = ''
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2008-02-08 01:19:58 +01:00
|
|
|
context = {
|
|
|
|
'ticket': t,
|
|
|
|
'queue': queue,
|
|
|
|
}
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2008-02-08 01:19:58 +01:00
|
|
|
if new:
|
2008-02-06 00:35:40 +01:00
|
|
|
|
2008-01-07 21:22:13 +01:00
|
|
|
if sender_email:
|
2008-04-02 01:26:12 +02:00
|
|
|
send_templated_mail('newticket_submitter', context, recipients=sender_email, sender=queue.from_address, fail_silently=True)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
if queue.new_ticket_cc:
|
2008-04-02 01:26:12 +02:00
|
|
|
send_templated_mail('newticket_cc', context, recipients=queue.new_ticket_cc, sender=queue.from_address, fail_silently=True)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
if queue.updated_ticket_cc and queue.updated_ticket_cc != queue.new_ticket_cc:
|
2008-04-02 01:26:12 +02:00
|
|
|
send_templated_mail('newticket_cc', context, recipients=queue.updated_ticket_cc, sender=queue.from_address, fail_silently=True)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
else:
|
2008-05-07 11:04:18 +02:00
|
|
|
update = _(' (Updated)')
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
if t.assigned_to:
|
2008-04-02 01:26:12 +02:00
|
|
|
send_templated_mail('updated_owner', context, recipients=t.assigned_to.email, sender=queue.from_address, fail_silently=True)
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
if queue.updated_ticket_cc:
|
2008-04-02 01:26:12 +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
|
|
|
|
2008-02-08 01:19:58 +01:00
|
|
|
f = FollowUp(
|
|
|
|
ticket = t,
|
2008-05-07 11:04:18 +02:00
|
|
|
title = _('E-Mail Received from %s' % sender_email),
|
2008-02-08 01:19:58 +01:00
|
|
|
date = datetime.now(),
|
|
|
|
public = True,
|
|
|
|
comment = body,
|
|
|
|
)
|
|
|
|
f.save()
|
2008-02-06 00:35:40 +01:00
|
|
|
|
|
|
|
print " [%s-%s] %s%s" % (t.queue.slug, t.id, t.title, update)
|
2008-01-07 21:22:13 +01:00
|
|
|
|
2008-02-08 01:19:58 +01:00
|
|
|
for file in files:
|
|
|
|
filename = file['filename'].replace(' ', '_')
|
|
|
|
a = Attachment(followup=f, filename=filename, mime_type=file['type'], size=len(file['content']))
|
2008-08-13 23:42:57 +02:00
|
|
|
#a.save_file_file(file['filename'], file['content'])
|
|
|
|
a.file.save(file['filename'], ContentFile(file['content']))
|
2008-02-08 01:19:58 +01:00
|
|
|
a.save()
|
|
|
|
print " - %s" % file['filename']
|
2008-01-07 21:22:13 +01:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
process_email()
|