Skip to content

Instantly share code, notes, and snippets.

@leblanc-simon
Created July 24, 2018 01:40
Show Gist options
  • Save leblanc-simon/ddf222c4dbf0ecc4cbb7d4b6b77bb35e to your computer and use it in GitHub Desktop.
Save leblanc-simon/ddf222c4dbf0ecc4cbb7d4b6b77bb35e to your computer and use it in GitHub Desktop.
Publish a mattermost message from email
# -*- 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