config = [ 'driver' => $_ENV['MAIL_DRIVER'] ?? 'smtp', 'host' => $_ENV['MAIL_HOST'] ?? 'localhost', 'port' => (int) ($_ENV['MAIL_PORT'] ?? 587), 'username' => $_ENV['MAIL_USERNAME'] ?? '', 'password' => $_ENV['MAIL_PASSWORD'] ?? '', 'encryption' => $_ENV['MAIL_ENCRYPTION'] ?? 'tls', 'from_address' => $_ENV['MAIL_FROM_ADDRESS'] ?? 'noreply@example.com', 'from_name' => $_ENV['MAIL_FROM_NAME'] ?? 'E-commerce Store' ]; $this->templates = [ 'verification' => $this->getVerificationTemplate(), 'password_reset' => $this->getPasswordResetTemplate(), 'welcome' => $this->getWelcomeTemplate(), 'order_confirmation' => $this->getOrderConfirmationTemplate() ]; } /** * Send verification email */ public function sendVerificationEmail(string $email, string $name, string $token): bool { $verificationUrl = $this->getAppUrl()."/api/auth/verify-email/{$token}"; $subject = 'Verify Your Email Address'; $body = $this->renderTemplate('verification', [ 'name' => $name, 'verification_url' => $verificationUrl, 'app_name' => $this->config['from_name'] ]); return $this->sendEmail($email, $subject, $body); } /** * Send password reset email */ public function sendPasswordResetEmail(string $email, string $name, string $token): bool { $resetUrl = $this->getAppUrl()."/reset-password?token={$token}"; $subject = 'Reset Your Password'; $body = $this->renderTemplate('password_reset', [ 'name' => $name, 'reset_url' => $resetUrl, 'app_name' => $this->config['from_name'] ]); return $this->sendEmail($email, $subject, $body); } /** * Send welcome email */ public function sendWelcomeEmail(string $email, string $name): bool { $subject = 'Welcome to '.$this->config['from_name']; $body = $this->renderTemplate('welcome', [ 'name' => $name, 'app_name' => $this->config['from_name'], 'app_url' => $this->getAppUrl() ]); return $this->sendEmail($email, $subject, $body); } /** * Send order confirmation email */ public function sendOrderConfirmationEmail(string $email, string $name, array $orderData): bool { $subject = 'Order Confirmation - '.$orderData['order_number']; $body = $this->renderTemplate('order_confirmation', [ 'name' => $name, 'order' => $orderData, 'app_name' => $this->config['from_name'] ]); return $this->sendEmail($email, $subject, $body); } /** * Send email using configured driver */ private function sendEmail(string $to, string $subject, string $body): bool { try { switch ($this->config['driver']) { case 'smtp': return $this->sendViaSMTP($to, $subject, $body); case 'mail': return $this->sendViaMail($to, $subject, $body); case 'log': return $this->sendViaLog($to, $subject, $body); default: throw new Exception('Unsupported mail driver: '.$this->config['driver']); } } catch (Exception $e) { error_log('Email sending failed: '.$e->getMessage()); return false; } } /** * Send email via SMTP */ private function sendViaSMTP(string $to, string $subject, string $body): bool { // For production, you would implement proper SMTP sending // For now, we'll log the email return $this->sendViaLog($to, $subject, $body); } /** * Send email via PHP mail() function */ private function sendViaMail(string $to, string $subject, string $body): bool { $headers = [ 'From: '.$this->config['from_name'].' <'.$this->config['from_address'].'>', 'Reply-To: '.$this->config['from_address'], 'Content-Type: text/html; charset=UTF-8', 'MIME-Version: 1.0' ]; return mail($to, $subject, $body, implode("\r\n", $headers)); } /** * Log email instead of sending (for development) */ private function sendViaLog(string $to, string $subject, string $body): bool { $logEntry = [ 'timestamp' => date('Y-m-d H:i:s'), 'to' => $to, 'subject' => $subject, 'body' => $body ]; $logFile = __DIR__.'/../../storage/logs/emails.log'; $logDir = dirname($logFile); if (!is_dir($logDir)) { @mkdir($logDir, 0755, true); } return file_put_contents($logFile, json_encode($logEntry)."\n", FILE_APPEND | LOCK_EX) !== false; } /** * Render email template */ private function renderTemplate(string $template, array $variables): string { if (!isset($this->templates[$template])) { throw new Exception("Email template '{$template}' not found"); } $content = $this->templates[$template]; // Replace variables foreach ($variables as $key => $value) { if (is_array($value)) { // Handle complex variables (like order data) $content = $this->replaceComplexVariable($content, $key, $value); } else { $content = str_replace('{{'.$key.'}}', $value, $content); } } return $content; } /** * Replace complex variables in templates */ private function replaceComplexVariable(string $content, string $key, array $data): string { // Handle order data if ($key === 'order') { $content = str_replace('{{order.number}}', $data['order_number'] ?? '', $content); $content = str_replace('{{order.total}}', number_format($data['total_amount'] ?? 0, 2), $content); $content = str_replace('{{order.status}}', $data['status'] ?? '', $content); $content = str_replace('{{order.date}}', date('F j, Y', strtotime($data['created_at'] ?? 'now')), $content); // Handle order items if (isset($data['items'])) { $itemsHtml = ''; foreach ($data['items'] as $item) { $itemsHtml .= ''; $itemsHtml .= ''.htmlspecialchars($item['product_name'] ?? '').''; $itemsHtml .= ''.($item['quantity'] ?? 0).''; $itemsHtml .= '฿'.number_format($item['price'] ?? 0, 2).''; $itemsHtml .= '฿'.number_format($item['total'] ?? 0, 2).''; $itemsHtml .= ''; } $content = str_replace('{{order.items}}', $itemsHtml, $content); } } return $content; } /** * Get application URL */ private function getAppUrl(): string { return $_ENV['APP_URL'] ?? 'http://localhost'; } /** * Get verification email template */ private function getVerificationTemplate(): string { return ' Verify Your Email

{{app_name}}

Verify Your Email Address

Hello {{name}},

Thank you for registering with {{app_name}}. Please click the button below to verify your email address:

Verify Email

If you cannot click the button, copy and paste this link into your browser:

{{verification_url}}

If you did not create an account, please ignore this email.

'; } /** * Get password reset email template */ private function getPasswordResetTemplate(): string { return ' Reset Your Password

{{app_name}}

Reset Your Password

Hello {{name}},

You have requested to reset your password. Click the button below to reset it:

Reset Password

If you cannot click the button, copy and paste this link into your browser:

{{reset_url}}

This link will expire in 1 hour for security reasons.

If you did not request a password reset, please ignore this email.

'; } /** * Get welcome email template */ private function getWelcomeTemplate(): string { return ' Welcome

Welcome to {{app_name}}!

Welcome {{name}}!

Thank you for joining {{app_name}}. We are excited to have you as part of our community.

You can now:

Start Shopping

If you have any questions, feel free to contact our support team.

'; } /** * Get order confirmation email template */ private function getOrderConfirmationTemplate(): string { return ' Order Confirmation

Order Confirmation

Thank you for your order, {{name}}!

Your order has been received and is being processed.

Order Details

Order Number: {{order.number}}

Order Date: {{order.date}}

Status: {{order.status}}

Items Ordered

{{order.items}}
Product Quantity Price Total

Total: ฿{{order.total}}

We will send you another email when your order ships.

'; } /** * Send order status update email */ public function sendOrderStatusUpdate(string $email, string $name, array $orderData, string $newStatus): bool { $statusMessages = [ 'confirmed' => 'Your order has been confirmed and is being prepared', 'processing' => 'Your order is being processed and will be shipped soon', 'shipped' => 'Your order has been shipped and is on its way', 'delivered' => 'Your order has been delivered successfully', 'cancelled' => 'Your order has been cancelled' ]; $subject = 'Order Status Update - '.$orderData['order_number']; $message = $this->getOrderStatusTemplate([ 'customer_name' => $name, 'order_number' => $orderData['order_number'], 'new_status' => ucfirst($newStatus), 'status_message' => $statusMessages[$newStatus] ?? 'Your order status has been updated', 'order_total' => number_format($orderData['total_amount'], 2), 'tracking_url' => $this->getAppUrl()."/orders/{$orderData['order_number']}/track", 'app_name' => $this->config['from_name'] ]); return $this->sendEmail($email, $subject, $message); } /** * Send order cancellation email */ public function sendOrderCancellation(array $orderData): bool { $shippingAddress = is_string($orderData['shipping_address']) ? json_decode($orderData['shipping_address'], true) : $orderData['shipping_address']; $customerName = $shippingAddress['first_name'].' '.$shippingAddress['last_name']; $subject = 'Order Cancelled - '.$orderData['order_number']; $message = $this->getCancellationTemplate([ 'customer_name' => $customerName, 'order_number' => $orderData['order_number'], 'order_total' => number_format($orderData['total_amount'], 2), 'cancellation_reason' => $orderData['notes'] ?? 'Order cancelled by customer', 'refund_info' => 'If payment was made, refund will be processed within 3-5 business days', 'app_name' => $this->config['from_name'] ]); return $this->sendEmail($orderData['email'], $subject, $message); } /** * Send low stock alert to admin */ public function sendLowStockAlert(array $productData): bool { $adminEmail = $_ENV['ADMIN_EMAIL'] ?? 'admin@example.com'; $subject = 'Low Stock Alert - '.$productData['name']; $message = $this->getLowStockTemplate([ 'product_name' => $productData['name'], 'product_sku' => $productData['sku'], 'current_stock' => $productData['current_stock'], 'min_stock_level' => $productData['min_stock_level'], 'product_url' => $this->getAppUrl()."/products/{$productData['id']}", 'app_name' => $this->config['from_name'] ]); return $this->sendEmail($adminEmail, $subject, $message); } /** * Get order status update template */ private function getOrderStatusTemplate(array $data): string { $template = ' Order Status Update

{{app_name}}

Order Status Update

Dear {{customer_name}},

{{status_message}}

Order Number: {{order_number}}

Status: {{new_status}}

Order Total: ฿{{order_total}}

Track Your Order

Thank you for shopping with us!

'; foreach ($data as $key => $value) { $template = str_replace('{{'.$key.'}}', $value, $template); } return $template; } /** * Get cancellation email template */ private function getCancellationTemplate(array $data): string { $template = ' Order Cancelled

{{app_name}}

Order Cancellation

Dear {{customer_name}},

Your order has been cancelled as requested.

Order Number: {{order_number}}

Order Total: ฿{{order_total}}

Reason: {{cancellation_reason}}

{{refund_info}}

We apologize for any inconvenience and hope to serve you again in the future.

'; foreach ($data as $key => $value) { $template = str_replace('{{'.$key.'}}', $value, $template); } return $template; } /** * Get low stock alert template */ private function getLowStockTemplate(array $data): string { $template = ' Low Stock Alert

{{app_name}} - Admin Alert

⚠️ Low Stock Alert

Action Required: The following product is running low on stock and needs to be restocked.

Product: {{product_name}}

SKU: {{product_sku}}

Current Stock: {{current_stock}} units

Minimum Level: {{min_stock_level}} units

Manage Product

Please restock this item as soon as possible to avoid stockouts.

'; foreach ($data as $key => $value) { $template = str_replace('{{'.$key.'}}', $value, $template); } return $template; } }