From 0827fddaa563970a6ef19fe595d725d4d4910252 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 9 Feb 2026 15:36:40 +0100 Subject: [PATCH 1/7] Add Synology DSM update parser and remove customer names from registry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added parser registry entry for Synology DSM automatic update cancelled notifications. These are informational messages that don't participate in schedule learning or reporting logic. Also removed real customer names from parser registry examples to prevent customer information from being stored in the codebase. Replaced with generic placeholders like NAS-HOSTNAME, SERVER-HOSTNAME, VM-HOSTNAME. Changes: - Added synology_dsm_update parser entry in registry.py (order 236) - Parser matches on DSM-update/DSM update in subject and automatic/automatische in body - Returns backup_software: Synology, backup_type: Updates, informational status - Replaced customer names in NTFS Auditing example (bouter.nl → example.local) - Replaced customer names in QNAP example (BETSIES-NAS01 → NAS-HOSTNAME) - Replaced customer names in NAKIVO example (kuiperbv.nl → VM-HOSTNAME) - Updated changelog Co-Authored-By: Claude Sonnet 4.5 --- .../src/backend/app/parsers/registry.py | 44 +++++++++++++++---- docs/changelog-claude.md | 2 + 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/containers/backupchecks/src/backend/app/parsers/registry.py b/containers/backupchecks/src/backend/app/parsers/registry.py index b2fc100..1ea80b4 100644 --- a/containers/backupchecks/src/backend/app/parsers/registry.py +++ b/containers/backupchecks/src/backend/app/parsers/registry.py @@ -50,13 +50,13 @@ PARSER_DEFINITIONS = [ }, "description": "Parses NTFS Auditing file audit report mails (attachment-based HTML reports).", "example": { - "subject": "Bouter btr-dc001.bouter.nl file audits → 6 ↑ 12", - "from_address": "auditing@bouter.nl", + "subject": "SERVER-HOSTNAME file audits → 6 ↑ 12", + "from_address": "auditing@example.local", "body_snippet": "(empty body, HTML report in attachment)", "parsed_result": { "backup_software": "NTFS Auditing", "backup_type": "Audit", - "job_name": "btr-dc001.bouter.nl file audits", + "job_name": "SERVER-HOSTNAME file audits", "objects": [], }, }, @@ -73,16 +73,42 @@ PARSER_DEFINITIONS = [ }, "description": "Parses QNAP Notification Center firmware update notifications (informational; excluded from reporting and missing logic).", "example": { - "subject": "[Info][Firmware Update] Notification from your device: BETSIES-NAS01", + "subject": "[Info][Firmware Update] Notification from your device: NAS-HOSTNAME", "from_address": "notifications@customer.tld", - "body_snippet": "NAS Name: BETSIES-NAS01\n...\nMessage: ...", + "body_snippet": "NAS Name: NAS-HOSTNAME\n...\nMessage: ...", "parsed_result": { "backup_software": "QNAP", "backup_type": "Firmware Update", "job_name": "Firmware Update", "overall_status": "Warning", "objects": [ - {"name": "BETSIES-NAS01", "status": "Warning", "error_message": None} + {"name": "NAS-HOSTNAME", "status": "Warning", "error_message": None} + ], + }, + }, + }, + { + "name": "synology_dsm_update", + "backup_software": "Synology", + "backup_types": ["Updates"], + "order": 236, + "enabled": True, + "match": { + "subject_contains_any": ["DSM-update", "DSM update"], + "body_contains_any": ["automatische DSM-update", "automatic DSM update", "Automatic update of DSM"], + }, + "description": "Parses Synology DSM automatic update cancelled notifications (informational; excluded from reporting and missing logic).", + "example": { + "subject": "Synology NAS-HOSTNAME - Automatische DSM-update op NAS-HOSTNAME is geannuleerd door het systeem", + "from_address": "backup@example.local", + "body_snippet": "Het systeem heeft de automatische DSM-update op NAS-HOSTNAME geannuleerd...", + "parsed_result": { + "backup_software": "Synology", + "backup_type": "Updates", + "job_name": "Synology Automatic Update", + "overall_status": "Warning", + "objects": [ + {"name": "NAS-HOSTNAME", "status": "Warning"} ], }, }, @@ -383,16 +409,16 @@ PARSER_DEFINITIONS = [ }, "description": "Parses NAKIVO Backup & Replication reports for VMware backup jobs.", "example": { - "subject": '"exchange01.kuiperbv.nl" job: Successful', + "subject": '"VM-HOSTNAME" job: Successful', "from_address": "NAKIVO Backup & Replication ", "body_snippet": "Job Run Report... Backup job for VMware ... Successful", "parsed_result": { "backup_software": "NAKIVO", "backup_type": "Backup job for VMware", - "job_name": "exchange01.kuiperbv.nl", + "job_name": "VM-HOSTNAME", "objects": [ { - "name": "exchange01.kuiperbv.nl", + "name": "VM-HOSTNAME", "status": "Success", "error_message": "", } diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 2bc0cab..f5eaf46 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -8,9 +8,11 @@ This file documents all changes made to this project via Claude Code. - 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) - Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing) +- Added parser registry entry for Synology DSM automatic update cancelled notifications (backup software: Synology, backup type: Updates, informational only, no schedule learning) ### Changed - Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status") +- Replaced real customer names in parser registry examples with generic placeholders (NTFS Auditing, QNAP Firmware Update, NAKIVO) to prevent customer information in codebase ### Fixed - Fixed Autotask ticket description being set to NULL when resolving tickets via `update_ticket_resolution_safe` by adding "description" to the optional_fields list, ensuring the original description is preserved during PUT operations From a05dbab5741278d728afe60cf861f15726758b51 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 9 Feb 2026 15:41:20 +0100 Subject: [PATCH 2/7] Extend Synology DSM update parser with additional detection patterns Extended the parser to recognize more email variants for Synology DSM automatic update cancelled notifications while maintaining backward compatibility with existing patterns. Changes: - Added "Automatische DSM-update" and "DSM-update op" to detection patterns - Extended hostname extraction regex to match "DSM-update op HOSTNAME" and "DSM update on HOSTNAME" - All existing patterns remain functional (backward compatible) - Updated changelog Co-Authored-By: Claude Sonnet 4.5 --- containers/backupchecks/src/backend/app/parsers/synology.py | 4 +++- docs/changelog-claude.md | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/containers/backupchecks/src/backend/app/parsers/synology.py b/containers/backupchecks/src/backend/app/parsers/synology.py index 8968e26..76c0f22 100644 --- a/containers/backupchecks/src/backend/app/parsers/synology.py +++ b/containers/backupchecks/src/backend/app/parsers/synology.py @@ -18,10 +18,12 @@ DSM_UPDATE_CANCELLED_PATTERNS = [ "Automatische update van DSM is geannuleerd", "Automatic DSM update was cancelled", "Automatic update of DSM was cancelled", + "Automatische DSM-update", + "DSM-update op", ] _DSM_UPDATE_CANCELLED_HOST_RE = re.compile( - r"\b(?:geannuleerd\s+op|cancelled\s+on)\s+(?P[A-Za-z0-9._-]+)\b", + r"\b(?:geannuleerd\s+op|cancelled\s+on|DSM-update\s+op|DSM\s+update\s+on)\s+(?P[A-Za-z0-9._-]+)\b", re.I, ) diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index f5eaf46..743d0fc 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -9,6 +9,7 @@ This file documents all changes made to this project via Claude Code. - 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) - Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing) - Added parser registry entry for Synology DSM automatic update cancelled notifications (backup software: Synology, backup type: Updates, informational only, no schedule learning) +- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op") and hostname extraction regex to recognize more email variants while maintaining backward compatibility with existing patterns ### Changed - Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status") From 1e3a64a78a7fcf3e670d59aa233f0b0b96c1a377 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 9 Feb 2026 15:46:49 +0100 Subject: [PATCH 3/7] Auto-commit local changes before build (2026-02-09 15:46:49) --- .last-branch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.last-branch b/.last-branch index 261aab8..7b2d1b6 100644 --- a/.last-branch +++ b/.last-branch @@ -1 +1 @@ -v20260209-05-responsive-navbar-fix +v20260209-06-synology-firmware-update-parser From 9576d1047ea8e33b52d6defc48533959b7137f69 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 9 Feb 2026 15:58:08 +0100 Subject: [PATCH 4/7] Extend Synology Updates parser to recognize out-of-date package notifications Extended the parser to recognize both DSM update cancelled notifications AND out-of-date package notifications under the same "Updates" job type, as they can appear together in combined notifications. Changes: - Added "Packages on", "out-of-date", "Package Center" to detection patterns - Extended hostname extraction regex to match "Packages on HOSTNAME" and "running on HOSTNAME" - Both notification types now fall under same job (backup_type: Updates) - All existing patterns remain functional (backward compatible) - Updated changelog Co-Authored-By: Claude Sonnet 4.5 --- containers/backupchecks/src/backend/app/parsers/synology.py | 5 ++++- docs/changelog-claude.md | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/containers/backupchecks/src/backend/app/parsers/synology.py b/containers/backupchecks/src/backend/app/parsers/synology.py index 76c0f22..0e46016 100644 --- a/containers/backupchecks/src/backend/app/parsers/synology.py +++ b/containers/backupchecks/src/backend/app/parsers/synology.py @@ -20,10 +20,13 @@ DSM_UPDATE_CANCELLED_PATTERNS = [ "Automatic update of DSM was cancelled", "Automatische DSM-update", "DSM-update op", + "Packages on", + "out-of-date", + "Package Center", ] _DSM_UPDATE_CANCELLED_HOST_RE = re.compile( - r"\b(?:geannuleerd\s+op|cancelled\s+on|DSM-update\s+op|DSM\s+update\s+on)\s+(?P[A-Za-z0-9._-]+)\b", + r"\b(?:geannuleerd\s+op|cancelled\s+on|DSM-update\s+op|DSM\s+update\s+on|Packages\s+on|running\s+on)\s+(?P[A-Za-z0-9._-]+)\b", re.I, ) diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 743d0fc..8ff8b06 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -9,7 +9,7 @@ This file documents all changes made to this project via Claude Code. - 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) - Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing) - Added parser registry entry for Synology DSM automatic update cancelled notifications (backup software: Synology, backup type: Updates, informational only, no schedule learning) -- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op") and hostname extraction regex to recognize more email variants while maintaining backward compatibility with existing patterns +- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op", "Packages on", "out-of-date", "Package Center") and hostname extraction regex to recognize DSM update cancelled and out-of-date package notifications under same Updates job type while maintaining backward compatibility with existing patterns ### Changed - Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status") From b4aa7ef2f6a3d176bec43b4516eeef2d229dc896 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 9 Feb 2026 16:03:11 +0100 Subject: [PATCH 5/7] Extend Synology Updates parser for new DSM update available notifications Extended the parser to recognize DSM update available notifications in addition to update cancelled and package out-of-date notifications. All variants fall under same Updates job type for unified monitoring. Changes: - Added "new DSM update", "Auto Update has detected", "new version of DSM", "Update & Restore" to detection patterns - Extended hostname extraction regex to match "detected on HOSTNAME" - Now recognizes three notification types: update cancelled, packages out-of-date, update available - All existing patterns remain functional (backward compatible) - Updated changelog Co-Authored-By: Claude Sonnet 4.5 --- containers/backupchecks/src/backend/app/parsers/synology.py | 6 +++++- docs/changelog-claude.md | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/containers/backupchecks/src/backend/app/parsers/synology.py b/containers/backupchecks/src/backend/app/parsers/synology.py index 0e46016..05339ab 100644 --- a/containers/backupchecks/src/backend/app/parsers/synology.py +++ b/containers/backupchecks/src/backend/app/parsers/synology.py @@ -23,10 +23,14 @@ DSM_UPDATE_CANCELLED_PATTERNS = [ "Packages on", "out-of-date", "Package Center", + "new DSM update", + "Auto Update has detected", + "new version of DSM", + "Update & Restore", ] _DSM_UPDATE_CANCELLED_HOST_RE = re.compile( - r"\b(?:geannuleerd\s+op|cancelled\s+on|DSM-update\s+op|DSM\s+update\s+on|Packages\s+on|running\s+on)\s+(?P[A-Za-z0-9._-]+)\b", + r"\b(?:geannuleerd\s+op|cancelled\s+on|DSM-update\s+op|DSM\s+update\s+on|Packages\s+on|running\s+on|detected\s+on)\s+(?P[A-Za-z0-9._-]+)\b", re.I, ) diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 8ff8b06..584676f 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -9,7 +9,7 @@ This file documents all changes made to this project via Claude Code. - 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) - Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing) - Added parser registry entry for Synology DSM automatic update cancelled notifications (backup software: Synology, backup type: Updates, informational only, no schedule learning) -- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op", "Packages on", "out-of-date", "Package Center") and hostname extraction regex to recognize DSM update cancelled and out-of-date package notifications under same Updates job type while maintaining backward compatibility with existing patterns +- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op", "Packages on", "out-of-date", "Package Center", "new DSM update", "Auto Update has detected", "Update & Restore") and hostname extraction regex to recognize DSM update cancelled, out-of-date packages, and new update available notifications under same Updates job type while maintaining backward compatibility with existing patterns ### Changed - Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status") From 5549323ff22d3be569dbe33c8260c1fcf46cf478 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 9 Feb 2026 16:25:27 +0100 Subject: [PATCH 6/7] Extend Synology Active Backup for Business parser for skipped tasks Extended the parser to recognize backup tasks that were skipped/ignored because a previous backup was still running. These are treated as Warning status for monitoring purposes. Changes: - Extended _ABB_COMPLETED_RE regex to match "genegeerd" (NL) and "skipped"/"ignored" (EN) - Added "van deze taak" pattern for Dutch phrasing variations - Added status detection for skipped tasks (Warning with "Skipped" message) - All existing patterns remain functional (backward compatible) - Updated changelog Co-Authored-By: Claude Sonnet 4.5 --- .../backupchecks/src/backend/app/parsers/synology.py | 11 +++++++++-- docs/changelog-claude.md | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/containers/backupchecks/src/backend/app/parsers/synology.py b/containers/backupchecks/src/backend/app/parsers/synology.py index 05339ab..8671df9 100644 --- a/containers/backupchecks/src/backend/app/parsers/synology.py +++ b/containers/backupchecks/src/backend/app/parsers/synology.py @@ -185,12 +185,14 @@ _ABB_SUBJECT_RE = re.compile(r"\bactive\s+backup\s+for\s+business\b", re.I) # Examples (NL): # "De back-uptaak vSphere-Task-1 op KANTOOR-NEW is voltooid." # "Virtuele machine back-uptaak vSphere-Task-1 op KANTOOR-NEW is gedeeltelijk voltooid." +# "back-uptaak vSphere-Task-1 op KANTOOR-NEW is genegeerd" # Examples (EN): # "The backup task vSphere-Task-1 on KANTOOR-NEW has completed." # "Virtual machine backup task vSphere-Task-1 on KANTOOR-NEW partially completed." +# "backup task vSphere-Task-1 on KANTOOR-NEW was skipped" _ABB_COMPLETED_RE = re.compile( - r"\b(?:virtuele\s+machine\s+)?(?:de\s+)?back-?up\s*taak\s+(?P.+?)\s+op\s+(?P[A-Za-z0-9._-]+)\s+is\s+(?Pvoltooid|gedeeltelijk\s+voltooid)\b" - r"|\b(?:virtual\s+machine\s+)?(?:the\s+)?back-?up\s+task\s+(?P.+?)\s+on\s+(?P[A-Za-z0-9._-]+)\s+(?:is\s+)?(?Pcompleted|finished|has\s+completed|partially\s+completed)\b", + r"\b(?:virtuele\s+machine\s+)?(?:de\s+)?back-?up\s*(?:taak|job)\s+(?:van\s+deze\s+taak\s+)?(?P.+?)\s+op\s+(?P[A-Za-z0-9._-]+)\s+is\s+(?Pvoltooid|gedeeltelijk\s+voltooid|genegeerd)\b" + r"|\b(?:virtual\s+machine\s+)?(?:the\s+)?back-?up\s+(?:task|job)\s+(?P.+?)\s+on\s+(?P[A-Za-z0-9._-]+)\s+(?:is\s+|was\s+)?(?Pcompleted|finished|has\s+completed|partially\s+completed|skipped|ignored)\b", re.I, ) @@ -242,6 +244,11 @@ def _parse_active_backup_for_business(subject: str, text: str) -> Tuple[bool, Di overall_status = "Warning" overall_message = "Partially completed" + # "genegeerd" / "skipped" / "ignored" should be treated as Warning + if "genegeerd" in status_raw or "skipped" in status_raw or "ignored" in status_raw: + overall_status = "Warning" + overall_message = "Skipped" + # Explicit failure wording overrides everything if _ABB_FAILED_RE.search(haystack): overall_status = "Error" diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 584676f..7775c28 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -10,6 +10,7 @@ This file documents all changes made to this project via Claude Code. - Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing) - Added parser registry entry for Synology DSM automatic update cancelled notifications (backup software: Synology, backup type: Updates, informational only, no schedule learning) - Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op", "Packages on", "out-of-date", "Package Center", "new DSM update", "Auto Update has detected", "Update & Restore") and hostname extraction regex to recognize DSM update cancelled, out-of-date packages, and new update available notifications under same Updates job type while maintaining backward compatibility with existing patterns +- Extended Synology Active Backup for Business parser to recognize skipped/ignored backup tasks ("genegeerd", "skipped", "ignored") as Warning status when backup was skipped due to previous backup still running ### Changed - Removed customer name from Autotask ticket title to keep titles concise (format changed from "[Backupchecks] Customer - Job Name - Status" to "[Backupchecks] Job Name - Status") From b6a85d1c8efd1d2cc6e8de9d70711ea17b3e39d5 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Mon, 9 Feb 2026 16:45:23 +0100 Subject: [PATCH 7/7] Extend Synology DSM update parser with automatic installation announcement patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add detection patterns for DSM update notifications that announce automatic installation ("belangrijke DSM-update", "kritieke oplossingen", "wordt automatisch geïnstalleerd", "is beschikbaar op"). This is the fourth variant of DSM update notifications now handled by the same Updates parser job. All changes maintain backward compatibility by extending existing pattern lists. Co-Authored-By: Claude Sonnet 4.5 --- containers/backupchecks/src/backend/app/parsers/synology.py | 4 ++++ docs/changelog-claude.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/containers/backupchecks/src/backend/app/parsers/synology.py b/containers/backupchecks/src/backend/app/parsers/synology.py index 8671df9..3164633 100644 --- a/containers/backupchecks/src/backend/app/parsers/synology.py +++ b/containers/backupchecks/src/backend/app/parsers/synology.py @@ -27,6 +27,10 @@ DSM_UPDATE_CANCELLED_PATTERNS = [ "Auto Update has detected", "new version of DSM", "Update & Restore", + "belangrijke DSM-update", + "kritieke oplossingen", + "wordt automatisch geïnstalleerd", + "is beschikbaar op", ] _DSM_UPDATE_CANCELLED_HOST_RE = re.compile( diff --git a/docs/changelog-claude.md b/docs/changelog-claude.md index 7775c28..f5a116d 100644 --- a/docs/changelog-claude.md +++ b/docs/changelog-claude.md @@ -9,7 +9,7 @@ This file documents all changes made to this project via Claude Code. - 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) - Added "Generate test emails" feature in Settings → Maintenance with three separate buttons to create fixed test email sets (success/warning/error) in inbox for testing parsers and maintenance operations (each set contains exactly 3 Veeam Backup Job emails with the same job name "Test-Backup-Job" and different dates/objects/statuses for reproducible testing and proper status flow testing) - Added parser registry entry for Synology DSM automatic update cancelled notifications (backup software: Synology, backup type: Updates, informational only, no schedule learning) -- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op", "Packages on", "out-of-date", "Package Center", "new DSM update", "Auto Update has detected", "Update & Restore") and hostname extraction regex to recognize DSM update cancelled, out-of-date packages, and new update available notifications under same Updates job type while maintaining backward compatibility with existing patterns +- Extended Synology DSM update parser with additional detection patterns ("Automatische DSM-update", "DSM-update op", "Packages on", "out-of-date", "Package Center", "new DSM update", "Auto Update has detected", "Update & Restore", "belangrijke DSM-update", "kritieke oplossingen", "wordt automatisch geïnstalleerd", "is beschikbaar op") and hostname extraction regex to recognize DSM update cancelled, out-of-date packages, new update available, and automatic installation announcements under same Updates job type while maintaining backward compatibility with existing patterns - Extended Synology Active Backup for Business parser to recognize skipped/ignored backup tasks ("genegeerd", "skipped", "ignored") as Warning status when backup was skipped due to previous backup still running ### Changed