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 Code confidential files
|
||||||
.claude/
|
.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
|
return schedule
|
||||||
if bs == 'qnap' and bt == 'firmware update':
|
if bs == 'qnap' and bt == 'firmware update':
|
||||||
return schedule
|
return schedule
|
||||||
|
if bs == '3cx' and bt == 'update':
|
||||||
|
return schedule
|
||||||
if bs == 'syncovery' and bt == 'syncovery':
|
if bs == 'syncovery' and bt == 'syncovery':
|
||||||
return schedule
|
return schedule
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -994,4 +996,3 @@ def _next_ticket_code(now_utc: datetime) -> str:
|
|||||||
seq = 1
|
seq = 1
|
||||||
|
|
||||||
return f"{prefix}{seq:04d}"
|
return f"{prefix}{seq:04d}"
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,10 @@ def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
|
|||||||
- SSL Certificate Renewal (informational)
|
- SSL Certificate Renewal (informational)
|
||||||
Subject: '3CX Notification: SSL Certificate Renewal - <host>'
|
Subject: '3CX Notification: SSL Certificate Renewal - <host>'
|
||||||
Body contains an informational message about the renewal.
|
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()
|
subject = (msg.subject or "").strip()
|
||||||
if not subject:
|
if not subject:
|
||||||
@ -38,11 +42,16 @@ def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
|
|||||||
subject,
|
subject,
|
||||||
flags=re.IGNORECASE,
|
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, {}, []
|
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 "")
|
body = (getattr(msg, "text_body", None) or getattr(msg, "body", None) or "")
|
||||||
if not body:
|
if not body:
|
||||||
@ -60,6 +69,17 @@ def try_parse_3cx(msg: MailMessage) -> Tuple[bool, Dict, List[Dict]]:
|
|||||||
}
|
}
|
||||||
return True, result, []
|
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 complete
|
||||||
backup_file = None
|
backup_file = None
|
||||||
m_file = re.search(r"^\s*Backup\s+name\s*:\s*(.+?)\s*$", body, flags=re.IGNORECASE | re.MULTILINE)
|
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
|
- 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
|
- 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
|
- 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]
|
## [2026-02-16]
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user