WizdomWeb/app/Utilities/EmailHelper.php

176 lines
5.3 KiB
PHP

<?php
/**
* File: EmailHelper.php
* Version: 2.10
* Path: /app/Utilities/EmailHelper.php
* Purpose: Low-level utility for PHPMailer configuration, rendering, and transport of outbound email.
* Project: Wizdom Networks Website
*/
namespace WizdomNetworks\WizeWeb\Utilities;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use WizdomNetworks\WizeWeb\Services\TokenService;
use WizdomNetworks\WizeWeb\Services\UnsubscribeTokenService;
class EmailHelper
{
/**
* Configures PHPMailer with environment settings.
*
* @param PHPMailer $mail
* @return void
*/
public static function configureMailer(PHPMailer $mail): void
{
$mail->isSMTP();
$mail->Host = $_ENV['SMTP_HOST'] ?? 'localhost';
$mail->Port = $_ENV['SMTP_PORT'] ?? 25;
$mail->SMTPAuth = filter_var($_ENV['SMTP_AUTH'] ?? false, FILTER_VALIDATE_BOOLEAN);
$mail->Username = $_ENV['SMTP_USER'] ?? '';
$mail->Password = $_ENV['SMTP_PASS'] ?? '';
$mail->SMTPAutoTLS = filter_var($_ENV['SMTP_AUTO_TLS'] ?? true, FILTER_VALIDATE_BOOLEAN);
$encryption = strtolower(trim($_ENV['SMTP_ENCRYPTION'] ?? ''));
if ($encryption === 'ssl') {
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
} elseif ($encryption === 'tls') {
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
} else {
$mail->SMTPSecure = '';
}
$fromEmail = $_ENV['SMTP_FROM_EMAIL'] ?? 'no-reply@localhost';
$fromName = $_ENV['SMTP_FROM_NAME'] ?? 'Wizdom Mailer';
$mail->setFrom($fromEmail, $fromName);
$mail->SMTPOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
];
}
/**
* Parses a comma-separated list of emails and returns an array of valid addresses.
*
* @param string $rawList
* @return array
*/
private static function parseRecipients(string $rawList): array
{
$emails = explode(',', $rawList);
$validEmails = [];
foreach ($emails as $email) {
$email = trim($email);
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$validEmails[] = $email;
}
}
return $validEmails;
}
/**
* Sends a basic HTML email.
*
* @param string $to
* @param string $subject
* @param string $body
* @return bool
*/
public static function send(string $to, string $subject, string $body): bool
{
try {
$mail = new PHPMailer(true);
self::configureMailer($mail);
$mail->addAddress($to);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->isHTML(true);
$mail->send();
Logger::info("Email sent successfully to $to with subject: $subject");
return true;
} catch (\Throwable $e) {
Logger::error("Email send failed to $to: " . $e->getMessage());
return false;
}
}
/**
* Sends a system-level alert email to admins using an HTML template.
*
* @param string $context
* @param string $errorMessage
* @param array|string $data
* @return void
*/
public static function alertAdmins(string $context, string $errorMessage, $data = []): void
{
$recipients = self::parseRecipients($_ENV['ADMIN_EMAILS'] ?? '');
if (empty($recipients)) {
Logger::error("EmailHelper: No valid ADMIN_EMAILS configured.");
return;
}
$htmlBody = self::renderTemplate('system_alert', [
'context' => $context,
'errorMessage' => $errorMessage,
'data' => $data
]);
foreach ($recipients as $email) {
self::send($email, "[System Alert] Error in {$context}", $htmlBody);
}
}
/**
* Renders an email template with dynamic variables.
*
* @param string $templateName
* @param array $vars
* @return string
*/
public static function renderTemplate(string $templateName, array $vars = []): string
{
try {
$templatePath = __DIR__ . '/../../resources/views/emails/' . $templateName . '.php';
if (!file_exists($templatePath)) {
throw new \Exception("Template not found: $templateName");
}
extract($vars);
ob_start();
include $templatePath;
return ob_get_clean();
} catch (\Throwable $e) {
Logger::error("Failed to render email template: $templateName - " . $e->getMessage());
ErrorHandler::exception($e);
return '';
}
}
/**
* Generate a secure unsubscribe link for a subscriber email.
*
* @param string $email
* @return string
*/
public static function buildUnsubscribeLink(string $email): string
{
$ts = time();
$tokenService = new TokenService();
$unsubscribeTokenService = new UnsubscribeTokenService($tokenService);
$sig = $unsubscribeTokenService->generate($email, $ts);
return $_ENV['APP_URL'] . "/unsubscribe?email=" . urlencode($email) . "&ts=$ts&sig=$sig";
}
}