0
|
1 <?php
|
|
2
|
|
3 /**
|
|
4 * Filters
|
|
5 *
|
|
6 * Plugin that adds a new tab to the settings section to create client-side e-mail filtering.
|
|
7 *
|
|
8 * @version 2.1.6
|
|
9 * @author Roberto Zarrelli <zarrelli@unimol.it>
|
|
10 * @developer Artur Petrov <admin@gtn18.ru>
|
|
11 */
|
|
12
|
|
13 class filters extends rcube_plugin{
|
|
14
|
|
15 public $task = 'login|mail|settings';
|
|
16
|
|
17 private $autoAddSpamFilterRule;
|
|
18 private $spam_subject;
|
|
19 private $caseInsensitiveSearch;
|
|
20 private $decodeBase64Msg;
|
|
21 private $searchstring = array();
|
|
22 private $destfolder = array();
|
|
23 private $msg_uids = array();
|
|
24 private $open_mbox;
|
|
25
|
|
26
|
|
27 function init(){
|
|
28
|
|
29 /* Filters parameters initialization. See readme.txt */
|
|
30 $this->load_config();
|
|
31 /* ***************************************************** */
|
|
32
|
|
33 $rcmail = rcmail::get_instance();
|
|
34 $this->rc = &$rcmail;
|
|
35
|
|
36 $this->autoAddSpamFilterRule = $this->rc->config->get('autoAddSpamFilterRule',TRUE);
|
|
37 $this->spam_subject = $this->rc->config->get('spam_subject','[SPAM]');
|
|
38 $this->caseInsensitiveSearch = $this->rc->config->get('caseInsensitiveSearch',TRUE);
|
|
39 $this->decodeBase64Msg = $this->rc->config->get('decodeBase64Msg',FALSE);
|
|
40
|
|
41 if($this->rc->task == 'mail' && !isset($_GET["_q"]))
|
|
42 $this->add_hook('messages_list', array($this, 'filters_checkmsg'));
|
|
43 else if ($this->rc->task == 'settings'){
|
|
44 $this->register_action('plugin.filters', array($this, 'filters_init'));
|
|
45 $this->register_action('plugin.filters-save', array($this, 'filters_save'));
|
|
46 $this->register_action('plugin.filters-delete', array($this, 'filters_delete'));
|
|
47 $this->add_texts('localization/', array('filters','nosearchstring'));
|
|
48 $this->rc->output->add_label('filters');
|
|
49 $this->include_script('filters.js');
|
|
50 }
|
|
51 else if ($this->rc->task == 'login'){
|
|
52 if ($this->autoAddSpamFilterRule)
|
|
53 $this->add_hook('login_after', array($this, 'filters_addMoveSpamRule'));
|
|
54 }
|
|
55
|
|
56 }
|
|
57
|
|
58 function filters_checkmsg($mlist){
|
|
59 $user = $this->rc->user;
|
|
60 if (method_exists($this->rc->imap,'get_mailbox_name')) {
|
|
61 $imap = $this->rc->imap;
|
|
62 $open_mbox = $imap->get_mailbox_name();
|
|
63 }
|
|
64 else {
|
|
65 $imap = $this->rc->storage;
|
|
66 $open_mbox = $imap->get_folder();
|
|
67 }
|
|
68
|
|
69 $this->open_mbox=$open_mbox;
|
|
70
|
|
71 // does not consider the messages already in the trash
|
|
72 if ($open_mbox == $this->rc->config->get('trash_mbox'))
|
|
73 return;
|
|
74
|
|
75 //load filters
|
|
76 $arr_prefs = $this->rc->config->get('filters', array());
|
|
77
|
|
78 foreach ($arr_prefs as $key => $saved_filter){
|
|
79 // if saved destination folder exists and current folder is INBOX
|
|
80 if (method_exists($imap,'mailbox_exists')){
|
|
81 if ($imap->mailbox_exists($saved_filter['destfolder']) && 'INBOX'==$open_mbox){
|
|
82 $saved_filter['searchstring'] = html_entity_decode($saved_filter['searchstring']);
|
|
83 // if (!isset($saved_filter['filterpriority'])) $saved_filter['filterpriority'] = '';
|
|
84 // destfolder#messages#filterpriority#markread
|
|
85 $this->searchstring[ $saved_filter['whatfilter'] ][ $saved_filter['searchstring'] ] =
|
|
86 $saved_filter['destfolder']."#".$saved_filter['messages']."#".$saved_filter['filterpriority']."#".$saved_filter['markread'];
|
|
87 }
|
|
88 }
|
|
89 if (!method_exists($imap,'mailbox_exists')){
|
|
90 if ($imap->folder_exists($saved_filter['destfolder']) && 'INBOX'==$open_mbox){
|
|
91 $saved_filter['searchstring'] = html_entity_decode($saved_filter['searchstring']);
|
|
92 // if (!isset($saved_filter['filterpriority'])) $saved_filter['filterpriority'] = '';
|
|
93 // destfolder#messages#filterpriority#markread
|
|
94 $this->searchstring[ $saved_filter['whatfilter'] ][ $saved_filter['searchstring'] ] =
|
|
95 $saved_filter['destfolder']."#".$saved_filter['messages']."#".$saved_filter['filterpriority']."#".$saved_filter['markread'];
|
|
96 }
|
|
97 }
|
|
98 }
|
|
99 // if there aren't filters return
|
|
100 if(!count($arr_prefs) || !count($this->searchstring) || !isset($mlist['messages']) || !is_array($mlist['messages']))
|
|
101 return;
|
|
102
|
|
103 // scan the messages
|
|
104 foreach($mlist["messages"] as $message){
|
|
105 $this->filters_search($message);
|
|
106 }
|
|
107
|
|
108 // move the filtered messages
|
|
109 if (count($this->destfolder) > 0){
|
|
110 foreach ($this->destfolder as $dfolder){
|
|
111 $uids = array();
|
|
112 foreach ($this->msg_uids[$dfolder] as $muids){
|
|
113 $uids[] = $muids;
|
|
114 }
|
|
115 if (count($uids)){
|
|
116 $imap->move_message($uids, $dfolder, $open_mbox);
|
|
117 // refresh
|
|
118 $unseen = $this->rc->storage->count($dfolder, 'UNSEEN');
|
|
119 $this->api->output->command('set_unread_count',$dfolder, $unseen);
|
|
120 $this->api->output->command('list_mailbox');
|
|
121 $this->api->output->send();
|
|
122 }
|
|
123 }
|
|
124 }
|
|
125
|
|
126 }
|
|
127
|
|
128
|
|
129 function filters_init(){
|
|
130 $this->add_texts('localization/');
|
|
131 $this->register_handler('plugin.body', array($this, 'filters_form'));
|
|
132 $this->rc->output->set_pagetitle($this->gettext('filters'));
|
|
133 $this->rc->output->send('plugin');
|
|
134 }
|
|
135
|
|
136 function filters_save(){
|
|
137 $user = $this->rc->user;
|
|
138
|
|
139 $this->add_texts('localization/');
|
|
140 $this->register_handler('plugin.body', array($this, 'filters_form'));
|
|
141 $this->rc->output->set_pagetitle($this->gettext('filters'));
|
|
142
|
|
143 $searchstring = trim(rcube_utils::get_input_value('_searchstring', RCUBE_INPUT_POST, true));
|
|
144 $destfolder = trim(rcube_utils::get_input_value('_folders', RCUBE_INPUT_POST, true));
|
|
145 $whatfilter = trim(rcube_utils::get_input_value('_whatfilter', RCUBE_INPUT_POST, true));
|
|
146 $messages = trim(rcube_utils::get_input_value('_messages', RCUBE_INPUT_POST, true));
|
|
147 $filterpriority = trim(rcube_utils::get_input_value('_checkbox', RCUBE_INPUT_POST, true));
|
|
148 $markread = trim(rcube_utils::get_input_value('_markread', RCUBE_INPUT_POST, true));
|
|
149
|
|
150 if ($searchstring == "")
|
|
151 $this->rc->output->command('display_message', $this->gettext('nosearchstring'), 'error');
|
|
152 else{
|
|
153 $new_arr['whatfilter'] = $whatfilter;
|
|
154 $new_arr['searchstring'] = htmlspecialchars(addslashes($searchstring));
|
|
155 $new_arr['destfolder'] = addslashes($destfolder);
|
|
156 $new_arr['messages'] = $messages;
|
|
157 $new_arr['filterpriority'] = $filterpriority;
|
|
158 $new_arr['markread'] = $markread;
|
|
159 $arr_prefs = $user->get_prefs();
|
|
160 $arr_prefs['filters'][] = $new_arr;
|
|
161 if ($user->save_prefs($arr_prefs))
|
|
162 $this->rc->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation');
|
|
163 else
|
|
164 $this->rc->output->command('display_message', $this->gettext('unsuccessfullysaved'), 'error');
|
|
165 }
|
|
166 $this->rc->overwrite_action('plugin.filters');
|
|
167 $this->rc->output->send('plugin');
|
|
168 }
|
|
169
|
|
170 function filters_delete(){
|
|
171 $user = $this->rc->user;
|
|
172
|
|
173 $this->add_texts('localization/');
|
|
174 $this->register_handler('plugin.body', array($this, 'filters_form'));
|
|
175 $this->rc->output->set_pagetitle($this->gettext('filters'));
|
|
176
|
|
177 if (isset($_GET[filterid])){
|
|
178 $filter_id = $_GET[filterid];
|
|
179 $arr_prefs = $user->get_prefs();
|
|
180 $arr_prefs['filters'][$filter_id] = '';
|
|
181 $arr_prefs['filters'] = array_diff($arr_prefs['filters'], array(''));
|
|
182 if ($user->save_prefs($arr_prefs))
|
|
183 $this->rc->output->command('display_message', $this->gettext('successfullydeleted'), 'confirmation');
|
|
184 else
|
|
185 $this->rc->output->command('display_message', $this->gettext('unsuccessfullydeleted'), 'error');
|
|
186 }
|
|
187
|
|
188 if (function_exists('rcmail::get_instance()->overwrite_action'))
|
|
189 rcmail::get_instance()->overwrite_action('plugin.filters');
|
|
190 else $this->rc->overwrite_action('plugin.filters');
|
|
191
|
|
192 $this->rc->output->send('plugin');
|
|
193 }
|
|
194
|
|
195 function filters_form(){
|
|
196
|
|
197 if (method_exists($this->rc,'imap_connect')) $this->rc->imap_connect();
|
|
198 else $this->rc->storage_connect();
|
|
199
|
|
200 $table = new html_table(array('cols' => 2));
|
|
201 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('whatfilter').":", 'html'));
|
|
202
|
|
203 $select = new html_select(array('name' => '_whatfilter', 'id' => 'whatfilter'));
|
|
204 $select->add($this->gettext('from'), 'from');
|
|
205 $select->add($this->gettext('to'), 'to');
|
|
206 $select->add($this->gettext('cc'), 'cc');
|
|
207 $select->add($this->gettext('subject'), 'subject');
|
|
208 $table->add('', $select->show($this->gettext('from')));
|
|
209
|
|
210 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('searchstring').":"), 'html');
|
|
211 $inputfield = new html_inputfield(array('name' => '_searchstring', 'id' => 'searchstring'));
|
|
212 $table->add('', $inputfield->show(""));
|
|
213
|
|
214 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('moveto').":"));
|
|
215 if (function_exists('rcmail::get_instance()->folder_selector'))
|
|
216 $select = rcmail::get_instance()->folder_selector(array('name' => '_folders', 'id' => 'folders'));
|
|
217 else $select = $this->rc->folder_selector(array('name' => '_folders', 'id' => 'folders'));
|
|
218 $table->add('title', $select->show());
|
|
219
|
|
220 # new option: all, read and unread messages
|
|
221 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('messagecount').":"), 'html');
|
|
222 $select = new html_select(array('name' => '_messages', 'id' => 'messages'));
|
|
223 $select->add($this->gettext('all'), 'all');
|
|
224 $select->add($this->gettext('unread'), 'unread');
|
|
225 $select->add($this->gettext('isread'), 'isread');
|
|
226 $table->add('', $select->show($this->gettext('all')));
|
|
227
|
|
228 # new option: markread or markunread messages
|
|
229 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('markmessages').":"), 'html');
|
|
230 $select = new html_select(array('name' => '_markread', 'id' => 'markread'));
|
|
231 $select->add($this->gettext('none'), 'none');
|
|
232 $select->add($this->gettext('markunread'), 'markunread');
|
|
233 $select->add($this->gettext('markread'), 'markread');
|
|
234 $table->add('', $select->show($this->gettext('none')));
|
|
235
|
|
236 # new option: filter priority, "on" as enable and "" as disable
|
|
237 $table->add('title', rcube_utils::rep_specialchars_output($this->gettext('filterpriority').":"), 'html');
|
|
238 $checkbox = new html_checkbox(array('name' => '_checkbox', 'id' => 'checkbox'));
|
|
239 $table->add('', $checkbox->show("0"));
|
|
240
|
|
241 // load saved filters
|
|
242 $user = $this->rc->user;
|
|
243 $arr_prefs = $user->get_prefs();
|
|
244 $i = 1;
|
|
245 $flag=false;
|
|
246 $table2 = new html_table(array('cols' => 2));
|
|
247 foreach ($arr_prefs['filters'] as $key => $saved_filter){
|
|
248 $flag=true;
|
|
249 if (empty($saved_filter['markread'])) $saved_filter['markread'] = 'none';
|
|
250 $folder_id = $saved_filter['destfolder'];
|
|
251 if (function_exists('rcmail::get_instance()->localize_folderpath'))
|
|
252 $folder_name = rcmail::get_instance()->localize_folderpath($folder_id);
|
|
253 else $folder_name = $this->rc->localize_folderpath($folder_id);
|
|
254
|
|
255 $messages = $saved_filter['messages'];
|
|
256
|
|
257 $msg = $i." - ".$this->gettext('msg_if_field')." <b>".$this->gettext($saved_filter['whatfilter'])."</b> ".$this->gettext('msg_contains').
|
|
258 " <b>".stripslashes($saved_filter['searchstring'])."</b> ".
|
|
259 $this->gettext('msg_move_msg_in')." <b>".$folder_name."</b> ".
|
|
260 "(".$this->gettext('messagecount').": ".$this->gettext($saved_filter['messages']).
|
|
261 ", ".$this->gettext('mark').": ".$this->gettext($saved_filter['markread']).")";
|
|
262 if ( !empty($saved_filter['filterpriority']))
|
|
263 $msg = "<font color='green'>".$msg."</font>";
|
|
264
|
|
265 $table2->add('title',$msg);
|
|
266 $dlink = "<a href='./?_task=settings&_action=plugin.filters-delete&filterid=".$key."'>".$this->gettext('delete')."</a>";
|
|
267 $table2->add('title',$dlink);
|
|
268 $i++;
|
|
269 }
|
|
270
|
|
271 if (!$flag){
|
|
272 $table2->add('title',rcube_utils::rep_specialchars_output($this->gettext('msg_no_stored_filters'), 'html'));
|
|
273 }
|
|
274
|
|
275 $out = html::div(array('class' => 'box'),
|
|
276 html::div(array('id' => 'prefs-title', 'class' => 'boxtitle'), $this->gettext('filters')) .
|
|
277 html::div(array('class' => 'boxcontent'), $table->show() .
|
|
278 html::p(null,
|
|
279 $this->rc->output->button(array(
|
|
280 'command' => 'plugin.filters-save',
|
|
281 'type' => 'input',
|
|
282 'class' => 'button mainaction',
|
|
283 'label' => 'save'
|
|
284 )))));
|
|
285 $out.= html::div(array('id' => 'prefs-title','class' => 'boxtitle'), $this->gettext('storedfilters')). html::div(array('class' => 'uibox listbox scroller','style'=>'margin-top:250px;'),
|
|
286 html::div(array('class' => 'boxcontent'), $table2->show() ));
|
|
287
|
|
288 $this->rc->output->add_gui_object('filtersform', 'filters-form');
|
|
289
|
|
290 return $this->rc->output->form_tag(array(
|
|
291 'id' => 'filters-form',
|
|
292 'name' => 'filters-form',
|
|
293 'method' => 'post',
|
|
294 'class' => 'propform',
|
|
295 'action' => './?_task=settings&_action=plugin.filters-save',
|
|
296 ), $out);
|
|
297
|
|
298 }
|
|
299
|
|
300 function filters_search($message){
|
|
301 // check if a message has been read
|
|
302 if (isset($message->flags['SEEN']) && $message->flags['SEEN'])
|
|
303 $msg_read = 1;
|
|
304 $headers = array('from','to','cc','subject');
|
|
305 $destination_folder = '';
|
|
306 $filter_flag = '';
|
|
307 $mark_flag = '';
|
|
308 foreach($headers as $whatfilter){
|
|
309 if (isset($this->searchstring[$whatfilter])){
|
|
310 foreach ($this->searchstring[$whatfilter] as $from => $dest){
|
|
311 $arr = explode("#",$dest);
|
|
312 $destination = $arr[0];
|
|
313 $msg_filter = $arr[1];
|
|
314 $filterpriority = $arr[2];
|
|
315 $markread = $arr[3];
|
|
316
|
|
317 switch ($whatfilter){
|
|
318 case 'from':
|
|
319 $field = $message->from;
|
|
320 break;
|
|
321 case 'to':
|
|
322 $field = $message->to;
|
|
323 break;
|
|
324 case 'cc':
|
|
325 $field = $message->cc;
|
|
326 break;
|
|
327 case 'subject':
|
|
328 $field = $message->subject;
|
|
329 break;
|
|
330 default:
|
|
331 $field = "";
|
|
332 }
|
|
333
|
|
334 if ($this->filters_searchString($field, $from) != false && $destination!=$this->open_mbox){
|
|
335 if (!empty($filterpriority)){
|
|
336 $destination_folder = $destination;
|
|
337 $filter_flag = $msg_filter;
|
|
338 $mark_flag = $markread;
|
|
339 break 2;
|
|
340 }
|
|
341 if (empty($destination_folder)){
|
|
342 $destination_folder = $destination;
|
|
343 $filter_flag = $msg_filter;
|
|
344 $mark_flag = $markread;
|
|
345 }
|
|
346 }
|
|
347 }
|
|
348 }
|
|
349 }
|
|
350 if (!empty($destination_folder)){
|
|
351 // if message as read and need unread message, then exit from function
|
|
352 // Если сообщение как прочитанное и нужно непрочитанное сообщение, то выход из функции
|
|
353 if (!empty($msg_read) && $filter_flag == "unread") return;
|
|
354 // if message as unread and need read message, then exit from function
|
|
355 // Если сообщение как непрочитанное и нужно прочитанное сообщение, то выход из функции
|
|
356 if (empty($msg_read) && $filter_flag == "isread") return;
|
|
357 $this->msg_uids[$destination_folder][] = $message->uid;
|
|
358 if (!in_array($destination_folder, $this->destfolder)) $this->destfolder[] = $destination_folder;
|
|
359 // Mark message as read if need mark message as read
|
|
360 // Отметить сообщение как прочитанное
|
|
361 if ($mark_flag == "markread") $this->filters_markread($message);
|
|
362 // Mark message as unread if need mark message as unread
|
|
363 // Отметить сообщение как непрочитанное
|
|
364 if ($mark_flag == "markunread") $this->filters_markread($message,'UNSEEN');
|
|
365 }
|
|
366 }
|
|
367 // Mark message as read (SEEN) or as unread (UNSEEN)
|
|
368 function filters_markread($message,$markread='SEEN'){
|
|
369 $storage = $this->rc->storage;
|
|
370 $storage->set_flag($message->uid, $markread, NULL);
|
|
371 }
|
|
372
|
|
373 function filters_searchString($msg,$stringToSearch){
|
|
374 $ret = FALSE;
|
|
375
|
|
376 $ciSearch = $this->caseInsensitiveSearch;
|
|
377 $decode_msg = rcube_mime::decode_header((string)$msg);
|
|
378
|
|
379 $stringToSearch=stripslashes($stringToSearch);
|
|
380
|
|
381 $decode_msg = addslashes($decode_msg);
|
|
382 $stringToSearch = addslashes($stringToSearch);
|
|
383
|
|
384 if ($ciSearch){
|
|
385 if (function_exists('mb_stripos')){
|
|
386 $tmp = mb_stripos($decode_msg, $stringToSearch);
|
|
387 }
|
|
388 else{
|
|
389 $tmp = stripos($decode_msg, $stringToSearch);
|
|
390 }
|
|
391 }
|
|
392 else{
|
|
393 if (function_exists('mb_strpos')){
|
|
394 $tmp = mb_strpos($decode_msg, $stringToSearch);
|
|
395 }
|
|
396 else{
|
|
397 $tmp = strpos($decode_msg, $stringToSearch);
|
|
398 }
|
|
399 }
|
|
400
|
|
401 if ($tmp !== FALSE){
|
|
402 $ret = TRUE;
|
|
403 }
|
|
404
|
|
405 else{
|
|
406 if ($this->decodeBase64Msg === TRUE){
|
|
407 // decode and search BASE64 msg
|
|
408 $decode_msg = rcube_mime::decode_header(base64_decode($msg));
|
|
409
|
|
410 if ($decode_msg !== FALSE){
|
|
411
|
|
412 if ($ciSearch){
|
|
413 if (function_exists('mb_stripos')){
|
|
414 $tmp = mb_stripos($decode_msg, $stringToSearch);
|
|
415 }
|
|
416 else{
|
|
417 $tmp = stripos($decode_msg, $stringToSearch);
|
|
418 }
|
|
419 }
|
|
420 else{
|
|
421 if (function_exists('mb_strpos')){
|
|
422 $tmp = mb_strpos($decode_msg, $stringToSearch);
|
|
423 }
|
|
424 else{
|
|
425 $tmp = strpos($decode_msg, $stringToSearch);
|
|
426 }
|
|
427 }
|
|
428 if ($tmp !== FALSE){
|
|
429 $ret = TRUE;
|
|
430 }
|
|
431 }
|
|
432 }
|
|
433 }
|
|
434
|
|
435 return $ret;
|
|
436 }
|
|
437
|
|
438
|
|
439 function filters_addMoveSpamRule(){
|
|
440
|
|
441 $user = $this->rc->user;
|
|
442
|
|
443 $searchstring = $this->spam_subject;
|
|
444 $destfolder = $this->rc->config->get('junk_mbox', null);
|
|
445 $whatfilter = "subject";
|
|
446 $messages = "all";
|
|
447
|
|
448 //load filters
|
|
449 $arr_prefs = $this->rc->config->get('filters', array());
|
|
450
|
|
451 // check if the rule is already enabled
|
|
452 $found = false;
|
|
453 foreach ($arr_prefs as $key => $saved_filter){
|
|
454 if ($saved_filter['searchstring'] == $searchstring && $saved_filter['whatfilter'] == $whatfilter){
|
|
455 $found = true;
|
|
456 }
|
|
457 }
|
|
458
|
|
459 if (!$found && $destfolder !== null && $destfolder !== ""){
|
|
460 $new_arr['whatfilter'] = $whatfilter;
|
|
461 $new_arr['searchstring'] = $searchstring;
|
|
462 $new_arr['destfolder'] = $destfolder;
|
|
463 $new_arr['messages'] = $messages;
|
|
464 $arr_prefs = $user->get_prefs();
|
|
465 $arr_prefs['filters'][] = $new_arr;
|
|
466 $user->save_prefs($arr_prefs);
|
|
467 }
|
|
468 }
|
|
469
|
|
470 }
|
|
471 ?>
|