144 lines
4.4 KiB
PHP
144 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use App\Http\Services\SignRSA;
|
|
use App\Models\Setting;
|
|
use App\Support\Cache\CacheKey;
|
|
use Illuminate\Mail\MailManager;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Config;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
final class MailSettings
|
|
{
|
|
private const TTL_SECONDS = 3600;
|
|
|
|
private const NON_DELIVERING_MAILERS = ['array', 'log'];
|
|
|
|
public static function cacheKey(): string
|
|
{
|
|
return CacheKey::build('settings', 'smtp');
|
|
}
|
|
|
|
public static function apply(): void
|
|
{
|
|
$settings = self::resolve();
|
|
if ($settings === null) {
|
|
return;
|
|
}
|
|
|
|
$config = config('mail');
|
|
if (!in_array($config['default'], self::NON_DELIVERING_MAILERS, true)) {
|
|
$config['default'] = $settings['transport'];
|
|
}
|
|
$config['from'] = [
|
|
'address' => $settings['from_address'] ?: ($config['from']['address'] ?? null) ?: 'no-reply@example.com',
|
|
'name' => $settings['from_name'],
|
|
];
|
|
$config['mailers'][$settings['transport']] = array_merge(
|
|
$config['mailers'][$settings['transport']] ?? [],
|
|
$settings['mailer'],
|
|
);
|
|
|
|
Config::set('mail', $config);
|
|
}
|
|
|
|
public static function isConfigured(): bool
|
|
{
|
|
return filled(self::resolve()['mailer']['host'] ?? null);
|
|
}
|
|
|
|
public static function isDelivering(): bool
|
|
{
|
|
return ! in_array(config('mail.default'), self::NON_DELIVERING_MAILERS, true);
|
|
}
|
|
|
|
public static function transport(): ?string
|
|
{
|
|
return self::resolve()['transport'] ?? null;
|
|
}
|
|
|
|
/**
|
|
* @return array{cc: array<int, string>, bcc: array<int, string>}
|
|
*/
|
|
public static function recipients(): array
|
|
{
|
|
$settings = self::resolve();
|
|
|
|
return [
|
|
'cc' => $settings['cc'] ?? [],
|
|
'bcc' => $settings['bcc'] ?? [],
|
|
];
|
|
}
|
|
|
|
public static function refresh(object $mailer): void
|
|
{
|
|
self::apply();
|
|
if ($mailer instanceof MailManager) {
|
|
$mailer->forgetMailers();
|
|
}
|
|
}
|
|
|
|
private static function resolve(): ?array
|
|
{
|
|
return Cache::remember(self::cacheKey(), self::TTL_SECONDS, function () {
|
|
if (!Schema::hasTable('setting')) {
|
|
return null;
|
|
}
|
|
|
|
$mail = Setting::where('key', 'smtp')->first();
|
|
$setting = Setting::where('key', 'setting')->first();
|
|
|
|
$mail = $mail ? json_decode((string) $mail->value) : null;
|
|
if (!is_object($mail)) {
|
|
return null;
|
|
}
|
|
|
|
$company = ($setting ? json_decode((string) $setting->value)->company ?? null : null) ?: config('mail.from.name');
|
|
|
|
$password = '';
|
|
if (isset($mail->password)) {
|
|
$decrypted = (new SignRSA())->DecryptFunc($mail->password);
|
|
$password = $decrypted ?: $mail->password;
|
|
}
|
|
|
|
$transport = ($mail->transport ?? null) ?: 'smtp';
|
|
$encryption = $mail->encryption ?? null;
|
|
|
|
if ($encryption === 0 || $encryption === '0' || $encryption === 'starttls') {
|
|
$encryption = 'tls';
|
|
}
|
|
|
|
return [
|
|
'transport' => $transport,
|
|
'from_address' => ($mail->from_address ?? null) ?: ($mail->user ?? null),
|
|
'from_name' => ($mail->from_name ?? null) ?: $company,
|
|
'cc' => self::emailList($mail->cc ?? []),
|
|
'bcc' => self::emailList($mail->bcc ?? []),
|
|
'mailer' => array_filter([
|
|
'transport' => $transport,
|
|
'host' => $mail->host ?? '',
|
|
'port' => $mail->port ?? 587,
|
|
'encryption' => $encryption,
|
|
'username' => $mail->user ?? '',
|
|
'password' => $password,
|
|
], fn ($value) => $value !== null),
|
|
];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
private static function emailList(mixed $value): array
|
|
{
|
|
$emails = is_array($value) ? $value : preg_split('/[,;\s]+/', (string) $value, -1, PREG_SPLIT_NO_EMPTY);
|
|
|
|
return array_values(array_unique(array_filter(
|
|
array_map(fn ($email) => strtolower(trim((string) $email)), $emails ?: []),
|
|
fn (string $email) => filter_var($email, FILTER_VALIDATE_EMAIL) !== false,
|
|
)));
|
|
}
|
|
}
|