diff --git a/.last-branch b/.last-branch index 5a4f9e9..a1d2ee6 100644 --- a/.last-branch +++ b/.last-branch @@ -1 +1 @@ -v20260108-34-runchecks-popup-mail-body +v20260108-35-3cx-ssl-certificate-tracking diff --git a/containers/backupchecks/src/backend/app/main/routes_parsers.py b/containers/backupchecks/src/backend/app/main/routes_parsers.py index 42c99c9..ec6920b 100644 --- a/containers/backupchecks/src/backend/app/main/routes_parsers.py +++ b/containers/backupchecks/src/backend/app/main/routes_parsers.py @@ -39,6 +39,18 @@ def parsers_overview(): } ], }, + { + "name": "3CX SSL certificate renewal", + "backup_software": "3CX", + "backup_types": ["SSL Certificate"], + "order": 11, + "enabled": True, + "match": { + "subject_regex": r"^3CX Notification:\\s*SSL Certificate Renewal\\s*-\\s*(.+)$", + }, + "description": "Parses 3CX SSL certificate renewal notifications (informational) so they are tracked and included in reporting.", + "examples": [], + }, { "name": "Veeam status mails", "backup_software": "Veeam", diff --git a/containers/backupchecks/src/backend/app/parsers/threecx.py b/containers/backupchecks/src/backend/app/parsers/threecx.py index bfd7c1b..a56ee93 100644 --- a/containers/backupchecks/src/backend/app/parsers/threecx.py +++ b/containers/backupchecks/src/backend/app/parsers/threecx.py @@ -6,28 +6,61 @@ from typing import Dict, Tuple, List from ..models import MailMessage -def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]: - """Parse 3CX backup notification e-mails. +def _normalize_text(text: str) -> str: + text = (text or "").replace("\r\n", "\n").replace("\r", "\n") + # Collapse excessive blank lines while keeping readability + text = re.sub(r"\n{4,}", "\n\n\n", text) + return text.strip() - Expected: - Subject: '3CX Notification: Backup Complete - ' - Body contains: 'Backup name: ' + +def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]: + """Parse 3CX notification e-mails. + + Supported: + - Backup Complete + Subject: '3CX Notification: Backup Complete - ' + Body contains: 'Backup name: ' + + - SSL Certificate Renewal (informational) + Subject: '3CX Notification: SSL Certificate Renewal - ' + Body contains an informational message about the renewal. """ subject = (msg.subject or "").strip() if not subject: return False, {}, [] - m = re.match(r"^3CX Notification:\s*Backup Complete\s*-\s*(.+)$", subject, flags=re.IGNORECASE) - if not m: + # Backup complete + m_backup = re.match(r"^3CX Notification:\s*Backup Complete\s*-\s*(.+)$", subject, flags=re.IGNORECASE) + + # SSL certificate renewal (informational) + m_ssl = re.match( + r"^3CX Notification:\s*SSL Certificate Renewal\s*-\s*(.+)$", + subject, + flags=re.IGNORECASE, + ) + + if not m_backup and not m_ssl: return False, {}, [] - job_name = m.group(1).strip() + job_name = (m_backup or m_ssl).group(1).strip() body = (getattr(msg, "text_body", None) or getattr(msg, "body", None) or "") - # Some sources store plain text in html_body; fall back if needed. if not body: body = getattr(msg, "html_body", None) or "" + body = _normalize_text(body) + # SSL certificate renewal: store as a tracked informational run + if m_ssl: + result = { + "backup_software": "3CX", + "backup_type": "SSL Certificate", + "job_name": job_name, + "overall_status": "Success", + "overall_message": body or None, + } + return True, result, [] + + # Backup complete backup_file = None m_file = re.search(r"^\s*Backup\s+name\s*:\s*(.+?)\s*$", body, flags=re.IGNORECASE | re.MULTILINE) if m_file: diff --git a/docs/changelog.md b/docs/changelog.md index f4ca00c..4747e42 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -70,6 +70,15 @@ - Added support to extract HTML content from stored EML when both html_body and text_body are blank (consistent with Inbox). - Updated Run Checks details API to return a safe HTML body for plain-text emails using
 wrapping.
 
+---
+
+## v20260108-35-3cx-ssl-certificate-info-tracking
+
+- Added parser support for 3CX SSL Certificate notifications.
+- Classified these emails as Backup: 3CX, Type: SSL Certificate.
+- Parsed the message content and displayed it in the Run Checks popup.
+- Stored the message as a successful run so it could be tracked over time.
+
 ================================================================================================================================================
 ## v0.1.18