notify feature

This commit is contained in:
2026-08-10 22:43:06 +02:00
parent 43f2e96720
commit 70efc66696
7 changed files with 123 additions and 3 deletions
+11
View File
@@ -39,8 +39,19 @@ class Config:
self.healthcheck_ping_url = os.environ.get("HEALTHCHECK_PING_URL", "")
self.smtp_host = os.environ.get("SMTP_HOST", "")
self.smtp_port = int(os.environ.get("SMTP_PORT", "587"))
self.smtp_user = os.environ.get("SMTP_USER", "")
self.smtp_password = os.environ.get("SMTP_PASSWORD", "")
self.notify_email_to = os.environ.get("NOTIFY_EMAIL_TO", "")
self.notify_email_from = os.environ.get("NOTIFY_EMAIL_FROM", "")
self.state_path = os.environ.get("STATE_PATH", "/app/data/last-known-ip.json")
@property
def email_notification_enabled(self) -> bool:
return bool(self.smtp_host and self.notify_email_to and self.notify_email_from)
def validate(self):
missing = [v for v in REQUIRED_VARS if not os.environ.get(v)]
if missing:
+2 -1
View File
@@ -7,7 +7,7 @@ import threading
from apscheduler.schedulers.background import BackgroundScheduler
from flask import Flask
from app import cloudflare, freedns, healthcheck, state
from app import cloudflare, freedns, healthcheck, notify, state
from app.config import config
from app.fritzbox import FritzBoxError, get_external_ip
@@ -67,6 +67,7 @@ def run_cycle(trigger: str = "unknown"):
status="success",
message=f"IP updated to {current_ip}",
)
notify.send_ip_changed_email(last_ip, current_ip)
else:
failed = {k: v for k, v in cf_results.items() if v != "ok"}
log.error(
+77
View File
@@ -0,0 +1,77 @@
# Copyright (c) 2026 Stefan Koelle (https://stefankoelle.de)
# Licensed under the MIT License. See LICENSE file in project root for details.
import logging
import smtplib
from email.message import EmailMessage
from app.config import config
log = logging.getLogger("notify")
def send_ip_changed_email(old_ip: str | None, new_ip: str) -> bool:
if not config.email_notification_enabled:
log.debug("E-Mail-Notification nicht konfiguriert, überspringe.")
return False
if old_ip is None:
old_ip = "unbekannt"
subject = f"🌐 IP-Update: {old_ip}{new_ip}"
html = f"""\
<html>
<body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #0f172a; color: #e2e8f0; padding: 32px; margin: 0;">
<div style="max-width: 480px; margin: 0 auto;">
<div style="text-align: center; font-size: 48px; margin-bottom: 16px;">🔄</div>
<h1 style="font-size: 20px; color: #38bdf8; text-align: center; margin-bottom: 24px;">
IP-Adresse geändert
</h1>
<div style="background: #1e293b; border-radius: 12px; padding: 24px; margin-bottom: 24px;">
<table style="width: 100%; border-collapse: collapse;">
<tr>
<td style="padding: 8px 0; color: #94a3b8; font-size: 14px;">📍 Alte IP</td>
<td style="padding: 8px 0; text-align: right; font-family: monospace; font-size: 16px; color: #f87171;">
{old_ip}
</td>
</tr>
<tr>
<td colspan="2" style="padding: 4px 0; text-align: center; font-size: 20px;">⬇️</td>
</tr>
<tr>
<td style="padding: 8px 0; color: #94a3b8; font-size: 14px;">🆕 Neue IP</td>
<td style="padding: 8px 0; text-align: right; font-family: monospace; font-size: 16px; color: #4ade80;">
{new_ip}
</td>
</tr>
</table>
</div>
<p style="font-size: 13px; color: #64748b; text-align: center; margin: 0;">
📡 DynDNS-Updater · Cloudflare + FreeDNS aktualisiert
</p>
</div>
</body>
</html>"""
text = f"IP-Adresse geändert: {old_ip}{new_ip}"
msg = EmailMessage()
msg["Subject"] = subject
msg["From"] = config.notify_email_from
msg["To"] = config.notify_email_to
msg.set_content(text)
msg.add_alternative(html, subtype="html")
try:
with smtplib.SMTP(config.smtp_host, config.smtp_port) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.login(config.smtp_user, config.smtp_password)
server.send_message(msg)
log.info("E-Mail gesendet: %s -> %s", subject, config.notify_email_to)
return True
except Exception as exc:
log.error("E-Mail-Versand fehlgeschlagen: %s", exc)
return False