137 lines
4.4 KiB
Python
137 lines
4.4 KiB
Python
# -*- encoding: utf-8 -*-
|
||
|
||
import os
|
||
import sys
|
||
import email
|
||
import tempfile
|
||
import uuid
|
||
import smtplib
|
||
import subprocess
|
||
|
||
import redmine
|
||
from redmine import Redmine
|
||
|
||
REDMINE_URL = os.environ.get('REDMINE_URL', 'https://dev.entrouvert.org')
|
||
REDMINE_KEY = os.environ.get('REDMINE_KEY')
|
||
TRACKER_ID = os.environ.get('REDMINE_TRACKER', '3')
|
||
PROJECT_ID = os.environ.get('PROJECT')
|
||
TECH_MANAGER_ROLE_ID = os.environ.get('TECH_MANAGER_ROLE_ID', 10)
|
||
FALLBACK_EMAIL = os.environ.get('FALLBACK_EMAIL', 'support@entrouvert.com')
|
||
|
||
|
||
class UnknownUser(Exception):
|
||
pass
|
||
|
||
def parse_header(header_text):
|
||
if isinstance(header_text, unicode):
|
||
return header_text
|
||
default_charset = 'ascii'
|
||
try:
|
||
headers = email.Header.decode_header(header_text)
|
||
except email.Errors.HeaderParseError:
|
||
return header_text.encode(default_charset, 'replace').decode(default_charset)
|
||
else:
|
||
for i, (text, charset) in enumerate(headers):
|
||
headers[i] = unicode(text, charset or default_charset, errors='replace')
|
||
return u' '.join(headers)
|
||
|
||
def parse_attachment(data):
|
||
disposition = data.get('Content-Disposition')
|
||
if disposition:
|
||
dispositions = disposition.strip().split(";")
|
||
if dispositions[0] == "attachment":
|
||
file_data = data.get_payload(decode=True)
|
||
with tempfile.NamedTemporaryFile(delete=False) as attachment:
|
||
attachment.write(file_data)
|
||
attachment.flush()
|
||
temp = tempfile.NamedTemporaryFile(delete=False)
|
||
attachment = {'path': attachment.name,
|
||
'content_type': data.get_content_type(),
|
||
'filename': parse_header(data.get_filename())}
|
||
return attachment
|
||
return None
|
||
|
||
def send_mail(to, subject, message):
|
||
s = smtplib.SMTP('localhost')
|
||
from_mail = 'noreply@entrouvert.com'
|
||
msg = email.mime.Text.MIMEText(message, 'plain', 'utf-8')
|
||
msg['From'] = from_mail
|
||
msg['To'] = to
|
||
msg['Subject'] = subject
|
||
s.sendmail(from_mail, to, msg.as_string())
|
||
s.quit()
|
||
|
||
|
||
def create_ticket(mail):
|
||
mail = email.message_from_string(mail)
|
||
r = Redmine(REDMINE_URL, key=REDMINE_KEY)
|
||
from_name, from_email = email.utils.parseaddr(mail['From'])
|
||
users = r.user.filter(name=from_email)
|
||
if not users:
|
||
raise UnknownUser
|
||
|
||
r = Redmine(REDMINE_URL, key=REDMINE_KEY, impersonate=users[0].login)
|
||
|
||
attachments = []
|
||
|
||
for data in mail.walk():
|
||
attachment = parse_attachment(data)
|
||
if attachment:
|
||
attachments.append(attachment)
|
||
elif data.get_content_type() == "text/plain":
|
||
body = data.get_payload(decode=True)
|
||
body = unicode(body, data.get_content_charset('utf-8')).encode('utf-8')
|
||
|
||
# get project tech manager
|
||
tech_manager = None
|
||
for membership in r.project_membership.filter(project_id=PROJECT_ID):
|
||
try:
|
||
if membership.roles.get(TECH_MANAGER_ROLE_ID):
|
||
tech_manager = membership.user
|
||
break
|
||
except redmine.resources.ResourceAttrError:
|
||
continue
|
||
|
||
issue = r.issue.create(project_id=PROJECT_ID,
|
||
subject=parse_header(mail['Subject']),
|
||
tracker_id=TRACKER_ID,
|
||
description=body,
|
||
uploads=attachments)
|
||
if tech_manager:
|
||
issue.assigned_to_id = tech_manager.id
|
||
issue.save()
|
||
|
||
message = u"""[ Ce courriel est envoyé par un automate. Merci de ne pas y répondre, votre message ne serait pas pris en compte. ]
|
||
|
||
|
||
Bonjour,
|
||
|
||
Votre demande a bien été prise en compte et enregistrée dans notre système sous
|
||
le numéro %s.
|
||
|
||
Vous pouvez suivre son évolution à l'adresse : %s .
|
||
|
||
Cordialement,
|
||
|
||
L'équipe Entr'ouvert"""
|
||
message = message % (issue.id, issue.url)
|
||
send_mail(mail['From'], u'Votre demande a été bien prise en compte', message)
|
||
# cleanup temporary attachment files
|
||
for attachment in attachments:
|
||
if os.path.exists(attachment['path']):
|
||
os.unlink(attachment['path'])
|
||
|
||
|
||
if __name__ == '__main__':
|
||
mail = sys.stdin.read()
|
||
mail_dumps_dir = '/var/tmp'
|
||
if not os.path.exists(mail_dumps_dir):
|
||
os.mkdir(mail_dumps_dir)
|
||
filename = os.path.join(mail_dumps_dir, '%s.mail' % uuid.uuid4())
|
||
with open(filename, 'w') as mail_dump:
|
||
mail_dump.write(mail)
|
||
try:
|
||
create_ticket(mail)
|
||
except:
|
||
exim = subprocess.Popen(['/usr/sbin/exim', FALLBACK_EMAIL], stdin=file(filename))
|