From 2a75b920a01bdd7c0b218f1219c78d4fe8280a9e Mon Sep 17 00:00:00 2001 From: MacRimi Date: Tue, 3 Mar 2026 20:49:36 +0100 Subject: [PATCH] Update notification_channels.py --- AppImage/scripts/notification_channels.py | 78 +++++++++++++++++------ 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/AppImage/scripts/notification_channels.py b/AppImage/scripts/notification_channels.py index 11ebc27f..5caf5907 100644 --- a/AppImage/scripts/notification_channels.py +++ b/AppImage/scripts/notification_channels.py @@ -414,21 +414,65 @@ class EmailChannel(NotificationChannel): return self._send_with_retry(_do_send) - def _send_smtp(self, subject: str, body: str, severity: str, - data: Optional[Dict] = None) -> Tuple[int, str]: - import smtplib - from email.message import EmailMessage + @staticmethod + def _get_logo_path() -> str: + """Locate the ProxMenux logo PNG for email embedding.""" + import os + candidates = [ + os.path.join(os.path.dirname(__file__), '..', 'public', 'images', 'proxmenux-logo.png'), + '/opt/proxmenux-monitor/public/images/proxmenux-logo.png', + os.path.join(os.path.dirname(__file__), 'proxmenux-logo.png'), + ] + for p in candidates: + real = os.path.realpath(p) + if os.path.isfile(real): + return real + return '' + + def _build_mime_message(self, subject: str, body: str, severity: str, + data: Optional[Dict] = None): + """Build a MIMEMultipart email with embedded logo.""" + from email.mime.multipart import MIMEMultipart + from email.mime.text import MIMEText + from email.mime.image import MIMEImage - msg = EmailMessage() + msg = MIMEMultipart('related') msg['Subject'] = subject msg['From'] = self.from_address msg['To'] = ', '.join(self.to_addresses) - msg.set_content(body) - # Add HTML alternative + # Create alternative container (plain text + HTML) + alt = MIMEMultipart('alternative') + msg.attach(alt) + + # Plain text version + alt.attach(MIMEText(body, 'plain', 'utf-8')) + + # HTML version html_body = self._format_html(subject, body, severity, data) if html_body: - msg.add_alternative(html_body, subtype='html') + alt.attach(MIMEText(html_body, 'html', 'utf-8')) + + # Embed logo as CID attachment + logo_path = self._get_logo_path() + if logo_path: + try: + with open(logo_path, 'rb') as f: + logo_data = f.read() + logo_img = MIMEImage(logo_data, _subtype='png') + logo_img.add_header('Content-ID', '') + logo_img.add_header('Content-Disposition', 'inline', filename='proxmenux-logo.png') + msg.attach(logo_img) + except Exception: + pass # Logo not found -- email still works without it + + return msg + + def _send_smtp(self, subject: str, body: str, severity: str, + data: Optional[Dict] = None) -> Tuple[int, str]: + import smtplib + + msg = self._build_mime_message(subject, body, severity, data) server = None try: @@ -479,22 +523,13 @@ class EmailChannel(NotificationChannel): data: Optional[Dict] = None) -> Tuple[int, str]: import os import subprocess - from email.message import EmailMessage sendmail = '/usr/sbin/sendmail' if not os.path.exists(sendmail): return 0, 'sendmail not found at /usr/sbin/sendmail' - msg = EmailMessage() - msg['Subject'] = subject - msg['From'] = self.from_address or 'proxmenux@localhost' - msg['To'] = ', '.join(self.to_addresses) - msg.set_content(body) - - # Add HTML alternative - html_body = self._format_html(subject, body, severity, data) - if html_body: - msg.add_alternative(html_body, subtype='html') + msg = self._build_mime_message(subject, body, severity, data) + msg.replace_header('From', self.from_address or 'proxmenux@localhost') try: proc = subprocess.run( @@ -606,7 +641,10 @@ class EmailChannel(NotificationChannel):
- +
+ + M +

ProxMenux Monitor

{html_mod.escape(section_label)} Report