From a4a8a2f462699046ed168696d1a1e6534e62ed3c Mon Sep 17 00:00:00 2001
From: Einar Forselv <eforselv@gmail.com>
Date: Wed, 4 Dec 2019 19:36:14 +0100
Subject: [PATCH] Working mail alerts + alert system tweaks

---
 restic_compose_backup/alerts/__init__.py | 17 ++++++++
 restic_compose_backup/alerts/base.py     | 12 +++---
 restic_compose_backup/alerts/config.py   | 20 ---------
 restic_compose_backup/alerts/discord.py  | 11 +++--
 restic_compose_backup/alerts/smtp.py     | 54 +++++++++++++++++++++---
 5 files changed, 79 insertions(+), 35 deletions(-)
 delete mode 100644 restic_compose_backup/alerts/config.py

diff --git a/restic_compose_backup/alerts/__init__.py b/restic_compose_backup/alerts/__init__.py
index 5c0453a..136b044 100644
--- a/restic_compose_backup/alerts/__init__.py
+++ b/restic_compose_backup/alerts/__init__.py
@@ -1,8 +1,25 @@
+from restic_compose_backup.alerts.smtp import SMTPAlert
+from restic_compose_backup.alerts.discord import DiscordWebhookAlert
+from restic_compose_backup.config import Config
+
 ALERT_INFO = 'INFO',
 ALERT_ERROR = 'ERROR'
 ALERT_TYPES = [ALERT_INFO, ALERT_ERROR]
+BACKENDS = [SMTPAlert, DiscordWebhookAlert]
 
 
 def send(subject: str = None, attachment: str = None, alert_type: str = ALERT_ERROR):
     """Send an alert"""
     pass
+
+
+def configured_alert_classes():
+    """Returns a list of configured alert class instances"""
+    entires = []
+
+    for cls in BACKENDS:
+        instance = cls.create_from_env()
+        if instance:
+            entires.append(instance)
+
+    return entires
diff --git a/restic_compose_backup/alerts/base.py b/restic_compose_backup/alerts/base.py
index 4df5ad2..2426758 100644
--- a/restic_compose_backup/alerts/base.py
+++ b/restic_compose_backup/alerts/base.py
@@ -1,14 +1,14 @@
-from restic_compose_backup.alerts import ALERT_INFO, ALERT_ERROR, ALERT_TYPES
 
 
 class BaseAlert:
     name = None
 
-    def __init__(self):
-        pass
+    def create_from_env(self):
+        return None
 
-    def create_from_config(self, config):
-        pass
+    @property
+    def properly_configured(self) -> bool:
+        return False
 
-    def send(self, self, subject=None, attachment=None, alert_type=ALERT_ERROR):
+    def send(self, subject: str = None, body: str = None, alert_type: str = None):
         pass
diff --git a/restic_compose_backup/alerts/config.py b/restic_compose_backup/alerts/config.py
deleted file mode 100644
index 2333c2a..0000000
--- a/restic_compose_backup/alerts/config.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""Check config and expose properly configured alert backends"""
-from restic_compose_backup.alerts.smtp import SMTPAlert
-from restic_compose_backup.alerts.discord import DiscordWebhookAlert
-from restic_compose_backup.config import Config
-
-
-BACKENDS = [SMTPAlert, DiscordWebhookAlert]
-
-
-def configured_alert_classes():
-    """Returns a list of configured alert class instances"""
-    config = Config()
-    entires = []
-
-    for cls in BACKENDS:
-        instance = cls.create_from_config(config)
-        if instance:
-            entires.append(instance)
-
-    return entires
diff --git a/restic_compose_backup/alerts/discord.py b/restic_compose_backup/alerts/discord.py
index 98c3a54..3fa918b 100644
--- a/restic_compose_backup/alerts/discord.py
+++ b/restic_compose_backup/alerts/discord.py
@@ -7,8 +7,13 @@ class DiscordWebhookAlert(BaseAlert):
     def __init__(self):
         pass
 
-    def create_from_config(self, config):
-        pass
+    @classmethod
+    def create_from_env(self):
+        return None
 
-    def send(self, self, subject=None, attachment=None, alert_type=ALERT_ERROR):
+    @property
+    def properly_configured(self) -> bool:
+        return False
+
+    def send(self, subject: str = None, attachment: str = None, alert_type: str = None):
         pass
diff --git a/restic_compose_backup/alerts/smtp.py b/restic_compose_backup/alerts/smtp.py
index 91b721e..5a9c18c 100644
--- a/restic_compose_backup/alerts/smtp.py
+++ b/restic_compose_backup/alerts/smtp.py
@@ -1,14 +1,56 @@
+import os
+import smtplib
+import logging
+from email.mime.text import MIMEText
+
 from restic_compose_backup.alerts.base import BaseAlert
 
+logger = logging.getLogger(__name__)
+
 
 class SMTPAlert(BaseAlert):
     name = 'smtp'
 
-    def __init__(self):
-        pass
+    def __init__(self, host, port, user, password, to):
+        self.host = host
+        self.port = port
+        self.user = user
+        self.password = password
+        self.to = to
 
-    def create_from_config(self, config):
-        pass
+    @classmethod
+    def create_from_env(cls):
+        instance = cls(
+            os.environ.get('EMAIL_HOST'),
+            os.environ.get('EMAIL_PORT'),
+            os.environ.get('EMAIL_HOST_USER'),
+            os.environ.get('EMAIL_HOST_PASSWORD'),
+            (os.environ.get('EMAIL_SEND_TO') or "").split(','),
+        )
+        if instance.properly_configured:
+            return instance
 
-    def send(self, self, subject=None, attachment=None, alert_type=ALERT_ERROR):
-        pass
+        return None
+
+    @property
+    def properly_configured(self) -> bool:
+        return self.host and self.port and self.user and self.password and len(self.to) > 0
+
+    def send(self, subject: str = None, body: str = None, alert_type: str = 'INFO'):
+        # send_mail("Hello world!")
+        msg = MIMEText(body)
+        msg['Subject'] = f"[{alert_type}] {subject}"
+        msg['From'] = self.user
+        msg['To'] = ', '.join(self.to)
+
+        try:
+            logger.info("Connecting to %s port %s", self.host, self.port)
+            server = smtplib.SMTP_SSL(self.host, self.port)
+            server.ehlo()
+            server.login(self.user, self.password)
+            server.sendmail(self.user, self.to, msg.as_string())
+            logger.info('Email Sent')
+        except Exception as ex:
+            logger.error(ex)
+        finally:
+            server.close()