Handle 3CX update mails as informational runs
This commit is contained in:
parent
3c629bb664
commit
441f5a8e50
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,2 +1,9 @@
|
||||
# Claude Code confidential files
|
||||
.claude/
|
||||
|
||||
# Codex local workspace files
|
||||
.codex/
|
||||
|
||||
# Python cache artifacts
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
@ -679,6 +679,8 @@ def _infer_schedule_map_from_runs(job_id: int):
|
||||
return schedule
|
||||
if bs == 'qnap' and bt == 'firmware update':
|
||||
return schedule
|
||||
if bs == '3cx' and bt == 'update':
|
||||
return schedule
|
||||
if bs == 'syncovery' and bt == 'syncovery':
|
||||
return schedule
|
||||
except Exception:
|
||||
@ -994,4 +996,3 @@ def _next_ticket_code(now_utc: datetime) -> str:
|
||||
seq = 1
|
||||
|
||||
return f"{prefix}{seq:04d}"
|
||||
|
||||
|
||||
@ -24,6 +24,10 @@ def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
|
||||
- SSL Certificate Renewal (informational)
|
||||
Subject: '3CX Notification: SSL Certificate Renewal - <host>'
|
||||
Body contains an informational message about the renewal.
|
||||
|
||||
- Update Successful (informational)
|
||||
Subject: '3CX Notification: Update Successful - <host>'
|
||||
Body confirms update completion and healthy services.
|
||||
"""
|
||||
subject = (msg.subject or "").strip()
|
||||
if not subject:
|
||||
@ -38,11 +42,16 @@ def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
|
||||
subject,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
m_update = re.match(
|
||||
r"^3CX Notification:\s*Update Successful\s*-\s*(.+)$",
|
||||
subject,
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
|
||||
if not m_backup and not m_ssl:
|
||||
if not m_backup and not m_ssl and not m_update:
|
||||
return False, {}, []
|
||||
|
||||
job_name = (m_backup or m_ssl).group(1).strip()
|
||||
job_name = (m_backup or m_ssl or m_update).group(1).strip()
|
||||
|
||||
body = (getattr(msg, "text_body", None) or getattr(msg, "body", None) or "")
|
||||
if not body:
|
||||
@ -60,6 +69,17 @@ def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
|
||||
}
|
||||
return True, result, []
|
||||
|
||||
# Update successful: store as tracked informational run
|
||||
if m_update:
|
||||
result = {
|
||||
"backup_software": "3CX",
|
||||
"backup_type": "Update",
|
||||
"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)
|
||||
|
||||
@ -12,6 +12,7 @@ This file documents all changes made to this project via Claude Code.
|
||||
- Approved Jobs import now only applies `autotask_company_id` and `autotask_company_name` when the import option is checked
|
||||
- Customers CSV import now only applies Autotask mapping fields when the import option is checked
|
||||
- Import success and audit output now includes whether Autotask IDs were imported
|
||||
- 3CX parser now recognizes `3CX Notification: Update Successful - <host>` as an informational run with `backup_software: 3CX`, `backup_type: Update`, and `overall_status: Success`, and excludes this type from schedule inference (no Expected/Missed generation)
|
||||
|
||||
## [2026-02-16]
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user