Auto-commit local changes before build (2026-01-08 15:26:35) #70

Merged
ivooskamp merged 1 commits from v20260108-35-3cx-ssl-certificate-tracking into main 2026-01-13 11:27:58 +01:00
4 changed files with 64 additions and 10 deletions
Showing only changes of commit ec1cbd2a2c - Show all commits

View File

@ -1 +1 @@
v20260108-34-runchecks-popup-mail-body
v20260108-35-3cx-ssl-certificate-tracking

View File

@ -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",

View File

@ -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 - <host>'
Body contains: 'Backup name: <file>'
def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
"""Parse 3CX notification e-mails.
Supported:
- Backup Complete
Subject: '3CX Notification: Backup Complete - <host>'
Body contains: 'Backup name: <file>'
- SSL Certificate Renewal (informational)
Subject: '3CX Notification: SSL Certificate Renewal - <host>'
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:

View File

@ -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 <pre> 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