154 lines
5.7 KiB
PHP
154 lines
5.7 KiB
PHP
<?php
|
|
|
|
namespace MintyPHP\Service\Mail;
|
|
|
|
use MintyPHP\Repository\Mail\MailLogRepository;
|
|
use MintyPHP\I18n;
|
|
use MintyPHP\Service\Settings\SettingService;
|
|
use PHPMailer\PHPMailer\PHPMailer;
|
|
use PHPMailer\PHPMailer\Exception as MailerException;
|
|
|
|
class MailService
|
|
{
|
|
public static function sendTemplate(
|
|
string $template,
|
|
array $vars,
|
|
string $to,
|
|
string $subject,
|
|
?string $locale = null
|
|
): array {
|
|
$locale = $locale ?: (I18n::$locale ?? I18n::$defaultLocale);
|
|
[$html, $text] = self::renderTemplate($template, $vars, $locale);
|
|
|
|
return self::send($to, $subject, $html, $text, [
|
|
'template' => $template,
|
|
]);
|
|
}
|
|
|
|
public static function send(
|
|
string $to,
|
|
string $subject,
|
|
string $html,
|
|
string $text,
|
|
array $meta = []
|
|
): array {
|
|
$logId = MailLogRepository::create([
|
|
'to_email' => $to,
|
|
'subject' => $subject,
|
|
'template' => $meta['template'] ?? null,
|
|
'status' => 'queued',
|
|
]);
|
|
|
|
if (!class_exists(PHPMailer::class)) {
|
|
if ($logId) {
|
|
MailLogRepository::markFailed($logId, 'PHPMailer is not installed');
|
|
}
|
|
return ['ok' => false, 'error' => 'mailer_missing'];
|
|
}
|
|
|
|
try {
|
|
$mailer = self::createMailer();
|
|
$mailer->addAddress($to);
|
|
$mailer->Subject = $subject;
|
|
$mailer->Body = $html;
|
|
$mailer->AltBody = $text;
|
|
$mailer->isHTML(true);
|
|
$mailer->send();
|
|
|
|
if ($logId) {
|
|
MailLogRepository::markSent($logId, $mailer->getLastMessageID() ?: null);
|
|
}
|
|
return ['ok' => true];
|
|
} catch (MailerException $e) {
|
|
if ($logId) {
|
|
MailLogRepository::markFailed($logId, $e->getMessage());
|
|
}
|
|
return ['ok' => false, 'error' => 'send_failed'];
|
|
}
|
|
}
|
|
|
|
private static function renderTemplate(string $template, array $vars, string $locale): array
|
|
{
|
|
$base = dirname(__DIR__, 3) . '/templates/emails';
|
|
$htmlPath = $base . '/' . $locale . '/' . $template . '.html';
|
|
$textPath = $base . '/' . $locale . '/' . $template . '.txt';
|
|
$htmlHeaderPath = $base . '/' . $locale . '/partials/header.html';
|
|
$htmlFooterPath = $base . '/' . $locale . '/partials/footer.html';
|
|
$textHeaderPath = $base . '/' . $locale . '/partials/header.txt';
|
|
$textFooterPath = $base . '/' . $locale . '/partials/footer.txt';
|
|
|
|
if (!is_file($htmlPath)) {
|
|
$htmlPath = $base . '/' . $template . '.html';
|
|
}
|
|
if (!is_file($textPath)) {
|
|
$textPath = $base . '/' . $template . '.txt';
|
|
}
|
|
if (!is_file($htmlHeaderPath)) {
|
|
$htmlHeaderPath = $base . '/partials/header.html';
|
|
}
|
|
if (!is_file($htmlFooterPath)) {
|
|
$htmlFooterPath = $base . '/partials/footer.html';
|
|
}
|
|
if (!is_file($textHeaderPath)) {
|
|
$textHeaderPath = $base . '/partials/header.txt';
|
|
}
|
|
if (!is_file($textFooterPath)) {
|
|
$textFooterPath = $base . '/partials/footer.txt';
|
|
}
|
|
|
|
$html = is_file($htmlPath) ? file_get_contents($htmlPath) : '';
|
|
$text = is_file($textPath) ? file_get_contents($textPath) : '';
|
|
if (!isset($vars['email_header'])) {
|
|
$vars['email_header'] = is_file($htmlHeaderPath) ? file_get_contents($htmlHeaderPath) : '';
|
|
}
|
|
if (!isset($vars['email_footer'])) {
|
|
$vars['email_footer'] = is_file($htmlFooterPath) ? file_get_contents($htmlFooterPath) : '';
|
|
}
|
|
if (!isset($vars['email_header_text'])) {
|
|
$vars['email_header_text'] = is_file($textHeaderPath) ? file_get_contents($textHeaderPath) : '';
|
|
}
|
|
if (!isset($vars['email_footer_text'])) {
|
|
$vars['email_footer_text'] = is_file($textFooterPath) ? file_get_contents($textFooterPath) : '';
|
|
}
|
|
|
|
foreach ($vars as $key => $value) {
|
|
$placeholder = '{{' . $key . '}}';
|
|
$html = str_replace($placeholder, (string) $value, $html);
|
|
$text = str_replace($placeholder, (string) $value, $text);
|
|
}
|
|
// Second pass to resolve placeholders inside injected header/footer content.
|
|
foreach ($vars as $key => $value) {
|
|
$placeholder = '{{' . $key . '}}';
|
|
$html = str_replace($placeholder, (string) $value, $html);
|
|
$text = str_replace($placeholder, (string) $value, $text);
|
|
}
|
|
|
|
return [$html, $text];
|
|
}
|
|
|
|
private static function createMailer(): PHPMailer
|
|
{
|
|
$mailer = new PHPMailer(true);
|
|
$mailer->isSMTP();
|
|
$host = SettingService::getSmtpHost() ?? (getenv('SMTP_HOST') ?: '');
|
|
$port = SettingService::getSmtpPort() ?? (int) (getenv('SMTP_PORT') ?: 587);
|
|
$user = SettingService::getSmtpUser() ?? (getenv('SMTP_USER') ?: '');
|
|
$pass = SettingService::getSmtpPassword() ?? (getenv('SMTP_PASS') ?: '');
|
|
$secure = SettingService::getSmtpSecure() ?? strtolower((string) (getenv('SMTP_SECURE') ?: 'tls'));
|
|
$from = SettingService::getSmtpFrom() ?? (getenv('SMTP_FROM') ?: ($user ?: 'no-reply@localhost'));
|
|
$fromName = SettingService::getSmtpFromName() ?? (getenv('SMTP_FROM_NAME') ?: appTitle());
|
|
|
|
$mailer->Host = $host;
|
|
$mailer->Port = $port;
|
|
$mailer->SMTPAuth = $user !== '' || $pass !== '';
|
|
$mailer->Username = $user;
|
|
$mailer->Password = $pass;
|
|
if (in_array($secure, ['tls', 'ssl'], true)) {
|
|
$mailer->SMTPSecure = $secure;
|
|
}
|
|
$mailer->setFrom($from, $fromName);
|
|
$mailer->CharSet = 'UTF-8';
|
|
return $mailer;
|
|
}
|
|
}
|