Skip to content

Conversation

@Grandi0z
Copy link
Member

@Grandi0z Grandi0z commented Jun 17, 2025

realted task

This PR introduces a spam reporting system in Cypht, allowing users to report unwanted messages to multiple external services.

Report Spam Feature

A comprehensive spam reporting system that allows users to report unwanted emails to multiple anti-spam services directly from their inbox.

Key Features:

  • Privacy protection - Automatic sanitization removes user email addresses and sensitive headers before submission
  • Reason categorization - Select from 7 predefined categories (unsolicited, phishing, malicious, advertising, offensive, wrong recipient, other)
  • User-configurable - Enable/disable services individually with per-service settings
  • Rate limiting - Built-in protection for API-based services (AbuseIPDB)
  • Error handling - Comprehensive error reporting with service-specific feedback
    Multi-service reporting - is implemented but removed from the UI, because services have different requirements for it..

Servives

  • 📮 SpamCop (email-based)
  • 🛡️ AbuseIPDB (IP via API)
  • 💬 APWG (Anti-Phishing Working Group)

@Grandi0z Grandi0z force-pushed the cypht-add-feature-report-spam branch from 816d1fb to c615ecb Compare October 25, 2025 19:03
@marclaporte
Copy link
Member

@Grandi0z This is turning out to be a big PR :-)

It's still in draft but would you like some preliminary feedback from Victor ?

@Grandi0z
Copy link
Member Author

I agree, it’s a good idea and it should simplify the next step.

@Grandi0z This is turning out to be a big PR :-)

It's still in draft but would you like some preliminary feedback from Victor ?

@marclaporte marclaporte requested a review from kroky November 18, 2025 17:36
@kroky
Copy link
Member

kroky commented Nov 20, 2025

AI is not yet good enough to write such a complicated feature and I see minimal intervention from you after it generated the code. The code is quite misplaced, bloated and certainly having many more features than the requested in the related task you post. I won't even try to read it all.

My suggestion is:

  1. Keep it simple (KISS principle).
  2. Address the immediate need to report spam to external services.
  3. Refrain from doing too many things in one go/PR - like rate limiting, local blocking, sieve blocking, etc. These deserve proper planning, discussion and definitely distinct PRs.
  4. Try to add the code yourself and use AI as a helper - ask questions, ask for suggestions but rarely use the complete code it generates.

Some examples of code misplace:

  • php cli scripts in the main dir rather than in scripts. Not even sure we need all those.
  • implementation of sieve client inside this repo when we use a distinct repo for this
  • tests placed in the wrong dir

@Grandi0z
Copy link
Member Author

  1. Keep it simple (KISS principle).
  2. Address the immediate need to report spam to external services.
  3. Refrain from doing too many things in one go/PR - like rate limiting, local blocking, sieve blocking, etc. These deserve proper planning, discussion and definitely distinct PRs.
  4. Try to add the code yourself and use AI as a helper - ask questions, ask for suggestions but rarely use the complete code it generates.

Some examples of code misplace:

  • php cli scripts in the main dir rather than in scripts. Not even sure we need all those.
  • implementation of sieve client inside this repo when we use a distinct repo for this
  • tests placed in the wrong dir

I GOT THE MESSAGE.
I understand your point, but I don’t see the value in allowing spam reporting without applying at least local filtering (if we don’t want to integrate Sieve blocking).

In practice, we report spam because we don’t want to see that message anymore. Limiting the process to reporting to external services only, without local filtering, means the message remains in the inbox, which reduces the effectiveness of the mechanism.

Don’t you think we should keep at least some form of filtering in place somewhere?

@kroky
Copy link
Member

kroky commented Nov 21, 2025

Regarding local filtering and spam report - these are two quite distinct tasks and mechanisms. I didn't see local filtering request in the original task and since it is a different thing, I suggest you put it in another PR. Reporting spam allows spam services to get better, thus having mail servers prevent spam at its origin or during the routing of a message which overall reduces spam and makes things work better. We already have blocking lists and features in Cypht but those depend on Sieve - which again is a step ahead as filtering on the server is better than filtering on a client. Last effort here would be implementing local filtering as it has some drawbacks: works only on that instance of the webmail client, is slower and has a performance impact. However, it is still something useful when all other efforts fails, that's why I suggested you put it in a different PR.

@Grandi0z
Copy link
Member Author

AI is not yet good enough to write such a complicated feature and I see minimal intervention from you after it generated the code. The code is quite misplaced, bloated and certainly having many more features than the requested in the related task you post. I won't even try to read it all.

Hello @kroky , thank you for pointing out this detail. Indeed, the code was going a bit in all directions.

I am currently in the process of refactoring everything.
This merge request will only contain the part related to reporting to external services. It should be ready very soon.

I also want to apologize for having modified your comment. My ego was hurt, and I reacted in an unprofessional manner.

Thank you very much for your guidance and support.

@Grandi0z Grandi0z force-pushed the cypht-add-feature-report-spam branch from 81a9c01 to 3992ee4 Compare November 24, 2025 14:46
@kroky
Copy link
Member

kroky commented Nov 26, 2025

Thanks @Grandi0z , you are awesome! Looking forward to review the new code...
Also, if you feel like you are stuck somewhere and have any questions regarding the codebase and how things are done, feel free to ask questions.

@Grandi0z Grandi0z changed the title feat(frontend/backend) add feature report spam feat(frontend/backend): add feature report spam Nov 27, 2025
@Grandi0z Grandi0z force-pushed the cypht-add-feature-report-spam branch from 5425ecf to f4e3205 Compare November 27, 2025 12:47
@Grandi0z Grandi0z force-pushed the cypht-add-feature-report-spam branch from f4e3205 to 4babe26 Compare November 27, 2025 13:03
@Grandi0z Grandi0z marked this pull request as ready for review November 27, 2025 13:18
/**
* Starts the Report Spam section on the settings page
* @subpackage core/output
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature is already big enough that it deserves its own module. Please move everything from core and imap modules to a new module 'report_spam' or similar.

* @return array Array with 'mime_message', 'mime_body', and 'boundary'
*/
if (!hm_exists('fix_spam_report_encoding')) {
function fix_spam_report_encoding($mime_message, $service_name) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use a lib for this? I'd like to avoid all these low-lever regex operations if there is already a lib for this and we already are using mime manipulation libs + have a low-lever mime classes ourselves.

if (!hm_exists('send_spam_report_via_smtp')) {
function send_spam_report_via_smtp($from_email, $to_email, $subject, $mime_body, $boundary, $user_config, $session, $service_name, $use_fallback_smtp = false) {
if (!class_exists('Hm_SMTP_List')) {
$smtp_file = (defined('APP_PATH') ? APP_PATH : dirname(__FILE__) . '/../') . 'modules/smtp/hm-smtp.php';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tight coupling of modules that we want to avoid. When you move all this code to a new module, make it depends on both - imap and smtp. Add your new handler modules after existing smtp modules that already load the server list ,connect to server, etc. We don't want to repeat operations. We don't want to have lower-level smtp calls in a module outside smtp...

ini_set('default_socket_timeout', $timeout);

try {
$mail_sent = @mail($to_email, $subject, $mime_body, implode("\r\n", $headers));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If smtp fails, just fail. Cypht doesn't use php mail default function and configuring that properly is outside the scope of this task.

$mime_message = preg_replace('/^X-Mailer:.*$/mi', '', $mime_message);
$mime_message = preg_replace('/\r\n\r\n+/', "\r\n\r\n", $mime_message); // Clean up extra blank lines

$encoding_result = fix_spam_report_encoding($mime_message, 'SpamCop');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could probably use the right encoding in get_mime_msg above and spare the "fixing" part here which seems hacky...

* @return string|false IP address (IPv4 or IPv6) or false if not found
*/
if (!hm_exists('extract_ip_from_message')) {
function extract_ip_from_message($message_source) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imap module already has methods to return message headers. Please spare the low-level parsing of mime messages whenever possible.

'comment' => $comment
);

$ch = curl_init('https://api.abuseipdb.com/api/v2/report');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a lib/api curl client - can't you reuse it here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants