Skip to content

Commit 791b582

Browse files
committed
implement comprehensive spam reporting system with email and API integrations
1 parent f02b5be commit 791b582

File tree

8 files changed

+797
-221
lines changed

8 files changed

+797
-221
lines changed

lib/framework.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,96 @@ public static function stream_ended($resource) {
252252
public static function stream_socket_enable_crypto($socket, $type) {
253253
return stream_socket_enable_crypto($socket, true, $type);
254254
}
255+
256+
/**
257+
* Send an email using PHP's mail function
258+
* @param string $to Recipient email address
259+
* @param array $headers Email headers
260+
* @param string $body Email body
261+
* @return boolean True if email was sent successfully
262+
*/
263+
public static function send_email($to, $headers, $body) {
264+
try {
265+
// Convert headers array to string format
266+
$header_string = '';
267+
foreach ($headers as $key => $value) {
268+
$header_string .= "$key: $value\r\n";
269+
}
270+
$header_string .= "MIME-Version: 1.0\r\n";
271+
272+
// Send the email
273+
$result = mail($to, $headers['Subject'], $body, $header_string);
274+
275+
if (!$result) {
276+
Hm_Debug::add('Failed to send spam report email: ' . error_get_last()['message']);
277+
return false;
278+
}
279+
280+
return true;
281+
} catch (Exception $e) {
282+
Hm_Debug::add('Exception sending spam report email: ' . $e->getMessage());
283+
return false;
284+
}
285+
}
286+
287+
/**
288+
* Make an HTTP request using cURL
289+
* @param string $url Target URL
290+
* @param string $method HTTP method (GET, POST, etc.)
291+
* @param array $data Request data
292+
* @param array $headers Request headers
293+
* @return string|false Response body or false on failure
294+
*/
295+
public static function http_request($url, $method = 'GET', $data = array(), $headers = array()) {
296+
try {
297+
$ch = curl_init();
298+
299+
// Set cURL options
300+
curl_setopt($ch, CURLOPT_URL, $url);
301+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
302+
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
303+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
304+
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
305+
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
306+
307+
// Set method and data
308+
if ($method === 'POST') {
309+
curl_setopt($ch, CURLOPT_POST, true);
310+
if (!empty($data)) {
311+
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
312+
}
313+
} elseif ($method !== 'GET') {
314+
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
315+
}
316+
317+
// Set headers
318+
if (!empty($headers)) {
319+
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
320+
}
321+
322+
// Execute request
323+
$response = curl_exec($ch);
324+
$error = curl_error($ch);
325+
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
326+
327+
curl_close($ch);
328+
329+
if ($error) {
330+
Hm_Debug::add('cURL error in spam report request: ' . $error);
331+
return false;
332+
}
333+
334+
if ($http_code < 200 || $http_code >= 300) {
335+
Hm_Debug::add('HTTP error in spam report request: ' . $http_code);
336+
return false;
337+
}
338+
339+
return $response;
340+
} catch (Exception $e) {
341+
Hm_Debug::add('Exception in spam report request: ' . $e->getMessage());
342+
return false;
343+
}
344+
}
255345
}
256346
}
257347

modules/core/js_modules/Hm_MessagesStore.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,17 @@ class Hm_MessagesStore {
226226
Hm_Ajax.request(
227227
config,
228228
(response) => {
229-
response.sourceId = store.hashObject(config);
229+
if (response === false) {
230+
// Create a proper response object for failed requests
231+
response = {
232+
formatted_message_list: {},
233+
pages: 0,
234+
folder_status: {},
235+
sourceId: store.hashObject(config)
236+
};
237+
} else {
238+
response.sourceId = store.hashObject(config);
239+
}
230240
resolve(response);
231241
},
232242
[],

modules/imap/handler_modules.php

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,13 +2094,9 @@ function process_ceo_amount_limit_callback($val) { return $val; }
20942094
* @subpackage imap/handler
20952095
*/
20962096
class Hm_Handler_imap_report_spam extends Hm_Handler_Module {
2097-
/**
2098-
* Use IMAP to move the selected message to the junk folder
2099-
*/
21002097
public function process() {
21012098
try {
21022099
delayed_debug_log('Report Spam handler starting');
2103-
// Remove spam_reason from required fields
21042100
list($success, $form) = $this->process_form(array('imap_msg_uid', 'imap_server_id', 'folder'));
21052101
delayed_debug_log('Form processing result:', array('success' => $success, 'form' => $form));
21062102

@@ -2122,7 +2118,6 @@ public function process() {
21222118
$form_folder = hex2bin($form['folder']);
21232119
$errors = 0;
21242120
$status = null;
2125-
// Get spam_reason from form if it exists, otherwise use default
21262121
$spam_reason = isset($form['spam_reason']) && !empty($form['spam_reason']) ?
21272122
$form['spam_reason'] : 'No reason provided';
21282123

@@ -2167,6 +2162,36 @@ public function process() {
21672162
}
21682163

21692164
if (!$errors) {
2165+
// Get message headers for spam reporting
2166+
$headers = $mailbox->get_message_headers($form_folder, $form['imap_msg_uid']);
2167+
$message_data = array(
2168+
'uid' => $form['imap_msg_uid'],
2169+
'folder' => $form_folder,
2170+
'from' => isset($headers['From']) ? $headers['From'] : '',
2171+
'subject' => isset($headers['Subject']) ? $headers['Subject'] : '',
2172+
'headers' => $headers
2173+
);
2174+
2175+
// Report to enabled spam services
2176+
$report_results = array();
2177+
$enabled_services = get_enabled_spam_services();
2178+
foreach ($enabled_services as $service_name => $service_config) {
2179+
delayed_debug_log("Processing spam report for service: $service_name");
2180+
$reporter = Hm_Spam_Reporter_Factory::create($service_name, $mailbox, $message_data);
2181+
if ($reporter) {
2182+
$result = $reporter->report($spam_reason);
2183+
$report_results[$service_name] = $result;
2184+
delayed_debug_log("Report result for $service_name:", $result);
2185+
2186+
if ($result['success']) {
2187+
Hm_Msgs::add($result['message']);
2188+
} else {
2189+
Hm_Msgs::add($result['error'], 'warning');
2190+
}
2191+
}
2192+
}
2193+
2194+
// Move message to junk folder
21702195
delayed_debug_log('Attempting to move message to junk folder', array(
21712196
'from_folder' => $form_folder,
21722197
'to_folder' => $junk_folder,

modules/imap/modules.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
require_once APP_PATH.'modules/imap/functions.php';
1414
require_once APP_PATH.'modules/imap/hm-imap.php';
1515
require_once APP_PATH.'modules/imap/hm-jmap.php';
16+
require_once APP_PATH.'modules/imap/spam_report_config.php';
17+
require_once APP_PATH.'modules/imap/spam_report_services.php';
18+
require_once APP_PATH.'modules/imap/spam_report_utils.php';

0 commit comments

Comments
 (0)