From 0e12d7489fe10c5781fe65cb2a19d185f12eb7a5 Mon Sep 17 00:00:00 2001 From: "r.mubarakzyanov" Date: Fri, 7 Aug 2026 12:27:52 +0300 Subject: [PATCH] fix enc --- public/userportal/api/_mail.php | 49 ++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/public/userportal/api/_mail.php b/public/userportal/api/_mail.php index 85c310f..fcfa122 100644 --- a/public/userportal/api/_mail.php +++ b/public/userportal/api/_mail.php @@ -12,7 +12,31 @@ function mail_env(string $key): string return ($value === 'null') ? '' : $value; } -/** Never surfaces the SMTP error to the caller: it can leak host and credentials. */ +/** + * PHPMailer compares SMTPSecure with ===, so "SSL" from .env would silently fall + * back to an unencrypted socket and hang on an implicit-TLS port. Normalise, and + * infer the usual encryption from the port when MAIL_ENCRYPTION is not set. + */ +function mail_encryption(int $port): string +{ + $enc = strtolower(mail_env('MAIL_ENCRYPTION')); + if ($enc === 'ssl' || $enc === 'tls') { + return $enc; + } + if ($enc !== '' && $enc !== 'none') { + error_log("mail: unknown MAIL_ENCRYPTION '{$enc}', falling back to the port default"); + } elseif ($enc === 'none') { + return ''; + } + + return in_array($port, [465, 2465], true) ? 'ssl' : 'tls'; +} + +/** + * Never surfaces the SMTP error to the caller: it can leak host and credentials. + * The error log gets the connection details (minus the password) instead — without + * them a failure is indistinguishable from a wrong recipient address. + */ function send_mail(string $to, string $subject, string $html): bool { if (!class_exists(PHPMailer::class)) { @@ -20,21 +44,26 @@ function send_mail(string $to, string $subject, string $html): bool return false; } + $host = mail_env('MAIL_HOST') ?: 'localhost'; + $port = (int) (mail_env('MAIL_PORT') ?: 587); + $user = mail_env('MAIL_USERNAME'); + $enc = mail_encryption($port); + $mail = new PHPMailer(true); try { $mail->isSMTP(); - $mail->Host = mail_env('MAIL_HOST') ?: 'localhost'; - $mail->Port = (int) (mail_env('MAIL_PORT') ?: 587); + $mail->Host = $host; + $mail->Port = $port; $mail->CharSet = 'UTF-8'; // Default is 300s: an unreachable SMTP would otherwise stall registration. $mail->Timeout = 10; - if ($user = mail_env('MAIL_USERNAME')) { + if ($user !== '') { $mail->SMTPAuth = true; $mail->Username = $user; $mail->Password = mail_env('MAIL_PASSWORD'); } - if ($enc = mail_env('MAIL_ENCRYPTION')) { + if ($enc !== '') { $mail->SMTPSecure = $enc; } @@ -47,9 +76,15 @@ function send_mail(string $to, string $subject, string $html): bool $mail->Subject = $subject; $mail->Body = $html; - return $mail->send(); + if ($mail->send()) { + return true; + } + error_log("mail failed to {$to} via {$enc}://{$user}@{$host}:{$port}: {$mail->ErrorInfo}"); + + return false; } catch (Throwable $e) { - error_log('mail failed: ' . $e->getMessage()); + error_log("mail failed to {$to} via {$enc}://{$user}@{$host}:{$port}: " . $e->getMessage()); + return false; } }