From f61455bad03947542eb79837912d981b1c7fb54e Mon Sep 17 00:00:00 2001 From: Mike Date: Wed, 7 Jun 2023 21:21:37 +0200 Subject: [PATCH] Bugfixes and implemented attachment forwarding --- main.py | 65 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/main.py b/main.py index 1453833..c24fab6 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,5 @@ import datetime, imaplib, email, time, utm, requests, json, os, smtplib, logging, sys +from urllib.parse import unquote from bs4 import BeautifulSoup if os.environ.get("DEBUG", False): @@ -91,6 +92,7 @@ class FetchEmail(): logger.debug(f"Using search term '{searchTerm}'") (result, messages) = self.connection.search(None, searchTerm) body = None + attachment = [] if result == "OK": mail_ids = messages[0] @@ -99,7 +101,7 @@ class FetchEmail(): if mail_ids == b"": logger.debug(f"No Email found") self.close_connection() - return None + return None, attachment try: #ret, data = self.connection.fetch(id_list[-1], '(UID BODY[TEXT])') @@ -115,19 +117,29 @@ class FetchEmail(): if email_msg.is_multipart(): for part in email_msg.walk(): if part.get_content_type() == "text/html": + logger.debug("Found HTML File in Email") + body = part.get_payload(decode=True) + body = body.decode() + elif part.get_content_type() == "text/plain": + logger.debug("Found Text in Email") body = part.get_payload(decode=True) body = body.decode() - elif part.get_content_type() == "text/plain": - body = part.get_payload(decode=True) - body = body.decode() + if part.get_content_type() == "application/pdf": + logger.debug("Found PDF File in Email") + attachment.append({ + "filename": part.get_filename(), + "type": "application/pdf", + "content": part.get_payload(decode=True) + }) + except Exception as err: logger.error(f"Could not retrieve email. Got: {err}", exc_info=True) self.close_connection() - return None + return None, attachment logger.debug(f"Found an email") - return str(body) + return str(body), attachment def parse_email_address(self, email_address): """ @@ -193,25 +205,25 @@ class Alarmdepesche(): for td in tds: key = str(str(td.string).strip()) - if key == "Druckdatum:": + if "Druckdatum:" in key: self.timestamp = datetime.datetime.strptime(self.get_string(td), "%d.%m.%Y %H:%M:%S") - if key == "Einsatzstichwort:": + if "Einsatzstichwort:" in key: self.intervention_code = self.get_string(td) - if key == "Sachverhalt:": + if "Sachverhalt:" in key: self.intervention_message = self.get_string(td) - if key == "Alarmiertes Einsatzmittel:": + if "Alarmiertes Einsatzmittel:" in key: engine = self.get_string(td) if "," in engine: logger.warning(f"Unusual engine format, got {engine} only using last entry") engine = engine.split(",")[-1].strip() self.engine = engine - if key == "Einsatznummer:": + if "Einsatznummer:" in key: self.intervention_number = self.get_string(td) - if key == "Stadt:": + if "Stadt:" in key: self.city = self.get_string(td) - if key == "Info:": + if "Info:" in key: self.info = self.get_string(td) - if key == "UTM - Koordinaten:": + if "UTM - Koordinaten:" in key: utm_string = self.get_string(td).split(" ") self.geo_point = utm.to_latlon(int(utm_string[1]), int(utm_string[2]), int(utm_string[0][:2]), utm_string[0][2]) @@ -281,13 +293,19 @@ class Email(): smtp_client : smtplib.SMTP def __init__(self, smtp_server, smtp_port, smtp_user, smtp_password): + if os.environ.get("SMTP_SERVER", None): + smtp_server = os.environ.get("SMTP_SERVER") + if os.environ.get("SMTP_PORT", None): + smtp_port = os.environ.get("SMTP_PORT") + logger.debug(f"Connecting to SMTP Server {smtp_server}") try: self.smtp_client = smtplib.SMTP(smtp_server, smtp_port) self.smtp_client.ehlo() if os.environ.get("MAIL_SMTP_STARTTLS", True): self.smtp_client.starttls() - self.smtp_client.login(smtp_user, smtp_password) + if os.environ.get("SMTP_AUTH", True): + self.smtp_client.login(smtp_user, smtp_password) logger.debug("Connection to SMTP Sever was successfull") except BaseException as err: logger.error(f"Connection to SMTP Sevrer failed. Got {err}", exc_info=True) @@ -297,9 +315,10 @@ class Email(): self.smtp_client.close() - def sendmail(self, alarmdepesche, msg_from, msg_to): + def sendmail(self, alarmdepesche, msg_from, msg_to, attachment=None): from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText + from email.mime.application import MIMEApplication logger.debug(f"Preparing email for {msg_to}") @@ -321,6 +340,11 @@ class Email(): msg.attach(part1) msg.attach(part2) + if attachment: + part3 = MIMEApplication(attachment[0]["content"], Name=unquote(attachment[0]["filename"]), _subtype="pdf") + part3['Content-Disposition'] = f'attachment; filename="{unquote(attachment[0]["filename"])}"' + msg.attach(part3) + logger.info(f"Sending email to {msg_to}") # sendmail function takes 3 arguments: sender's address, recipient's address @@ -341,6 +365,7 @@ if __name__ == '__main__': mail_user = os.environ.get('MAIL_USER', None) mail_from = os.environ.get('MAIL_FROM', mail_user) mail_pass = os.environ.get('MAIL_PASS', None) + mail_port = os.environ.get('MAIL_PORT', 587) if not mail_server or not mail_user or not mail_pass: logger.error("Environment variables not set!, exiting...") @@ -363,18 +388,18 @@ if __name__ == '__main__': fetchmail = FetchEmail(mail_server, mail_user, mail_pass) fetchmail.select_mailbox() - html_message = fetchmail.fetch_messages_content("FROM els.112@cgdis.lu (UNSEEN)") + html_message, attachment = fetchmail.fetch_messages_content("FROM els.112@cgdis.lu (UNSEEN)") if html_message: current_alarmdepsche = Alarmdepesche() current_alarmdepsche.from_html(html_message) current_alarmdepsche.saveToDisk() metric_api_up = current_alarmdepsche.metric_api_up members = current_alarmdepsche.get_members_emails() - sendmail = Email(mail_server, 587, mail_user, mail_pass) + sendmail = Email(mail_server, mail_port, mail_user, mail_pass) for email_addr in members: - sendmail.sendmail(current_alarmdepsche, mail_from, email_addr) + sendmail.sendmail(current_alarmdepsche, mail_from, email_addr, attachment) else: - logger.info("Message could not be loaded, exiting...") + logger.info("No message found, exiting...") timer_global.end() prometheus.append_gauge_metric("permaalert_execution_time", timer_global.took,