diff --git a/containers/backupchecks/src/backend/app/parsers/veeam.py b/containers/backupchecks/src/backend/app/parsers/veeam.py index 297220d..ddd6464 100644 --- a/containers/backupchecks/src/backend/app/parsers/veeam.py +++ b/containers/backupchecks/src/backend/app/parsers/veeam.py @@ -1177,6 +1177,38 @@ def try_parse_veeam(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]: } return True, result, [] + # Job did not start on schedule: special error notification (no objects, plain text body). + # Example subject: "[Veeam Backup for Microsoft 365] Job did not start on schedule: Backup MDS at Work" + subject_lower = subject.lower() + if 'job did not start on schedule' in subject_lower: + # Extract backup type from subject (e.g., "Veeam Backup for Microsoft 365") + backup_type = None + for candidate in VEEAM_BACKUP_TYPES: + if candidate.lower() in subject_lower: + backup_type = candidate + break + if not backup_type: + backup_type = "Backup Job" + + # Extract job name after the colon (e.g., "Backup MDS at Work") + job_name = None + m_job = re.search(r'job did not start on schedule:\s*(.+)$', subject, re.IGNORECASE) + if m_job: + job_name = (m_job.group(1) or '').strip() + + # Get overall message from text_body (can be base64 encoded) + text_body = (getattr(msg, 'text_body', None) or '').strip() + overall_message = text_body if text_body else 'Job did not start on schedule' + + result = { + 'backup_software': 'Veeam', + 'backup_type': backup_type, + 'job_name': job_name or 'Unknown Job', + 'overall_status': 'Error', + 'overall_message': overall_message, + } + return True, result, [] + # Configuration Job detection (may not have object details) subj_lower = subject.lower() is_config_job = ('backup configuration job' in subj_lower) or ('configuration backup for' in html_lower) diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 737a6f0..112ba3f 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -5,6 +5,7 @@ This file documents all changes made to this project via Claude Code. ## [2026-02-09] ### Added +- Extended Veeam parser to recognize "Job did not start on schedule" error notifications for Veeam Backup for Microsoft 365 (and other Veeam backup types) with job name extraction from subject and error message from plain text body (proxy server offline, scheduled run failed) - Added parser for Synology monthly drive health reports (backup software: Synology, backup type: Health Report, job name: Monthly Drive Health, informational only, no schedule learning) with support for both Dutch and English notifications ("schijfintegriteitsrapport"/"Drive Health Report") and automatic status detection (Healthy/Gezond → Success, problems → Warning) - Added "Cleanup orphaned jobs" maintenance option in Settings → Maintenance to delete jobs without valid customer links and their associated emails/runs permanently from database (useful when customers are removed) - Added "Preview orphaned jobs" button to show detailed list of jobs to be deleted with run/email counts before confirming deletion (verification step for safety)