lastError; } public function isConfigured(): bool { return filter_var((string) config('mail.from.address'), FILTER_VALIDATE_EMAIL) !== false; } public function send( string $ownerPublicId, string $to, string $subject, string $html, ?string $text = null, ?string $replyToEmail = null, ?string $replyToName = null, ): bool { $this->lastError = null; if (! $this->isConfigured()) { $this->lastError = 'Outbound email is not configured on this Events instance.'; return false; } if (! $this->billing->canAfford($ownerPublicId, self::EMAIL_PRICE_MINOR)) { $this->lastError = 'Insufficient Ladill wallet balance. Add funds in Billing and try again.'; return false; } $reference = 'events_email:'.Str::uuid(); try { Mail::html($html, function ($message) use ($to, $subject, $text, $replyToEmail, $replyToName): void { $message->to($to) ->subject($subject) ->from( (string) config('mail.from.address'), (string) config('mail.from.name'), ); if ($replyToEmail) { $message->replyTo($replyToEmail, $replyToName ?: null); } if ($text) { $message->text($text); } }); } catch (\Throwable $e) { Log::warning('Events mail send failed', ['error' => $e->getMessage(), 'to' => $to]); $this->lastError = 'The email could not be sent. Please try again.'; return false; } if (! $this->billing->debit( $ownerPublicId, self::EMAIL_PRICE_MINOR, 'smtp', 'events_email', $reference, null, 'Events email to '.$to, )) { $this->lastError = 'Insufficient Ladill wallet balance. Add funds in Billing and try again.'; return false; } return true; } }