Files
alrahma_sunday_school_api/app/Services/Email/EmailDispatchService.php
T
2026-06-11 11:46:12 -04:00

128 lines
4.4 KiB
PHP

<?php
namespace App\Services\Email;
use PHPMailer\PHPMailer\Exception as MailerException;
use PHPMailer\PHPMailer\PHPMailer;
class EmailDispatchService
{
public function __construct(private EmailProfileService $profiles) {}
public function send(
string $recipient,
string $subject,
string $htmlMessage,
?string $profile = null,
?string $replyToEmail = null,
?string $replyToName = null,
array $attachments = []
): bool {
$profile = $this->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;
}
}
}