diff --git a/includes/Core/Notifications/EmailManager.php b/includes/Core/Notifications/EmailManager.php index 1eb6643..586f074 100644 --- a/includes/Core/Notifications/EmailManager.php +++ b/includes/Core/Notifications/EmailManager.php @@ -60,6 +60,9 @@ class EmailManager { // New customer account add_action('woocommerce_created_customer', [$this, 'send_new_customer_email'], 10, 3); + // Password reset - intercept WordPress default email and use our template + add_filter('retrieve_password_message', [$this, 'handle_password_reset_email'], 10, 4); + // Low stock / Out of stock add_action('woocommerce_low_stock', [$this, 'send_low_stock_email'], 10, 1); add_action('woocommerce_no_stock', [$this, 'send_out_of_stock_email'], 10, 1); @@ -304,6 +307,101 @@ class EmailManager { ]); } + /** + * Handle password reset email - intercept WordPress default and use our template + * + * @param string $message Email message (we replace this) + * @param string $key Reset key + * @param string $user_login User login + * @param WP_User $user_data User object + * @return string Empty string to prevent WordPress sending default email + */ + public function handle_password_reset_email($message, $key, $user_login, $user_data) { + // Check if WooNooW notification system is enabled + if (!self::is_enabled()) { + return $message; // Use WordPress default + } + + // Check if event is enabled + if (!$this->is_event_enabled('password_reset', 'email', 'customer')) { + return $message; // Use WordPress default + } + + // Build reset URL - use SPA route if available, otherwise WordPress default + $site_url = get_site_url(); + + // Check if this is a WooCommerce customer - use SPA reset page + // Otherwise fall back to WordPress default reset page + $reset_link = network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'login'); + + // Create a pseudo WC_Customer for template rendering + $customer = null; + if (class_exists('WC_Customer')) { + try { + $customer = new \WC_Customer($user_data->ID); + } catch (\Exception $e) { + $customer = null; + } + } + + // Send our custom email + $this->send_password_reset_email($user_data, $key, $reset_link, $customer); + + // Return empty string to prevent WordPress from sending its default plain-text email + return ''; + } + + /** + * Send password reset email using our template + * + * @param WP_User $user User object + * @param string $key Reset key + * @param string $reset_link Full reset link URL + * @param WC_Customer|null $customer WooCommerce customer object if available + */ + private function send_password_reset_email($user, $key, $reset_link, $customer = null) { + // Get email renderer + $renderer = EmailRenderer::instance(); + + // Build extra data for template variables + $extra_data = [ + 'reset_key' => $key, + 'reset_link' => $reset_link, + 'user_login' => $user->user_login, + 'user_email' => $user->user_email, + 'customer_name' => $user->display_name ?: $user->user_login, + 'customer_email' => $user->user_email, + ]; + + // Use WC_Customer if available for better template rendering + $data = $customer ?: $user; + + // Render email + $email = $renderer->render('password_reset', 'customer', $data, $extra_data); + + if (!$email) { + if (defined('WP_DEBUG') && WP_DEBUG) { + error_log('[EmailManager] Password reset email rendering failed for user: ' . $user->user_login); + } + return; + } + + // Send email via wp_mail + $headers = [ + 'Content-Type: text/html; charset=UTF-8', + 'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>', + ]; + + $sent = wp_mail($email['to'], $email['subject'], $email['body'], $headers); + + if (defined('WP_DEBUG') && WP_DEBUG) { + error_log('[EmailManager] Password reset email sent to ' . $email['to'] . ' - Result: ' . ($sent ? 'success' : 'failed')); + } + + // Log email sent + do_action('woonoow_email_sent', 'password_reset', 'customer', $email); + } + /** * Send low stock email * diff --git a/includes/Core/Notifications/EventRegistry.php b/includes/Core/Notifications/EventRegistry.php index b26fdec..43f8bd6 100644 --- a/includes/Core/Notifications/EventRegistry.php +++ b/includes/Core/Notifications/EventRegistry.php @@ -43,6 +43,22 @@ class EventRegistry { 'wc_email' => 'customer_new_account', 'enabled' => true, ], + 'password_reset' => [ + 'id' => 'password_reset', + 'label' => __('Password Reset', 'woonoow'), + 'description' => __('When a customer requests a password reset', 'woonoow'), + 'category' => 'customers', + 'recipient_type' => 'customer', + 'wc_email' => '', + 'enabled' => true, + 'variables' => [ + '{reset_link}' => __('Password reset link', 'woonoow'), + '{reset_key}' => __('Password reset key', 'woonoow'), + '{user_login}' => __('Username', 'woonoow'), + '{user_email}' => __('User email', 'woonoow'), + '{site_name}' => __('Site name', 'woonoow'), + ], + ], // ===== NEWSLETTER EVENTS ===== 'newsletter_welcome' => [ diff --git a/includes/Email/DefaultTemplates.php b/includes/Email/DefaultTemplates.php index 0ce7607..5724a08 100644 --- a/includes/Email/DefaultTemplates.php +++ b/includes/Email/DefaultTemplates.php @@ -214,6 +214,43 @@ Got questions? Our customer service team is ready to help: {support_email} [/card]'; } + /** + * Customer: Password Reset + * Sent when customer requests a password reset + */ + private static function customer_password_reset() + { + return '[card type="hero"] +## Reset Your Password 🔐 + +Hi {customer_name}, + +You\'ve requested to reset your password for your {site_name} account. +[/card] + +[card type="warning"] +**Click the button below to reset your password:** + +[button url="{reset_link}" style="solid"]Reset My Password[/button] + +This link will expire in 24 hours for security reasons. +[/card] + +[card type="basic"] +**Didn\'t request this?** + +If you didn\'t request a password reset, you can safely ignore this email. Your password will remain unchanged. + +For security, never share this link with anyone. +[/card] + +[card type="basic" bg="#f5f5f5"] +If the button above doesn\'t work, copy and paste this link into your browser: + +{reset_link} +[/card]'; + } + /** * Customer: Newsletter Campaign * Master design template for newsletter campaigns