166 lines
6.3 KiB
PHP
166 lines
6.3 KiB
PHP
<?php
|
||
/**
|
||
* File: EmailService.php
|
||
* Version: 1.4
|
||
* Path: /app/Services/EmailService.php
|
||
* Purpose: Centralized service for composing and sending all application emails including contact, newsletter, and system notifications.
|
||
* Includes support for unified contact + newsletter welcome messages.
|
||
* Project: Wizdom Networks Website
|
||
*/
|
||
|
||
namespace WizdomNetworks\WizeWeb\Services;
|
||
|
||
use WizdomNetworks\WizeWeb\Utilities\Database;
|
||
use WizdomNetworks\WizeWeb\Utilities\Logger;
|
||
use WizdomNetworks\WizeWeb\Utilities\EmailHelper;
|
||
use WizdomNetworks\WizeWeb\Utilities\ErrorHandler;
|
||
use WizdomNetworks\WizeWeb\Services\VerificationService;
|
||
|
||
class EmailService
|
||
{
|
||
private const TEMPLATE_VERIFICATION_CONTACT = 'verify_contact';
|
||
private const TEMPLATE_VERIFICATION_NEWSLETTER = 'verify_newsletter';
|
||
private const TEMPLATE_CONFIRMATION_CONTACT = 'verified_confirmation';
|
||
private const TEMPLATE_SALES_ALERT = 'sales_lead_alert';
|
||
private const TEMPLATE_CONTACT_NEWSLETTER = 'contact_and_newsletter';
|
||
private const TABLE_SUBSCRIBERS = 'subscribers';
|
||
|
||
private VerificationService $verificationService;
|
||
|
||
/**
|
||
* Initializes the email service and loads the verification code service dependency.
|
||
*/
|
||
public function __construct()
|
||
{
|
||
$this->verificationService = new VerificationService();
|
||
}
|
||
|
||
/**
|
||
* Sends a verification email using the specified template and context.
|
||
*
|
||
* @param string $email Recipient email address
|
||
* @param string $code Verification code
|
||
* @param string $template Email template to render
|
||
* @param array $context Template variables to inject
|
||
* @return bool True on success, false on failure
|
||
*/
|
||
public function sendVerificationEmail(string $email, string $code, string $template, array $context = []): bool
|
||
{
|
||
$context['verification_link'] = rtrim($_ENV['APP_URL'], '/') . "/verify/" . $code;
|
||
$body = EmailHelper::renderTemplate($template, $context);
|
||
$subject = 'Please verify your email';
|
||
|
||
return EmailHelper::send($email, $subject, $body);
|
||
}
|
||
|
||
/**
|
||
* Handles a new or existing newsletter subscription and sends a verification email.
|
||
*
|
||
* @param string $email User's email address
|
||
* @param string $ip User's IP address
|
||
* @param string $userAgent User agent string
|
||
* @return bool True if verification email sent, false otherwise
|
||
*/
|
||
public function subscribeNewsletter(string $email, string $ip, string $userAgent): bool
|
||
{
|
||
try {
|
||
$db = Database::getConnection();
|
||
|
||
$stmt = $db->prepare("SELECT is_verified FROM subscribers WHERE email = ?");
|
||
$stmt->execute([$email]);
|
||
$row = $stmt->fetch();
|
||
|
||
if ($row && (int)$row['is_verified'] === 1) {
|
||
Logger::info("Newsletter signup skipped (already verified): $email");
|
||
return false;
|
||
}
|
||
|
||
$code = $this->verificationService->generateCode();
|
||
$expiresAt = $this->verificationService->getExpirationTime();
|
||
|
||
if ($row) {
|
||
$stmt = $db->prepare("UPDATE subscribers SET verification_code = ?, ip_address = ?, user_agent = ?, created_at = NOW() WHERE email = ?");
|
||
$stmt->execute([$code, $ip, $userAgent, $email]);
|
||
} else {
|
||
$stmt = $db->prepare("INSERT INTO subscribers (email, verification_code, is_verified, ip_address, user_agent, created_at) VALUES (?, ?, 0, ?, ?, NOW())");
|
||
$stmt->execute([$email, $code, $ip, $userAgent]);
|
||
}
|
||
|
||
Logger::info("Newsletter subscription initiated for $email, verification code generated.");
|
||
|
||
return $this->sendVerificationEmail($email, $code, self::TEMPLATE_VERIFICATION_NEWSLETTER);
|
||
} catch (\Throwable $e) {
|
||
Logger::error("Newsletter subscription failed for $email: " . $e->getMessage());
|
||
ErrorHandler::exception($e);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Sends a confirmation email to a contact form submitter after successful verification.
|
||
*
|
||
* @param array $data Associative array containing user data and message details
|
||
* @return bool True on success, false on failure
|
||
*/
|
||
public function sendConfirmationToUser(array $data): bool
|
||
{
|
||
$body = EmailHelper::renderTemplate(self::TEMPLATE_CONFIRMATION_CONTACT, $data);
|
||
$subject = 'Your Email is Verified – Wizdom Networks';
|
||
|
||
return EmailHelper::send($data['email'], $subject, $body);
|
||
}
|
||
|
||
/**
|
||
* Sends a notification to the internal sales team when a new contact form submission is received.
|
||
*
|
||
* @param array $data The contact form data
|
||
* @return bool True if at least one email sent, false otherwise
|
||
*/
|
||
public function sendSalesNotification(array $data): bool
|
||
{
|
||
$recipients = $_ENV['SALES_EMAILS'] ?? '';
|
||
if (empty($recipients)) {
|
||
return false;
|
||
}
|
||
|
||
$body = EmailHelper::renderTemplate(self::TEMPLATE_SALES_ALERT, $data);
|
||
$subject = 'New Contact Form Submission';
|
||
|
||
foreach (explode(',', $recipients) as $email) {
|
||
$trimmed = trim($email);
|
||
if (!empty($trimmed)) {
|
||
EmailHelper::send($trimmed, $subject, $body);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Sends a unified welcome email when a user both contacts us and subscribes to the newsletter.
|
||
*
|
||
* @param array $data Associative array containing contact form fields and metadata
|
||
* @return bool True on successful send, false otherwise
|
||
*/
|
||
public function sendContactAndNewsletterWelcome(array $data): bool
|
||
{
|
||
$body = EmailHelper::renderTemplate(self::TEMPLATE_CONTACT_NEWSLETTER, $data);
|
||
$subject = 'Thanks for reaching out – and welcome!';
|
||
|
||
return EmailHelper::send($data['email'], $subject, $body);
|
||
}
|
||
|
||
/**
|
||
* Sends a system alert to configured admin recipients.
|
||
*
|
||
* @param string $context Description of the error context or origin
|
||
* @param string $errorMessage The error message or exception
|
||
* @param array|string $data Optional contextual data to include in the alert
|
||
* @return void
|
||
*/
|
||
public function alertAdmins(string $context, string $errorMessage, $data = []): void
|
||
{
|
||
EmailHelper::alertAdmins($context, $errorMessage, $data);
|
||
}
|
||
}
|