getEmailSettings(); } /** * Get app settings from database */ public static function getAppSettings(): array { return self::getSettingModel()->getAppSettings(); } /** * Create and configure a PHPMailer instance with proper settings */ public static function createMailer(): PHPMailer { $emailSettings = self::getEmailSettings(); $mail = new PHPMailer(true); // Server settings $mail->isSMTP(); $mail->Host = $emailSettings['mail_host']; $mail->SMTPAuth = !empty($emailSettings['mail_username']); $mail->Username = $emailSettings['mail_username']; $mail->Password = $emailSettings['mail_password']; $mail->Port = (int)$emailSettings['mail_port']; // Configure encryption based on port $port = (int)$emailSettings['mail_port']; $encryption = $emailSettings['mail_encryption']; // Auto-detect encryption for common ports if ($port === 465) { // Port 465 typically uses SSL $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; } elseif ($port === 587) { // Port 587 typically uses TLS $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; } elseif ($port === 25 || $port === 2525) { // Port 25/2525 might use TLS or no encryption if ($encryption === 'tls') { $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; } else { $mail->SMTPSecure = ''; } } else { // Use configured encryption for other ports if ($encryption === 'ssl') { $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; } elseif ($encryption === 'tls') { $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; } else { $mail->SMTPSecure = ''; } } // Configure timeouts and SSL options $mail->Timeout = 30; // 30 seconds total timeout $mail->SMTPOptions = [ 'ssl' => [ 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true ] ]; // Set character encoding $mail->CharSet = 'UTF-8'; return $mail; } /** * Send a test email */ public static function sendTestEmail(string $toEmail): array { try { $emailSettings = self::getEmailSettings(); $appSettings = self::getAppSettings(); $mail = self::createMailer(); // Always capture SMTP dialog for test emails (no env flag needed) $mail->SMTPDebug = PHPMailer::DEBUG_SERVER; // verbose for diagnostics $mail->Debugoutput = function($str, $level) { $lvlMap = [1 => 'CLIENT', 2 => 'SERVER', 3 => 'CONN', 4 => 'LOW']; $label = $lvlMap[$level] ?? (string)$level; self::getLogger()->debug('SMTP ' . $label . ': ' . trim($str)); }; // Set sender $mail->setFrom($emailSettings['mail_from_address'], $emailSettings['mail_from_name']); $mail->addAddress($toEmail); // Content $mail->isHTML(true); $mail->Subject = 'Test Email from ' . $appSettings['app_name']; $appName = htmlspecialchars($appSettings['app_name']); $appUrl = htmlspecialchars($appSettings['app_url']); $currentTime = date('F j, Y g:i A'); $mail->Body = "

✅ Email Test Successful!

Success! Your email configuration is working correctly.

This is a test email from {$appName}.

If you're seeing this message, it means your SMTP settings are configured properly and emails are being delivered successfully.

SMTP Host: " . htmlspecialchars($emailSettings['mail_host']) . "
SMTP Port: " . htmlspecialchars($emailSettings['mail_port']) . "
Encryption: " . htmlspecialchars($emailSettings['mail_encryption'] ?: 'None') . "
From Address: " . htmlspecialchars($emailSettings['mail_from_address']) . "
Test Time: {$currentTime}
"; $mail->AltBody = "Email Test Successful!\n\n" . "This is a test email from {$appName}.\n" . "Your SMTP configuration is working correctly.\n\n" . "SMTP Host: {$emailSettings['mail_host']}\n" . "SMTP Port: {$emailSettings['mail_port']}\n" . "From: {$emailSettings['mail_from_address']}\n" . "Test Time: {$currentTime}"; $mail->send(); return [ 'success' => true, 'message' => "Test email sent successfully to {$toEmail}. Please check your inbox." ]; } catch (Exception $e) { $errorMessage = "Failed to send test email: " . $e->getMessage(); $debugInfo = $mail->ErrorInfo ?? 'No debug info available'; // Log the error using the application's logger self::getLogger()->error($errorMessage, [ 'email' => $toEmail, 'smtp_error' => $debugInfo, 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => $errorMessage, 'error' => $e->getMessage(), 'debug_info' => $debugInfo ]; } } /** * Send a notification email */ public static function sendNotificationEmail(string $toEmail, string $subject, string $message, array $data = [], bool $isHtml = false): array { try { $emailSettings = self::getEmailSettings(); $appSettings = self::getAppSettings(); $mail = self::createMailer(); // Set sender $mail->setFrom($emailSettings['mail_from_address'], $emailSettings['mail_from_name']); $mail->addAddress($toEmail); // Content $mail->isHTML(true); $mail->Subject = $subject; if ($isHtml) { // Message is already formatted HTML, use it directly $mail->Body = $message; $mail->AltBody = strip_tags($message); } else { // Message is plain text, format it with template $mail->Body = self::formatHtmlBody($message, $data, $appSettings); $mail->AltBody = strip_tags($message); } $mail->send(); return [ 'success' => true, 'message' => "Email sent successfully to {$toEmail}" ]; } catch (Exception $e) { $errorMessage = "Failed to send email: " . $e->getMessage(); $debugInfo = $mail->ErrorInfo ?? 'No debug info available'; // Log the error using the application's logger self::getLogger()->error($errorMessage, [ 'email' => $toEmail, 'subject' => $subject, 'smtp_error' => $debugInfo, 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => $errorMessage, 'error' => $e->getMessage(), 'debug_info' => $debugInfo ]; } } /** * Format HTML email body */ private static function formatHtmlBody(string $message, array $data, array $appSettings): string { $messageHtml = nl2br(htmlspecialchars($message)); $appName = htmlspecialchars($appSettings['app_name']); $appUrl = htmlspecialchars($appSettings['app_url']); // Build domain link if domain ID is available $domainLink = ''; if (isset($data['domain_id'])) { $domainUrl = rtrim($appUrl, '/') . '/domains/' . $data['domain_id']; $domainLink = "

View Domain Details

"; } return "

🔔 {$appName} Alert

$messageHtml

$domainLink
"; } /** * Send verification email */ public static function sendVerificationEmail(string $email, string $fullName, string $token): array { try { $appSettings = self::getAppSettings(); $verifyUrl = $appSettings['app_url'] . '/verify-email?token=' . $token; $subject = 'Verify Your Email Address'; // Create a properly formatted HTML email $htmlContent = "

🔔 Welcome to {$appSettings['app_name']}!

Hello {$fullName},

Thank you for registering with {$appSettings['app_name']}! To complete your account setup, please verify your email address by clicking the button below:

✅ Verify Email Address

Or copy and paste this URL into your browser:

{$verifyUrl}

⏰ Important: This verification link will expire in 24 hours for security reasons.

If you did not create an account with {$appSettings['app_name']}, please ignore this email. No further action is required.

This is an automated message from {$appSettings['app_name']}

Visit Dashboard
"; return self::sendNotificationEmail($email, $subject, $htmlContent, [], true); } catch (\Exception $e) { $errorMessage = "Failed to send verification email: " . $e->getMessage(); // Log the error using the application's logger self::getLogger()->error($errorMessage, [ 'email' => $email, 'full_name' => $fullName, 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => $errorMessage, 'error' => $e->getMessage() ]; } } /** * Send password reset email */ public static function sendPasswordResetEmail(string $email, string $fullName, string $token): array { try { $appSettings = self::getAppSettings(); $resetUrl = $appSettings['app_url'] . '/reset-password?token=' . $token; $subject = 'Reset Your Password'; // Create a properly formatted HTML email $htmlContent = "

🔒 Password Reset Request

Hello {$fullName},

We received a request to reset your password for your {$appSettings['app_name']} account. If you made this request, click the button below to create a new password:

🔑 Reset Password

Or copy and paste this URL into your browser:

{$resetUrl}

⏰ Important: This password reset link will expire in 1 hour for security reasons.

🔒 Security Notice: If you did not request a password reset, please ignore this email. Your password will remain unchanged and no action is required.

This is an automated message from {$appSettings['app_name']}

Visit Dashboard
"; return self::sendNotificationEmail($email, $subject, $htmlContent, [], true); } catch (\Exception $e) { $errorMessage = "Failed to send password reset email: " . $e->getMessage(); // Log the error using the application's logger self::getLogger()->error($errorMessage, [ 'email' => $email, 'full_name' => $fullName, 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => $errorMessage, 'error' => $e->getMessage() ]; } } /** * Get email subject based on data */ public static function getEmailSubject(array $data): string { if (isset($data['domain'])) { $daysLeft = $data['days_left']; if ($daysLeft <= 0) { return "🚨 URGENT: Domain {$data['domain']} has EXPIRED"; } if ($daysLeft == 1) { return "⚠️ CRITICAL: Domain {$data['domain']} expires TOMORROW"; } return "⚠️ Domain Expiration Alert: {$data['domain']} ({$daysLeft} days)"; } return "Domain Monitor Alert"; } /** * Send 2FA verification code email */ public static function sendTwoFactorCode(string $email, string $fullName, string $code): array { try { $appSettings = self::getAppSettings(); $subject = 'Your Two-Factor Authentication Code'; // Create a properly formatted HTML email $htmlContent = "

🔐 Two-Factor Authentication

Your Verification Code

Hello {$fullName},

Use this code to complete your two-factor authentication:

{$code}

⏰ Important: This code expires in 10 minutes for security reasons.

If you did not request this code, please ignore this email. No further action is required.

This is an automated message from {$appSettings['app_name']}

Visit Dashboard
"; return self::sendNotificationEmail($email, $subject, $htmlContent, [], true); } catch (\Exception $e) { $errorMessage = "Failed to send 2FA verification email: " . $e->getMessage(); // Log the error using the application's logger self::getLogger()->error($errorMessage, [ 'email' => $email, 'full_name' => $fullName, 'exception' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return [ 'success' => false, 'message' => $errorMessage, 'error' => $e->getMessage() ]; } } }