"Fossies" - the Fresh Open Source Software Archive

Member "ispconfig3_install/server/plugins-available/rspamd_plugin.inc.php" (8 Jun 2021, 21840 Bytes) of package /linux/privat/ISPConfig-3.2.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "rspamd_plugin.inc.php": 3.2.4_vs_3.2.5.

    1 <?php
    2 
    3 /*
    4 Copyright (c) 2018, Falko Timme, Timme Hosting GmbH & Co. KG
    5 All rights reserved.
    6 
    7 Redistribution and use in source and binary forms, with or without modification,
    8 are permitted provided that the following conditions are met:
    9 
   10     * Redistributions of source code must retain the above copyright notice,
   11       this list of conditions and the following disclaimer.
   12     * Redistributions in binary form must reproduce the above copyright notice,
   13       this list of conditions and the following disclaimer in the documentation
   14       and/or other materials provided with the distribution.
   15     * Neither the name of ISPConfig nor the names of its contributors
   16       may be used to endorse or promote products derived from this software without
   17       specific prior written permission.
   18 
   19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   22 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
   23 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
   26 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   27 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   28 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29 */
   30 
   31 class rspamd_plugin {
   32 
   33     var $plugin_name = 'rspamd_plugin';
   34     var $class_name  = 'rspamd_plugin';
   35     var $users_config_dir = '/etc/rspamd/local.d/users/';
   36 
   37     //* This function is called during ispconfig installation to determine
   38     //  if a symlink shall be created for this plugin.
   39     function onInstall() {
   40         global $conf;
   41 
   42         if($conf['services']['mail'] == true) {
   43             return true;
   44         } else {
   45             return false;
   46         }
   47     }
   48 
   49     private function isValidEmail($email) {
   50         $atIndex = strrpos($email, '@');
   51         if($atIndex === false) {
   52             return false;
   53         }
   54 
   55         $domain = substr($email, $atIndex + 1);
   56         $local = substr($email, 0, $atIndex);
   57         $localLen = strlen($local);
   58         $domainLen = strlen($domain);
   59         if($localLen > 64) {
   60             return false;
   61         } elseif($domainLen < 1 || $domainLen > 255) {
   62             return false;
   63         } elseif(substr($local, 0, 1) == '.' || substr($local, -1, 1) == '.') {
   64             return false; // first or last sign is dot
   65         } elseif(strpos($local, '..') !== false) {
   66             return false; // two dots not allowed
   67         } elseif(!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
   68             return false; // invalid character
   69         } elseif(strpos($domain, '..') !== false) {
   70             return false; // two dots not allowed
   71         } elseif($local && !preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\", "", $local))) {
   72             // character not valid in local part unless
   73             // local part is quoted
   74             if(!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\", "", $local))) {
   75                 return false;
   76             }
   77         }
   78 
   79         $domain_array = explode('.', $domain);
   80         for($i = 0; $i < count($domain_array); $i++) {
   81             if(!preg_match("/^(([A-Za-z0-9!#$%&'*+\/=?^_`{|}~-][A-Za-z0-9!#$%&'*+\/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$/", $domain_array[$i])) {
   82                 return false;
   83             }
   84         }
   85 
   86         if(!preg_match("/^\[?[0-9\.]+\]?$/", $domain)) {
   87             $domain_array = explode('.', $domain);
   88             if(count($domain_array) < 2) {
   89                 return false; // Not enough parts to domain
   90             }
   91 
   92             for($i = 0; $i < count($domain_array); $i++) {
   93                 if(!preg_match("/^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$/", $domain_array[$i])) {
   94                     return false;
   95                 }
   96             }
   97         }
   98 
   99         return true;
  100     }
  101 
  102     /*
  103         This function is called when the plugin is loaded
  104     */
  105 
  106     function onLoad() {
  107         global $app;
  108 
  109         /*
  110         Register for the events
  111         */
  112 
  113         //* spamfilter_wblist
  114         $app->plugins->registerEvent('spamfilter_wblist_insert', $this->plugin_name, 'spamfilter_wblist_insert');
  115         $app->plugins->registerEvent('spamfilter_wblist_update', $this->plugin_name, 'spamfilter_wblist_update');
  116         $app->plugins->registerEvent('spamfilter_wblist_delete', $this->plugin_name, 'spamfilter_wblist_delete');
  117 
  118         //* global mail access filters
  119         $app->plugins->registerEvent('mail_access_insert', $this->plugin_name, 'spamfilter_wblist_insert');
  120         $app->plugins->registerEvent('mail_access_update', $this->plugin_name, 'spamfilter_wblist_update');
  121         $app->plugins->registerEvent('mail_access_delete', $this->plugin_name, 'spamfilter_wblist_delete');
  122 
  123         //* server
  124         $app->plugins->registerEvent('server_insert', $this->plugin_name, 'server_update');
  125         $app->plugins->registerEvent('server_update', $this->plugin_name, 'server_update');
  126 
  127         //* server ip
  128         $app->plugins->registerEvent('server_ip_insert', $this->plugin_name, 'server_update');
  129         $app->plugins->registerEvent('server_ip_update', $this->plugin_name, 'server_update');
  130         $app->plugins->registerEvent('server_ip_delete', $this->plugin_name, 'server_update');
  131 
  132         //* spamfilter_users
  133         $app->plugins->registerEvent('spamfilter_users_insert', $this->plugin_name, 'user_settings_update');
  134         $app->plugins->registerEvent('spamfilter_users_update', $this->plugin_name, 'user_settings_update');
  135         $app->plugins->registerEvent('spamfilter_users_delete', $this->plugin_name, 'user_settings_update');
  136 
  137         //* mail user / fwd / catchall changed (greylisting)
  138         $app->plugins->registerEvent('mail_user_insert', $this->plugin_name, 'user_settings_update');
  139         $app->plugins->registerEvent('mail_user_update', $this->plugin_name, 'user_settings_update');
  140         $app->plugins->registerEvent('mail_user_delete', $this->plugin_name, 'user_settings_update');
  141         $app->plugins->registerEvent('mail_forwarding_insert', $this->plugin_name, 'user_settings_update');
  142         $app->plugins->registerEvent('mail_forwarding_update', $this->plugin_name, 'user_settings_update');
  143         $app->plugins->registerEvent('mail_forwarding_delete', $this->plugin_name, 'user_settings_update');
  144     }
  145 
  146     function user_settings_update($event_name, $data, $internal = false) {
  147         global $app, $conf;
  148 
  149         if(!is_dir('/etc/rspamd')) {
  150             return;
  151         }
  152 
  153         $use_data = 'new';
  154         if(substr($event_name, -7) === '_delete') {
  155             $mode = 'delete';
  156             $use_data = 'old';
  157         } elseif(substr($event_name, -7) === '_insert') {
  158             $mode = 'insert';
  159         } else {
  160             $mode = 'update';
  161         }
  162 
  163         // get the config
  164         $app->uses('getconf,system,functions');
  165         $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
  166 
  167         $type = false;
  168         $identifier = false;
  169         $entry_id = false;
  170         if(substr($event_name, 0, 17) === 'spamfilter_users_') {
  171             $identifier = 'email';
  172             $type = 'spamfilter_user';
  173             $entry_id = $data[$use_data]['id'];
  174         } elseif(substr($event_name, 0, 16) === 'mail_forwarding_') {
  175             $identifier = 'source';
  176             $type = 'mail_forwarding';
  177             $entry_id = $data[$use_data]['forwarding_id'];
  178         } elseif(substr($event_name, 0, 10) === 'mail_user_') {
  179             $identifier = 'email';
  180             $type = 'mail_user';
  181             $entry_id = $data[$use_data]['mailuser_id'];
  182         } else {
  183             // invalid event
  184             $app->log('Invalid event name for rspamd_plugin: ' . $event_name, LOGLEVEL_WARN);
  185             return;
  186         }
  187 
  188         $is_domain = false;
  189         $email_address = $data[$use_data][$identifier];
  190         $settings_name =  $email_address;
  191         if($email_address === '*@' || $email_address === '@') {
  192             // we will ignore those global targets
  193             $app->log('Ignoring @ spamfilter_user as rspamd does not support it this way.', LOGLEVEL_DEBUG);
  194             return;
  195         } elseif(!$email_address) {
  196             // problem reading identifier
  197             $app->log('Empty email address in rspamd_plugin from identifier: ' . $use_data . '/' . $identifier, LOGLEVEL_WARN);
  198             return;
  199         } elseif(substr($email_address, 0, 1) === '@') {
  200             $settings_name = substr($email_address, 1);
  201             $is_domain = true;
  202         } elseif(strpos($email_address, '@') === false) {
  203             $email_address = '@' . $email_address;
  204             $is_domain = true;
  205         }
  206 
  207         $app->log("rspamd: user_settings_update() for $type $email_address", LOGLEVEL_DEBUG);
  208 
  209         if($settings_name == '') {
  210             // missing settings file name
  211             $app->log('Empty rspamd identifier in rspamd_plugin from identifier: ' . $use_data . '/' . $identifier, LOGLEVEL_WARN);
  212             return;
  213         }
  214 
  215         $entries_to_update = [
  216             'mail_user' => [],
  217             'mail_forwarding' => []
  218         ];
  219         if($is_domain === true) {
  220             // get all child records to update / delete
  221             $mailusers = $app->db->queryAllRecords("SELECT mu.* FROM mail_user as mu LEFT JOIN spamfilter_users as su ON (su.email = mu.email) WHERE mu.email LIKE ? AND su.id IS NULL", '%' . $email_address);
  222             if(is_array($mailusers) && !empty($mailusers)) {
  223                 $entries_to_update['mail_user'] = $mailusers;
  224             }
  225 
  226             $forwardings = $app->db->queryAllRecords("SELECT mf.* FROM mail_forwarding as mf LEFT JOIN spamfilter_users as su ON (su.email = mf.source) WHERE mf.source LIKE ? AND su.id IS NULL", '%_' . $email_address);
  227             if(is_array($forwardings) && !empty($forwardings)) {
  228                 $entries_to_update['mail_forwarding'] = $forwardings;
  229             }
  230         }
  231 
  232         $old_settings_name = $settings_name;
  233         $settings_name = $app->functions->idn_encode($settings_name);
  234 
  235         if($old_settings_name !== $settings_name) {
  236             // we changed naming to idn-encoded form due to path check issues. Delete old file if existing.
  237             $old_settings_file = $this->users_config_dir . str_replace('@', '_', $old_settings_name) . '.conf';
  238             if(is_file($old_settings_file)) {
  239                 unlink($old_settings_file);
  240             }
  241         }
  242 
  243         $settings_file = $this->users_config_dir . str_replace('@', '_', $settings_name) . '.conf';
  244         //$app->log('Settings file for rspamd is ' . $settings_file, LOGLEVEL_WARN);
  245         if($mode === 'delete') {
  246             $delete_file = true;
  247             if($type === 'spamfilter_user') {
  248                 $search_for_policy[] = $email_address;
  249                 $search_for_policy[] = substr($email_address, strpos($email_address, '@'));
  250 
  251                 $policy = $app->db->queryOneRecord("SELECT p.* FROM spamfilter_users as u INNER JOIN spamfilter_policy as p ON (p.id = u.policy_id) WHERE u.server_id = ? AND u.email IN ? ORDER BY u.priority DESC", $conf['server_id'], $search_for_policy);
  252                 if($policy) {
  253                     $delete_file = false;
  254                 }
  255             }
  256             if($delete_file === true && is_file($settings_file)) {
  257                 unlink($settings_file);
  258             }
  259         } else {
  260             if(isset($data[$use_data]['priority'])) {
  261                 $settings_priority = ($is_domain ? 10 : 20) + intval($data[$use_data]['priority']);
  262             } else {
  263                 $settings_priority = ($is_domain ? 10 : 20) + 5;
  264             }
  265 
  266             // get policy for entry
  267             if($type === 'spamfilter_user') {
  268                 $policy = $app->db->queryOneRecord("SELECT * FROM spamfilter_policy WHERE id = ?", intval($data['new']['policy_id']));
  269 
  270                 $check = $app->db->queryOneRecord('SELECT `greylisting` FROM `mail_user` WHERE `server_id` = ? AND `email` = ? UNION SELECT `greylisting` FROM `mail_forwarding` WHERE `server_id` = ? AND `source` = ? ORDER BY (`greylisting` = ?) DESC', $conf['server_id'], $email_address, $conf['server_id'], $email_address, 'y');
  271                 if($check) {
  272                     $greylisting = $check['greylisting'];
  273                 } else {
  274                     $greylisting = 'n';
  275                 }
  276             } else {
  277                 $search_for_policy[] = $email_address;
  278                 $search_for_policy[] = substr($email_address, strpos($email_address, '@'));
  279 
  280                 $policy = $app->db->queryOneRecord("SELECT p.* FROM spamfilter_users as u INNER JOIN spamfilter_policy as p ON (p.id = u.policy_id) WHERE u.server_id = ? AND u.email IN ? ORDER BY u.priority DESC", $conf['server_id'], $search_for_policy);
  281 
  282                 $greylisting = $data[$use_data]['greylisting'];
  283             }
  284 
  285             if(!is_dir($this->users_config_dir)){
  286                 $app->system->mkdirpath($this->users_config_dir);
  287             }
  288 
  289             if(!$this->isValidEmail($app->functions->idn_encode($email_address))) {
  290                 if(is_file($settings_file)) {
  291                     unlink($settings_file);
  292                 }
  293             } else {
  294 
  295                 $app->load('tpl');
  296 
  297                 $tpl = new tpl();
  298                 if (file_exists($conf['rootpath']."/conf-custom/install/rspamd_users.inc.conf.master")) {
  299                     $tpl->newTemplate($conf['rootpath']."/conf-custom/install/rspamd_users.inc.conf.master");
  300                 } else {
  301                     $tpl->newTemplate("rspamd_users.inc.conf.master");
  302                 }
  303 
  304                 $tpl->setVar('record_identifier', 'ispc_' . $type . '_' . $entry_id);
  305                 $tpl->setVar('priority', $settings_priority);
  306 
  307                 if($type === 'spamfilter_user') {
  308                     if($data[$use_data]['local'] === 'Y') {
  309                         $tpl->setVar('to_email', $app->functions->idn_encode($email_address));
  310                     } else {
  311                         $tpl->setVar('from_email', $app->functions->idn_encode($email_address));
  312                     }
  313                     $spamfilter = $data[$use_data];
  314                 } else {
  315                     $tpl->setVar('to_email', $app->functions->idn_encode($email_address));
  316 
  317                     // need to get matching spamfilter user if any
  318                     $spamfilter = $app->db->queryOneRecord('SELECT * FROM spamfilter_users WHERE `email` = ?', $email_address);
  319                 }
  320 
  321                 if(!isset($policy['rspamd_spam_tag_level'])) {
  322                     $policy['rspamd_spam_tag_level'] = 6.0;
  323                 }
  324                 if(!isset($policy['rspamd_spam_tag_method'])) {
  325                     $policy['rspamd_spam_tag_method'] = 'add_header';
  326                 }
  327                 if(!isset($policy['rspamd_spam_kill_level'])) {
  328                     $policy['rspamd_spam_kill_level'] = 15.0;
  329                 }
  330                 if(!isset($policy['rspamd_virus_kill_level'])) {
  331                     $policy['rspamd_virus_kill_level'] = floatval($policy['rspamd_spam_kill_level']) + 1000;
  332                 }
  333 
  334                 $tpl->setVar('rspamd_spam_tag_level', floatval($policy['rspamd_spam_tag_level']));
  335                 $tpl->setVar('rspamd_spam_tag_method', $policy['rspamd_spam_tag_method']);
  336                 $tpl->setVar('rspamd_spam_kill_level', floatval($policy['rspamd_spam_kill_level']));
  337                 $tpl->setVar('rspamd_virus_kill_level', floatval($policy['rspamd_spam_kill_level']) + 1000);
  338 
  339                 if(isset($policy['spam_lover']) && $policy['spam_lover'] == 'Y') {
  340                     $tpl->setVar('spam_lover', true);
  341                 }
  342                 if(isset($policy['virus_lover']) && $policy['virus_lover'] == 'Y') {
  343                     $tpl->setVar('virus_lover', true);
  344                 }
  345 
  346                 $tpl->setVar('greylisting', $greylisting);
  347 
  348                 if(isset($policy['rspamd_spam_greylisting_level'])) {
  349                     $tpl->setVar('greylisting_level', floatval($policy['rspamd_spam_greylisting_level']));
  350                 } else {
  351                     $tpl->setVar('greylisting_level', 0.1);
  352                 }
  353 
  354                 $app->system->file_put_contents($settings_file, $tpl->grab());
  355             }
  356         }
  357 
  358         if($is_domain === true) {
  359             foreach($entries_to_update['mail_user'] as $entry) {
  360                 $this->user_settings_update('mail_user_' . $mode, ['old' => $entry, 'new' => $entry], true);
  361             }
  362             foreach($entries_to_update['mail_forwarding'] as $entry) {
  363                 $this->user_settings_update('mail_forwarding_' . $mode, ['old' => $entry, 'new' => $entry], true);
  364             }
  365         }
  366 
  367         if($internal !== true && $mail_config['content_filter'] == 'rspamd'){
  368             $app->services->restartServiceDelayed('rspamd', 'reload');
  369         }
  370     }
  371 
  372     function spamfilter_wblist_insert($event_name, $data) {
  373         $this->action = 'insert';
  374         // just run the spamfilter_wblist_update function
  375         $this->spamfilter_wblist_update($event_name, $data);
  376     }
  377 
  378     function spamfilter_wblist_update($event_name, $data) {
  379         global $app, $conf;
  380 
  381         $app->uses('getconf,system,functions');
  382         $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
  383 
  384         if(is_dir('/etc/rspamd')) {
  385             $global_filter = false;
  386             //* Create the config file
  387             $filter = null;
  388             if($event_name === 'mail_access_insert' || $event_name === 'mail_access_update') {
  389                 $global_filter = true;
  390                 $record_id = intval($data['new']['access_id']);
  391                 $wblist_file = $this->users_config_dir.'global_wblist_'.$record_id.'.conf';
  392                 $filter = array(
  393                     'wb' => ($data['new']['access'] === 'OK' ? 'W' : 'B'),
  394                     'from' => ($data['new']['type'] === 'sender' ? $app->functions->idn_encode($data['new']['source']) : ''),
  395                     'rcpt' => ($data['new']['type'] === 'recipient' ? $app->functions->idn_encode($data['new']['source']) : ''),
  396                     'ip' => ($data['new']['type'] === 'client' && $this->_is_valid_ip_address($data['new']['source']) ? $data['new']['source'] : ''),
  397                     'hostname' => ($data['new']['type'] === 'client' && !$this->_is_valid_ip_address($data['new']['source']) ? $data['new']['source'] : '')
  398                 );
  399             } else {
  400                 $record_id = intval($data['new']['wblist_id']);
  401                 $wblist_file = $this->users_config_dir.'spamfilter_wblist_'.$record_id.'.conf';
  402                 $tmp = $app->db->queryOneRecord("SELECT email FROM spamfilter_users WHERE id = ?", intval($data['new']['rid']));
  403                 if($tmp && !empty($tmp)) {
  404                     $filter = array(
  405                         'wb' => $data['new']['wb'],
  406                         'from' => $app->functions->idn_encode($data['new']['email']),
  407                         'rcpt' => $app->functions->idn_encode($tmp['email']),
  408                         'ip' => '',
  409                         'hostname' => ''
  410                     );
  411                 }
  412             }
  413 
  414             if($data['new']['active'] == 'y' && is_array($filter) && !empty($filter)){
  415                 if(!is_dir($this->users_config_dir)){
  416                     $app->system->mkdirpath($this->users_config_dir);
  417                 }
  418 
  419                 $app->load('tpl');
  420 
  421                 $filter_from = $filter['from'];
  422                 if($filter_from != '') {
  423                     if(strpos($filter_from, '@') === false) {
  424                         $filter_from = '@' . $filter_from;
  425                     } elseif(substr($filter_from, 0, 2) === '*@') {
  426                         $filter_from = substr($filter_from, 1);
  427                     }
  428                 }
  429                 $filter_rcpt = $filter['rcpt'];
  430                 if($filter_rcpt != '') {
  431                     if(strpos($filter_rcpt, '@') === false) {
  432                         $filter_rcpt = '@' . $filter_rcpt;
  433                     } elseif(substr($filter_rcpt, 0, 2) === '*@') {
  434                         $filter_rcpt = substr($filter_rcpt, 1);
  435                     }
  436                 }
  437 
  438                 if(!$this->isValidEmail($filter_from)) {
  439                     $filter_from = '';
  440                 }
  441                 if(!$this->isValidEmail($filter_rcpt)) {
  442                     $filter_rcpt = '';
  443                 }
  444                 if(($global_filter === true && !$filter_from && !$filter_rcpt) || ($global_filter === false && (!$filter_from || !$filter_rcpt))) {
  445                     if(is_file($wblist_file)) {
  446                         unlink($wblist_file);
  447                     }
  448                 } else {
  449                     $tpl = new tpl();
  450                     if (file_exists($conf['rootpath']."/conf-custom/install/rspamd_wblist.inc.conf.master")) {
  451                                     $tpl->newTemplate($conf['rootpath']."/conf-custom/install/rspamd_wblist.inc.conf.master");
  452                     } else {
  453                         $tpl->newTemplate("rspamd_wblist.inc.conf.master");
  454                     }
  455 
  456                     $tpl->setVar('list_scope', ($global_filter ? 'global' : 'spamfilter'));
  457                     $tpl->setVar('record_id', $record_id);
  458                     // add 30/40 to priority to avoid collisions and prefer white/blacklists above mailbox/domain spamfilter settings
  459                     $tpl->setVar('priority', intval($data['new']['priority']) + ($global_filter ? 30 : 40));
  460                     $tpl->setVar('from', $filter_from);
  461                     $tpl->setVar('recipient', $filter_rcpt);
  462                     $tpl->setVar('hostname', $filter['hostname']);
  463                     $tpl->setVar('ip', $filter['ip']);
  464                     $tpl->setVar('wblist', $filter['wb']);
  465 
  466                     $app->system->file_put_contents($wblist_file, $tpl->grab());
  467                 }
  468             } elseif(is_file($wblist_file)) {
  469                 unlink($wblist_file);
  470             }
  471 
  472             if($mail_config['content_filter'] == 'rspamd') {
  473                 $app->services->restartServiceDelayed('rspamd', 'reload');
  474             }
  475         }
  476     }
  477 
  478     function spamfilter_wblist_delete($event_name, $data) {
  479         global $app, $conf;
  480 
  481         $app->uses('getconf');
  482         $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
  483 
  484         if(is_dir('/etc/rspamd')) {
  485             //* delete the config file
  486             if($event_name === 'mail_access_delete') {
  487                 $wblist_file = $this->users_config_dir.'global_wblist_'.intval($data['old']['access_id']).'.conf';
  488             } else {
  489                 $wblist_file = $this->users_config_dir.'spamfilter_wblist_'.intval($data['old']['wblist_id']).'.conf';
  490             }
  491             if(is_file($wblist_file)) {
  492                 unlink($wblist_file);
  493             }
  494 
  495             if($mail_config['content_filter'] == 'rspamd'){
  496                 $app->services->restartServiceDelayed('rspamd', 'reload');
  497             }
  498         }
  499     }
  500 
  501     function server_update($event_name, $data) {
  502         global $app, $conf;
  503 
  504         if(!is_dir('/etc/rspamd')) {
  505             return;
  506         }
  507 
  508         $app->load('tpl');
  509 
  510         $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
  511 
  512         $local_addrs = array();
  513         $ips = $app->db->queryAllRecords('SELECT `ip_address`, `ip_type` FROM ?? WHERE `server_id` = ?', $conf['mysql']['database'].'.server_ip', $conf['server_id']);
  514         if(is_array($ips) && !empty($ips)){
  515             foreach($ips as $ip){
  516                 $local_addrs[] = array(
  517                     'ip' => $ip['ip_address'],
  518                     'quoted_ip' => "\"".$ip['ip_address']."\",\n",
  519                 );
  520             }
  521         }
  522 
  523         # local.d templates with template tags
  524         # note: ensure these template files are in server/conf/ and symlinked in install/tpl/
  525         $local_d = array(
  526             'dkim_signing.conf',
  527             'options.inc',
  528             'redis.conf',
  529             'classifier-bayes.conf',
  530         );
  531         foreach ($local_d as $f) {
  532             $tpl = new tpl();
  533             if (file_exists($conf['rootpath']."/conf-custom/install/rspamd_${f}.master")) {
  534                 $tpl->newTemplate($conf['rootpath']."/conf-custom/install/rspamd_${f}.master");
  535             } else {
  536                 $tpl->newTemplate("rspamd_${f}.master");
  537             }
  538 
  539             $tpl->setVar('dkim_path', $mail_config['dkim_path']);
  540             $tpl->setVar('rspamd_redis_servers', $mail_config['rspamd_redis_servers']);
  541             $tpl->setVar('rspamd_redis_password', $mail_config['rspamd_redis_password']);
  542             $tpl->setVar('rspamd_redis_bayes_servers', $mail_config['rspamd_redis_bayes_servers']);
  543             $tpl->setVar('rspamd_redis_bayes_password', $mail_config['rspamd_redis_bayes_password']);
  544             if(count($local_addrs) > 0) {
  545                 $tpl->setLoop('local_addrs', $local_addrs);
  546             }
  547 
  548             $app->system->file_put_contents("/etc/rspamd/local.d/${f}", $tpl->grab());
  549 
  550             if($mail_config['content_filter'] == 'rspamd'){
  551                 $app->services->restartServiceDelayed('rspamd', 'reload');
  552             }
  553         }
  554 
  555         # protect passwords in these files
  556         exec('chgrp _rspamd /etc/rspamd/local.d/redis.conf /etc/rspamd/local.d/classifier-bayes.conf /etc/rspamd/local.d/worker-controller.inc');
  557         exec('chmod 640 /etc/rspamd/local.d/redis.conf /etc/rspamd/local.d/classifier-bayes.conf /etc/rspamd/local.d/worker-controller.inc');
  558 
  559     }
  560 
  561     private function _is_valid_ip_address($ip) {
  562         if(function_exists('filter_var')) {
  563             if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
  564                 return false;
  565             } else {
  566                 return true;
  567             }
  568         } else {
  569             return false;
  570         }
  571     }
  572 } // end class