Integrate markasjunk2 features into markasjunk - marking as non-junk + learning engine (#6504)
parent
70657e34b0
commit
cb6c79e2dd
@ -0,0 +1,133 @@
|
||||
Roundcube Webmail MarkAsJunk Plugin
|
||||
===================================
|
||||
This plugin adds "mark as spam" or "mark as not spam" button to the message
|
||||
menu.
|
||||
|
||||
When not in the Junk mailbox:
|
||||
Messages are moved into the Junk mailbox and marked as read
|
||||
|
||||
When in the Junk mailbox:
|
||||
The buttons are changed to "mark as not spam" or "this message is not spam"
|
||||
and the message is moved to the Inbox
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This plugin is released under the [GNU General Public License Version 3+][gpl].
|
||||
|
||||
Even if skins might contain some programming work, they are not considered
|
||||
as a linked part of the plugin and therefore skins DO NOT fall under the
|
||||
provisions of the GPL license. See the README file located in the core skins
|
||||
folder for details on the skin license.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The default config file is plugins/markasjunk/config.inc.php.dist
|
||||
Rename this to plugins/markasjunk/config.inc.php
|
||||
|
||||
All config parameters are optional.
|
||||
|
||||
|
||||
The Learning Driver
|
||||
-------------------
|
||||
|
||||
The learning driver allows you to perform additional processing on each message
|
||||
marked as spam/ham. A driver must contain a class named markasjunk_{driver
|
||||
file name}. The class must contain 3 functions:
|
||||
|
||||
**spam:** This function should take 2 arguments: an array of UIDs of message(s)
|
||||
being marked as spam, the name of the mailbox containing those messages
|
||||
|
||||
**ham:** This function should take 2 arguments: an array of UIDs of message(s)
|
||||
being marked as ham, the name of the mailbox containing those messages
|
||||
|
||||
**init:** Optional, this function should take 0 arguments. eg: allows drivers
|
||||
to add JS to the page to control which of the spam/ham options are displayed.
|
||||
The `jsevents` driver is available to show how to use the JS events.
|
||||
|
||||
Several drivers are provided by default they are:
|
||||
|
||||
**cmd_learn:** This driver calls an external command (for example salearn) to
|
||||
process the message
|
||||
|
||||
**dir_learn:** This driver places a copy of the message in a predefined folder,
|
||||
for example to allow for processing later
|
||||
|
||||
**email_learn:** This driver emails the message either as an attachment or
|
||||
directly to a set address. This driver requires Roundcube 1.4 or above.
|
||||
|
||||
**sa_blacklist:** This driver adds the sender address of a spam message to the
|
||||
users blacklist (or whitelist of ham messages) Requires SAUserPrefs plugin
|
||||
|
||||
**amavis_blacklist:** This driver adds the sender address of a spam message to
|
||||
the users blacklist (or whitelist of ham messages) Requires Amacube plugin.
|
||||
Driver by Der-Jan
|
||||
|
||||
**sa_detach:** If the message is a Spamassassin spam report with the original
|
||||
email attached then this is detached and saved in the Inbox, the spam report is
|
||||
deleted
|
||||
|
||||
**edit_headers:** Edit the message headers. Headers are edited using
|
||||
preg_replace.
|
||||
|
||||
**WARNING:** Be sure to match the entire header line, including the name of the
|
||||
header, and include the ^ and $ and test carefully before use on real messages.
|
||||
This driver alters the message source
|
||||
|
||||
|
||||
Running multiple drivers
|
||||
------------------------
|
||||
|
||||
**WARNING:** This is very dangerous please always test carefully. Run multiple
|
||||
drivers at your own risk! It may be safer to create one driver that does
|
||||
everything you want.
|
||||
|
||||
It is possible to run multiple drivers when marking a message as spam/ham. For
|
||||
example running sa_blacklist followed by cmd_learn or edit_headers and
|
||||
cmd_learn. An [example multi-driver][multidriver] is available. This is a
|
||||
starting point only, it requires modification for individual cases.
|
||||
|
||||
|
||||
Spam learning commands
|
||||
----------------------
|
||||
|
||||
Spamassassin:
|
||||
|
||||
```sa-learn --spam --username=%u %f``` or
|
||||
```sa-learn --spam --prefs-file=/var/mail/%d/%l/.spamassassin/user_prefs %f```
|
||||
|
||||
|
||||
Ham learning commands
|
||||
---------------------
|
||||
|
||||
Spamassassin:
|
||||
|
||||
```sa-learn --ham --username=%u %f``` or
|
||||
```sa-learn --ham --prefs-file=/var/mail/%d/%l/.spamassassin/user_prefs %f```
|
||||
|
||||
|
||||
edit_headers example config
|
||||
---------------------------
|
||||
|
||||
**WARNING:** These are simple examples of how to configure the driver options,
|
||||
use at your own risk
|
||||
|
||||
```php
|
||||
$config['markasjunk_spam_patterns'] = array(
|
||||
'patterns' => array('/^(Subject:\s*)(.*)$/m'),
|
||||
'replacements' => array('$1[SPAM] $2')
|
||||
);
|
||||
```
|
||||
|
||||
```php
|
||||
$config['markasjunk_ham_patterns'] = array(
|
||||
'patterns' => array('/^(Subject:\s*)\[SPAM\](.*)$/m'),
|
||||
'replacements' => array('$1$2')
|
||||
);
|
||||
```
|
||||
|
||||
[gpl]: https://www.gnu.org/licenses/gpl.html
|
||||
[multidriver]: https://gist.github.com/johndoh/8173505
|
@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
// Learning driver
|
||||
// Use an external process such as sa-learn to learn from spam/ham messages. Default: null.
|
||||
// Please see the README for more information
|
||||
$config['markasjunk_learning_driver'] = null;
|
||||
|
||||
// Ham mailbox
|
||||
// Mailbox messages should be moved to when they are marked as ham. null = INBOX
|
||||
// set to FALSE to disable message moving
|
||||
$config['markasjunk_ham_mbox'] = null;
|
||||
|
||||
// Spam mailbox
|
||||
// Mailbox messages should be moved to when they are marked as spam.
|
||||
// null = the mailbox assigned as the spam folder in Roundcube settings
|
||||
// set to FALSE to disable message moving
|
||||
$config['markasjunk_spam_mbox'] = null;
|
||||
|
||||
// Mark messages as read when reporting them as spam
|
||||
$config['markasjunk_read_spam'] = false;
|
||||
|
||||
// Mark messages as unread when reporting them as ham
|
||||
$config['markasjunk_unread_ham'] = false;
|
||||
|
||||
// Add flag to messages marked as spam (flag will be removed when marking as ham)
|
||||
// If you do not want to use message flags set this to false
|
||||
$config['markasjunk_spam_flag'] = 'Junk';
|
||||
|
||||
// Add flag to messages marked as ham (flag will be removed when marking as spam)
|
||||
// If you do not want to use message flags set this to false
|
||||
$config['markasjunk_ham_flag'] = 'NonJunk';
|
||||
|
||||
// Write output from spam/ham commands to the log for debug
|
||||
$config['markasjunk_debug'] = false;
|
||||
|
||||
// The mark as spam/ham icon can either be displayed on the toolbar or as part of the mark messages menu.
|
||||
// Set to False to use Mark menu instead of the toolbar. Default: true.
|
||||
$config['markasjunk_toolbar'] = true;
|
||||
|
||||
// Learn any message moved to the spam mailbox as spam (not just when the button is pressed)
|
||||
$config['markasjunk_move_spam'] = false;
|
||||
|
||||
// Learn any message moved from the spam mailbox to the ham mailbox as ham (not just when the button is pressed)
|
||||
$config['markasjunk_move_ham'] = false;
|
||||
|
||||
// Some drivers create new copies of the target message(s), in this case the original message(s) will be deleted
|
||||
// Rather than deleting the message(s) (moving to Trash) setting this option true will cause the original message(s) to be permanently removed
|
||||
$config['markasjunk_permanently_remove'] = false;
|
||||
|
||||
// Display only a mark as spam button
|
||||
$config['markasjunk_spam_only'] = false;
|
||||
|
||||
// Activate markasjunk for selected mail hosts only. If this is not set all mail hosts are allowed.
|
||||
// Example: $config['markasjunk_allowed_hosts'] = array('mail1.domain.tld', 'mail2.domain.tld');
|
||||
$config['markasjunk_allowed_hosts'] = null;
|
||||
|
||||
// Load specific config for different mail hosts
|
||||
// Example: $config['markasjunk_host_config'] = array(
|
||||
// 'mail1.domain.tld' => 'mail1_config.inc.php',
|
||||
// 'mail2.domain.tld' => 'mail2_config.inc.php',
|
||||
// );
|
||||
$config['markasjunk_host_config'] = null;
|
||||
|
||||
// cmd_learn Driver options
|
||||
// ------------------------
|
||||
// The command used to learn that a message is spam
|
||||
// The command can contain the following macros that will be expanded as follows:
|
||||
// %u is replaced with the username (from the session info)
|
||||
// %l is replaced with the local part of the username (if the username is an email address)
|
||||
// %d is replaced with the domain part of the username (if the username is an email address or default mail domain if not)
|
||||
// %i is replaced with the email address from the user's default identity
|
||||
// %s is replaced with the email address the message is from
|
||||
// %f is replaced with the path to the message file
|
||||
// %h:<header name> is replaced with the content of that header from the message (lower case) eg: %h:x-dspam-signature
|
||||
// If you do not want to run the command set this to null
|
||||
$config['markasjunk_spam_cmd'] = null;
|
||||
|
||||
// The command used to learn that a message is ham
|
||||
// The command can contain the following macros that will be expanded as follows:
|
||||
// %u is replaced with the username (from the session info)
|
||||
// %l is replaced with the local part of the username (if the username is an email address)
|
||||
// %d is replaced with the domain part of the username (if the username is an email address or default mail domain if not)
|
||||
// %i is replaced with the email address from the user's default identity
|
||||
// %s is replaced with the email address the message is from
|
||||
// %f is replaced with the path to the message file
|
||||
// %h:<header name> is replaced with the content of that header from the message (lower case) eg: %h:x-dspam-signature
|
||||
// If you do not want to run the command set this to null
|
||||
$config['markasjunk_ham_cmd'] = null;
|
||||
|
||||
// dir_learn Driver options
|
||||
// ------------------------
|
||||
// The full path of the directory used to store spam (must be writable by webserver)
|
||||
$config['markasjunk_spam_dir'] = null;
|
||||
|
||||
// The full path of the directory used to store ham (must be writable by webserver)
|
||||
$config['markasjunk_ham_dir'] = null;
|
||||
|
||||
// The filename prefix
|
||||
// The filename can contain the following macros that will be expanded as follows:
|
||||
// %u is replaced with the username (from the session info)
|
||||
// %l is replaced with the local part of the username (if the username is an email address)
|
||||
// %d is replaced with the domain part of the username (if the username is an email address or default mail domain if not)
|
||||
// %t is replaced with the type of message (spam/ham)
|
||||
$config['markasjunk_filename'] = null;
|
||||
|
||||
// email_learn Driver options
|
||||
// --------------------------
|
||||
// The email address that spam messages will be sent to
|
||||
// The address can contain the following macros that will be expanded as follows:
|
||||
// %u is replaced with the username (from the session info)
|
||||
// %l is replaced with the local part of the username (if the username is an email address)
|
||||
// %d is replaced with the domain part of the username (if the username is an email address or default mail domain if not)
|
||||
// %i is replaced with the email address from the user's default identity
|
||||
// If you do not want to send an email set this to null
|
||||
$config['markasjunk_email_spam'] = null;
|
||||
|
||||
// The email address that ham messages will be sent to
|
||||
// The address can contain the following macros that will be expanded as follows:
|
||||
// %u is replaced with the username (from the session info)
|
||||
// %l is replaced with the local part of the username (if the username is an email address)
|
||||
// %d is replaced with the domain part of the username (if the username is an email address or default mail domain if not)
|
||||
// %i is replaced with the email address from the user's default identity
|
||||
// If you do not want to send an email set this to null
|
||||
$config['markasjunk_email_ham'] = null;
|
||||
|
||||
// Should the spam/ham message be sent as an attachment
|
||||
$config['markasjunk_email_attach'] = true;
|
||||
|
||||
// The email subject (when sending as attachment)
|
||||
// The subject can contain the following macros that will be expanded as follows:
|
||||
// %u is replaced with the username (from the session info)
|
||||
// %l is replaced with the local part of the username (if the username is an email address)
|
||||
// %d is replaced with the domain part of the username (if the username is an email address or default mail domain if not)
|
||||
// %t is replaced with the type of message (spam/ham)
|
||||
$config['markasjunk_email_subject'] = 'learn this message as %t';
|
||||
|
||||
// sa_blacklist Driver options
|
||||
// ---------------------------
|
||||
// Path to SAUserPrefs config file
|
||||
$config['markasjunk_sauserprefs_config'] = '../sauserprefs/config.inc.php';
|
||||
|
||||
// amavis_blacklist Driver options
|
||||
// ---------------------------
|
||||
// Path to amacube config file
|
||||
$config['markasjunk_amacube_config'] = '../amacube/config.inc.php';
|
||||
|
||||
// edit_headers Driver options
|
||||
// ---------------------------
|
||||
// Patterns to match and replace headers for spam messages
|
||||
// Replacement method uses preg_replace - http://www.php.net/manual/function.preg-replace.php
|
||||
// WARNING: Be sure to match the entire header line, including the name of the header, also use ^ and $ and the 'm' flag
|
||||
// see the README for an example
|
||||
// TEST CAREFULLY BEFORE USE ON REAL MESSAGES
|
||||
$config['markasjunk_spam_patterns'] = array(
|
||||
'patterns' => array(),
|
||||
'replacements' => array()
|
||||
);
|
||||
|
||||
// Patterns to match and replace headers for spam messages
|
||||
// Replacement method uses preg_replace - http://www.php.net/manual/function.preg-replace.php
|
||||
// WARNING: Be sure to match the entire header line, including the name of the header, also use ^ and $ and the 'm' flag
|
||||
// see the README for an example
|
||||
// TEST CAREFULLY BEFORE USE ON REAL MESSAGES
|
||||
$config['markasjunk_ham_patterns'] = array(
|
||||
'patterns' => array(),
|
||||
'replacements' => array()
|
||||
);
|
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* AmavisD Blacklist driver
|
||||
*
|
||||
* @version 1.0
|
||||
* @requires Amacube plugin
|
||||
*
|
||||
* @author Der-Jan
|
||||
*
|
||||
* Copyright (C) 2014 Der-Jan
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/* # 'SELECT wb'.
|
||||
* # ' FROM wblist JOIN mailaddr ON wblist.sid=mailaddr.id'.
|
||||
* # ' WHERE wblist.rid=? AND mailaddr.email IN (%k)'.
|
||||
* # ' ORDER BY mailaddr.priority DESC';
|
||||
*/
|
||||
|
||||
class markasjunk_amavis_blacklist
|
||||
{
|
||||
private $user_email = '';
|
||||
|
||||
public function spam($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_list($uids, true);
|
||||
}
|
||||
|
||||
public function ham($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_list($uids, false);
|
||||
}
|
||||
|
||||
private function _do_list($uids, $spam)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$this->user_email = $rcube->user->data['username'];
|
||||
|
||||
if (is_file($rcube->config->get('markasjunk_amacube_config')) && !$rcube->config->load_from_file($rcube->config->get('markasjunk_amacube_config'))) {
|
||||
rcube::raise_error(array('code' => 527, 'type' => 'php',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Failed to load config from " . $rcube->config->get('markasjunk_amacube_config')
|
||||
), true, false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$db = rcube_db::factory($rcube->config->get('amacube_db_dsn'), '', true);
|
||||
$db->set_debug((bool) $rcube->config->get('sql_debug'));
|
||||
$db->db_connect('w');
|
||||
|
||||
$debug = $rcube->config->get('markasjunk_debug');
|
||||
|
||||
// check DB connections and exit on failure
|
||||
if ($err_str = $db->is_error()) {
|
||||
rcube::raise_error(array(
|
||||
'code' => 603,
|
||||
'type' => 'db',
|
||||
'message' => $err_str
|
||||
), false, true);
|
||||
}
|
||||
|
||||
$sql_result = $db->query("SELECT `id` FROM `users` WHERE `email` = ?", $this->user_email);
|
||||
if ($sql_result && ($res_array = $db->fetch_assoc($sql_result))) {
|
||||
$rid = $res_array['id'];
|
||||
}
|
||||
else {
|
||||
if ($debug) {
|
||||
rcube::write_log('markasjunk', $this->user_email . ' not found in users table');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($uids as $uid) {
|
||||
$message = new rcube_message($uid);
|
||||
$email = $message->sender['mailto'];
|
||||
$sql_result = $db->query("SELECT `id` FROM `mailaddr` WHERE `email` = ? ORDER BY `priority` DESC", $email);
|
||||
|
||||
if ($sql_result && ($res_array = $db->fetch_assoc($sql_result))) {
|
||||
$sid = $res_array['id'];
|
||||
}
|
||||
else {
|
||||
if ($debug) {
|
||||
rcube::write_log('markasjunk', $email . ' not found in mailaddr table - add it');
|
||||
}
|
||||
|
||||
$sql_result = $db->query("INSERT INTO `mailaddr` ( `priority`, `email` ) VALUES ( 20, ? )", $email);
|
||||
if ($sql_result) {
|
||||
$sid = $db->insert_id();
|
||||
}
|
||||
else {
|
||||
if ($debug) {
|
||||
rcube::write_log('markasjunk', 'Cannot add ' . $email . ' to mailaddr table: ' . $db->is_error($sql_result));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$wb = '';
|
||||
$sql_result = $db->query("SELECT `wb` FROM `wblist` WHERE `sid` = ? AND `rid` =?", $sid, $rid);
|
||||
if ($sql_result && ($res_array = $db->fetch_assoc($sql_result))) {
|
||||
$wb = $res_array['wb'];
|
||||
}
|
||||
|
||||
if (!$wb || (!$spam && preg_match('/^([BbNnFf])[\s]*\z/', $wb)) || ($spam && preg_match('/^([WwYyTt])[\s]*\z/', $wb))) {
|
||||
$newwb = 'w';
|
||||
|
||||
if ($spam) {
|
||||
$newwb = 'b';
|
||||
}
|
||||
|
||||
if ($wb) {
|
||||
$sql_result = $db->query('UPDATE `wblist` SET `wb` = ? WHERE `sid` = ? AND `rid` = ?',
|
||||
$newwb, $sid, $rid);
|
||||
}
|
||||
else {
|
||||
$sql_result = $db->query('INSERT INTO `wblist` (`sid`, `rid`, `wb`) VALUES (?,?,?)',
|
||||
$sid, $rid, $newwb);
|
||||
}
|
||||
|
||||
if (!$sql_result) {
|
||||
if ($debug) {
|
||||
rcube::write_log('markasjunk', 'Cannot update wblist for user ' . $this->user_email . ' with ' . $email);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Command line learn driver
|
||||
*
|
||||
* @version 3.0
|
||||
*
|
||||
* @author Philip Weir
|
||||
* Patched by Julien Vehent to support DSPAM
|
||||
* Enhanced support for DSPAM by Stevan Bajic <stevan@bajic.ch>
|
||||
*
|
||||
* Copyright (C) 2009-2018 Philip Weir
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
class markasjunk_cmd_learn
|
||||
{
|
||||
public function spam($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_salearn($uids, true, $src_mbox);
|
||||
}
|
||||
|
||||
public function ham($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_salearn($uids, false, $src_mbox);
|
||||
}
|
||||
|
||||
private function _do_salearn($uids, $spam, $src_mbox)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$temp_dir = realpath($rcube->config->get('temp_dir'));
|
||||
$command = $rcube->config->get($spam ? 'markasjunk_spam_cmd' : 'markasjunk_ham_cmd');
|
||||
$debug = $rcube->config->get('markasjunk_debug');
|
||||
|
||||
if (!$command) {
|
||||
return;
|
||||
}
|
||||
|
||||
// backwards compatibility %xds removed in markasjunk v1.12
|
||||
$command = str_replace('%xds', '%h:x-dspam-signature', $command);
|
||||
$command = str_replace('%u', $_SESSION['username'], $command);
|
||||
$command = str_replace('%l', $rcube->user->get_username('local'), $command);
|
||||
$command = str_replace('%d', $rcube->user->get_username('domain'), $command);
|
||||
if (strpos($command, '%i') !== false) {
|
||||
$identity_arr = $rcube->user->get_identity();
|
||||
$command = str_replace('%i', $identity_arr['email'], $command);
|
||||
}
|
||||
|
||||
foreach ($uids as $uid) {
|
||||
// reset command for next message
|
||||
$tmp_command = $command;
|
||||
|
||||
if (strpos($tmp_command, '%s') !== false) {
|
||||
$message = new rcube_message($uid);
|
||||
$tmp_command = str_replace('%s', escapeshellarg($message->sender['mailto']), $tmp_command);
|
||||
}
|
||||
|
||||
if (strpos($command, '%h') !== false) {
|
||||
$storage = $rcube->get_storage();
|
||||
$storage->check_connection();
|
||||
$storage->conn->select($src_mbox);
|
||||
|
||||
preg_match_all('/%h:([\w-_]+)/', $tmp_command, $header_names, PREG_SET_ORDER);
|
||||
foreach ($header_names as $header) {
|
||||
$val = null;
|
||||
if ($msg = $storage->conn->fetchHeader($src_mbox, $uid, true, false, array($header[1]))) {
|
||||
$val = $msg->{$header[1]} ?: $msg->others[$header[1]];
|
||||
}
|
||||
|
||||
if (!empty($val)) {
|
||||
$tmp_command = str_replace($header[0], escapeshellarg($val), $tmp_command);
|
||||
}
|
||||
else {
|
||||
if ($debug) {
|
||||
rcube::write_log('markasjunk', 'header ' . $header[1] . ' not found in message ' . $src_mbox . '/' . $uid);
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strpos($command, '%f') !== false) {
|
||||
$tmpfname = tempnam($temp_dir, 'rcmSALearn');
|
||||
file_put_contents($tmpfname, $rcube->storage->get_raw_body($uid));
|
||||
$tmp_command = str_replace('%f', escapeshellarg($tmpfname), $tmp_command);
|
||||
}
|
||||
|
||||
$output = shell_exec($tmp_command);
|
||||
|
||||
if ($debug) {
|
||||
rcube::write_log('markasjunk', $tmp_command);
|
||||
rcube::write_log('markasjunk', $output);
|
||||
}
|
||||
|
||||
if (strpos($command, '%f') !== false) {
|
||||
unlink($tmpfname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copy spam/ham messages to a direcotry for learning later
|
||||
*
|
||||
* @version 2.0
|
||||
*
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) 2009-2014 Philip Weir
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
class markasjunk_dir_learn
|
||||
{
|
||||
public function spam($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_messagemove($uids, true);
|
||||
}
|
||||
|
||||
public function ham($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_messagemove($uids, false);
|
||||
}
|
||||
|
||||
private function _do_messagemove($uids, $spam)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$dest_dir = unslashify($rcube->config->get($spam ? 'markasjunk_spam_dir' : 'markasjunk_ham_dir'));
|
||||
|
||||
if (!$dest_dir) {
|
||||
return;
|
||||
}
|
||||
|
||||
$debug = $rcube->config->get('markasjunk_debug');
|
||||
$filename = $rcube->config->get('markasjunk_filename');
|
||||
$filename = str_replace('%u', $_SESSION['username'], $filename);
|
||||
$filename = str_replace('%t', ($spam) ? 'spam' : 'ham', $filename);
|
||||
$filename = str_replace('%l', $rcube->user->get_username('local'), $filename);
|
||||
$filename = str_replace('%d', $rcube->user->get_username('domain'), $filename);
|
||||
|
||||
foreach ($uids as $uid) {
|
||||
$tmpfname = tempnam($dest_dir, $filename);
|
||||
file_put_contents($tmpfname, $rcube->storage->get_raw_body($uid));
|
||||
|
||||
if ($debug) {
|
||||
rcube::write_log('markasjunk', $tmpfname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Edit headers
|
||||
*
|
||||
* @version 1.0
|
||||
*
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) 2012-2014 Philip Weir
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
class markasjunk_edit_headers
|
||||
{
|
||||
public function spam(&$uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_edit_headers($uids, true, $dst_mbox);
|
||||
}
|
||||
|
||||
public function ham(&$uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_edit_headers($uids, false, $dst_mbox);
|
||||
}
|
||||
|
||||
private function _edit_headers(&$uids, $spam, $dst_mbox)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$args = $rcube->config->get($spam ? 'markasjunk_spam_patterns' : 'markasjunk_ham_patterns');
|
||||
|
||||
if (count($args['patterns']) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$new_uids = array();
|
||||
foreach ($uids as $uid) {
|
||||
$raw_message = $rcube->storage->get_raw_body($uid);
|
||||
$raw_headers = $rcube->storage->get_raw_headers($uid);
|
||||
|
||||
$updated_headers = preg_replace($args['patterns'], $args['replacements'], $raw_headers);
|
||||
$raw_message = str_replace($raw_headers, $updated_headers, $raw_message);
|
||||
|
||||
$saved = $rcube->storage->save_message($dst_mbox, $raw_message);
|
||||
|
||||
if ($saved !== false) {
|
||||
$rcube->output->command('rcmail_markasjunk_move', null, $uid);
|
||||
array_push($new_uids, $saved);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($new_uids) > 0) {
|
||||
$uids = $new_uids;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Email learn driver
|
||||
*
|
||||
* @version 3.0
|
||||
*
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) 2009-2017 Philip Weir
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
class markasjunk_email_learn
|
||||
{
|
||||
private $rcube;
|
||||
|
||||
public function spam($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_emaillearn($uids, true);
|
||||
}
|
||||
|
||||
public function ham($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_emaillearn($uids, false);
|
||||
}
|
||||
|
||||
private function _do_emaillearn($uids, $spam)
|
||||
{
|
||||
$this->rcube = rcube::get_instance();
|
||||
$identity_arr = $this->rcube->user->get_identity();
|
||||
$from = $identity_arr['email'];
|
||||
$from_string = format_email_recipient($identity_arr['email'], $identity_arr['name']);
|
||||
$attach = $this->rcube->config->get('markasjunk_email_attach', false);
|
||||
$temp_dir = unslashify($this->rcube->config->get('temp_dir'));
|
||||
|
||||
$mailto = $this->rcube->config->get($spam ? 'markasjunk_email_spam' : 'markasjunk_email_ham');
|
||||
$mailto = $this->_parse_vars($mailto, $spam, $from);
|
||||
|
||||
// no address to send to, exit
|
||||
if (!$mailto) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subject = $this->rcube->config->get('markasjunk_email_subject');
|
||||
$subject = $this->_parse_vars($subject, $spam, $from);
|
||||
|
||||
foreach ($uids as $uid) {
|
||||
$MESSAGE = new rcube_message($uid);
|
||||
$message_file = null;
|
||||
|
||||
// set message charset as default
|
||||
if (!empty($MESSAGE->headers->charset)) {
|
||||
$this->rcube->storage->set_charset($MESSAGE->headers->charset);
|
||||
}
|
||||
|
||||
$OUTPUT = $this->rcube->output;
|
||||
$SENDMAIL = new rcmail_sendmail(null, array(
|
||||
'sendmail' => true,
|
||||
'from' => $from,
|
||||
'mailto' => $mailto,
|
||||
'dsn_enabled' => false,
|
||||
'charset' => 'UTF-8',
|
||||
'error_handler' => function() use ($OUTPUT) {
|
||||
call_user_func_array(array($OUTPUT, 'show_message'), func_get_args());
|
||||
$OUTPUT->send();
|
||||
}
|
||||
));
|
||||
|
||||
if ($attach) {
|
||||
$headers = array(
|
||||
'Date' => $this->rcube->user_date(),
|
||||
'From' => $from_string,
|
||||
'To' => $mailto,
|
||||
'Subject' => $subject,
|
||||
'User-Agent' => $this->rcube->config->get('useragent'),
|
||||
'Message-ID' => $this->rcube->gen_message_id($from),
|
||||
'X-Sender' => $from
|
||||
);
|
||||
|
||||
$message_text = ($spam ? 'Spam' : 'Ham') . ' report from ' . $this->rcube->config->get('product_name');
|
||||
|
||||
// create attachment
|
||||
$orig_subject = $MESSAGE->get_header('subject');
|
||||
$disp_name = (!empty($orig_subject) ? $orig_subject : 'message_rfc822') . '.eml';
|
||||
$message_file = tempnam($temp_dir, 'rcm');
|
||||
$attachment = array();
|
||||
|
||||
if ($fp = fopen($message_file, 'w')) {
|
||||
$this->rcube->storage->get_raw_body($uid, $fp);
|
||||
fclose($fp);
|
||||
|
||||
$attachment = array(
|
||||
'name' => $disp_name,
|
||||
'mimetype' => 'message/rfc822',
|
||||
'path' => $message_file,
|
||||
'size' => filesize($message_file),
|
||||
'charset' => $MESSAGE->headers->charset
|
||||
);
|
||||
}
|
||||
|
||||
// create message
|
||||
$MAIL_MIME = $SENDMAIL->create_message($headers, $message_text, false, array($attachment));
|
||||
|
||||
if (count($attachment) > 0) { // sanity check incase creating the attachment failed
|
||||
$folding = (int) $this->rcube->config->get('mime_param_folding');
|
||||
|
||||
$MAIL_MIME->addAttachment($attachment['path'],
|
||||
$attachment['mimetype'], $attachment['name'], true,
|
||||
'8bit', 'attachment', $attachment['charset'], '', '',
|
||||
$folding ? 'quoted-printable' : null,
|
||||
$folding == 2 ? 'quoted-printable' : null,
|
||||
'', RCUBE_CHARSET
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$headers = array(
|
||||
'Resent-From' => $from_string,
|
||||
'Resent-To' => $mailto,
|
||||
'Resent-Date' => $this->rcube->user_date(),
|
||||
'Resent-Message-ID' => $this->rcube->gen_message_id($from)
|
||||
);
|
||||
|
||||
// create the bounce message
|
||||
$MAIL_MIME = new rcmail_resend_mail(array(
|
||||
'bounce_message' => $MESSAGE,
|
||||
'bounce_headers' => $headers,
|
||||
));
|
||||
}
|
||||
|
||||
$SENDMAIL->deliver_message($MAIL_MIME);
|
||||
$message_file = $message_file ?: $MAIL_MIME->mailbody_file;
|
||||
|
||||
// clean up
|
||||
if ($message_file) {
|
||||
unlink($message_file);
|
||||
}
|
||||
|
||||
if ($this->rcube->config->get('markasjunk_debug')) {
|
||||
rcube::write_log('', $uid . ($spam ? ' SPAM ' : ' HAM ') . $mailto . ' (' . $subject . ')');
|
||||
|
||||
if ($smtp_error['vars']) {
|
||||
rcube::write_log('', $smtp_error['vars']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function _parse_vars($data, $spam, $from)
|
||||
{
|
||||
$data = str_replace('%u', $_SESSION['username'], $data);
|
||||
$data = str_replace('%t', $spam ? 'spam' : 'ham', $data);
|
||||
$data = str_replace('%l', $this->rcube->user->get_username('local'), $data);
|
||||
$data = str_replace('%d', $this->rcube->user->get_username('domain'), $data);
|
||||
$data = str_replace('%i', $from, $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* MarkAsJunk JS events example
|
||||
* This is an example of how to interact with the markasjunk JS event
|
||||
* markasjunk-update to change the spam/ham options shown for specific
|
||||
* folders
|
||||
*
|
||||
* @version 0.1
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) 2016 Philip Weir
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
class markasjunk_jsevent
|
||||
{
|
||||
private $addition_spam_folders = array('spam2', 'spam3');
|
||||
private $suspicious_folders = array('unknown1', 'unknown2');
|
||||
|
||||
public function init()
|
||||
{
|
||||
$js_addition_spam_folders = json_encode($this->addition_spam_folders);
|
||||
$js_suspicious_folders = json_encode($this->suspicious_folders);
|
||||
|
||||
$script = <<<EOL
|
||||
rcmail.addEventListener('markasjunk-update', function(props) {
|
||||
var addition_spam_folders = {$js_addition_spam_folders};
|
||||
var suspicious_folders = {$js_suspicious_folders};
|
||||
|
||||
// ignore this special code when in a multifolder listing
|
||||
if (rcmail.is_multifolder_listing())
|
||||
return;
|
||||
|
||||
if ($.inArray(rcmail.env.mailbox, addition_spam_folders) > -1) {
|
||||
props.disp.spam = false;
|
||||
props.disp.ham = true;
|
||||
}
|
||||
else if ($.inArray(rcmail.env.mailbox, suspicious_folders) > -1) {
|
||||
props.disp.spam = true;
|
||||
props.disp.ham = true;
|
||||
|
||||
// from here it is also possible to alter the buttons themselves...
|
||||
props.objs.spamobj.find('a > span').text('As possibly spam');
|
||||
}
|
||||
else {
|
||||
props.objs.spamobj.find('a > span').text(rcmail.get_label('markasjunk.markasjunk'));
|
||||
}
|
||||
|
||||
return props;
|
||||
});
|
||||
EOL;
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
$rcmail->output->add_script($script, 'docready');
|
||||
}
|
||||
|
||||
public function spam(&$uids, $mbox)
|
||||
{
|
||||
// Treat message as spam...
|
||||
}
|
||||
|
||||
public function ham(&$uids, $mbox)
|
||||
{
|
||||
// Treat message as ham...
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SpamAssassin Blacklist driver
|
||||
*
|
||||
* @version 2.0
|
||||
* @requires SAUserPrefs plugin
|
||||
*
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) 2010-2014 Philip Weir
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
class markasjunk_sa_blacklist
|
||||
{
|
||||
private $sa_user;
|
||||
private $sa_table;
|
||||
private $sa_username_field;
|
||||
private $sa_preference_field;
|
||||
private $sa_value_field;
|
||||
|
||||
public function spam($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_list($uids, true);
|
||||
}
|
||||
|
||||
public function ham($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$this->_do_list($uids, false);
|
||||
}
|
||||
|
||||
private function _do_list($uids, $spam)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$this->sa_user = $rcube->config->get('sauserprefs_userid', "%u");
|
||||
$this->sa_table = $rcube->config->get('sauserprefs_sql_table_name');
|
||||
$this->sa_username_field = $rcube->config->get('sauserprefs_sql_username_field');
|
||||
$this->sa_preference_field = $rcube->config->get('sauserprefs_sql_preference_field');
|
||||
$this->sa_value_field = $rcube->config->get('sauserprefs_sql_value_field');
|
||||
|
||||
$identity_arr = $rcube->user->get_identity();
|
||||
$identity = $identity_arr['email'];
|
||||
|
||||
$this->sa_user = str_replace('%u', $_SESSION['username'], $this->sa_user);
|
||||
$this->sa_user = str_replace('%l', $rcube->user->get_username('local'), $this->sa_user);
|
||||
$this->sa_user = str_replace('%d', $rcube->user->get_username('domain'), $this->sa_user);
|
||||
$this->sa_user = str_replace('%i', $identity, $this->sa_user);
|
||||
|
||||
if (is_file($rcube->config->get('markasjunk_sauserprefs_config')) && !$rcube->config->load_from_file($rcube->config->get('markasjunk_sauserprefs_config'))) {
|
||||
rcube::raise_error(array('code' => 527, 'type' => 'php',
|
||||
'file' => __FILE__, 'line' => __LINE__,
|
||||
'message' => "Failed to load config from " . $rcube->config->get('markasjunk_sauserprefs_config')
|
||||
), true, false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$db = rcube_db::factory($rcube->config->get('sauserprefs_db_dsnw'), $rcube->config->get('sauserprefs_db_dsnr'), $rcube->config->get('sauserprefs_db_persistent'));
|
||||
$db->set_debug((bool) $rcube->config->get('sql_debug'));
|
||||
$db->db_connect('w');
|
||||
|
||||
// check DB connections and exit on failure
|
||||
if ($err_str = $db->is_error()) {
|
||||
rcube::raise_error(array(
|
||||
'code' => 603,
|
||||
'type' => 'db',
|
||||
'message' => $err_str
|
||||
), false, true);
|
||||
}
|
||||
|
||||
foreach ($uids as $uid) {
|
||||
$message = new rcube_message($uid);
|
||||
$email = $message->sender['mailto'];
|
||||
|
||||
if ($spam) {
|
||||
// delete any whitelisting for this address
|
||||
$db->query(
|
||||
"DELETE FROM `{$this->sa_table}` WHERE `{$this->sa_username_field}` = ? AND `{$this->sa_preference_field}` = ? AND `{$this->sa_value_field}` = ?",
|
||||
$this->sa_user,
|
||||
'whitelist_from',
|
||||
$email);
|
||||
|
||||
// check address is not already blacklisted
|
||||
$sql_result = $db->query(
|
||||
"SELECT `value` FROM `{$this->sa_table}` WHERE `{$this->sa_username_field}` = ? AND `{$this->sa_preference_field}` = ? AND `{$this->sa_value_field}` = ?",
|
||||
$this->sa_user,
|
||||
'blacklist_from',
|
||||
$email);
|
||||
|
||||
if (!$db->fetch_array($sql_result)) {
|
||||
$db->query(
|
||||
"INSERT INTO `{$this->sa_table}` (`{$this->sa_username_field}`, `{$this->sa_preference_field}`, `{$this->sa_value_field}`) VALUES (?, ?, ?)",
|
||||
$this->sa_user,
|
||||
'blacklist_from',
|
||||
$email);
|
||||
|
||||
if ($rcube->config->get('markasjunk_debug')) {
|
||||
rcube::write_log('markasjunk', $this->sa_user . ' blacklist ' . $email);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// delete any blacklisting for this address
|
||||
$db->query(
|
||||
"DELETE FROM `{$this->sa_table}` WHERE `{$this->sa_username_field}` = ? AND `{$this->sa_preference_field}` = ? AND `{$this->sa_value_field}` = ?",
|
||||
$this->sa_user,
|
||||
'blacklist_from',
|
||||
$email);
|
||||
|
||||
// check address is not already whitelisted
|
||||
$sql_result = $db->query(
|
||||
"SELECT `value` FROM `{$this->sa_table}` WHERE `{$this->sa_username_field}` = ? AND `{$this->sa_preference_field}` = ? AND `{$this->sa_value_field}` = ?",
|
||||
$this->sa_user,
|
||||
'whitelist_from',
|
||||
$email);
|
||||
|
||||
if (!$db->fetch_array($sql_result)) {
|
||||
$db->query(
|
||||
"INSERT INTO `{$this->sa_table}` (`{$this->sa_username_field}`, `{$this->sa_preference_field}`, `{$this->sa_value_field}`) VALUES (?, ?, ?)",
|
||||
$this->sa_user,
|
||||
'whitelist_from',
|
||||
$email);
|
||||
|
||||
if ($rcube->config->get('markasjunk_debug')) {
|
||||
rcube::write_log('markasjunk', $this->sa_user . ' whitelist ' . $email);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SpamAssassin detach ham driver
|
||||
*
|
||||
* @version 2.0
|
||||
*
|
||||
* @author Philip Weir
|
||||
*
|
||||
* Copyright (C) 2011-2014 Philip Weir
|
||||
*
|
||||
* This driver is part of the MarkASJunk plugin for Roundcube.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
class markasjunk_sa_detach
|
||||
{
|
||||
public function spam($uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public function ham(&$uids, $src_mbox, $dst_mbox)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$storage = $rcube->storage;
|
||||
$new_uids = array();
|
||||
|
||||
foreach ($uids as $uid) {
|
||||
$saved = false;
|
||||
$message = new rcube_message($uid);
|
||||
|
||||
if (count($message->attachments) > 0) {
|
||||
foreach ($message->attachments as $part) {
|
||||
if ($part->ctype_primary == 'message' && $part->ctype_secondary == 'rfc822' && $part->ctype_parameters['x-spam-type'] == 'original') {
|
||||
$orig_message_raw = $message->get_part_body($part->mime_id);
|
||||
|
||||
if ($saved = $storage->save_message($dst_mbox, $orig_message_raw)) {
|
||||
$rcube->output->command('rcmail_markasjunk_move', null, $uid);
|
||||
array_push($new_uids, $saved);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($new_uids) > 0) {
|
||||
$uids = $new_uids;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +1,321 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Mark as Junk
|
||||
* MarkAsJunk
|
||||
*
|
||||
* Sample plugin that adds a new button to the mailbox toolbar
|
||||
* A plugin that adds a new button to the mailbox toolbar
|
||||
* to mark the selected messages as Junk and move them to the Junk folder
|
||||
* or to move messages in the Junk folder to the inbox - moving only the
|
||||
* attachment if it is a Spamassassin spam report email
|
||||
*
|
||||
* @license GNU GPLv3+
|
||||
* @author Philip Weir
|
||||
* @author Thomas Bruederli
|
||||
*
|
||||
* Copyright (C) 2009-2018 The Roundcube Dev Team
|
||||
* Copyright (C) 2009-2018 Philip Weir
|
||||
*
|
||||
* This program is a Roundcube (https://roundcube.net) plugin.
|
||||
* For more information see README.md.
|
||||
* For configuration see config.inc.php.dist.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Roundcube. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
class markasjunk extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail';
|
||||
|
||||
function init()
|
||||
private $rcube;
|
||||
private $spam_mbox;
|
||||
private $ham_mbox;
|
||||
private $flags = array(
|
||||
'JUNK' => 'Junk',
|
||||
'NONJUNK' => 'NonJunk'
|
||||
);
|
||||
|
||||
|
||||
public function init()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$this->register_action('plugin.markasjunk.junk', array($this, 'mark_message'));
|
||||
$this->register_action('plugin.markasjunk.not_junk', array($this, 'mark_message'));
|
||||
|
||||
$this->register_action('plugin.markasjunk', array($this, 'request_action'));
|
||||
$this->add_hook('storage_init', array($this, 'storage_init'));
|
||||
$this->rcube = rcube::get_instance();
|
||||
$this->load_config();
|
||||
$this->_load_host_config();
|
||||
|
||||
if ($rcmail->action == '' || $rcmail->action == 'show') {
|
||||
$this->add_texts('localization', true);
|
||||
// Host exceptions
|
||||
$hosts = $this->rcube->config->get('markasjunk_allowed_hosts');
|
||||
if (!empty($hosts) && !in_array($_SESSION['storage_host'], (array) $hosts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->ham_mbox = $this->rcube->config->get('markasjunk_ham_mbox', 'INBOX');
|
||||
$this->spam_mbox = $this->rcube->config->get('markasjunk_spam_mbox', $this->rcube->config->get('junk_mbox'));
|
||||
$toolbar = $this->rcube->config->get('markasjunk_toolbar', true);
|
||||
$this->_init_flags();
|
||||
|
||||
if ($this->rcube->action == '' || $this->rcube->action == 'show') {
|
||||
$this->include_script('markasjunk.js');
|
||||
$this->add_texts('localization', true);
|
||||
$this->include_stylesheet($this->local_skin_path() . '/markasjunk.css');
|
||||
|
||||
$this->add_button(array(
|
||||
'type' => 'link',
|
||||
'label' => 'buttontext',
|
||||
'command' => 'plugin.markasjunk',
|
||||
'title' => 'buttontitle',
|
||||
'domain' => 'markasjunk',
|
||||
'class' => 'button buttonPas junk disabled',
|
||||
'classact' => 'button junk',
|
||||
'innerclass' => 'inner',
|
||||
),'toolbar');
|
||||
if ($toolbar) {
|
||||
// add the buttons to the main toolbar
|
||||
$this->add_button(array(
|
||||
'command' => 'plugin.markasjunk.junk',
|
||||
'type' => 'link',
|
||||
'class' => 'button buttonPas junk disabled',
|
||||
'classact' => 'button junk',
|
||||
'classsel' => 'button junk pressed',
|
||||
'title' => 'markasjunk.buttonjunk',
|
||||
'innerclass' => 'inner',
|
||||
'label' => 'junk'
|
||||
), 'toolbar');
|
||||
|
||||
$this->add_button(array(
|
||||
'command' => 'plugin.markasjunk.not_junk',
|
||||
'type' => 'link',
|
||||
'class' => 'button buttonPas notjunk disabled',
|
||||
'classact' => 'button notjunk',
|
||||
'classsel' => 'button notjunk pressed',
|
||||
'title' => 'markasjunk.buttonnotjunk',
|
||||
'innerclass' => 'inner',
|
||||
'label' => 'markasjunk.notjunk'
|
||||
), 'toolbar');
|
||||
}
|
||||
else {
|
||||
// add the buttons to the mark message menu
|
||||
$this->add_button(array(
|
||||
'command' => 'plugin.markasjunk.junk',
|
||||
'type' => 'link-menuitem',
|
||||
'label' => 'markasjunk.asjunk',
|
||||
'id' => 'markasjunk',
|
||||
'class' => 'icon junk',
|
||||
'classact' => 'icon junk active',
|
||||
'innerclass' => 'icon junk'
|
||||
), 'markmenu');
|
||||
|
||||
$this->add_button(array(
|
||||
'command' => 'plugin.markasjunk.not_junk',
|
||||
'type' => 'link-menuitem',
|
||||
'label' => 'markasjunk.asnotjunk',
|
||||
'id' => 'markasnotjunk',
|
||||
'class' => 'icon notjunk',
|
||||
'classact' => 'icon notjunk active',
|
||||
'innerclass' => 'icon notjunk'
|
||||
), 'markmenu');
|
||||
}
|
||||
|
||||
// add markasjunk folder settings to the env for JS
|
||||
$this->rcube->output->set_env('markasjunk_ham_mailbox', $this->ham_mbox);
|
||||
$this->rcube->output->set_env('markasjunk_spam_mailbox', $this->spam_mbox);
|
||||
$this->rcube->output->set_env('markasjunk_move_spam', $this->rcube->config->get('markasjunk_move_spam', false));
|
||||
$this->rcube->output->set_env('markasjunk_move_ham', $this->rcube->config->get('markasjunk_move_ham', false));
|
||||
$this->rcube->output->set_env('markasjunk_permanently_remove', $this->rcube->config->get('markasjunk_permanently_remove', false));
|
||||
$this->rcube->output->set_env('markasjunk_spam_only', $this->rcube->config->get('markasjunk_spam_only', false));
|
||||
|
||||
// check for init method from driver
|
||||
$this->_call_driver('init');
|
||||
}
|
||||
}
|
||||
|
||||
public function mark_message()
|
||||
{
|
||||
$this->add_texts('localization');
|
||||
|
||||
$is_spam = $this->rcube->action == 'plugin.markasjunk.junk' ? true : false;
|
||||
$messageset = rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST);
|
||||
$mbox_name = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_POST);
|
||||
$dest_mbox = $is_spam ? $this->spam_mbox : $this->ham_mbox;
|
||||
$result = $is_spam ? $this->_spam($messageset, $dest_mbox) : $this->_ham($messageset, $dest_mbox);
|
||||
|
||||
if ($result) {
|
||||
if ($dest_mbox && ($mbox_name !== $dest_mbox || $multifolder)) {
|
||||
$this->rcube->output->command('rcmail_markasjunk_move', $dest_mbox, $this->_messageset_to_uids($messageset, $multifolder));
|
||||
}
|
||||
else {
|
||||
$this->rcube->output->command('command', 'list', $mbox_name);
|
||||
}
|
||||
|
||||
$this->rcube->output->command('display_message', $is_spam ? $this->gettext('reportedasjunk') : $this->gettext('reportedasnotjunk'), 'confirmation');
|
||||
}
|
||||
|
||||
$this->rcube->output->send();
|
||||
}
|
||||
|
||||
public function set_flags($p)
|
||||
{
|
||||
$p['message_flags'] = array_merge((array) $p['message_flags'], $this->flags);
|
||||
|
||||
return $p;
|
||||
}
|
||||
|
||||
function storage_init($args)
|
||||
private function _spam(&$messageset, $dest_mbox = null)
|
||||
{
|
||||
$flags = array(
|
||||
'JUNK' => 'Junk',
|
||||
'NONJUNK' => 'NonJunk',
|
||||
);
|
||||
$storage = $this->rcube->get_storage();
|
||||
$result = true;
|
||||
|
||||
// register message flags
|
||||
$args['message_flags'] = array_merge((array)$args['message_flags'], $flags);
|
||||
foreach ($messageset as $source_mbox => &$uids) {
|
||||
$storage->set_folder($source_mbox);
|
||||
|
||||
return $args;
|
||||
$result = $this->_call_driver('spam', $uids, $source_mbox, $dest_mbox);
|
||||
|
||||
// abort function of the driver says so
|
||||
if (!$result) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->rcube->config->get('markasjunk_read_spam', false)) {
|
||||
$storage->set_flag($uids, 'SEEN', $source_mbox);
|
||||
}
|
||||
|
||||
if (array_key_exists('JUNK', $this->flags)) {
|
||||
$storage->set_flag($uids, 'JUNK', $source_mbox);
|
||||
}
|
||||
|
||||
if (array_key_exists('NONJUNK', $this->flags)) {
|
||||
$storage->unset_flag($uids, 'NONJUNK', $source_mbox);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
function request_action()
|
||||
private function _ham(&$messageset, $dest_mbox = null)
|
||||
{
|
||||
$this->add_texts('localization');
|
||||
$storage = $this->rcube->get_storage();
|
||||
$result = true;
|
||||
|
||||
foreach ($messageset as $source_mbox => &$uids) {
|
||||
$storage->set_folder($source_mbox);
|
||||
|
||||
$result = $this->_call_driver('ham', $uids, $source_mbox, $dest_mbox);
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
$storage = $rcmail->get_storage();
|
||||
// abort function of the driver says so
|
||||
if (!$result) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (rcmail::get_uids(null, null, $multifolder, rcube_utils::INPUT_POST) as $mbox => $uids) {
|
||||
$storage->unset_flag($uids, 'NONJUNK', $mbox);
|
||||
$storage->set_flag($uids, 'JUNK', $mbox);
|
||||
if ($this->rcube->config->get('markasjunk_unread_ham', false)) {
|
||||
$storage->unset_flag($uids, 'SEEN', $source_mbox);
|
||||
}
|
||||
|
||||
if (array_key_exists('JUNK', $this->flags)) {
|
||||
$storage->unset_flag($uids, 'JUNK', $source_mbox);
|
||||
}
|
||||
|
||||
if (array_key_exists('NONJUNK', $this->flags)) {
|
||||
$storage->set_flag($uids, 'NONJUNK', $source_mbox);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function _call_driver($action, &$uids = null, $source_mbox = null, $dest_mbox = null)
|
||||
{
|
||||
$driver_name = $this->rcube->config->get('markasjunk_learning_driver');
|
||||
|
||||
if (empty($driver_name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$driver = $this->home . "/drivers/$driver_name.php";
|
||||
$class = "markasjunk_$driver_name";
|
||||
|
||||
if (!is_readable($driver)) {
|
||||
rcube::raise_error(array(
|
||||
'code' => 600,
|
||||
'type' => 'php',
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "markasjunk plugin: Unable to open driver file $driver"
|
||||
), true, false);
|
||||
}
|
||||
|
||||
include_once $driver;
|
||||
|
||||
if (!class_exists($class, false) || !method_exists($class, 'spam') || !method_exists($class, 'ham')) {
|
||||
rcube::raise_error(array(
|
||||
'code' => 600,
|
||||
'type' => 'php',
|
||||
'file' => __FILE__,
|
||||
'line' => __LINE__,
|
||||
'message' => "markasjunk plugin: Broken driver: $driver"
|
||||
), true, false);
|
||||
}
|
||||
|
||||
// call the relevant function from the driver
|
||||
$object = new $class();
|
||||
if ($action == 'spam') {
|
||||
$object->spam($uids, $source_mbox, $dest_mbox);
|
||||
}
|
||||
elseif ($action == 'ham') {
|
||||
$object->ham($uids, $source_mbox, $dest_mbox);
|
||||
}
|
||||
elseif ($action == 'init' && method_exists($object, 'init')) { // method_exists check here for backwards compatibility
|
||||
$object->init();
|
||||
}
|
||||
|
||||
return $object->is_error ? false : true;
|
||||
}
|
||||
|
||||
private function _messageset_to_uids($messageset, $multifolder)
|
||||
{
|
||||
$a_uids = array();
|
||||
|
||||
foreach ($messageset as $mbox => $uids) {
|
||||
foreach ($uids as $uid) {
|
||||
$a_uids[] = $multifolder ? $uid . '-' . $mbox : $uid;
|
||||
}
|
||||
}
|
||||
|
||||
if (($junk_mbox = $rcmail->config->get('junk_mbox'))) {
|
||||
$rcmail->output->command('move_messages', $junk_mbox);
|
||||
return $a_uids;
|
||||
}
|
||||
|
||||
private function _load_host_config()
|
||||
{
|
||||
$configs = $this->rcube->config->get('markasjunk_host_config');
|
||||
if (empty($configs) || !array_key_exists($_SESSION['storage_host'], (array) $configs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rcmail->output->command('display_message', $this->gettext('reportedasjunk'), 'confirmation');
|
||||
$rcmail->output->send();
|
||||
$file = $configs[$_SESSION['storage_host']];
|
||||
$this->load_config($file);
|
||||
}
|
||||
|
||||
private function _init_flags()
|
||||
{
|
||||
$spam_flag = $this->rcube->config->get('markasjunk_spam_flag');
|
||||
$ham_flag = $this->rcube->config->get('markasjunk_ham_flag');
|
||||
|
||||
if ($spam_flag === false) {
|
||||
unset($this->flags['JUNK']);
|
||||
}
|
||||
elseif (!empty($spam_flag)) {
|
||||
$this->flags['JUNK'] = $spam_flag;
|
||||
}
|
||||
|
||||
if ($ham_flag === false) {
|
||||
unset($this->flags['NONJUNK']);
|
||||
}
|
||||
elseif (!empty($ham_flag)) {
|
||||
$this->flags['NONJUNK'] = $ham_flag;
|
||||
}
|
||||
|
||||
if (count($this->flags) > 0) {
|
||||
// register the ham/spam flags with the core
|
||||
$this->add_hook('storage_init', array($this, 'set_flags'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
@ -1,6 +1,43 @@
|
||||
#messagetoolbar a.junk,
|
||||
#messagetoolbar a.notjunk
|
||||
{
|
||||
text-indent: -5000px;
|
||||
background-image: url(images/mail_toolbar.png);
|
||||
}
|
||||
|
||||
#messagetoolbar a.junk
|
||||
{
|
||||
background-position: -32px 0;
|
||||
}
|
||||
|
||||
#messagetoolbar a.junk.pressed
|
||||
{
|
||||
background-position: -32px -32px;
|
||||
}
|
||||
|
||||
#messagetoolbar a.notjunk
|
||||
{
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
#messagetoolbar a.notjunk.pressed
|
||||
{
|
||||
background-position: 0 -32px;
|
||||
}
|
||||
|
||||
#messagetoolbar a.button.junk {
|
||||
text-indent: -5000px;
|
||||
background: url(junk_act.png) 0 0 no-repeat;
|
||||
ul.toolbarmenu li a.junk,
|
||||
ul.toolbarmenu li a.notjunk
|
||||
{
|
||||
background-image: url(images/messageactions.png) !important;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
ul.toolbarmenu li a.junk
|
||||
{
|
||||
background-position: 6px -17px !important;
|
||||
}
|
||||
|
||||
ul.toolbarmenu li a.notjunk
|
||||
{
|
||||
background-position: 6px 1px !important;
|
||||
}
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 1014 B |
Binary file not shown.
After Width: | Height: | Size: 640 B |
@ -0,0 +1,31 @@
|
||||
#messagetoolbar a.junk,
|
||||
#messagetoolbar a.notjunk
|
||||
{
|
||||
background-image: url(images/mail_toolbar.png);
|
||||
}
|
||||
|
||||
#messagetoolbar a.junk
|
||||
{
|
||||
background-position: center -14px;
|
||||
}
|
||||
|
||||
#messagetoolbar a.notjunk
|
||||
{
|
||||
background-position: center -61px;
|
||||
}
|
||||
|
||||
ul.toolbarmenu li a.junk span.icon,
|
||||
ul.toolbarmenu li a.notjunk span.icon
|
||||
{
|
||||
background-image: url(images/messageactions.png) !important;
|
||||
}
|
||||
|
||||
ul.toolbarmenu li a.junk span.icon
|
||||
{
|
||||
background-position: 1px -17px !important;
|
||||
}
|
||||
|
||||
ul.toolbarmenu li a.notjunk span.icon
|
||||
{
|
||||
background-position: 1px 4px !important;
|
||||
}
|
Loading…
Reference in New Issue