Created
July 24, 2018 01:40
-
-
Save leblanc-simon/ddf222c4dbf0ecc4cbb7d4b6b77bb35e to your computer and use it in GitHub Desktop.
Publish a mattermost message from email
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from email.parser import Parser | |
from email.header import decode_header | |
import json | |
import pyinotify | |
import requests | |
from StringIO import StringIO | |
import sys | |
import tempfile | |
from unidecode import unidecode | |
# Données pour l'envoi via l'API | |
mattermost_access_token = '' | |
channel_id = '' | |
mattermost_url = 'https://example.org/api/v4' | |
# Répertoire à observer | |
path_watch = '/var/vmail/example.org/username/new' | |
''' | |
Parse une partie d'un mail pour en extraire la pièce jointe si s'en est une | |
@param string file Le nom du fichier à traiter | |
''' | |
def parse_attachment(message_part): | |
content_disposition = message_part.get("Content-Disposition", None) | |
if not content_disposition: | |
return None | |
dispositions = content_disposition.strip().split(";") | |
if not bool(content_disposition and dispositions[0].lower() == "attachment"): | |
return None | |
file_data = message_part.get_payload(decode=True) | |
attachment = StringIO(file_data) | |
attachment.content_type = message_part.get_content_type() | |
attachment.size = len(file_data) | |
attachment.name = None | |
attachment.create_date = None | |
attachment.mod_date = None | |
attachment.read_date = None | |
for param in dispositions[1:]: | |
name,value = param.split("=") | |
name = name.lower().strip() | |
if name == "filename": | |
attachment.name = value.strip('"') | |
return attachment | |
''' | |
Parse le mail et ajoute envoie les données à Mattermost | |
@param string file Le nom du fichier à traiter | |
''' | |
def parse_mail(file): | |
# On ouvre le mail | |
with open(file, 'rb') as fp: | |
# on converti le fichier en objet mail.message | |
mail = Parser().parse(fp) | |
if mail['subject'] is None: | |
# Rien à faire | |
return | |
# Récupération du sujet | |
subject = decode_header(mail['subject']) | |
subject_fragments = [] | |
for string, encodage in subject: | |
if encodage: | |
string = unicode(string, encodage).encode('utf8','replace') | |
subject_fragments.append(string) | |
subject = ''.join(subject_fragments) | |
subject = subject.replace('\\n', '\n') | |
# Récupération des pièces jointes | |
attachments = [] | |
for part in mail.walk(): | |
attachment = parse_attachment(part) | |
if attachment: | |
file = tempfile.TemporaryFile() | |
file.write(attachment.getvalue()) | |
file.seek(0) | |
attachments.append({'file': file, 'name': attachment.name}) | |
# S'il n'y a aucune pièce jointe, on quitte | |
if len(attachments) == 0: | |
return | |
# Envoi des pièces jointes | |
file_ids = [] | |
for attachment in attachments: | |
files = {'files': (attachment['name'], attachment['file'])} | |
datas = {'channel_id': channel_id} | |
response = requests.post( | |
mattermost_url + '/files', | |
files = files, | |
data = datas, | |
headers = {'Authorization': 'Bearer ' + mattermost_access_token}, | |
verify = False, | |
allow_redirects = False | |
) | |
if 201 != response.status_code: | |
# Il y a une erreur dans l'envoi des données | |
print response.text | |
attachment['file'].close() | |
return | |
json_data = json.loads(response.text) | |
file_ids.append(json_data['file_infos'][0]['id']) | |
attachment['file'].close() | |
# Envoi du message | |
params = {'channel_id': channel_id, 'message': subject, 'file_ids': file_ids} | |
response = requests.post( | |
mattermost_url + '/posts', | |
data = json.dumps(params), | |
headers = {'Authorization': 'Bearer ' + mattermost_access_token}, | |
verify=False, | |
allow_redirects=False | |
) | |
if 201 != response.status_code: | |
# Il y a une erreur dans l'envoi des données | |
print response.status_code | |
print response.text | |
''' | |
Classe gérant les notifications de fichier | |
@see: http://github.com/seb-m/pyinotify/wiki/Tutorial | |
''' | |
class EventHandler(pyinotify.ProcessEvent): | |
def process_IN_CREATE(self, event): | |
print "Create:", event.pathname | |
try: | |
parse_mail(event.pathname) | |
except Exception, e: | |
print e | |
def process_IN_MOVED_TO(self, event): | |
print "Modify:", event.pathname | |
try: | |
parse_mail(event.pathname) | |
except Exception, e: | |
print e | |
def process_IN_DELETE(self, event): | |
print "Removing:", event.pathname | |
################################################################################ | |
# | |
# MAIN PROGRAM | |
# | |
################################################################################ | |
wm = pyinotify.WatchManager() # Watch Manager | |
mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MOVED_TO # watched events | |
handler = EventHandler() | |
notifier = pyinotify.Notifier(wm, handler) | |
wdd = wm.add_watch(path_watch, mask, rec=True) | |
notifier.loop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment