From fe77ee8679a9d1aa432bb6d525820e7b2bba34ab Mon Sep 17 00:00:00 2001 From: DevEnv nis2-agile Date: Sun, 31 May 2026 18:46:55 +0200 Subject: [PATCH] [SEC] EmailService: kill-switch invio email (EMAIL_SENDING_ENABLED) Ambiente con soli dati demo: NESSUNA email deve partire. Aggiunto guard all'inizio di sendViaRelay() e sendViaTemplate() (gli UNICI due punti che fanno HTTP al relay -> copre tutti i canali: incidenti, training, inviti, reminder, welcome, password reset, feedback, OTP portale fornitori). EMAIL_SENDING_ENABLED in config: default false in sviluppo, true in produzione, override via .env. Quando false l'invio viene loggato e scartato (return false), nessuna chiamata di rete. Co-Authored-By: Claude Opus 4.8 --- application/config/config.php | 14 ++++++++++++++ application/services/EmailService.php | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/application/config/config.php b/application/config/config.php index c556691..91b9130 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -14,6 +14,20 @@ define('APP_NAME', Env::get('APP_NAME', 'NIS2 Agile')); define('APP_VERSION', Env::get('APP_VERSION', '1.0.0')); define('APP_URL', Env::get('APP_URL', 'http://localhost:8080')); +// ───────────────────────────────────────────────────────────────────────────── +// KILL-SWITCH INVIO EMAIL (ambiente con soli dati demo) +// ───────────────────────────────────────────────────────────────────────────── +// Quando true, EmailService NON effettua NESSUNA chiamata HTTP al relay: ogni +// invio (incidenti, training, inviti, reminder, OTP portale fornitori, ecc.) +// viene registrato a log e scartato. Difesa contro invii accidentali a indirizzi +// reali finche' l'ambiente contiene solo dati demo. +// DEFAULT: in sviluppo le email sono DISABILITATE (true). In produzione abilitate +// (false) salvo override esplicito EMAIL_SENDING_ENABLED nel .env. +define('EMAIL_SENDING_ENABLED', filter_var( + Env::get('EMAIL_SENDING_ENABLED', APP_ENV === 'production' ? 'true' : 'false'), + FILTER_VALIDATE_BOOLEAN +)); + // ═══════════════════════════════════════════════════════════════════════════ // PERCORSI // ═══════════════════════════════════════════════════════════════════════════ diff --git a/application/services/EmailService.php b/application/services/EmailService.php index 3859666..2b813ba 100644 --- a/application/services/EmailService.php +++ b/application/services/EmailService.php @@ -66,6 +66,12 @@ class EmailService */ private function sendViaRelay(string $to, string $subject, string $fullHtml, string $from): bool { + // KILL-SWITCH: in ambiente con soli dati demo nessuna email deve partire. + if (defined('EMAIL_SENDING_ENABLED') && !EMAIL_SENDING_ENABLED) { + error_log('[EmailService] invio DISABILITATO (EMAIL_SENDING_ENABLED=false): scartato "' . $subject . '" per ' . self::maskEmail($to)); + return false; + } + $base = rtrim(self::env('EMAIL_MS_URL', 'https://agilehub.agile.software/api/emails'), '/'); $key = self::env('INTERNAL_EMAIL_KEY', ''); @@ -132,6 +138,12 @@ class EmailService */ public function sendViaTemplate(string $to, string $template, array $vars, ?string $brandName = null): bool { + // KILL-SWITCH: in ambiente con soli dati demo nessuna email deve partire. + if (defined('EMAIL_SENDING_ENABLED') && !EMAIL_SENDING_ENABLED) { + error_log('[EmailService] invio DISABILITATO (EMAIL_SENDING_ENABLED=false): template "' . $template . '" scartato per ' . self::maskEmail($to)); + return false; + } + $base = rtrim(self::env('EMAIL_MS_URL', 'https://agilehub.agile.software/api/emails'), '/'); $key = self::env('INTERNAL_EMAIL_KEY', '');