profiles->resolveProfile($profile); $cfg = $this->profiles->getProfileConfig($profile); if (empty($cfg['host']) || empty($cfg['user']) || $cfg['pass'] === '') { logger()->error("[mail:$profile] Missing SMTP config (host/user/pass). Check MAIL_{$this->profiles->envKeyFromProfile($profile)}_* or MAIL_DEFAULT_*/MAIL_*."); return false; } $debugEnabled = (bool) env('MAIL_DEBUG', false); $timeout = (int) env('MAIL_TIMEOUT', 15); $keepAlive = (bool) env('MAIL_KEEPALIVE', false); $verifyPeer = filter_var(env('MAIL_VERIFY_PEER', 'true'), FILTER_VALIDATE_BOOLEAN); $mail = new PHPMailer(true); try { if ($debugEnabled) { ob_start(); } $mail->isSMTP(); $mail->Host = $cfg['host']; $mail->Port = $cfg['port']; $mail->SMTPAuth = true; $mail->Username = $cfg['user']; $mail->Password = $cfg['pass']; $mail->CharSet = 'UTF-8'; $mail->Timeout = $timeout; $mail->SMTPKeepAlive = $keepAlive; $mail->SMTPAutoTLS = true; if ($cfg['encryption'] === 'ssl') { $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; } else { $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; } $mail->SMTPOptions = [ 'ssl' => [ 'verify_peer' => $verifyPeer, 'verify_peer_name' => $verifyPeer, 'allow_self_signed' => !$verifyPeer, ], ]; $mail->SMTPDebug = $debugEnabled ? 3 : 0; $mail->Debugoutput = 'error_log'; $mail->setFrom($cfg['fromEmail'], $cfg['fromName']); if (!empty($cfg['returnPath'])) { $mail->Sender = $cfg['returnPath']; } $mail->clearReplyTos(); $rtEmail = env('MAIL_DEFAULT_REPLY_TO'); $rtName = env('MAIL_DEFAULT_REPLY_TO_NAME'); if (!$rtEmail || !filter_var($rtEmail, FILTER_VALIDATE_EMAIL)) { $rtEmail = $replyToEmail ?: ($cfg['replyTo'] ?: $cfg['fromEmail']); } if (!$rtName) { $rtName = $replyToName ?: ($cfg['replyToName'] ?: $cfg['fromName']); } $rtName = $this->profiles->sanitizeReplyToName($rtName, $cfg['fromName']); if ($rtEmail) { $mail->addReplyTo($rtEmail, $rtName); } if (!empty($cfg['dkim']['domain']) && !empty($cfg['dkim']['private']) && !empty($cfg['dkim']['selector'])) { $mail->DKIM_domain = $cfg['dkim']['domain']; $mail->DKIM_private = $cfg['dkim']['private']; $mail->DKIM_selector = $cfg['dkim']['selector']; $mail->DKIM_identity = $cfg['fromEmail']; } $mail->addAddress($recipient); foreach ($attachments as $att) { if (!empty($att['path']) && is_file($att['path'])) { $mail->addAttachment($att['path'], $att['name'] ?? ''); } } $mail->isHTML(true); $mail->Subject = $subject; $mail->Body = $htmlMessage; $ok = $mail->send(); $dbg = $debugEnabled ? (ob_get_clean() ?: '') : ''; if ($ok) { logger()->info("[mail:$profile] Sent to {$recipient}, subj='{$subject}' via {$cfg['host']}:{$cfg['port']}/{$cfg['encryption']}"); return true; } logger()->error("[mail:$profile] Failed: {$mail->ErrorInfo}. Debug: {$dbg}"); return false; } catch (MailerException $e) { $dbg = $debugEnabled ? (ob_get_clean() ?: '') : ''; logger()->error("[mail:$profile] Exception: {$e->getMessage()} | PHPMailer: {$mail->ErrorInfo} | Debug: {$dbg}"); return false; } } }