#!/usr/bin/env python3 """ Thy pylokid main program """ import os import re from datetime import datetime import asyncio import logging import time import email import email.parser import imaplib import aioeasywebdav from dotenv import load_dotenv, find_dotenv import paho.mqtt.client as mqtt from lodur_connect import create_einsatzrapport, upload_alarmdepesche _EMAIL_SUBJECTS = '(OR SUBJECT "Einsatzausdruck_FW" SUBJECT "Einsatzprotokoll" UNSEEN)' load_dotenv(find_dotenv()) imap_server = os.getenv("IMAP_SERVER") imap_username = os.getenv("IMAP_USERNAME") imap_password = os.getenv("IMAP_PASSWORD") imap_mailbox = os.getenv("IMAP_MAILBOX", "INBOX") imap_mailbox_archive = os.getenv("IMAP_MAILBOX_ARCHIVE", "Archive") webdav_url = os.getenv("WEBDAV_URL") webdav_username = os.getenv("WEBDAV_USERNAME") webdav_password = os.getenv("WEBDAV_PASSWORD") webdav_basedir = os.getenv("WEBDAV_BASEDIR") tmp_dir = os.getenv("TMP_DIR", "/tmp") mqtt_server = os.getenv("MQTT_SERVER") mqtt_user = os.getenv("MQTT_USER") mqtt_password = os.getenv("MQTT_PASSWORD") lodur_user = os.getenv("LODUR_USER") lodur_password = os.getenv("LODUR_PASSWORD") lodur_base_url = os.getenv("LODUR_BASE_URL") logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) def get_attachments(mqtt_client): # imap connection logger.info('Connecting to IMAP server ' + imap_server) imap = imaplib.IMAP4_SSL(imap_server) imap.login(imap_username, imap_password) imap.select(imap_mailbox, readonly=False) # search for matching messages logger.info('Searching for messages matching the subject') typ, msg_ids = imap.search( None, _EMAIL_SUBJECTS, ) if typ != 'OK': logger.error('Error searching for matching messages') raise logger.info('Found ' + str(len(msg_ids[0].split())) + ' matching messages') for msg_id in msg_ids[0].split(): subject = str() f_id = str() f_type = str() # download message typ, msg_data = imap.fetch(msg_id, '(RFC822)') for response_part in msg_data: if isinstance(response_part, tuple): msg = email.message_from_string(str(response_part[1], 'utf-8')) subject = msg["subject"] # extract F id from subject parse_subject = re.search('(.*): (F[0-9].*)', subject) f_type = parse_subject.group(1) f_id = parse_subject.group(2) # mark as seen imap.store(msg_id, '+FLAGS', '(\\Seen)') logger.info('Processing message: ' + subject) logger.info('Detected type: ' + f_type) logger.info('Detected F ID: ' + f_id) # publish over MQTT mqtt_client.publish("pylokid/einsatz/" + f_id, f_type) # Talk to Lodur if f_type == 'Einsatzausdruck_FW': # create new Einsatzrapport in Lodur logger.info('Sending data to Lodur') lodur_id = create_einsatzrapport( lodur_user, lodur_password, lodur_base_url, f_id, ) logger.info('Sent data to Lodur. Assigned Lodur ID: ' + lodur_id) elif f_type == 'Einsatzprotokoll': logger.info('Updating data in Lodur') else: logger.error('Unknown type: ' + f_type) # extract attachment from body mail = email.message_from_string(str(msg_data[0][1], 'utf-8')) for part in mail.walk(): if part.get_content_maintype() == 'multipart': continue if part.get('Content-Disposition') is None: continue file_name = part.get_filename() logger.info('Extracting attachment: ' + file_name) if bool(file_name): # save attachment to filesystem file_path = os.path.join(tmp_dir, file_name) logger.info('Saving attachment to ' + file_path) if not os.path.isfile(file_path): file = open(file_path, 'wb') file.write(part.get_payload(decode=True)) file.close() upload_attachment(file_path, file_name, f_id) logger.info('Uploading PDF to Lodur') upload_alarmdepesche( lodur_user, lodur_password, lodur_base_url, lodur_id, file_name, file_path, ) def upload_attachment(file, file_name, f_id): # webdav connection logger.info('Connecting to WebDAV server ' + webdav_url) loop = asyncio.get_event_loop() webdav = aioeasywebdav.connect( webdav_url, username=webdav_username, password=webdav_password, ) # upload with webdav upload_dir = webdav_basedir + "/" + str(datetime.now().year) + "/" + f_id logger.info('Uploading attachment to ' + upload_dir) # create directory if not yet there if not loop.run_until_complete(webdav.exists(upload_dir)): logger.info('Creating directory ' + upload_dir) loop.run_until_complete(webdav.mkdir(upload_dir)) remote_file_path = upload_dir + "/" + file_name if loop.run_until_complete(webdav.exists(remote_file_path)): logger.info('File ' + file_name + ' already uploaded') else: loop.run_until_complete( webdav.upload(file, remote_file_path) ) logger.info('File ' + file_name + ' uploaded') def on_connect(client, userdata, flags, rc): logger.info('Connected to MQTT with result code ' + str(rc)) def main(): """ main """ logger.info('Connecting to MQTT broker ' + mqtt_server) client = mqtt.Client('pylokid') client.on_connect = on_connect client.username_pw_set(mqtt_user, password=mqtt_password) client.tls_set() client.connect(mqtt_server, 8883, 60) client.loop_start() while True: get_attachments(client) time.sleep(60) if __name__ == '__main__': main()