diff --git a/AppImage/ProxMenux-1.2.1.2-beta.AppImage b/AppImage/ProxMenux-1.2.1.2-beta.AppImage index d106f65d..f084082a 100755 Binary files a/AppImage/ProxMenux-1.2.1.2-beta.AppImage and b/AppImage/ProxMenux-1.2.1.2-beta.AppImage differ diff --git a/AppImage/ProxMenux-Monitor.AppImage.sha256 b/AppImage/ProxMenux-Monitor.AppImage.sha256 index 95067813..18c9eb2f 100644 --- a/AppImage/ProxMenux-Monitor.AppImage.sha256 +++ b/AppImage/ProxMenux-Monitor.AppImage.sha256 @@ -1 +1 @@ -d0b86c07819056f121c5e86f1246462cadba982f56d414b7dc062eff47f3af1f ProxMenux-1.2.1.2-beta.AppImage +37819f92b22f4860908f3f4dbe26f071f5c971e903e36ac3cf6e5fcdd9b162a7 ProxMenux-1.2.1.2-beta.AppImage diff --git a/AppImage/scripts/notification_events.py b/AppImage/scripts/notification_events.py index 02b7d2d4..5e1c4f8b 100644 --- a/AppImage/scripts/notification_events.py +++ b/AppImage/scripts/notification_events.py @@ -3925,11 +3925,23 @@ class ProxmoxHookWatcher: return 'update_available', 'node', '' if pve_type == 'system-mail': - # Parse smartd messages to extract useful info and filter noise. - # smartd sends system-mail when it detects SMART issues. + # PVE forwards every local mail to root over its notification + # framework. That bucket is genuinely heterogeneous: smartd + # alerts (useful, want them), mail bouncebacks (sometimes), + # AND routine output from operator-defined cron jobs (almost + # always noise — reported by user Heriberto whose periodic + # historical-data agent printed one line of stdout every 5 min + # and produced 288 Telegram messages a day). + # + # Split the firehose into two distinct event types so each can + # have its own default and toggle: + # - cron_output : `Cron ` subject → OFF by default. + # - system_mail : everything else (smartd, mail bounces) → ON. + # The operator can independently enable/disable each in + # Settings → Notifications. msg_lower = (message or '').lower() title_lower_sm = (title or '').lower() - + # ── Record disk observation regardless of noise filter ── # Even "noise" events are recorded as observations so the user # can see them in the Storage UI. We just don't send notifications. @@ -3937,7 +3949,7 @@ class ProxmoxHookWatcher: # JournalWatcher; calling it via `self` here raised AttributeError # on every PVE webhook with a smartd payload. See audit Tier 6 #2. _record_smartd_observation_impl(title or '', message or '') - + # ── Filter smartd noise (suppress notification, not observation) ── smartd_noise = [ 'failedreadsmarterrorlog', @@ -3947,7 +3959,16 @@ class ProxmoxHookWatcher: for noise in smartd_noise: if noise in title_lower_sm or noise in msg_lower: return '_skip', '', '' - + + # ── Detect cron-generated mail by the canonical subject ── + # cron(8) prefixes every mail it sends with "Cron + # ". This is the format every Unix cron has used for + # ~30 years, regardless of distro, so matching the literal + # prefix is robust and won't accidentally catch smartd or + # other system mail. + if title_lower_sm.startswith('cron <'): + return 'cron_output', 'node', '' + return 'system_mail', 'node', '' # ── Fallback for unknown/empty pve_type ── diff --git a/AppImage/scripts/notification_templates.py b/AppImage/scripts/notification_templates.py index 3de2b19b..af0eca4b 100644 --- a/AppImage/scripts/notification_templates.py +++ b/AppImage/scripts/notification_templates.py @@ -899,11 +899,36 @@ TEMPLATES = { 'default_enabled': True, 'hidden': True, }, + 'cron_output': { + 'title': '{hostname}: {pve_title}', + 'body': '{reason}', + # Output of operator-defined cron jobs forwarded via PVE's + # system-mail bucket. Default OFF because the typical pattern is + # a periodic job that prints a status line every N minutes (one + # user reported 288 messages/day from a `*/5 * * * *` agent). The + # smartd / mail-bounce signal that lives in the same PVE bucket + # is kept on a separate `system_mail` event so smartd warnings + # stay default-on while cron noise is opt-in. + 'label': 'Cron job output (per-cron stdout via mail)', + 'group': 'services', + 'default_enabled': False, + }, 'system_mail': { 'title': '{hostname}: {pve_title}', 'body': '{reason}', - 'label': 'PVE system mail (cron output, smartd, mail bounces)', - 'group': 'other', + # Label phrased starting with the word the user actually sees on + # smartd-driven notifications. Cron output has been split into a + # separate `cron_output` event; this one now covers only smartd + # warnings, mail bouncebacks, and other non-cron PVE system mail. + 'label': 'Smartd / mail bounces (PVE system mail)', + # Placed in 'services' (not 'other') because the 'other' category + # is intentionally hidden from the channel UI: it historically + # only contained internal events (webhook_test, burst_generic) + # that the operator shouldn't toggle. system_mail is a real + # operator-facing toggle, and smartd / mail bounces are + # conceptually system services, so 'services' is the right + # bucket for surfacing this in Settings → Notifications. + 'group': 'services', 'default_enabled': True, # NOT hidden — operators need to be able to mute this when PVE is # configured to forward root@ mail via the notification webhook.