mailFactory = $mailFactory ?? app(MailFactory::class); } public function forTenant(string $tenantCode): self { parent::forTenant($tenantCode); $this->tenant = Tenant::query() ->where('codigo', $tenantCode) ->firstOrFail(); if ($this->tenantIntegration) { $this->mailer = $this->resolveMailer(); $this->usesTenantMailer = true; } else { $this->mailer = $this->mailFactory->mailer(); $this->usesTenantMailer = false; } return $this; } public function getHeaders(): array { return []; } public function send(string|array $recipient, string $subject, string $content): void { if (! $this->mailer || ! $this->tenant) { throw new Exception('MailService no está configurado. Llamá a forTenant() primero.'); } $this->tenant->loadMissing(['headerLogo', 'footerLogo']); $html = Blade::render( <<<'BLADE' {!! $content !!} BLADE, [ 'tenant' => $this->tenant, 'headerLogoUrl' => $this->tenant->headerLogo?->getTemporaryUrl(1440), 'footerLogoUrl' => $this->tenant->footerLogo?->getTemporaryUrl(1440), 'content' => $content, ], ); $mail = (new Mailable) ->subject($subject) ->html($html); $this->mailer->to($recipient)->send($mail); } public function mailerName(): string { return $this->usesTenantMailer ? 'tenant-smtp' : (string) config('mail.default'); } public function onSetup(): void { if (! $this->tenant) { throw new Exception('MailService no está configurado. Llamá a forTenant() primero.'); } $recipient = $this->getIntegrationSetting('MAIL_FROM_ADDRESS'); if (! is_string($recipient) || $recipient === '') { throw new InvalidArgumentException('Falta MAIL_FROM_ADDRESS en la configuración SMTP del tenant.'); } $this->send( $recipient, 'Configuración de correo validada', '

Configuración de correo validada

' .'

La integración SMTP de '.e($this->tenant->nombre).' fue configurada correctamente.

' .'

Este mensaje fue enviado automáticamente para validar las credenciales de correo.

', ); } private function resolveMailer(): Mailer { $data = $this->tenantIntegration?->integration_data; if (! is_array($data)) { throw new InvalidArgumentException('La configuración SMTP del tenant no es válida.'); } foreach (self::REQUIRED_SMTP_FIELDS as $field) { if (! array_key_exists($field, $data) || $data[$field] === null || $data[$field] === '') { throw new InvalidArgumentException("Falta {$field} en la configuración SMTP del tenant."); } } // MailFake implements MailFactory but cannot build transports. if (! $this->mailFactory instanceof MailManager) { return $this->mailFactory->mailer(); } $mailer = $this->mailFactory->build([ 'name' => "tenant-smtp-{$this->tenantCode}", 'transport' => 'smtp', 'scheme' => $data['MAIL_SCHEME'] ?? null, 'host' => $data['MAIL_HOST'], 'port' => (int) $data['MAIL_PORT'], 'username' => $data['MAIL_USERNAME'], 'password' => $data['MAIL_PASSWORD'], 'timeout' => isset($data['MAIL_TIMEOUT']) ? (int) $data['MAIL_TIMEOUT'] : null, 'local_domain' => $data['MAIL_EHLO_DOMAIN'] ?? null, ]); $mailer->alwaysFrom( $data['MAIL_FROM_ADDRESS'], $data['MAIL_FROM_NAME'] ?? $this->tenant?->nombre, ); return $mailer; } }