mailFactory = $mailFactory ?? app(MailFactory::class); $this->emailIntegration = TenantIntegration::query() ->where('tenant_code', $this->tenant->codigo) ->where('integration_code', self::INTEGRATION_CODE) ->first(); $this->mailer = $this->resolveMailer(); } public function send(string|array $recipient, Mailable $mail): void { $this->mailer->to($recipient)->send($mail); } public function mailerName(): string { return $this->emailIntegration ? 'tenant-smtp' : (string) config('mail.default'); } private function resolveMailer(): Mailer { if (! $this->emailIntegration) { return $this->mailFactory->mailer(); } // MailFake implements the mail factory contract, but deliberately cannot // build transports. Returning it keeps normal Mail::fake() assertions useful. if (! $this->mailFactory instanceof MailManager) { return $this->mailFactory->mailer(); } $data = $this->emailIntegration->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."); } } $mailer = $this->mailFactory->build([ 'name' => "tenant-smtp-{$this->tenant->codigo}", '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; } }