fix mailing an email
This commit is contained in:
@@ -28,16 +28,17 @@ class BackupRunCommand extends Command
|
||||
{
|
||||
$this->info('Avvio backup...');
|
||||
|
||||
$options = [];
|
||||
if ($this->option('no-files')) {
|
||||
$this->backupService->saveConfig(['backup_include_files' => false]);
|
||||
$options['include_files'] = false;
|
||||
$this->warn('Files esclusi dal backup.');
|
||||
}
|
||||
if ($this->option('no-env')) {
|
||||
$this->backupService->saveConfig(['backup_include_env' => false]);
|
||||
$options['include_env'] = false;
|
||||
$this->warn('.env escluso dal backup.');
|
||||
}
|
||||
|
||||
$result = $this->backupService->run();
|
||||
$result = $this->backupService->run($options);
|
||||
|
||||
if ($result['success']) {
|
||||
$this->info(' Backup completato con successo!');
|
||||
@@ -45,6 +46,13 @@ class BackupRunCommand extends Command
|
||||
$this->line('Dimensione: ' . $result['size_formatted']);
|
||||
$this->line('Percorso: ' . storage_path('app/backups/' . $result['filename']));
|
||||
|
||||
if (!empty($result['steps'])) {
|
||||
$this->line('Contenuto:');
|
||||
foreach ($result['steps'] as $step) {
|
||||
$this->line(' - ' . $step);
|
||||
}
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,9 @@ class BackupController extends Controller
|
||||
$result = $this->backupService->run();
|
||||
|
||||
if ($result['success']) {
|
||||
$steps = !empty($result['steps']) ? ' — ' . implode(', ', $result['steps']) : '';
|
||||
return redirect()->route('admin.backup.index')
|
||||
->with('success', 'Backup completato: ' . ($result['filename'] ?? '') . ' (' . ($result['size_formatted'] ?? '') . ')');
|
||||
->with('success', 'Backup completato: ' . ($result['filename'] ?? '') . ' (' . ($result['size_formatted'] ?? '') . ')' . $steps);
|
||||
}
|
||||
|
||||
return redirect()->route('admin.backup.index')
|
||||
|
||||
@@ -7,12 +7,15 @@ use App\Http\Controllers\Controller;
|
||||
use App\Models\EmailAttachment;
|
||||
use App\Models\EmailFolder;
|
||||
use App\Models\EmailSetting;
|
||||
use App\Models\Firma;
|
||||
use App\Models\SenderAccount;
|
||||
use App\Services\GoogleOAuthService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
class EmailSettingsController extends Controller
|
||||
{
|
||||
@@ -22,7 +25,8 @@ class EmailSettingsController extends Controller
|
||||
$settings = EmailSetting::first() ?? new EmailSetting();
|
||||
$senderAccounts = SenderAccount::orderBy('email_address')->get();
|
||||
$googleStatus = app(GoogleOAuthService::class)->getConnectionStatus();
|
||||
return view('admin.email-settings.index', compact('settings', 'senderAccounts', 'googleStatus'));
|
||||
$firme = $settings->exists ? $settings->firme : collect();
|
||||
return view('admin.email-settings.index', compact('settings', 'senderAccounts', 'googleStatus', 'firme'));
|
||||
}
|
||||
|
||||
public function save(Request $request)
|
||||
@@ -41,6 +45,8 @@ class EmailSettingsController extends Controller
|
||||
'smtp_password' => 'nullable|string',
|
||||
'email_address' => 'required|email',
|
||||
'email_name' => 'nullable|string|max:255',
|
||||
'from_email' => 'nullable|email|max:255',
|
||||
'from_name' => 'nullable|string|max:255',
|
||||
'reply_to' => 'nullable|email',
|
||||
'sync_interval_minutes' => 'nullable|integer|min:1|max:60',
|
||||
'is_active' => 'boolean',
|
||||
@@ -128,25 +134,20 @@ class EmailSettingsController extends Controller
|
||||
return response()->json(['success' => false, 'message' => 'Impossibile creare il mailer SMTP. Verifica la configurazione.']);
|
||||
}
|
||||
|
||||
$fromName = $settings->email_name ?? '';
|
||||
if (filter_var($fromName, FILTER_VALIDATE_EMAIL)) {
|
||||
$fromName = 'Glastree';
|
||||
} else {
|
||||
$fromName = preg_replace('/[^\p{L}\p{N}\s]/u', '', $fromName);
|
||||
$fromName = trim($fromName);
|
||||
if (empty($fromName) || strlen($fromName) > 50) {
|
||||
$fromName = 'Glastree';
|
||||
}
|
||||
}
|
||||
$smtpUser = $settings->smtp_username ?: $settings->email_address;
|
||||
$fromName = $settings->getEffectiveFromName();
|
||||
$replyToEmail = $settings->from_email ?: $smtpUser;
|
||||
|
||||
$fromAddress = \Symfony\Component\Mime\Address::create($settings->email_address, $fromName);
|
||||
|
||||
$email = (new \Symfony\Component\Mime\Email())
|
||||
->from($fromAddress)
|
||||
$email = (new Email())
|
||||
->from(Address::create($smtpUser, $fromName))
|
||||
->to($request->email)
|
||||
->subject('Test Configurazione SMTP - Glastree')
|
||||
->text('Test email da Glastree - Configurazione SMTP funziona!');
|
||||
|
||||
if ($replyToEmail !== $smtpUser) {
|
||||
$email->replyTo(Address::create($replyToEmail, $fromName));
|
||||
}
|
||||
|
||||
$mailer->send($email);
|
||||
|
||||
\Illuminate\Support\Facades\Log::info('Test SMTP ok', ['to' => $request->email, 'from' => $settings->email_address]);
|
||||
@@ -294,4 +295,66 @@ class EmailSettingsController extends Controller
|
||||
return response()->json(['success' => false, 'message' => 'Errore invio: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function firmaStore(Request $request)
|
||||
{
|
||||
$this->authorizeWrite('settings');
|
||||
$data = $request->validate([
|
||||
'nome' => 'required|string|max:255',
|
||||
'contenuto_html' => 'nullable|string',
|
||||
'is_default' => 'boolean',
|
||||
]);
|
||||
|
||||
$settings = EmailSetting::getActive();
|
||||
if (!$settings) {
|
||||
return redirect('/impostazioni/email')->with('error', 'Account email non configurato.');
|
||||
}
|
||||
|
||||
$firma = $settings->firme()->create($data);
|
||||
|
||||
if ($data['is_default'] ?? false) {
|
||||
$settings->firme()->where('id', '!=', $firma->id)->update(['is_default' => false]);
|
||||
}
|
||||
|
||||
return redirect('/impostazioni/email#firme')->with('success', 'Firma "' . $firma->nome . '" creata.');
|
||||
}
|
||||
|
||||
public function firmaUpdate(Request $request, int $id)
|
||||
{
|
||||
$this->authorizeWrite('settings');
|
||||
$data = $request->validate([
|
||||
'nome' => 'required|string|max:255',
|
||||
'contenuto_html' => 'nullable|string',
|
||||
'is_default' => 'boolean',
|
||||
]);
|
||||
|
||||
$firma = Firma::findOrFail($id);
|
||||
$firma->update($data);
|
||||
|
||||
if ($data['is_default'] ?? false) {
|
||||
Firma::where('email_setting_id', $firma->email_setting_id)
|
||||
->where('id', '!=', $firma->id)
|
||||
->update(['is_default' => false]);
|
||||
}
|
||||
|
||||
return redirect('/impostazioni/email#firme')->with('success', 'Firma "' . $firma->nome . '" aggiornata.');
|
||||
}
|
||||
|
||||
public function firmaSetDefault(int $id)
|
||||
{
|
||||
$this->authorizeWrite('settings');
|
||||
$firma = Firma::findOrFail($id);
|
||||
Firma::where('email_setting_id', $firma->email_setting_id)->update(['is_default' => false]);
|
||||
$firma->update(['is_default' => true]);
|
||||
return redirect('/impostazioni/email#firme')->with('success', 'Firma "' . $firma->nome . '" impostata come predefinita.');
|
||||
}
|
||||
|
||||
public function firmaDestroy(int $id)
|
||||
{
|
||||
$this->authorizeWrite('settings');
|
||||
$firma = Firma::findOrFail($id);
|
||||
$nome = $firma->nome;
|
||||
$firma->delete();
|
||||
return redirect('/impostazioni/email#firme')->with('success', 'Firma "' . $nome . '" eliminata.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Models\MailingList;
|
||||
use App\Models\Gruppo;
|
||||
use App\Models\Individuo;
|
||||
use App\Models\Documento;
|
||||
use App\Models\Firma;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -96,6 +97,9 @@ class EmailController extends Controller
|
||||
|
||||
$documenti = Documento::orderBy('nome_file')->get();
|
||||
|
||||
$settings = EmailSetting::getActive();
|
||||
$firme = $settings?->firme ?? collect();
|
||||
|
||||
$prefill = [];
|
||||
if ($request->reply_to) {
|
||||
$original = EmailMessage::find($request->reply_to);
|
||||
@@ -113,7 +117,7 @@ class EmailController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
return view('email.compose', compact('folders', 'mailingLists', 'gruppi', 'individui', 'documenti', 'prefill', 'senderAccounts'));
|
||||
return view('email.compose', compact('folders', 'mailingLists', 'gruppi', 'individui', 'documenti', 'prefill', 'senderAccounts', 'firme'));
|
||||
}
|
||||
|
||||
public function send(Request $request)
|
||||
@@ -128,6 +132,7 @@ class EmailController extends Controller
|
||||
$rules['to'] = 'required';
|
||||
}
|
||||
|
||||
$rules['firma_id'] = 'nullable|integer|exists:firme,id';
|
||||
$validated = $request->validate($rules);
|
||||
|
||||
$recipients = $this->resolveRecipients($request);
|
||||
@@ -159,9 +164,11 @@ class EmailController extends Controller
|
||||
$imapError = null;
|
||||
$attachments = $this->processAttachments($request);
|
||||
|
||||
$firmaId = $request->firma_id;
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
try {
|
||||
$bodyWithSig = $this->appendSignature($validated['body'], $settings->getSignature(), $settings->signature_enabled ?? false);
|
||||
$bodyWithSig = $this->appendSignature($validated['body'], $firmaId, $settings);
|
||||
$this->sendViaImap($settings, $recipient, $validated['subject'], $bodyWithSig, $request->cc, $attachments);
|
||||
$imapSuccess = true;
|
||||
} catch (\Exception $e) {
|
||||
@@ -171,7 +178,7 @@ class EmailController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
$bodyWithSig = $this->appendSignature($validated['body'], $settings->getSignature(), $settings->signature_enabled ?? false);
|
||||
$bodyWithSig = $this->appendSignature($validated['body'], $firmaId, $settings);
|
||||
$this->storeSentMessage($settings, $recipients, $validated['subject'], $bodyWithSig, $request->cc);
|
||||
} catch (\Exception $e) {
|
||||
\Illuminate\Support\Facades\Log::error('Store sent message error', ['error' => $e->getMessage()]);
|
||||
@@ -189,12 +196,16 @@ class EmailController extends Controller
|
||||
{
|
||||
$sender = SenderAccount::findOrFail($request->mittente_id);
|
||||
$attachmentPaths = $this->resolveAttachmentPaths($request);
|
||||
|
||||
$settings = EmailSetting::getActive();
|
||||
$body = $this->appendSignature($validated['body'], $request->firma_id, $settings);
|
||||
|
||||
$ok = 0;
|
||||
$errors = [];
|
||||
|
||||
foreach ($recipients as $recipient) {
|
||||
try {
|
||||
$sender->sendEmail($recipient, $validated['subject'], $validated['body'], $attachmentPaths);
|
||||
$sender->sendEmail($recipient, $validated['subject'], $body, $attachmentPaths);
|
||||
$ok++;
|
||||
} catch (\Exception $e) {
|
||||
$errors[] = $recipient . ': ' . $e->getMessage();
|
||||
@@ -237,8 +248,8 @@ class EmailController extends Controller
|
||||
'body_text' => $request->body,
|
||||
'to_email' => $request->to,
|
||||
'is_draft' => true,
|
||||
'from_email' => $settings->email_address ?? '',
|
||||
'from_name' => $settings->email_name ?? '',
|
||||
'from_email' => $settings->getEffectiveFromAddress(),
|
||||
'from_name' => $settings->getEffectiveFromName(),
|
||||
]);
|
||||
|
||||
return response()->json(['success' => true, 'draft_id' => $message->id]);
|
||||
@@ -496,12 +507,20 @@ class EmailController extends Controller
|
||||
return array_filter(array_unique($recipients));
|
||||
}
|
||||
|
||||
private function appendSignature(string $body, ?string $signature, bool $enabled): string
|
||||
private function appendSignature(string $body, int|string|null $firmaId = null, ?EmailSetting $settings = null): string
|
||||
{
|
||||
if (empty($signature) || !$enabled) {
|
||||
return $body;
|
||||
if ($firmaId) {
|
||||
$firma = Firma::find($firmaId);
|
||||
if ($firma && $firma->contenuto_html) {
|
||||
return $body . "\n\n---\n" . $firma->contenuto_html;
|
||||
}
|
||||
}
|
||||
return $body . "\n\n---\n" . $signature;
|
||||
|
||||
if ($settings && $settings->signature && ($settings->signature_enabled ?? false)) {
|
||||
return $body . "\n\n---\n" . $settings->signature;
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function sendViaImap($settings, $to, $subject, $body, $cc = null, array $attachmentPaths = [])
|
||||
@@ -526,26 +545,23 @@ class EmailController extends Controller
|
||||
try {
|
||||
$transport = \Symfony\Component\Mailer\Transport::fromDsn($dsn);
|
||||
$mailer = new \Symfony\Component\Mailer\Mailer($transport);
|
||||
|
||||
$fromName = $settings->email_name ?? '';
|
||||
if (filter_var($fromName, FILTER_VALIDATE_EMAIL)) {
|
||||
$fromName = 'Glastree';
|
||||
} else {
|
||||
$fromName = preg_replace('/[^\p{L}\p{N}\s]/u', '', $fromName);
|
||||
$fromName = trim($fromName);
|
||||
if (empty($fromName)) {
|
||||
$fromName = 'Glastree';
|
||||
}
|
||||
}
|
||||
|
||||
$fromAddress = \Symfony\Component\Mime\Address::create($settings->email_address, $fromName);
|
||||
$fromAddress = \Symfony\Component\Mime\Address::create(
|
||||
$settings->getEffectiveFromAddress(),
|
||||
$settings->getEffectiveFromName()
|
||||
);
|
||||
|
||||
$email = (new \Symfony\Component\Mime\Email())
|
||||
->from($fromAddress)
|
||||
->to($to)
|
||||
->subject($subject)
|
||||
->text($body);
|
||||
|
||||
|
||||
$replyTo = $settings->getEffectiveReplyTo();
|
||||
if ($replyTo) {
|
||||
$email->replyTo($replyTo);
|
||||
}
|
||||
|
||||
if ($cc) {
|
||||
$email->cc($cc);
|
||||
}
|
||||
@@ -619,14 +635,14 @@ class EmailController extends Controller
|
||||
private function storeSentMessage($settings, $recipients, $subject, $body, $cc = null)
|
||||
{
|
||||
$sentFolder = EmailFolder::where('type', 'sent')->first();
|
||||
$bodyWithSignature = $this->appendSignature($body, $settings->getSignature(), $settings->signature_enabled ?? false);
|
||||
$bodyWithSignature = $body;
|
||||
|
||||
$message = EmailMessage::create([
|
||||
'email_folder_id' => $sentFolder->id,
|
||||
'subject' => $subject,
|
||||
'body_text' => $bodyWithSignature,
|
||||
'from_email' => $settings->email_address,
|
||||
'from_name' => $settings->email_name,
|
||||
'from_email' => $settings->getEffectiveFromAddress(),
|
||||
'from_name' => $settings->getEffectiveFromName(),
|
||||
'to_email' => implode(', ', $recipients),
|
||||
'cc' => $cc,
|
||||
'is_sent' => true,
|
||||
|
||||
@@ -66,7 +66,7 @@ class GruppoController extends Controller
|
||||
$entityType = 'gruppi';
|
||||
$columnWidths = $vista && $vista->colonne_larghezze ? $vista->colonne_larghezze : [];
|
||||
|
||||
$gruppiQuery = Gruppo::with(['diocesi', 'parent', 'children', 'individui', 'avatar', 'tags']);
|
||||
$gruppiQuery = Gruppo::with(['diocesi', 'gruppoContatti', 'parent', 'children', 'individui', 'avatar', 'tags']);
|
||||
|
||||
if (request()->filled('tag')) {
|
||||
$tagSlugs = (array) request()->input('tag');
|
||||
@@ -142,7 +142,7 @@ class GruppoController extends Controller
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->authorizeWrite('gruppi');
|
||||
$diocesi = Diocesi::orderBy('nome')->get();
|
||||
$diocesi = Diocesi::orderBy('id')->get();
|
||||
$allGruppi = Gruppo::orderBy('nome')->get();
|
||||
$selectedParent = $request->query('parent_id') ? Gruppo::find($request->query('parent_id')) : null;
|
||||
$individui = Individuo::orderBy('cognome')->orderBy('nome')->get();
|
||||
@@ -157,7 +157,8 @@ class GruppoController extends Controller
|
||||
'nome' => 'required|string|max:255',
|
||||
'descrizione' => 'nullable|string',
|
||||
'parent_id' => 'nullable|exists:gruppi,id',
|
||||
'diocesi_id' => 'nullable|exists:diocesi,id',
|
||||
'diocesi_ids' => 'nullable|array',
|
||||
'diocesi_ids.*' => 'exists:diocesi,id',
|
||||
'responsabile_ids' => 'nullable|array',
|
||||
'responsabile_ids.*' => 'exists:individui,id',
|
||||
'indirizzo_incontro' => 'nullable|string|max:500',
|
||||
@@ -165,6 +166,11 @@ class GruppoController extends Controller
|
||||
'città_incontro' => 'nullable|string|max:255',
|
||||
'sigla_provincia_incontro' => 'nullable|string|max:2',
|
||||
'mappa_posizione' => 'nullable|string',
|
||||
'contatti' => 'nullable|array',
|
||||
'contatti.*.tipo' => 'required|string|in:email,telefono,cellulare',
|
||||
'contatti.*.valore' => 'required|string|max:255',
|
||||
'contatti.*.etichetta' => 'nullable|string|max:255',
|
||||
'contatti.*.is_primary' => 'nullable|boolean',
|
||||
'tags' => 'nullable|array',
|
||||
'tags.*' => 'exists:tags,id',
|
||||
]);
|
||||
@@ -175,6 +181,21 @@ class GruppoController extends Controller
|
||||
|
||||
$gruppo = Gruppo::create($data);
|
||||
|
||||
if (!empty($data['diocesi_ids'])) {
|
||||
$gruppo->diocesi()->sync($data['diocesi_ids']);
|
||||
}
|
||||
|
||||
if (!empty($data['contatti'])) {
|
||||
foreach ($data['contatti'] as $contattoData) {
|
||||
$gruppo->gruppoContatti()->create([
|
||||
'tipo' => $contattoData['tipo'],
|
||||
'valore' => $contattoData['valore'],
|
||||
'etichetta' => $contattoData['etichetta'] ?? null,
|
||||
'is_primary' => $contattoData['is_primary'] ?? false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('tags')) {
|
||||
$gruppo->tags()->sync($request->tags);
|
||||
}
|
||||
@@ -196,7 +217,7 @@ class GruppoController extends Controller
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorizeRead('gruppi');
|
||||
$gruppo = Gruppo::with(['parent', 'children', 'diocesi', 'individui.contatti', 'individui.documenti', 'individui' => function ($q) {
|
||||
$gruppo = Gruppo::with(['parent', 'children', 'diocesi', 'gruppoContatti', 'individui.contatti', 'individui.documenti', 'individui' => function ($q) {
|
||||
$q->withPivot('ruolo_ids', 'ruolo_nel_gruppo', 'data_adesione');
|
||||
}, 'avatar', 'tags', 'eventi' => function ($q) {
|
||||
$q->where('is_incontro_gruppo', true);
|
||||
@@ -207,13 +228,14 @@ class GruppoController extends Controller
|
||||
public function edit($id)
|
||||
{
|
||||
$this->authorizeWrite('gruppi');
|
||||
$gruppo = Gruppo::with(['individui.contatti', 'individui.documenti', 'avatar', 'tags'])->findOrFail($id);
|
||||
$diocesi = Diocesi::orderBy('nome')->get();
|
||||
$gruppo = Gruppo::with(['individui.contatti', 'individui.documenti', 'gruppoContatti', 'avatar', 'tags'])->findOrFail($id);
|
||||
$diocesi = Diocesi::orderBy('id')->get();
|
||||
$gruppi = Gruppo::where('id', '!=', $gruppo->id)->orderBy('nome')->get();
|
||||
$membri = $gruppo->individui()->withPivot('ruolo_ids', 'ruolo_nel_gruppo', 'data_adesione')->orderBy('cognome')->orderBy('nome')->get();
|
||||
$tags = Tag::orderBy('name')->get();
|
||||
$selectedTags = $gruppo->tags->pluck('id')->toArray();
|
||||
return view('gruppi.edit', compact('gruppo', 'diocesi', 'gruppi', 'membri', 'tags', 'selectedTags'));
|
||||
$selectedDiocesiIds = $gruppo->diocesi()->pluck('diocesi.id')->toArray();
|
||||
return view('gruppi.edit', compact('gruppo', 'diocesi', 'gruppi', 'membri', 'tags', 'selectedTags', 'selectedDiocesiIds'));
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
@@ -224,7 +246,8 @@ class GruppoController extends Controller
|
||||
'nome' => 'required|string|max:255',
|
||||
'descrizione' => 'nullable|string',
|
||||
'parent_id' => 'nullable|exists:gruppi,id',
|
||||
'diocesi_id' => 'nullable|exists:diocesi,id',
|
||||
'diocesi_ids' => 'nullable|array',
|
||||
'diocesi_ids.*' => 'exists:diocesi,id',
|
||||
'responsabile_ids' => 'nullable|array',
|
||||
'responsabile_ids.*' => 'exists:individui,id',
|
||||
'indirizzo_incontro' => 'nullable|string|max:500',
|
||||
@@ -232,6 +255,11 @@ class GruppoController extends Controller
|
||||
'città_incontro' => 'nullable|string|max:255',
|
||||
'sigla_provincia_incontro' => 'nullable|string|max:2',
|
||||
'mappa_posizione' => 'nullable|string',
|
||||
'contatti' => 'nullable|array',
|
||||
'contatti.*.tipo' => 'required|string|in:email,telefono,cellulare',
|
||||
'contatti.*.valore' => 'required|string|max:255',
|
||||
'contatti.*.etichetta' => 'nullable|string|max:255',
|
||||
'contatti.*.is_primary' => 'nullable|boolean',
|
||||
'tags' => 'nullable|array',
|
||||
'tags.*' => 'exists:tags,id',
|
||||
]);
|
||||
@@ -244,6 +272,24 @@ class GruppoController extends Controller
|
||||
|
||||
$gruppo->update($data);
|
||||
|
||||
if ($request->has('diocesi_ids')) {
|
||||
$gruppo->diocesi()->sync($data['diocesi_ids'] ?? []);
|
||||
} else {
|
||||
$gruppo->diocesi()->detach();
|
||||
}
|
||||
|
||||
if ($request->has('contatti')) {
|
||||
$gruppo->gruppoContatti()->delete();
|
||||
foreach ($data['contatti'] as $contattoData) {
|
||||
$gruppo->gruppoContatti()->create([
|
||||
'tipo' => $contattoData['tipo'],
|
||||
'valore' => $contattoData['valore'],
|
||||
'etichetta' => $contattoData['etichetta'] ?? null,
|
||||
'is_primary' => $contattoData['is_primary'] ?? false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('tags')) {
|
||||
$gruppo->tags()->sync($request->tags);
|
||||
} else {
|
||||
|
||||
@@ -152,7 +152,7 @@ public function create()
|
||||
{
|
||||
$this->authorizeWrite('individui');
|
||||
$comuni = Comune::orderBy('nome')->get();
|
||||
$diocesi = Diocesi::orderBy('nome')->get();
|
||||
$diocesi = Diocesi::orderBy('id')->get();
|
||||
$tags = Tag::orderBy('name')->get();
|
||||
return view('individui.create', compact('comuni', 'diocesi', 'tags'));
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ use App\Models\MailingMessaggio;
|
||||
use App\Models\SenderAccount;
|
||||
use App\Models\Individuo;
|
||||
use App\Models\Documento;
|
||||
use App\Models\EmailSetting;
|
||||
use App\Models\Firma;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -30,6 +32,8 @@ class MailingController extends Controller
|
||||
$liste = MailingList::all();
|
||||
$documenti = Documento::orderBy('nome_file')->get();
|
||||
$senderAccounts = SenderAccount::active()->get();
|
||||
$settings = EmailSetting::getActive();
|
||||
$firme = $settings?->firme ?? collect();
|
||||
|
||||
$documentiSelezionati = collect();
|
||||
if ($request->has('documenti_selezionati')) {
|
||||
@@ -37,7 +41,7 @@ class MailingController extends Controller
|
||||
$documentiSelezionati = Documento::whereIn('id', $docIds)->get();
|
||||
}
|
||||
|
||||
return view('mailing.nuovo', compact('individui', 'liste', 'documenti', 'documentiSelezionati', 'senderAccounts'));
|
||||
return view('mailing.nuovo', compact('individui', 'liste', 'documenti', 'documentiSelezionati', 'senderAccounts', 'firme'));
|
||||
}
|
||||
|
||||
public function invia(Request $request)
|
||||
@@ -46,16 +50,22 @@ class MailingController extends Controller
|
||||
$data = $request->validate([
|
||||
'oggetto' => 'required|string|max:255',
|
||||
'corpo' => 'required',
|
||||
'lista_id' => 'nullable|exists:mailing_liste,id',
|
||||
'lista_id' => 'nullable|exists:mailing_lists,id',
|
||||
'destinatari_ids' => 'nullable|string',
|
||||
'documenti_selezionati' => 'nullable|string',
|
||||
'allegato' => 'nullable|file|max:10240',
|
||||
'mittente_id' => 'nullable|integer|exists:sender_accounts,id',
|
||||
'firma_id' => 'nullable|integer|exists:firme,id',
|
||||
]);
|
||||
|
||||
$sender = null;
|
||||
if (!empty($data['mittente_id'])) {
|
||||
$sender = SenderAccount::findOrFail($data['mittente_id']);
|
||||
} elseif (!empty($data['lista_id'])) {
|
||||
$lista = MailingList::with('senderAccount')->find($data['lista_id']);
|
||||
if ($lista && $lista->senderAccount) {
|
||||
$sender = $lista->senderAccount;
|
||||
}
|
||||
}
|
||||
|
||||
$documentiAllegati = [];
|
||||
@@ -112,6 +122,20 @@ class MailingController extends Controller
|
||||
|
||||
$attachmentPaths = $this->resolveMailingAttachmentPaths($documentiAllegati);
|
||||
|
||||
$firmaId = $data['firma_id'] ?? null;
|
||||
if (!$firmaId && !empty($data['lista_id'])) {
|
||||
$lista = MailingList::with('firma')->find($data['lista_id']);
|
||||
$firmaId = $lista?->firma?->id;
|
||||
}
|
||||
|
||||
$corpoConFirma = $data['corpo'];
|
||||
if ($firmaId) {
|
||||
$firma = Firma::find($firmaId);
|
||||
if ($firma && $firma->contenuto_html) {
|
||||
$corpoConFirma .= "\n\n---\n" . $firma->contenuto_html;
|
||||
}
|
||||
}
|
||||
|
||||
$messaggio = MailingMessaggio::create([
|
||||
'mailing_list_id' => $data['lista_id'] ?? null,
|
||||
'user_id' => auth()->id(),
|
||||
@@ -121,6 +145,7 @@ class MailingController extends Controller
|
||||
'totale_destinatari' => $emails->count(),
|
||||
'mittente_nome' => $sender?->email_name,
|
||||
'mittente_email' => $sender?->email_address,
|
||||
'firma_id' => $firmaId,
|
||||
]);
|
||||
|
||||
$ok = 0;
|
||||
@@ -130,9 +155,9 @@ class MailingController extends Controller
|
||||
foreach ($emails as $email) {
|
||||
try {
|
||||
if ($sender) {
|
||||
$sender->sendEmail($email, $data['oggetto'], $data['corpo'], $attachmentPaths);
|
||||
$sender->sendEmail($email, $data['oggetto'], $corpoConFirma, $attachmentPaths);
|
||||
} else {
|
||||
$this->sendViaSystem($email, $data['oggetto'], $data['corpo'], $attachmentPaths);
|
||||
$this->sendViaSystem($email, $data['oggetto'], $corpoConFirma, $attachmentPaths);
|
||||
}
|
||||
$ok++;
|
||||
} catch (\Throwable $e) {
|
||||
@@ -181,11 +206,13 @@ class MailingController extends Controller
|
||||
public function invio(Request $request)
|
||||
{
|
||||
$this->authorizeWrite('mailing');
|
||||
$liste = MailingList::where('attiva', true)->orderBy('nome')->get();
|
||||
$liste = MailingList::with('firma')->where('attiva', true)->orderBy('nome')->get();
|
||||
$documenti = Documento::orderBy('nome_file')->get();
|
||||
$senderAccounts = SenderAccount::active()->get();
|
||||
$settings = EmailSetting::getActive();
|
||||
$firme = $settings?->firme ?? collect();
|
||||
|
||||
return view('mailing.invio', compact('liste', 'documenti', 'senderAccounts'));
|
||||
return view('mailing.invio', compact('liste', 'documenti', 'senderAccounts', 'firme'));
|
||||
}
|
||||
|
||||
public function invioElabora(Request $request)
|
||||
@@ -193,18 +220,23 @@ class MailingController extends Controller
|
||||
$this->authorizeWrite('mailing');
|
||||
$data = $request->validate([
|
||||
'liste' => 'required|array',
|
||||
'liste.*' => 'exists:mailing_liste,id',
|
||||
'liste.*' => 'exists:mailing_lists,id',
|
||||
'oggetto' => 'required|string|max:255',
|
||||
'corpo' => 'required',
|
||||
'documenti_selezionati' => 'nullable|array',
|
||||
'documenti_selezionati.*' => 'exists:documenti,id',
|
||||
'allegato' => 'nullable|file|max:10240',
|
||||
'mittente_id' => 'nullable|integer|exists:sender_accounts,id',
|
||||
'firma_id' => 'nullable|integer|exists:firme,id',
|
||||
]);
|
||||
|
||||
$listeModels = MailingList::with('firma', 'senderAccount')->whereIn('id', $data['liste'])->get();
|
||||
|
||||
$sender = null;
|
||||
if (!empty($data['mittente_id'])) {
|
||||
$sender = SenderAccount::findOrFail($data['mittente_id']);
|
||||
} elseif ($listeModels->count() === 1) {
|
||||
$sender = $listeModels->first()->senderAccount;
|
||||
}
|
||||
|
||||
$documentiAllegati = [];
|
||||
@@ -254,7 +286,20 @@ class MailingController extends Controller
|
||||
|
||||
$attachmentPaths = $this->resolveMailingAttachmentPaths($documentiAllegati);
|
||||
|
||||
$listeNomi = MailingList::whereIn('id', $data['liste'])->pluck('nome')->implode(', ');
|
||||
$firmaId = $data['firma_id'] ?? null;
|
||||
if (!$firmaId && $listeModels->count() === 1) {
|
||||
$firmaId = $listeModels->first()->firma_id;
|
||||
}
|
||||
|
||||
$corpoConFirma = $data['corpo'];
|
||||
if ($firmaId) {
|
||||
$firma = Firma::find($firmaId);
|
||||
if ($firma && $firma->contenuto_html) {
|
||||
$corpoConFirma .= "\n\n---\n" . $firma->contenuto_html;
|
||||
}
|
||||
}
|
||||
|
||||
$listeNomi = $listeModels->pluck('nome')->implode(', ');
|
||||
|
||||
$messaggio = MailingMessaggio::create([
|
||||
'mailing_list_id' => null,
|
||||
@@ -265,6 +310,7 @@ class MailingController extends Controller
|
||||
'totale_destinatari' => $emails->count(),
|
||||
'mittente_nome' => $sender?->email_name,
|
||||
'mittente_email' => $sender?->email_address,
|
||||
'firma_id' => $firmaId,
|
||||
]);
|
||||
|
||||
$ok = 0;
|
||||
@@ -274,9 +320,9 @@ class MailingController extends Controller
|
||||
foreach ($emails as $email) {
|
||||
try {
|
||||
if ($sender) {
|
||||
$sender->sendEmail($email, $data['oggetto'], $data['corpo'], $attachmentPaths);
|
||||
$sender->sendEmail($email, $data['oggetto'], $corpoConFirma, $attachmentPaths);
|
||||
} else {
|
||||
$this->sendViaSystem($email, $data['oggetto'], $data['corpo'], $attachmentPaths);
|
||||
$this->sendViaSystem($email, $data['oggetto'], $corpoConFirma, $attachmentPaths);
|
||||
}
|
||||
$ok++;
|
||||
} catch (\Throwable $e) {
|
||||
@@ -347,18 +393,10 @@ class MailingController extends Controller
|
||||
$transport = \Symfony\Component\Mailer\Transport::fromDsn($dsn);
|
||||
$mailer = new \Symfony\Component\Mailer\Mailer($transport);
|
||||
|
||||
$fromName = $settings->email_name ?? '';
|
||||
if (filter_var($fromName, FILTER_VALIDATE_EMAIL)) {
|
||||
$fromName = 'Glastree';
|
||||
} else {
|
||||
$fromName = preg_replace('/[^\p{L}\p{N}\s]/u', '', $fromName);
|
||||
$fromName = trim($fromName);
|
||||
if (empty($fromName) || strlen($fromName) > 50) {
|
||||
$fromName = 'Glastree';
|
||||
}
|
||||
}
|
||||
|
||||
$fromAddress = \Symfony\Component\Mime\Address::create($settings->email_address, $fromName);
|
||||
$fromAddress = \Symfony\Component\Mime\Address::create(
|
||||
$settings->getEffectiveFromAddress(),
|
||||
$settings->getEffectiveFromName()
|
||||
);
|
||||
|
||||
$email = (new \Symfony\Component\Mime\Email())
|
||||
->from($fromAddress)
|
||||
@@ -366,6 +404,11 @@ class MailingController extends Controller
|
||||
->subject($subject)
|
||||
->text($body);
|
||||
|
||||
$replyTo = $settings->getEffectiveReplyTo();
|
||||
if ($replyTo) {
|
||||
$email->replyTo($replyTo);
|
||||
}
|
||||
|
||||
foreach ($attachmentPaths as $path) {
|
||||
$email->attachFromPath($path);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\MailingList;
|
||||
use App\Models\SenderAccount;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -60,7 +61,10 @@ class MailingListController extends Controller
|
||||
{
|
||||
$this->authorizeWrite('mailing');
|
||||
$tags = Tag::orderBy('name')->get();
|
||||
return view('mailing-liste.create', compact('tags'));
|
||||
$settings = \App\Models\EmailSetting::getActive();
|
||||
$firme = $settings?->firme ?? collect();
|
||||
$senderAccounts = SenderAccount::active()->get();
|
||||
return view('mailing-liste.create', compact('tags', 'firme', 'senderAccounts'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
@@ -73,6 +77,8 @@ class MailingListController extends Controller
|
||||
'contatti_json' => 'nullable|string',
|
||||
'tags' => 'nullable|array',
|
||||
'tags.*' => 'exists:tags,id',
|
||||
'firma_id' => 'nullable|integer|exists:firme,id',
|
||||
'sender_account_id' => 'nullable|integer|exists:sender_accounts,id',
|
||||
]);
|
||||
|
||||
$data['user_id'] = auth()->id();
|
||||
@@ -83,6 +89,8 @@ class MailingListController extends Controller
|
||||
'descrizione' => $data['descrizione'] ?? null,
|
||||
'attiva' => $data['attiva'],
|
||||
'user_id' => $data['user_id'],
|
||||
'firma_id' => $data['firma_id'] ?? null,
|
||||
'sender_account_id' => $data['sender_account_id'] ?? null,
|
||||
]);
|
||||
|
||||
if ($request->has('tags')) {
|
||||
@@ -117,10 +125,13 @@ class MailingListController extends Controller
|
||||
public function edit($mailingList)
|
||||
{
|
||||
$this->authorizeWrite('mailing');
|
||||
$mailingList = MailingList::with(['contatti.individuo.contatti', 'tags'])->findOrFail($mailingList);
|
||||
$mailingList = MailingList::with(['contatti.individuo.contatti', 'tags', 'firma', 'senderAccount'])->findOrFail($mailingList);
|
||||
$tags = Tag::orderBy('name')->get();
|
||||
$selectedTags = $mailingList->tags->pluck('id')->toArray();
|
||||
return view('mailing-liste.edit', compact('mailingList', 'tags', 'selectedTags'));
|
||||
$settings = \App\Models\EmailSetting::getActive();
|
||||
$firme = $settings?->firme ?? collect();
|
||||
$senderAccounts = SenderAccount::active()->get();
|
||||
return view('mailing-liste.edit', compact('mailingList', 'tags', 'selectedTags', 'firme', 'senderAccounts'));
|
||||
}
|
||||
|
||||
public function update(Request $request, $mailingList)
|
||||
@@ -135,6 +146,8 @@ class MailingListController extends Controller
|
||||
'contatti_json' => 'nullable|string',
|
||||
'tags' => 'nullable|array',
|
||||
'tags.*' => 'exists:tags,id',
|
||||
'firma_id' => 'nullable|integer|exists:firme,id',
|
||||
'sender_account_id' => 'nullable|integer|exists:sender_accounts,id',
|
||||
]);
|
||||
|
||||
$data['attiva'] = $data['attiva'] ?? false;
|
||||
@@ -143,6 +156,8 @@ class MailingListController extends Controller
|
||||
'nome' => $data['nome'],
|
||||
'descrizione' => $data['descrizione'] ?? null,
|
||||
'attiva' => $data['attiva'],
|
||||
'firma_id' => $data['firma_id'] ?? null,
|
||||
'sender_account_id' => $data['sender_account_id'] ?? null,
|
||||
]);
|
||||
|
||||
if ($request->has('tags')) {
|
||||
|
||||
@@ -515,7 +515,7 @@ class ReportController extends Controller
|
||||
$rows[] = [
|
||||
'livello' => 0,
|
||||
'nome' => $gruppo->nome,
|
||||
'diocesi' => $gruppo->diocesi?->nome ?? '-',
|
||||
'diocesi' => $gruppo->diocesi->count() > 0 ? $gruppo->diocesi->pluck('nome')->implode(', ') : '-',
|
||||
'membri' => $gruppo->individui()->count(),
|
||||
'padre' => '-',
|
||||
];
|
||||
@@ -538,7 +538,7 @@ class ReportController extends Controller
|
||||
$rows[] = [
|
||||
'livello' => $level,
|
||||
'nome' => str_repeat(' ', $level) . $child->nome,
|
||||
'diocesi' => $child->diocesi?->nome ?? '-',
|
||||
'diocesi' => $child->diocesi->count() > 0 ? $child->diocesi->pluck('nome')->implode(', ') : '-',
|
||||
'membri' => $child->individui()->count(),
|
||||
'padre' => $parent?->nome ?? '-',
|
||||
];
|
||||
@@ -554,7 +554,7 @@ class ReportController extends Controller
|
||||
$parent = $g->parent;
|
||||
return [
|
||||
'nome' => $g->full_path,
|
||||
'diocesi' => $g->diocesi?->nome ?? '-',
|
||||
'diocesi' => $g->diocesi->count() > 0 ? $g->diocesi->pluck('nome')->implode(', ') : '-',
|
||||
'membri' => $g->individui_count,
|
||||
'padre' => $parent?->nome ?? '-',
|
||||
'responsabili' => $g->getResponsabili()->pluck('cognome')->implode(', ') ?: '-',
|
||||
@@ -895,7 +895,7 @@ class ReportController extends Controller
|
||||
return [
|
||||
'nome' => $g->nome,
|
||||
'descrizione' => $g->descrizione ?? '-',
|
||||
'diocesi' => $g->diocesi?->nome ?? '-',
|
||||
'diocesi' => $g->diocesi->count() > 0 ? $g->diocesi->pluck('nome')->implode(', ') : '-',
|
||||
'livello' => $g->parent_id ? (count($g->getAncestors()) + 1) : 0,
|
||||
'membri' => $g->individui_count,
|
||||
'padre' => $parent?->nome ?? '-',
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class Diocesi extends Model
|
||||
{
|
||||
protected $table = 'diocesi';
|
||||
protected $fillable = ['nome', 'regione'];
|
||||
|
||||
public function gruppi(): HasMany
|
||||
public function gruppi(): BelongsToMany
|
||||
{
|
||||
return $this->hasMany(Gruppo::class);
|
||||
return $this->belongsToMany(Gruppo::class, 'diocesi_gruppo');
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,8 @@ class EmailSetting extends Model
|
||||
protected $fillable = [
|
||||
'imap_host', 'imap_port', 'imap_encryption', 'imap_username', 'imap_password',
|
||||
'smtp_host', 'smtp_port', 'smtp_encryption', 'smtp_username', 'smtp_password',
|
||||
'email_address', 'email_name', 'reply_to', 'sync_interval_minutes',
|
||||
'email_address', 'email_name', 'from_email', 'from_name', 'reply_to',
|
||||
'sync_interval_minutes',
|
||||
'last_sync_at', 'is_active', 'signature', 'signature_enabled',
|
||||
'auth_method', 'google_oauth_connection_id',
|
||||
];
|
||||
@@ -247,4 +248,38 @@ class EmailSetting extends Model
|
||||
{
|
||||
return $this->signature;
|
||||
}
|
||||
|
||||
public function getEffectiveFromAddress(): string
|
||||
{
|
||||
return $this->from_email ?: $this->email_address;
|
||||
}
|
||||
|
||||
public function getEffectiveFromName(): string
|
||||
{
|
||||
$name = $this->from_name ?: $this->email_name;
|
||||
if (filter_var($name, FILTER_VALIDATE_EMAIL)) {
|
||||
return 'Glastree';
|
||||
}
|
||||
$name = preg_replace('/[^\p{L}\p{N}\s]/u', '', $name);
|
||||
$name = trim($name);
|
||||
return empty($name) ? 'Glastree' : $name;
|
||||
}
|
||||
|
||||
public function getEffectiveReplyTo(): ?string
|
||||
{
|
||||
if ($this->from_email) {
|
||||
return $this->from_email;
|
||||
}
|
||||
return $this->reply_to ?: null;
|
||||
}
|
||||
|
||||
public function firme(): HasMany
|
||||
{
|
||||
return $this->hasMany(Firma::class);
|
||||
}
|
||||
|
||||
public function firmaPredefinita(): ?Firma
|
||||
{
|
||||
return $this->firme()->where('is_default', true)->first() ?? $this->firme()->first();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Firma extends Model
|
||||
{
|
||||
protected $table = 'firme';
|
||||
|
||||
protected $fillable = [
|
||||
'email_setting_id',
|
||||
'nome',
|
||||
'contenuto_html',
|
||||
'is_default',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_default' => 'boolean',
|
||||
];
|
||||
|
||||
public function emailSetting(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(EmailSetting::class);
|
||||
}
|
||||
}
|
||||
+21
-2
@@ -24,6 +24,8 @@ class Gruppo extends Model
|
||||
'responsabile_ids' => 'array',
|
||||
];
|
||||
|
||||
protected $appends = ['email_primaria', 'telefono_primario'];
|
||||
|
||||
public function tenant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Tenant::class);
|
||||
@@ -39,9 +41,14 @@ class Gruppo extends Model
|
||||
return $this->hasMany(Gruppo::class, 'parent_id');
|
||||
}
|
||||
|
||||
public function diocesi(): BelongsTo
|
||||
public function diocesi(): BelongsToMany
|
||||
{
|
||||
return $this->belongsTo(Diocesi::class);
|
||||
return $this->belongsToMany(Diocesi::class, 'diocesi_gruppo');
|
||||
}
|
||||
|
||||
public function gruppoContatti(): HasMany
|
||||
{
|
||||
return $this->hasMany(GruppoContatto::class, 'gruppo_id');
|
||||
}
|
||||
|
||||
public function individui(): BelongsToMany
|
||||
@@ -66,6 +73,18 @@ class Gruppo extends Model
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getEmailPrimariaAttribute(): ?string
|
||||
{
|
||||
return $this->gruppoContatti()->where('tipo', 'email')->where('is_primary', true)->first()?->valore
|
||||
?? $this->gruppoContatti()->where('tipo', 'email')->first()?->valore;
|
||||
}
|
||||
|
||||
public function getTelefonoPrimarioAttribute(): ?string
|
||||
{
|
||||
return $this->gruppoContatti()->whereIn('tipo', ['telefono', 'cellulare'])->where('is_primary', true)->first()?->valore
|
||||
?? $this->gruppoContatti()->whereIn('tipo', ['telefono', 'cellulare'])->first()?->valore;
|
||||
}
|
||||
|
||||
public function getResponsabili()
|
||||
{
|
||||
if (empty($this->responsabile_ids)) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class GruppoContatto extends Model
|
||||
{
|
||||
protected $table = 'gruppo_contatti';
|
||||
protected $fillable = ['gruppo_id', 'tipo', 'valore', 'etichetta', 'is_primary'];
|
||||
|
||||
protected $casts = [
|
||||
'is_primary' => 'boolean',
|
||||
];
|
||||
|
||||
public function gruppo(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Gruppo::class);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ class MailingList extends Model
|
||||
use HasTagsLight;
|
||||
|
||||
protected $table = 'mailing_lists';
|
||||
protected $fillable = ['tenant_id', 'user_id', 'nome', 'descrizione', 'attiva'];
|
||||
protected $fillable = ['tenant_id', 'user_id', 'nome', 'descrizione', 'attiva', 'firma_id', 'sender_account_id'];
|
||||
|
||||
protected $casts = ['attiva' => 'boolean'];
|
||||
|
||||
@@ -36,6 +36,16 @@ class MailingList extends Model
|
||||
return $this->hasMany(MailingMessaggio::class);
|
||||
}
|
||||
|
||||
public function firma(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Firma::class);
|
||||
}
|
||||
|
||||
public function senderAccount(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(SenderAccount::class);
|
||||
}
|
||||
|
||||
public function getIndividui()
|
||||
{
|
||||
return Individuo::whereHas('mailingContacts', function ($q) {
|
||||
|
||||
@@ -11,7 +11,7 @@ class MailingMessaggio extends Model
|
||||
protected $fillable = [
|
||||
'tenant_id', 'mailing_list_id', 'user_id', 'oggetto', 'corpo',
|
||||
'canale', 'stato', 'inviato_al', 'totale_destinatari', 'invii_ok', 'invii_falliti',
|
||||
'log_falliti', 'mittente_nome', 'mittente_email',
|
||||
'log_falliti', 'mittente_nome', 'mittente_email', 'firma_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
||||
+5
-4
@@ -197,12 +197,13 @@ class User extends Authenticatable implements CanResetPasswordContract
|
||||
|
||||
$resetUrl = url('/password/reset/' . $token);
|
||||
|
||||
$fromName = $settings->email_name ?? config('app.name');
|
||||
$fromName = preg_replace('/[^\p{L}\p{N}\s]/u', '', $fromName);
|
||||
$fromName = trim($fromName) ?: config('app.name');
|
||||
$fromAddress = new Address(
|
||||
$settings->getEffectiveFromAddress(),
|
||||
$settings->getEffectiveFromName()
|
||||
);
|
||||
|
||||
$email = (new Email())
|
||||
->from(new Address($settings->email_address, $fromName))
|
||||
->from($fromAddress)
|
||||
->to($this->email)
|
||||
->subject('Reset della password - ' . config('app.name'))
|
||||
->html(view('auth.emails.reset-password', [
|
||||
|
||||
@@ -60,7 +60,7 @@ class BackupService
|
||||
return $backups;
|
||||
}
|
||||
|
||||
public function run(): array
|
||||
public function run(array $options = []): array
|
||||
{
|
||||
$result = ['success' => true, 'message' => '', 'filename' => ''];
|
||||
|
||||
@@ -74,12 +74,28 @@ class BackupService
|
||||
$filename = $appName . '_' . $timestamp . '.zip';
|
||||
$filepath = $this->backupDir . '/' . $filename;
|
||||
|
||||
$includeFiles = $options['include_files'] ?? (bool) AppSetting::getSetting('backup_include_files', true);
|
||||
$includeEnv = $options['include_env'] ?? (bool) AppSetting::getSetting('backup_include_env', true);
|
||||
|
||||
$steps = [];
|
||||
$includedComponents = [];
|
||||
|
||||
$steps[] = $this->backupDatabase();
|
||||
$steps[] = $this->backupEnv();
|
||||
$steps[] = $this->backupFiles();
|
||||
$this->writeManifest($timestamp);
|
||||
$includedComponents[] = 'database';
|
||||
|
||||
$stepEnv = $this->backupEnv($includeEnv);
|
||||
$steps[] = $stepEnv;
|
||||
if ($includeEnv) {
|
||||
$includedComponents[] = 'env';
|
||||
}
|
||||
|
||||
$stepFiles = $this->backupFiles($includeFiles);
|
||||
$steps[] = $stepFiles;
|
||||
if ($includeFiles) {
|
||||
$includedComponents[] = 'files';
|
||||
}
|
||||
|
||||
$this->writeManifest($timestamp, $includedComponents);
|
||||
|
||||
$zipResult = $this->createZip($filepath);
|
||||
if (!$zipResult) {
|
||||
@@ -90,7 +106,7 @@ class BackupService
|
||||
|
||||
$size = file_exists($filepath) ? filesize($filepath) : 0;
|
||||
|
||||
Log::info("Backup completato: {$filename} (" . $this->formatBytes($size) . ")");
|
||||
Log::info("Backup completato: {$filename} (" . $this->formatBytes($size) . ')');
|
||||
|
||||
$this->cleanupOldBackups();
|
||||
|
||||
@@ -100,6 +116,7 @@ class BackupService
|
||||
'filename' => $filename,
|
||||
'size' => $size,
|
||||
'size_formatted' => $this->formatBytes($size),
|
||||
'steps' => $steps,
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
$this->cleanTemp();
|
||||
@@ -109,6 +126,7 @@ class BackupService
|
||||
'success' => false,
|
||||
'message' => 'Backup fallito: ' . $e->getMessage(),
|
||||
'filename' => '',
|
||||
'steps' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -181,9 +199,9 @@ class BackupService
|
||||
return 'database.sql (' . $this->formatBytes(filesize($sqlFile)) . ')';
|
||||
}
|
||||
|
||||
private function backupEnv(): string
|
||||
private function backupEnv(bool $includeEnv = true): string
|
||||
{
|
||||
if (!AppSetting::getSetting('backup_include_env', true)) {
|
||||
if (!$includeEnv) {
|
||||
return '.env (escluso)';
|
||||
}
|
||||
|
||||
@@ -200,9 +218,9 @@ class BackupService
|
||||
return '.env copiato';
|
||||
}
|
||||
|
||||
private function backupFiles(): string
|
||||
private function backupFiles(bool $includeFiles = true): string
|
||||
{
|
||||
if (!AppSetting::getSetting('backup_include_files', true)) {
|
||||
if (!$includeFiles) {
|
||||
return 'files (esclusi)';
|
||||
}
|
||||
|
||||
@@ -220,7 +238,7 @@ class BackupService
|
||||
return 'files copiati';
|
||||
}
|
||||
|
||||
private function writeManifest(string $timestamp): void
|
||||
private function writeManifest(string $timestamp, array $includedComponents = ['database']): void
|
||||
{
|
||||
$manifest = [
|
||||
'created_at' => $timestamp,
|
||||
@@ -230,6 +248,7 @@ class BackupService
|
||||
'db_name' => config('database.connections.mysql.database'),
|
||||
'php_version' => PHP_VERSION,
|
||||
'laravel_version' => app()->version(),
|
||||
'included_components' => $includedComponents,
|
||||
];
|
||||
|
||||
File::put($this->tempDir . '/manifest.json', json_encode($manifest, JSON_PRETTY_PRINT));
|
||||
|
||||
Reference in New Issue
Block a user