Skip to content

Commit c615ecb

Browse files
committed
implement local block list and Sieve sync integration for spam reporting
1 parent 4fbf5d2 commit c615ecb

25 files changed

+4443
-79
lines changed

HANDLER_MODIFICATION_SNIPPET.php

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?php
2+
/**
3+
* CODE SNIPPET: Replace synchronous auto-block with queue
4+
*
5+
* Location: modules/imap/handler_modules.php
6+
* Class: Hm_Handler_imap_report_spam
7+
* Method: process()
8+
*
9+
* STEP 1: Add this after line 2278 (after loading spam_report_services.php)
10+
*/
11+
12+
// Include queue integration functions
13+
if (!function_exists('queue_spam_sender_for_blocking')) {
14+
require_once APP_PATH.'modules/imap/spam_queue_integration.php';
15+
}
16+
17+
/**
18+
* STEP 2: Replace lines 2363-2437 with this code
19+
*
20+
* Find this section (starts around line 2363):
21+
* $move_result = $mailbox->message_action($form_folder, 'MOVE', array($uid), $junk_folder);
22+
*
23+
* Replace everything from there until:
24+
* $bulk_results[] = $result;
25+
*
26+
* With the code below:
27+
*/
28+
29+
// Move message to junk folder
30+
$move_result = $mailbox->message_action($form_folder, 'MOVE', array($uid), $junk_folder);
31+
if ($move_result['status']) {
32+
$result['success'] = true;
33+
34+
// Queue sender for async Sieve synchronization (non-blocking)
35+
$queue_result = queue_spam_sender_for_blocking(
36+
$this->user_config,
37+
$form['imap_server_id'],
38+
$message_data,
39+
$spam_reason,
40+
$junk_folder
41+
);
42+
43+
if ($queue_result['success'] && $queue_result['queued']) {
44+
// Successfully queued
45+
delayed_debug_log('Spam sender queued for Sieve sync', array(
46+
'entry_id' => $queue_result['entry_id'],
47+
'sender' => $queue_result['sender'],
48+
'server_id' => $form['imap_server_id']
49+
));
50+
51+
// Store queue info for UI feedback (optional)
52+
$result['queue_info'] = $queue_result;
53+
54+
} else if (!$queue_result['success']) {
55+
// Queueing failed - log warning but don't fail the whole operation
56+
delayed_debug_log('Failed to queue sender for blocking', array(
57+
'error' => isset($queue_result['error']) ? $queue_result['error'] : 'Unknown error',
58+
'sender' => isset($message_data['from']) ? $message_data['from'] : 'unknown'
59+
), 'warning');
60+
61+
// Message is still in junk, just won't be auto-blocked
62+
$result['error'] .= 'Auto-block queuing failed (sender will not be blocked automatically); ';
63+
}
64+
// If success=true but queued=false: auto-blocking is disabled by user
65+
66+
} else {
67+
$result['error'] .= 'Move to junk failed; ';
68+
}
69+
70+
$bulk_results[] = $result;
71+
72+
/**
73+
* OPTIONAL STEP 3: Enhance success message
74+
*
75+
* Find this section (around line 2447-2451):
76+
* if ($status) {
77+
* Hm_Msgs::add('Message reported as spam and moved to junk folder', 'success');
78+
* } else {
79+
* Hm_Msgs::add('Failed to report message as spam', 'danger');
80+
* }
81+
*
82+
* Replace with:
83+
*/
84+
85+
if ($status) {
86+
// Check if sender was queued for blocking
87+
if (isset($bulk_results[0]['queue_info']['queued']) && $bulk_results[0]['queue_info']['queued']) {
88+
Hm_Msgs::add(
89+
'Message reported as spam and moved to junk folder. Sender will be blocked automatically.',
90+
'success'
91+
);
92+
} else {
93+
Hm_Msgs::add('Message reported as spam and moved to junk folder', 'success');
94+
}
95+
} else {
96+
Hm_Msgs::add('Failed to report message as spam', 'danger');
97+
}
98+
99+
/**
100+
* BULK OPERATION VERSION (around line 2461-2467)
101+
*
102+
* Find:
103+
* if ($success_count === count($bulk_results)) {
104+
* Hm_Msgs::add('All messages reported as spam and moved to junk folder', 'success');
105+
* } elseif ($success_count > 0) {
106+
* Hm_Msgs::add("$success_count of " . count($bulk_results) . " messages reported as spam", 'warning');
107+
* } else {
108+
* Hm_Msgs::add('Failed to report messages as spam', 'danger');
109+
* }
110+
*
111+
* Replace with:
112+
*/
113+
114+
// Count queued senders
115+
$queued_count = 0;
116+
foreach ($bulk_results as $result) {
117+
if (isset($result['queue_info']['queued']) && $result['queue_info']['queued']) {
118+
$queued_count++;
119+
}
120+
}
121+
122+
if ($success_count === count($bulk_results)) {
123+
if ($queued_count > 0) {
124+
$msg = sprintf(
125+
'All %d messages reported as spam and moved to junk folder. %d sender(s) queued for automatic blocking.',
126+
count($bulk_results),
127+
$queued_count
128+
);
129+
} else {
130+
$msg = 'All messages reported as spam and moved to junk folder';
131+
}
132+
Hm_Msgs::add($msg, 'success');
133+
} elseif ($success_count > 0) {
134+
if ($queued_count > 0) {
135+
$msg = sprintf(
136+
'%d of %d messages reported as spam. %d sender(s) queued for blocking.',
137+
$success_count,
138+
count($bulk_results),
139+
$queued_count
140+
);
141+
} else {
142+
$msg = "$success_count of " . count($bulk_results) . " messages reported as spam";
143+
}
144+
Hm_Msgs::add($msg, 'warning');
145+
} else {
146+
Hm_Msgs::add('Failed to report messages as spam', 'danger');
147+
}
148+
149+
/**
150+
* THAT'S IT!
151+
*
152+
* Summary of changes:
153+
* 1. Added require_once for spam_queue_integration.php
154+
* 2. Replaced ~70 lines of synchronous Sieve code with ~30 lines of queue code
155+
* 3. Enhanced user messages to mention queuing
156+
*
157+
* Result:
158+
* - Users get instant response (no waiting for Sieve)
159+
* - Senders are queued for blocking
160+
* - Cron job will process queue in background
161+
* - Automatic retries on failure
162+
* - No data loss
163+
*/
164+

debug_local_filter.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
/**
3+
* Debug Local Filter
4+
* Quick script to check if local filtering is working
5+
*/
6+
7+
define('APP_PATH', __DIR__ . '/');
8+
define('DEBUG_MODE', true);
9+
define('VENDOR_PATH', APP_PATH.'vendor/');
10+
11+
require APP_PATH.'lib/framework.php';
12+
13+
echo "=== Local Filter Debug ===\n\n";
14+
15+
// Check if LocalBlockList exists
16+
if (class_exists('LocalBlockList')) {
17+
echo "✅ LocalBlockList class loaded\n";
18+
} else {
19+
echo "❌ LocalBlockList class NOT found\n";
20+
exit(1);
21+
}
22+
23+
// Get blocked senders
24+
$blocked = LocalBlockList::getAll();
25+
echo "\n📋 Blocked Senders:\n";
26+
if (empty($blocked)) {
27+
echo " (empty)\n";
28+
} else {
29+
foreach ($blocked as $email) {
30+
echo " - $email\n";
31+
}
32+
}
33+
34+
// Test with a known blocked sender
35+
if (!empty($blocked)) {
36+
$test_email = $blocked[0];
37+
echo "\n🧪 Testing: $test_email\n";
38+
39+
if (LocalBlockList::exists($test_email)) {
40+
echo " ✅ EXISTS check: TRUE\n";
41+
} else {
42+
echo " ❌ EXISTS check: FALSE\n";
43+
}
44+
45+
// Try with different formats
46+
$test_variations = [
47+
$test_email,
48+
strtoupper($test_email),
49+
"Name <$test_email>",
50+
"<$test_email>"
51+
];
52+
53+
echo "\n📧 Email format variations:\n";
54+
foreach ($test_variations as $variant) {
55+
$normalized = strtolower(trim($variant));
56+
if (preg_match('/<([^>]+)>/', $normalized, $matches)) {
57+
$normalized = $matches[1];
58+
}
59+
$exists = LocalBlockList::exists($normalized);
60+
echo " '$variant' → '$normalized' → " . ($exists ? '✅ BLOCKED' : '❌ NOT BLOCKED') . "\n";
61+
}
62+
}
63+
64+
// Check data file
65+
$file_path = APP_PATH . 'data/local_blocked.json';
66+
echo "\n📁 File: $file_path\n";
67+
if (file_exists($file_path)) {
68+
echo " ✅ File exists\n";
69+
$content = file_get_contents($file_path);
70+
echo " Size: " . strlen($content) . " bytes\n";
71+
echo " Content:\n";
72+
echo " " . str_replace("\n", "\n ", $content) . "\n";
73+
} else {
74+
echo " ❌ File NOT found\n";
75+
}
76+
77+
echo "\n=== Done ===\n";
78+

debug_sieve_sync_js.php

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
/**
3+
* Debug Script for Sieve Sync JavaScript Loading
4+
* Checks if the JavaScript functions are properly loaded
5+
*/
6+
7+
define('APP_PATH', dirname(__FILE__) . '/');
8+
define('VENDOR_PATH', APP_PATH . 'vendor/');
9+
define('DEBUG_MODE', true);
10+
11+
require VENDOR_PATH . 'autoload.php';
12+
require APP_PATH . 'lib/framework.php';
13+
14+
echo "=== Sieve Sync JavaScript Debug ===\n\n";
15+
16+
// Check if the JavaScript file exists and contains our functions
17+
$js_file = APP_PATH . 'modules/imap/site.js';
18+
if (file_exists($js_file)) {
19+
echo "✅ modules/imap/site.js exists\n";
20+
21+
$js_content = file_get_contents($js_file);
22+
23+
// Check for our functions
24+
$functions = [
25+
'triggerSieveSync',
26+
'updateSieveSyncStatus',
27+
'select_imap_folder'
28+
];
29+
30+
foreach ($functions as $func) {
31+
if (strpos($js_content, "function $func") !== false) {
32+
echo "✅ Function $func found in JavaScript\n";
33+
} else {
34+
echo "❌ Function $func NOT found in JavaScript\n";
35+
}
36+
}
37+
38+
// Check for INBOX trigger
39+
if (strpos($js_content, 'path.includes("INBOX")') !== false) {
40+
echo "✅ INBOX trigger code found\n";
41+
} else {
42+
echo "❌ INBOX trigger code NOT found\n";
43+
}
44+
45+
// Check for AJAX request
46+
if (strpos($js_content, 'ajax_sieve_sync') !== false) {
47+
echo "✅ AJAX sieve_sync request found\n";
48+
} else {
49+
echo "❌ AJAX sieve_sync request NOT found\n";
50+
}
51+
52+
} else {
53+
echo "❌ modules/imap/site.js does not exist\n";
54+
}
55+
56+
echo "\n=== Browser Testing Commands ===\n";
57+
echo "1. Open browser console (F12)\n";
58+
echo "2. Run these commands:\n\n";
59+
60+
echo "// Check if functions are loaded\n";
61+
echo "console.log('triggerSieveSync:', typeof triggerSieveSync);\n";
62+
echo "console.log('updateSieveSyncStatus:', typeof updateSieveSyncStatus);\n\n";
63+
64+
echo "// Test status indicator\n";
65+
echo "updateSieveSyncStatus('success', {synced: 4, failed: 0});\n\n";
66+
67+
echo "// Test manual trigger\n";
68+
echo "triggerSieveSync();\n\n";
69+
70+
echo "// Check page context\n";
71+
echo "console.log('Page:', getParam('page'));\n";
72+
echo "console.log('Path:', getListPathParam());\n\n";
73+
74+
echo "// Test AJAX directly\n";
75+
echo "Hm_Ajax.request([\n";
76+
echo " {'name': 'hm_ajax_hook', 'value': 'ajax_sieve_sync'}\n";
77+
echo "], function(response) {\n";
78+
echo " console.log('AJAX Response:', response);\n";
79+
echo "}, null, true);\n\n";
80+
81+
echo "=== Expected Results ===\n";
82+
echo "✅ All functions should be defined\n";
83+
echo "✅ Status indicator should appear\n";
84+
echo "✅ AJAX request should complete\n";
85+
echo "✅ Console should show debug messages\n\n";
86+
87+
echo "=== Troubleshooting ===\n";
88+
echo "If functions are undefined:\n";
89+
echo "1. Check if modules/imap/site.js is loaded\n";
90+
echo "2. Check for JavaScript errors in console\n";
91+
echo "3. Verify the file was saved correctly\n\n";
92+
93+
echo "If AJAX fails:\n";
94+
echo "1. Check Network tab for failed requests\n";
95+
echo "2. Verify ajax_sieve_sync endpoint is registered\n";
96+
echo "3. Check if user is logged in\n\n";
97+
98+
echo "=== Debug Complete ===\n";

0 commit comments

Comments
 (0)