feat: Add comprehensive email flow diagnostics and logging

🔍 Email Flow Diagnostic Tool:
Created test-email-flow.php - comprehensive diagnostic dashboard:
- System status (notification mode, email channel, Action Scheduler)
- Event configuration checker
- Email queue status (wp_options)
- Action Scheduler queue status
- Recent email logs viewer
- Test actions (queue test email, process queue, test order email)
- Troubleshooting guide

📝 Enhanced Debug Logging:
Added detailed logging to EmailManager:
- Hook trigger logging
- Order validation logging
- Event enabled/disabled logging
- Email rendering status
- wp_mail() call result
- Full email flow traceability

🎯 Usage:
1. Visit: /wp-content/plugins/woonoow/test-email-flow.php
2. Check all system status indicators
3. Use test buttons to trigger emails
4. Monitor debug logs for detailed flow

📋 Logs to Watch:
[EmailManager] send_order_processing_email triggered
[EmailManager] order_processing email is disabled/enabled
[EmailManager] Sending order_processing email
[EmailManager] Email rendered successfully
[EmailManager] wp_mail called - Result: success/failed
[WooNooW MailQueue] Queued email ID
[WooNooW MailQueue] Processing email_id
[WooNooW MailQueue] Sent and deleted email ID

🚀 Troubleshooting Steps:
1. Check notification system mode (woonoow vs woocommerce)
2. Check email channel enabled
3. Check event-specific email enabled
4. Check Action Scheduler for failures
5. Check debug logs for flow
6. Test with diagnostic tool
This commit is contained in:
dwindown
2025-11-18 15:44:08 +07:00
parent f77c9b828e
commit 7394d2f213
2 changed files with 285 additions and 1 deletions

View File

@@ -115,19 +115,33 @@ class EmailManager {
* @param WC_Order $order * @param WC_Order $order
*/ */
public function send_order_processing_email($order_id, $order = null) { public function send_order_processing_email($order_id, $order = null) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] send_order_processing_email triggered for order #' . $order_id);
}
if (!$order) { if (!$order) {
$order = wc_get_order($order_id); $order = wc_get_order($order_id);
} }
if (!$order) { if (!$order) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] Order not found for ID: ' . $order_id);
}
return; return;
} }
// Check if event is enabled // Check if event is enabled
if (!$this->is_event_enabled('order_processing', 'email', 'customer')) { if (!$this->is_event_enabled('order_processing', 'email', 'customer')) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] order_processing email is disabled in settings');
}
return; return;
} }
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] Sending order_processing email for order #' . $order_id);
}
// Send email // Send email
$this->send_email('order_processing', 'customer', $order); $this->send_email('order_processing', 'customer', $order);
} }
@@ -364,6 +378,10 @@ class EmailManager {
* @param array $extra_data * @param array $extra_data
*/ */
private function send_email($event_id, $recipient_type, $data, $extra_data = []) { private function send_email($event_id, $recipient_type, $data, $extra_data = []) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] send_email called - Event: ' . $event_id . ', Recipient: ' . $recipient_type);
}
// Get email renderer // Get email renderer
$renderer = EmailRenderer::instance(); $renderer = EmailRenderer::instance();
@@ -371,16 +389,27 @@ class EmailManager {
$email = $renderer->render($event_id, $recipient_type, $data, $extra_data); $email = $renderer->render($event_id, $recipient_type, $data, $extra_data);
if (!$email) { if (!$email) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] Email rendering failed for event: ' . $event_id);
}
return; return;
} }
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] Email rendered successfully - To: ' . $email['to'] . ', Subject: ' . $email['subject']);
}
// Send email via wp_mail // Send email via wp_mail
$headers = [ $headers = [
'Content-Type: text/html; charset=UTF-8', 'Content-Type: text/html; charset=UTF-8',
'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>', 'From: ' . get_bloginfo('name') . ' <' . get_option('admin_email') . '>',
]; ];
wp_mail($email['to'], $email['subject'], $email['body'], $headers); $sent = wp_mail($email['to'], $email['subject'], $email['body'], $headers);
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log('[EmailManager] wp_mail called - Result: ' . ($sent ? 'success' : 'failed'));
}
// Log email sent // Log email sent
do_action('woonoow_email_sent', $event_id, $recipient_type, $email); do_action('woonoow_email_sent', $event_id, $recipient_type, $email);

255
test-email-flow.php Normal file
View File

@@ -0,0 +1,255 @@
<?php
/**
* Email Flow Diagnostic Tool
*
* Usage: Visit https://yoursite.com/wp-content/plugins/woonoow/test-email-flow.php
*/
// Load WordPress
require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/wp-load.php';
if (!current_user_can('manage_options')) {
die('Access denied');
}
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
<head>
<title>Email Flow Diagnostic</title>
<style>
body { font-family: monospace; padding: 20px; background: #1e1e1e; color: #d4d4d4; }
.pass { color: #4ec9b0; }
.fail { color: #f48771; }
.warn { color: #dcdcaa; }
h1 { color: #569cd6; }
h2 { color: #4ec9b0; margin-top: 30px; }
pre { background: #2d2d2d; padding: 10px; border-radius: 4px; overflow-x: auto; }
.status { display: inline-block; width: 60px; font-weight: bold; }
button { background: #0e639c; color: white; border: none; padding: 10px 20px; cursor: pointer; border-radius: 4px; margin: 10px 5px; }
button:hover { background: #1177bb; }
</style>
</head>
<body>
<h1>Email Flow Diagnostic Tool</h1>
<h2>1. System Status</h2>
<?php
// Check notification system mode
$system_mode = get_option('woonoow_notification_system_mode', 'woonoow');
$status = ($system_mode === 'woonoow') ? '<span class="pass">✓ ENABLED</span>' : '<span class="fail">✗ DISABLED</span>';
echo "<div>$status - Notification System Mode: <strong>$system_mode</strong></div>";
// Check email channel
$email_enabled = get_option('woonoow_email_notifications_enabled', false);
$status = $email_enabled ? '<span class="pass">✓ ENABLED</span>' : '<span class="fail">✗ DISABLED</span>';
echo "<div>$status - Email Channel: <strong>" . ($email_enabled ? 'enabled' : 'disabled') . "</strong></div>";
// Check Action Scheduler
$as_exists = function_exists('as_enqueue_async_action');
$status = $as_exists ? '<span class="pass">✓ AVAILABLE</span>' : '<span class="warn">⚠ NOT AVAILABLE</span>';
echo "<div>$status - Action Scheduler: <strong>" . ($as_exists ? 'available' : 'not available (using wp-cron)') . "</strong></div>";
?>
<h2>2. Event Configuration</h2>
<?php
$settings = get_option('woonoow_notification_settings', []);
$events = $settings['events'] ?? [];
if (empty($events)) {
echo "<div><span class='fail'>✗ FAIL</span> - No events configured!</div>";
} else {
echo "<div><span class='pass'>✓ PASS</span> - " . count($events) . " events configured</div>";
echo "<pre>";
foreach ($events as $event_id => $event_data) {
$email_enabled = $event_data['channels']['email']['enabled'] ?? false;
$status_icon = $email_enabled ? '✓' : '✗';
echo "$status_icon $event_id: email " . ($email_enabled ? 'enabled' : 'disabled') . "\n";
}
echo "</pre>";
}
?>
<h2>3. Email Queue Status</h2>
<?php
// Check for queued emails in wp_options
global $wpdb;
$queued_emails = $wpdb->get_results(
"SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE 'woonoow_mail_%' LIMIT 10"
);
if (empty($queued_emails)) {
echo "<div><span class='warn'>⚠ INFO</span> - No emails currently queued</div>";
} else {
echo "<div><span class='pass'>✓ INFO</span> - " . count($queued_emails) . " emails in queue</div>";
echo "<pre>";
foreach ($queued_emails as $email) {
$payload = maybe_unserialize($email->option_value);
echo "ID: {$email->option_name}\n";
echo "To: " . ($payload['to'] ?? 'unknown') . "\n";
echo "Subject: " . ($payload['subject'] ?? 'unknown') . "\n";
echo "---\n";
}
echo "</pre>";
}
?>
<h2>4. Action Scheduler Queue</h2>
<?php
if ($as_exists) {
$pending = $wpdb->get_var(
"SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
WHERE hook = 'woonoow/mail/send' AND status = 'pending'"
);
$failed = $wpdb->get_var(
"SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
WHERE hook = 'woonoow/mail/send' AND status = 'failed'"
);
$complete = $wpdb->get_var(
"SELECT COUNT(*) FROM {$wpdb->prefix}actionscheduler_actions
WHERE hook = 'woonoow/mail/send' AND status = 'complete'
ORDER BY action_id DESC LIMIT 10"
);
echo "<div><span class='pass'>✓ INFO</span> - Pending: <strong>$pending</strong></div>";
echo "<div><span class='pass'>✓ INFO</span> - Completed (last 10): <strong>$complete</strong></div>";
if ($failed > 0) {
echo "<div><span class='fail'>✗ WARN</span> - Failed: <strong>$failed</strong></div>";
// Show failed actions
$failed_actions = $wpdb->get_results(
"SELECT * FROM {$wpdb->prefix}actionscheduler_actions
WHERE hook = 'woonoow/mail/send' AND status = 'failed'
ORDER BY action_id DESC LIMIT 5"
);
if ($failed_actions) {
echo "<pre>Recent failures:\n";
foreach ($failed_actions as $action) {
echo "ID: {$action->action_id}\n";
echo "Args: {$action->args}\n";
echo "Scheduled: {$action->scheduled_date_gmt}\n";
echo "---\n";
}
echo "</pre>";
}
} else {
echo "<div><span class='pass'>✓ PASS</span> - Failed: <strong>0</strong></div>";
}
} else {
echo "<div><span class='warn'>⚠ WARN</span> - Action Scheduler not available, using wp-cron</div>";
}
?>
<h2>5. Recent Email Logs</h2>
<?php
// Check debug log for email activity
$debug_log = WP_CONTENT_DIR . '/debug.log';
if (file_exists($debug_log)) {
$log_lines = file($debug_log);
$email_logs = array_filter($log_lines, function($line) {
return strpos($line, '[WooNooW MailQueue]') !== false ||
strpos($line, 'woonoow_email_sent') !== false;
});
if (empty($email_logs)) {
echo "<div><span class='warn'>⚠ INFO</span> - No email logs found (enable WP_DEBUG to see logs)</div>";
} else {
echo "<div><span class='pass'>✓ INFO</span> - " . count($email_logs) . " email log entries found</div>";
echo "<pre>";
echo implode('', array_slice($email_logs, -10)); // Last 10 entries
echo "</pre>";
}
} else {
echo "<div><span class='warn'>⚠ INFO</span> - Debug log not found (enable WP_DEBUG_LOG)</div>";
}
?>
<h2>6. Test Actions</h2>
<?php
if (isset($_GET['action'])) {
echo "<div style='margin: 20px 0; padding: 15px; background: #2d2d2d; border-left: 4px solid #4ec9b0;'>";
if ($_GET['action'] === 'test_email') {
echo "<h3>Testing Email Queue...</h3>";
// Queue a test email
$test_payload = [
'to' => get_option('admin_email'),
'subject' => 'WooNooW Test Email - ' . date('Y-m-d H:i:s'),
'html' => '<h1>Test Email</h1><p>This is a test email from WooNooW email queue system.</p><p>Time: ' . date('Y-m-d H:i:s') . '</p>',
'headers' => ['Content-Type: text/html; charset=UTF-8'],
'attachments' => [],
];
\WooNooW\Core\Mail\MailQueue::enqueue($test_payload);
echo "<p><span class='pass'>✓ SUCCESS</span> - Test email queued to: " . get_option('admin_email') . "</p>";
echo "<p>Check your inbox in a few moments. Also check Action Scheduler queue above.</p>";
}
if ($_GET['action'] === 'process_queue') {
echo "<h3>Processing Email Queue...</h3>";
if (function_exists('as_run_queue')) {
as_run_queue();
echo "<p><span class='pass'>✓ SUCCESS</span> - Action Scheduler queue processed</p>";
} else {
echo "<p><span class='warn'>⚠ WARN</span> - Action Scheduler not available</p>";
}
}
if ($_GET['action'] === 'test_order_email') {
echo "<h3>Testing Order Email...</h3>";
// Get a recent order
$orders = wc_get_orders(['limit' => 1, 'orderby' => 'date', 'order' => 'DESC']);
if (empty($orders)) {
echo "<p><span class='fail'>✗ FAIL</span> - No orders found. Create a test order first.</p>";
} else {
$order = $orders[0];
echo "<p>Using order #" . $order->get_id() . "</p>";
// Trigger order processing email
$email_manager = \WooNooW\Core\Notifications\EmailManager::instance();
$email_manager->send_order_processing_email($order->get_id(), $order);
echo "<p><span class='pass'>✓ SUCCESS</span> - Order processing email triggered</p>";
echo "<p>Check Action Scheduler queue and email logs above.</p>";
}
}
echo "</div>";
}
?>
<div style="margin-top: 20px;">
<button onclick="window.location.href='?action=test_email'">Queue Test Email</button>
<button onclick="window.location.href='?action=process_queue'">Process Queue Now</button>
<button onclick="window.location.href='?action=test_order_email'">Test Order Email</button>
<button onclick="window.location.reload()">Refresh</button>
</div>
<h2>7. Troubleshooting</h2>
<div>
<h3>If emails are not sending:</h3>
<ol>
<li>Check that "Notification System Mode" is set to "woonoow" (not "woocommerce")</li>
<li>Check that "Email Channel" is enabled</li>
<li>Check that specific events have email enabled in configuration</li>
<li>Check Action Scheduler for failed actions</li>
<li>Enable WP_DEBUG and WP_DEBUG_LOG to see detailed logs</li>
<li>Check your server's mail configuration (SMTP, sendmail, etc.)</li>
<li>Test with "Queue Test Email" button above</li>
</ol>
</div>
<div style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #444; color: #888;">
Generated: <?php echo date('Y-m-d H:i:s'); ?>
</div>
</body>
</html>