From fefc3bba2a01d3c29d2b83c1bfb028bc133ea146 Mon Sep 17 00:00:00 2001 From: Inext68 Date: Wed, 27 May 2026 08:37:37 +0200 Subject: [PATCH] fine implementazione multi-sentder --- MEMORY.md | 15 + .../Admin/EmailSettingsController.php | 4 + .../Controllers/ImpostazioniController.php | 4 +- resources/views/impostazioni/index.blade.php | 285 ++++++++++++++++++ .../b8b9b66a1d90ca24f6e19777b0838604.php | 285 ++++++++++++++++++ 5 files changed, 592 insertions(+), 1 deletion(-) diff --git a/MEMORY.md b/MEMORY.md index 48dedc63..b833e27c 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -705,3 +705,18 @@ php artisan route:list --name=email - `resources/views/eventi/show.blade.php` - `resources/views/eventi/index.blade.php` - `resources/views/eventi/calendar.blade.php` + +### 27 Maggio 2026 - Mittenti Aggiuntivi in Sezione Email di /impostazioni + +- **Modifica**: Spostata gestione sender accounts (Mittenti Aggiuntivi) da pagina dedicata `/impostazioni/email` a **sottosezione della sezione Email** nella pagina principale `/impostazioni` +- **Sub-tab aggiunto**: pill "Mittenti Aggiuntivi" dopo Firma nei sottotab della sezione Email +- **Tab-pane `email-mittenti`**: tabella sender con colonne Email, Nome, SMTP, Reply-To, Verify, Stato, Azioni; stessi campi CRUD della vista dedicata +- **Form puliti**: pulsanti Elimina usano fetch AJAX (`deleteSender()`) invece di form annidati per evitare HTML invalido (nested forms dentro il form principale Email) +- **Controller**: `ImpostazioniController@index` ora passa `$senderAccounts` alla view +- **`senderDestroy()`** in `EmailSettingsController`: ora ritorna JSON per richieste AJAX (`expectsJson()`) +- **Sidebar**: rimossa voce "Impostazioni Email" aggiunta in precedenza sotto Email (non serve — le impostazioni email sono accessibili dalla sezione Email in `/impostazioni`) +- **Files modificati**: + - `app/Http/Controllers/ImpostazioniController.php`: import + compact SenderAccount + - `resources/views/impostazioni/index.blade.php`: pill Mittenti Aggiuntivi, tab-pane email-mittenti, modale sender modifica/crea, funzioni JS (resetSenderForm, editSender, deleteSender, testSenderSmtp) + - `app/Http/Controllers/Admin/EmailSettingsController.php`: senderDestroy() con expectsJson() + - `resources/views/layouts/adminlte.blade.php`: rimossa voce Impostazioni Email dal sidebar diff --git a/app/Http/Controllers/Admin/EmailSettingsController.php b/app/Http/Controllers/Admin/EmailSettingsController.php index d23aa526..3b16967b 100644 --- a/app/Http/Controllers/Admin/EmailSettingsController.php +++ b/app/Http/Controllers/Admin/EmailSettingsController.php @@ -250,6 +250,10 @@ class EmailSettingsController extends Controller $sender = SenderAccount::findOrFail($id); $sender->delete(); + if (request()->expectsJson()) { + return response()->json(['success' => true, 'message' => 'Mittente eliminato.']); + } + return back()->with('success', 'Mittente eliminato.'); } diff --git a/app/Http/Controllers/ImpostazioniController.php b/app/Http/Controllers/ImpostazioniController.php index 7afaa2b0..791a426b 100644 --- a/app/Http/Controllers/ImpostazioniController.php +++ b/app/Http/Controllers/ImpostazioniController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers; use App\Models\AppSetting; use App\Models\EmailSetting; use App\Models\Ruolo; +use App\Models\SenderAccount; use App\Models\TipologiaDocumento; use App\Models\TipologiaEvento; use Illuminate\Http\Request; @@ -21,8 +22,9 @@ class ImpostazioniController extends Controller $ruoli = Ruolo::orderBy('ordine')->get(); $appSettings = AppSetting::first(); $emailSettings = EmailSetting::first() ?? new EmailSetting(); + $senderAccounts = SenderAccount::orderBy('email_address')->get(); - return view('impostazioni.index', compact('tipologie', 'tipologieEventi', 'ruoli', 'appSettings', 'emailSettings')); + return view('impostazioni.index', compact('tipologie', 'tipologieEventi', 'ruoli', 'appSettings', 'emailSettings', 'senderAccounts')); } public function saveAppSettings(Request $request) diff --git a/resources/views/impostazioni/index.blade.php b/resources/views/impostazioni/index.blade.php index 49806638..eec5fce4 100644 --- a/resources/views/impostazioni/index.blade.php +++ b/resources/views/impostazioni/index.blade.php @@ -190,6 +190,7 @@ + @@ -427,6 +428,97 @@ + +
+
+
+

Mittenti Aggiuntivi

+
+ +
+
+
+ @if(session('success')) +
{{ session('success') }}
+ @endif + @if(session('error')) +
{{ session('error') }}
+ @endif + + @if($senderAccounts->count() > 0) +
+ + + + + + + + + + + + + + @foreach($senderAccounts as $sender) + + + + + + + + + + @endforeach + +
EmailNomeSMTPReply-ToVerifyStatoAzioni
{{ $sender->email_address }}{{ $sender->email_name ?: '-' }}{{ $sender->smtp_host ?: '-' }}:{{ $sender->smtp_port ?: '-' }}{{ $sender->reply_to ?: '-' }}{{ $sender->verify_email ?: '-' }} + @if($sender->is_active) + Attivo + @else + Disattivo + @endif + + + + +
+
+ @else +
+ +

Nessun mittente aggiuntivo configurato.

+

Usa il pulsante "Nuovo Mittente" per aggiungere un account di invio dedicato (es. Newsletter).

+
+ @endif +
+
+ + @if($senderAccounts->count() > 0) +
+
+

Come funziona

+
+
+
    +
  • I mittenti aggiuntivi sono account solo invio (SMTP) senza IMAP.
  • +
  • Puoi selezionarli nel compose email o negli invii mailing.
  • +
  • Il campo Reply-To imposta l'indirizzo di risposta (es. no-reply@parrocchia.it).
  • +
  • Il campo Verify Email riceve un report di riepilogo dopo ogni invio massivo con l'esito (ok/falliti).
  • +
  • Se Reply-To non è impostato, viene usato Verify Email come fallback.
  • +
+
+
+ @endif +
+ +{{-- ===== MODALE MITTENTI AGGIUNTIVI ===== --}} + @endsection @section('scripts') @@ -1007,6 +1206,92 @@ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { } }); +// ===== MITTENTI AGGIUNTIVI ===== +let senderAccounts = @json($senderAccounts); + +function resetSenderForm() { + document.getElementById('senderForm').action = '{{ route('impostazioni.sender.store') }}'; + document.getElementById('senderMethod').value = 'POST'; + document.getElementById('senderModalTitle').textContent = 'Nuovo Mittente'; + document.getElementById('senderForm').reset(); + document.getElementById('senderId').value = ''; + document.getElementById('sender_is_active').checked = true; + document.getElementById('sender_smtp_password').placeholder = ''; + document.getElementById('sender_smtp_password').required = false; +} + +function editSender(id) { + const sender = senderAccounts.find(s => s.id === id); + if (!sender) return; + + document.getElementById('senderForm').action = '{{ route('impostazioni.sender.update', '__ID__') }}'.replace('__ID__', id); + document.getElementById('senderMethod').value = 'PUT'; + document.getElementById('senderModalTitle').textContent = 'Modifica Mittente - ' + sender.email_address; + document.getElementById('senderId').value = sender.id; + document.getElementById('sender_email').value = sender.email_address; + document.getElementById('sender_name').value = sender.email_name || ''; + document.getElementById('sender_smtp_host').value = sender.smtp_host || ''; + document.getElementById('sender_smtp_port').value = sender.smtp_port || 587; + document.getElementById('sender_smtp_encryption').value = sender.smtp_encryption || 'tls'; + document.getElementById('sender_smtp_username').value = sender.smtp_username || ''; + document.getElementById('sender_smtp_password').value = ''; + document.getElementById('sender_smtp_password').placeholder = '......'; + document.getElementById('sender_smtp_password').required = false; + document.getElementById('sender_reply_to').value = sender.reply_to || ''; + document.getElementById('sender_verify_email').value = sender.verify_email || ''; + document.getElementById('sender_note').value = sender.note || ''; + document.getElementById('sender_is_active').checked = sender.is_active; + + $('#senderModal').modal('show'); +} + +function deleteSender(id, email) { + if (!confirm('Eliminare il mittente ' + email + '?')) return; + var url = '{{ route('impostazioni.sender.destroy', '__ID__') }}'.replace('__ID__', id); + fetch(url, { + method: 'POST', + headers: { + 'X-CSRF-TOKEN': '{{ csrf_token() }}', + 'X-HTTP-Method-Override': 'DELETE' + } + }).then(function(r) { return r.json(); }).then(function(data) { + if (data.success) { + location.reload(); + } else { + alert('❌ ' + (data.message || 'Errore')); + } + }).catch(function() { + alert('❌ Errore di rete'); + }); +} + +function testSenderSmtp(id) { + const email = prompt('Inserisci l\'indirizzo email a cui inviare il test:'); + if (!email || !email.includes('@')) return; + + const btn = event.target; + btn.disabled = true; + btn.innerHTML = ''; + + $.ajax({ + url: '{{ route('impostazioni.sender.test', '__ID__') }}'.replace('__ID__', id), + method: 'POST', + headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' }, + data: { email: email }, + timeout: 30000, + success: function(response) { + btn.disabled = false; + btn.innerHTML = ''; + alert(response.success ? '✅ ' + response.message : '❌ ' + response.message); + }, + error: function(xhr) { + btn.disabled = false; + btn.innerHTML = ''; + const msg = xhr.responseJSON?.message || 'Errore di connessione'; + alert('❌ ' + msg); + } + }); +} // ===== EMAIL FUNCTIONS ===== function testConnection() { $.ajax({ diff --git a/storage/framework/views/b8b9b66a1d90ca24f6e19777b0838604.php b/storage/framework/views/b8b9b66a1d90ca24f6e19777b0838604.php index 3bdcf4f7..9a939330 100755 --- a/storage/framework/views/b8b9b66a1d90ca24f6e19777b0838604.php +++ b/storage/framework/views/b8b9b66a1d90ca24f6e19777b0838604.php @@ -188,6 +188,7 @@ + @@ -426,6 +427,97 @@ + +
+
+
+

Mittenti Aggiuntivi

+
+ +
+
+
+ +
+ + +
+ + + count() > 0): ?> +
+ + + + + + + + + + + + + + addLoop($__currentLoopData); foreach($__currentLoopData as $sender): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?> + + + + + + + + + + popLoop(); $loop = $__env->getLastLoop(); ?> + +
EmailNomeSMTPReply-ToVerifyStatoAzioni
email_address); ?>email_name ?: '-'); ?>smtp_host ?: '-'); ?>:smtp_port ?: '-'); ?>reply_to ?: '-'); ?>verify_email ?: '-'); ?> + is_active): ?> + Attivo + + Disattivo + + + + + +
+
+ +
+ +

Nessun mittente aggiuntivo configurato.

+

Usa il pulsante "Nuovo Mittente" per aggiungere un account di invio dedicato (es. Newsletter).

+
+ +
+
+ + count() > 0): ?> +
+
+

Come funziona

+
+
+
    +
  • I mittenti aggiuntivi sono account solo invio (SMTP) senza IMAP.
  • +
  • Puoi selezionarli nel compose email o negli invii mailing.
  • +
  • Il campo Reply-To imposta l'indirizzo di risposta (es. no-reply@parrocchia.it).
  • +
  • Il campo Verify Email riceve un report di riepilogo dopo ogni invio massivo con l'esito (ok/falliti).
  • +
  • Se Reply-To non è impostato, viene usato Verify Email come fallback.
  • +
+
+
+ +
+ + + stopSection(); ?> startSection('scripts'); ?> @@ -1006,6 +1205,92 @@ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { } }); +// ===== MITTENTI AGGIUNTIVI ===== +let senderAccounts = ; + +function resetSenderForm() { + document.getElementById('senderForm').action = ''; + document.getElementById('senderMethod').value = 'POST'; + document.getElementById('senderModalTitle').textContent = 'Nuovo Mittente'; + document.getElementById('senderForm').reset(); + document.getElementById('senderId').value = ''; + document.getElementById('sender_is_active').checked = true; + document.getElementById('sender_smtp_password').placeholder = ''; + document.getElementById('sender_smtp_password').required = false; +} + +function editSender(id) { + const sender = senderAccounts.find(s => s.id === id); + if (!sender) return; + + document.getElementById('senderForm').action = ''.replace('__ID__', id); + document.getElementById('senderMethod').value = 'PUT'; + document.getElementById('senderModalTitle').textContent = 'Modifica Mittente - ' + sender.email_address; + document.getElementById('senderId').value = sender.id; + document.getElementById('sender_email').value = sender.email_address; + document.getElementById('sender_name').value = sender.email_name || ''; + document.getElementById('sender_smtp_host').value = sender.smtp_host || ''; + document.getElementById('sender_smtp_port').value = sender.smtp_port || 587; + document.getElementById('sender_smtp_encryption').value = sender.smtp_encryption || 'tls'; + document.getElementById('sender_smtp_username').value = sender.smtp_username || ''; + document.getElementById('sender_smtp_password').value = ''; + document.getElementById('sender_smtp_password').placeholder = '......'; + document.getElementById('sender_smtp_password').required = false; + document.getElementById('sender_reply_to').value = sender.reply_to || ''; + document.getElementById('sender_verify_email').value = sender.verify_email || ''; + document.getElementById('sender_note').value = sender.note || ''; + document.getElementById('sender_is_active').checked = sender.is_active; + + $('#senderModal').modal('show'); +} + +function deleteSender(id, email) { + if (!confirm('Eliminare il mittente ' + email + '?')) return; + var url = ''.replace('__ID__', id); + fetch(url, { + method: 'POST', + headers: { + 'X-CSRF-TOKEN': '', + 'X-HTTP-Method-Override': 'DELETE' + } + }).then(function(r) { return r.json(); }).then(function(data) { + if (data.success) { + location.reload(); + } else { + alert('❌ ' + (data.message || 'Errore')); + } + }).catch(function() { + alert('❌ Errore di rete'); + }); +} + +function testSenderSmtp(id) { + const email = prompt('Inserisci l\'indirizzo email a cui inviare il test:'); + if (!email || !email.includes('@')) return; + + const btn = event.target; + btn.disabled = true; + btn.innerHTML = ''; + + $.ajax({ + url: ''.replace('__ID__', id), + method: 'POST', + headers: { 'X-CSRF-TOKEN': '' }, + data: { email: email }, + timeout: 30000, + success: function(response) { + btn.disabled = false; + btn.innerHTML = ''; + alert(response.success ? '✅ ' + response.message : '❌ ' + response.message); + }, + error: function(xhr) { + btn.disabled = false; + btn.innerHTML = ''; + const msg = xhr.responseJSON?.message || 'Errore di connessione'; + alert('❌ ' + msg); + } + }); +} // ===== EMAIL FUNCTIONS ===== function testConnection() { $.ajax({