\ No newline at end of file
+
diff --git a/interface/web/mail/templates/spamfilter_policy_list.htm b/interface/web/mail/templates/spamfilter_policy_list.htm
index da1183d75f9af0dcbf526e0ac68cb400c33d6942..84b1a04403cacd0586936c5221057d7be94bfdb5 100644
--- a/interface/web/mail/templates/spamfilter_policy_list.htm
+++ b/interface/web/mail/templates/spamfilter_policy_list.htm
@@ -19,16 +19,20 @@
-
\ No newline at end of file
+
diff --git a/interface/web/mail/templates/spamfilter_taglevel_edit.htm b/interface/web/mail/templates/spamfilter_taglevel_edit.htm
index ba92662ba6f1b96a138dc0afcfc43136eac68cf3..73fd4e6ac42bd2b049427c0f45352edeb90dab8e 100644
--- a/interface/web/mail/templates/spamfilter_taglevel_edit.htm
+++ b/interface/web/mail/templates/spamfilter_taglevel_edit.htm
@@ -4,7 +4,7 @@
-
+
@@ -32,6 +32,33 @@
+
+
+
+
+
+ {tmpl_var name='rspamd_greylisting'}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/conf/apache_apps.vhost.master b/server/conf/apache_apps.vhost.master
index ecd3ff1a0ec076731e0f99dd8fa79dc52beb78c1..d77cde2e4208373d79f5480ef675b8ea63d3cb84 100644
--- a/server/conf/apache_apps.vhost.master
+++ b/server/conf/apache_apps.vhost.master
@@ -52,6 +52,16 @@
+{tmpl_if name="use_rspamd"}
+
+ Order allow,deny
+ Allow from all
+
+ RewriteEngine On
+ RewriteRule ^/rspamd$ /rspamd/ [R,L]
+ RewriteRule ^/rspamd/(.*) http://127.0.0.1:11334/$1 [P]
+{/tmpl_if}
+
diff --git a/server/conf/autoresponder.master b/server/conf/autoresponder.master
index 0126c998d49f8177d28e147c1642a6e9fe4532c4..3e84b802f227d7ec7f765bb86c30c23fb8467ccd 100644
--- a/server/conf/autoresponder.master
+++ b/server/conf/autoresponder.master
@@ -4,7 +4,7 @@ if ($RETURNCODE==1)
{
if (!/^List-Unsubscribe:.*/:h )
{
- if (!/^X-Spam-Flag: YES/:h )
+ if (!/^(X-Spam-Flag: YES|X-Spam: Yes|Subject: \*\*\*\s*SPAM\s*\*\*\*.*)/:h )
{
NOW=time
if ({start_date} lt $NOW && {end_date} gt $NOW)
@@ -20,4 +20,4 @@ if ($RETURNCODE==1)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/server/conf/nginx_apps.vhost.master b/server/conf/nginx_apps.vhost.master
index 75daa4df8f1692f48eacca62c217583473d9cbbf..1c8c4e70aef60e816f22b099aff5989ac4297e92 100644
--- a/server/conf/nginx_apps.vhost.master
+++ b/server/conf/nginx_apps.vhost.master
@@ -199,4 +199,29 @@ server {
alias /var/lib/mailman/archives/public;
autoindex on;
}
+
+ {use_rspamd}location /rspamd/ {
+ {use_rspamd}proxy_pass http://127.0.0.1:11334/;
+ {use_rspamd}rewrite ^//(.*) /$1;
+ {use_rspamd}proxy_set_header X-Forwarded-Proto $scheme;
+ {use_rspamd}proxy_set_header Host $host;
+ {use_rspamd}proxy_set_header X-Real-IP $remote_addr;
+ {use_rspamd}proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ {use_rspamd}proxy_pass_header Authorization;
+ {use_rspamd}client_max_body_size 0;
+ {use_rspamd}client_body_buffer_size 1m;
+ {use_rspamd}proxy_intercept_errors on;
+ {use_rspamd}proxy_buffering on;
+ {use_rspamd}proxy_buffer_size 128k;
+ {use_rspamd}proxy_buffers 256 16k;
+ {use_rspamd}proxy_busy_buffers_size 256k;
+ {use_rspamd}proxy_temp_file_write_size 256k;
+ {use_rspamd}proxy_max_temp_file_size 0;
+ {use_rspamd}proxy_read_timeout 300;
+ {use_rspamd}
+ {use_rspamd}location ~* ^/rspamd/(.+\.(jpg|jpeg|gif|css|png|js|ico|html?|xml|txt))$ {
+ {use_rspamd}alias /usr/share/rspamd/www/$1;
+ {use_rspamd}}
+ {use_rspamd}}
+
}
diff --git a/server/conf/rspamd.local.lua.master b/server/conf/rspamd.local.lua.master
new file mode 100644
index 0000000000000000000000000000000000000000..8ef81da2645f0cc8ff1ea797edc49b198a9e724d
--- /dev/null
+++ b/server/conf/rspamd.local.lua.master
@@ -0,0 +1,3 @@
+rspamd_config.R_DUMMY = function (task)
+ return true
+end
\ No newline at end of file
diff --git a/server/conf/rspamd_antivirus.conf.master b/server/conf/rspamd_antivirus.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..71427d762079bed5517f344ea348d093990f4aa5
--- /dev/null
+++ b/server/conf/rspamd_antivirus.conf.master
@@ -0,0 +1,30 @@
+clamav {
+ # If set force this action if any virus is found (default unset: no action is forced)
+ #action = "reject";
+ # if `true` only messages with non-image attachments will be checked (default true)
+ attachments_only = true;
+ # If `max_size` is set, messages > n bytes in size are not scanned
+ #max_size = 20000000;
+ # symbol to add (add it to metric if you want non-zero weight)
+ symbol = "CLAM_VIRUS";
+ # type of scanner: "clamav", "fprot", "sophos" or "savapi"
+ type = "clamav";
+ # For "savapi" you must also specify the following variable
+ #product_id = 12345;
+ # You can enable logging for clean messages
+ #log_clean = true;
+ # servers to query (if port is unspecified, scanner-specific default is used)
+ # can be specified multiple times to pool servers
+ # can be set to a path to a unix socket
+ # Enable this in local.d/antivirus.conf
+ #servers = "127.0.0.1:3310";
+ servers = "/var/run/clamav/clamd.ctl";
+ # if `patterns` is specified virus name will be matched against provided regexes and the related
+ # symbol will be yielded if a match is found. If no match is found, default symbol is yielded.
+ patterns {
+ # symbol_name = "pattern";
+ JUST_EICAR = "^Eicar-Test-Signature$";
+ }
+ # `whitelist` points to a map of IP addresses. Mail from these addresses is not scanned.
+ whitelist = "/etc/rspamd/antivirus.wl";
+}
\ No newline at end of file
diff --git a/server/conf/rspamd_classifier-bayes.conf.master b/server/conf/rspamd_classifier-bayes.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..1688d57e217673cdfa50ff36c31f4beb782aae70
--- /dev/null
+++ b/server/conf/rspamd_classifier-bayes.conf.master
@@ -0,0 +1,3 @@
+autolearn = [-0.01, 5.00];
+per_user = true;
+per_language = true;
\ No newline at end of file
diff --git a/server/conf/rspamd_dkim_signing.conf.master b/server/conf/rspamd_dkim_signing.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..0e55a7ead24c371004df6bb4bad5c620a0cca295
--- /dev/null
+++ b/server/conf/rspamd_dkim_signing.conf.master
@@ -0,0 +1,2 @@
+path = "/$domain.private";
+selector = "default";
\ No newline at end of file
diff --git a/server/conf/rspamd_greylist.conf.master b/server/conf/rspamd_greylist.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..74ea715a22cc6fa76671fd47a3f1bf89cfe92d49
--- /dev/null
+++ b/server/conf/rspamd_greylist.conf.master
@@ -0,0 +1 @@
+servers = "127.0.0.1:6379";
\ No newline at end of file
diff --git a/server/conf/rspamd_metrics.conf.master b/server/conf/rspamd_metrics.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..f59eff0f0171e06e4d701ba53b9ce221164a6b4b
--- /dev/null
+++ b/server/conf/rspamd_metrics.conf.master
@@ -0,0 +1,17 @@
+subject = "***SPAM*** %s";
+
+symbol {
+ weight = 50;
+ name = "CLAM_VIRUS";
+ description = "Clamav has found a virus.";
+}
+symbol {
+ weight = 50;
+ name = "JUST_EICAR";
+ description = "Clamav has found a virus.";
+}
+symbol {
+ weight = 0.0;
+ name = "R_DUMMY";
+ description = "Dummy symbol";
+}
\ No newline at end of file
diff --git a/server/conf/rspamd_metrics_override.conf.master b/server/conf/rspamd_metrics_override.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..8e3df15eddaf429312b6e313f52b649ac4703260
--- /dev/null
+++ b/server/conf/rspamd_metrics_override.conf.master
@@ -0,0 +1,159 @@
+# RBL
+symbol "RBL_SENDERSCORE" {
+ weight = 4.0;
+ description = "From address is listed in senderscore.com BL";
+}
+symbol "RBL_SPAMHAUS_SBL" {
+ weight = 2.0;
+ description = "From address is listed in zen sbl";
+}
+symbol "RBL_SPAMHAUS_CSS" {
+ weight = 2.0;
+ description = "From address is listed in zen css";
+}
+symbol "RBL_SPAMHAUS_XBL" {
+ weight = 4.0;
+ description = "From address is listed in zen xbl";
+}
+symbol "RBL_SPAMHAUS_XBL_ANY" {
+ weight = 4.0;
+ description = "From or receive address is listed in zen xbl (any list)";
+}
+symbol "RBL_SPAMHAUS_PBL" {
+ weight = 2.0;
+ description = "From address is listed in zen pbl (ISP list)";
+}
+symbol "RBL_SPAMHAUS_DROP" {
+ weight = 7.0;
+ description = "From address is listed in zen drop bl";
+}
+symbol "RECEIVED_SPAMHAUS_XBL" {
+ weight = 3.0;
+ description = "Received address is listed in zen xbl";
+ one_shot = true;
+}
+symbol "RBL_MAILSPIKE_WORST" {
+ weight = 2.0;
+ description = "From address is listed in RBL - worst possible reputation";
+}
+symbol "RBL_MAILSPIKE_VERYBAD" {
+ weight = 1.5;
+ description = "From address is listed in RBL - very bad reputation";
+}
+symbol "RBL_MAILSPIKE_BAD" {
+ weight = 1.0;
+ description = "From address is listed in RBL - bad reputation";
+}
+symbol "RBL_SEM" {
+ weight = 1.0;
+ description = "Address is listed in Spameatingmonkey RBL";
+}
+# /RBL
+# SURBL
+symbol "PH_SURBL_MULTI" {
+ weight = 5.5;
+ description = "SURBL: Phishing sites";
+}
+symbol "MW_SURBL_MULTI" {
+ weight = 5.5;
+ description = "SURBL: Malware sites";
+}
+symbol "ABUSE_SURBL" {
+ weight = 5.5;
+ description = "SURBL: ABUSE";
+}
+symbol "CRACKED_SURBL" {
+ weight = 4.0;
+ description = "SURBL: cracked site";
+}
+symbol "RAMBLER_URIBL" {
+ weight = 4.5;
+ description = "Rambler uribl";
+ one_shot = true;
+}
+symbol "RAMBLER_EMAILBL" {
+ weight = 9.5;
+ description = "Rambler emailbl";
+ one_shot = true;
+}
+symbol "MSBL_EBL" {
+ weight = 7.5;
+ description = "MSBL emailbl";
+ one_shot = true;
+}
+symbol "SEM_URIBL" {
+ weight = 3.5;
+ description = "Spameatingmonkey uribl";
+}
+symbol "SEM_URIBL_FRESH15" {
+ weight = 3.0;
+ description = "Spameatingmonkey uribl. Domains registered in the last 15 days (.AERO,.BIZ,.COM,.INFO,.NAME,.NET,.PRO,.SK,.TEL,.US)";
+}
+symbol "DBL" {
+ weight = 0.0;
+ description = "DBL unknown result";
+}
+symbol "DBL_SPAM" {
+ weight = 6.5;
+ description = "DBL uribl spam";
+}
+symbol "DBL_PHISH" {
+ weight = 6.5;
+ description = "DBL uribl phishing";
+}
+symbol "DBL_MALWARE" {
+ weight = 6.5;
+ description = "DBL uribl malware";
+}
+symbol "DBL_BOTNET" {
+ weight = 5.5;
+ description = "DBL uribl botnet C&C domain";
+}
+symbol "DBL_ABUSE" {
+ weight = 6.5;
+ description = "DBL uribl abused legit spam";
+}
+symbol "DBL_ABUSE_REDIR" {
+ weight = 1.5;
+ description = "DBL uribl abused spammed redirector domain";
+}
+symbol "DBL_ABUSE_PHISH" {
+ weight = 7.5;
+ description = "DBL uribl abused legit phish";
+}
+symbol "DBL_ABUSE_MALWARE" {
+ weight = 7.5;
+ description = "DBL uribl abused legit malware";
+}
+symbol "DBL_ABUSE_BOTNET" {
+ weight = 5.5;
+ description = "DBL uribl abused legit botnet C&C";
+}
+symbol "URIBL_BLACK" {
+ weight = 7.5;
+ description = "uribl.com black url";
+}
+symbol "URIBL_RED" {
+ weight = 3.5;
+ description = "uribl.com red url";
+}
+symbol "URIBL_GREY" {
+ weight = 1.5;
+ description = "uribl.com grey url";
+ one_shot = true;
+}
+symbol "URIBL_SBL" {
+ weight = 6.5;
+ description = "Spamhaus SBL URIBL";
+}
+symbol "URIBL_SBL_CSS" {
+ weight = 6.5;
+ description = "Spamhaus SBL CSS URIBL";
+}
+symbol "RBL_SARBL_BAD" {
+ weight = 2.5;
+ description = "A domain listed in the mail is blacklisted in SARBL";
+}
+# /SURBL
+actions {
+}
\ No newline at end of file
diff --git a/server/conf/rspamd_mx_check.conf.master b/server/conf/rspamd_mx_check.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..0a628f9c8382ee1f0def03883c91b91d7701e625
--- /dev/null
+++ b/server/conf/rspamd_mx_check.conf.master
@@ -0,0 +1,9 @@
+enabled = true;
+servers = "localhost";
+key_prefix = "rmx";
+symbol_bad_mx = "MX_INVALID";
+symbol_no_mx = "MX_MISSING";
+symbol_good_mx = "MX_GOOD";
+expire = 86400;
+expire_novalid = 7200;
+greylist_invalid = false;
\ No newline at end of file
diff --git a/server/conf/rspamd_users.conf.master b/server/conf/rspamd_users.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..975300bf9b650a97cc6e350e6acfa8519e8958a4
--- /dev/null
+++ b/server/conf/rspamd_users.conf.master
@@ -0,0 +1,43 @@
+settings {
+ authenticated {
+ priority = 10;
+ authenticated = yes;
+ #apply "default" { groups_disabled = ["rbl", "spf"]; }
+ apply "default" {
+ symbols_enabled = [];
+ symbols_disabled = [];
+ groups_enabled = [];
+ groups_disabled = [];
+ }
+ }
+ whitelist {
+ priority = 10;
+ rcpt = "postmaster";
+ rcpt = "hostmaster";
+ rcpt = "abuse";
+ want_spam = yes;
+ }
+ whitelist-ip {
+ priority = 10;
+
+ ip = "";
+
+
+ want_spam = yes;
+ }
+ whitelist-timmehosting {
+ priority = 20;
+ from = "@timmehosting.de";
+ from = "@timmehosting.com";
+ want_spam = yes;
+ }
+ whitelist-ca {
+ priority = 20;
+ from = "@comodo.com";
+ from = "@geotrust.com";
+ from = "@geotrusteurope.com";
+ want_spam = yes;
+ }
+ .include(try=true; glob=true) "$LOCAL_CONFDIR/local.d/users/*.conf"
+ .include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/users.local.conf"
+}
diff --git a/server/conf/rspamd_users.inc.conf.master b/server/conf/rspamd_users.inc.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..1fe08439a7db24e6403302123d1a7d63b5592689
--- /dev/null
+++ b/server/conf/rspamd_users.inc.conf.master
@@ -0,0 +1,41 @@
+spamfilter_users- {
+ priority = ;
+ rcpt = "";
+
+ want_spam = yes;
+
+
+ apply "default" {
+ CLAM_VIRUS = 1999.0;
+ JUST_EICAR = 1999.0;
+ actions {
+ reject = 999.0;
+ }
+ }
+
+
+ apply "default" {
+ CLAM_VIRUS = -999.0;
+ JUST_EICAR = -999.0;
+ actions {
+ greylist = ;
+
+ = ;
+ reject = ;
+ }
+ }
+
+
+ apply "default" {
+ CLAM_VIRUS = ;
+ JUST_EICAR = ;
+ actions {
+ greylist = ;
+
+ = ;
+ reject = ;
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/server/conf/rspamd_wblist.inc.conf.master b/server/conf/rspamd_wblist.inc.conf.master
new file mode 100644
index 0000000000000000000000000000000000000000..fc06127eae69ed43309f050983c90a5c12bdc9f0
--- /dev/null
+++ b/server/conf/rspamd_wblist.inc.conf.master
@@ -0,0 +1,18 @@
+spamfilter_wblist- {
+ priority = ;
+ from = "";
+ rcpt = "";
+
+ want_spam = yes;
+
+ apply "default" {
+ R_DUMMY = 999.0;
+ actions {
+ reject = 0.2;
+ add_header = 0.1;
+ greylist = 0.1;
+ rewrite_subject = 0.1;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/server/conf/rspamd_worker-controller.inc.master b/server/conf/rspamd_worker-controller.inc.master
new file mode 100644
index 0000000000000000000000000000000000000000..75b744c88380c3ce63394caaadf79653e0fa8815
--- /dev/null
+++ b/server/conf/rspamd_worker-controller.inc.master
@@ -0,0 +1,8 @@
+# Included from top-level .conf file
+
+type = "controller";
+count = 1;
+password = "";
+secure_ip = "127.0.0.1";
+secure_ip = "::1";
+static_dir = "${WWWDIR}";
\ No newline at end of file
diff --git a/server/conf/sieve_filter.master b/server/conf/sieve_filter.master
index bfd75c4d43e6279ecba65701c7151ccade11fa79..13c08dd56b18987573c18fd1fe1aee432db17e44 100644
--- a/server/conf/sieve_filter.master
+++ b/server/conf/sieve_filter.master
@@ -1,4 +1,4 @@
-require ["fileinto", "regex", "vacation", "imap4flags", "envelope", "subaddress"];
+require ["fileinto", "regex", "date", "relational", "vacation", "imap4flags", "envelope", "subaddress", "copy", "reject"];
# Send a copy of email to
@@ -9,7 +9,7 @@ redirect "";
# Move spam to spam folder
-if header :contains "X-Spam-Flag" "YES" {
+if anyof (header :contains "X-Spam-Flag" "YES", header :contains "X-Spam" "Yes", header :contains "subject" "*** SPAM ***", header :contains "subject" "***SPAM***") {
fileinto "Junk";
# Stop here so that we do not reply on spams
stop;
@@ -26,7 +26,7 @@ keep;
#################################################################
# Move spam to spam folder
-if header :contains "X-Spam-Flag" "YES" {
+if anyof (header :contains "X-Spam-Flag" "YES", header :contains "X-Spam" "Yes", header :contains "subject" "*** SPAM ***", header :contains "subject" "***SPAM***") {
fileinto "Junk";
# Stop here so that we do not reply on spams
stop;
diff --git a/server/conf/sieve_filter_1.2.master b/server/conf/sieve_filter_1.2.master
index 8a1c80713fb7fafda8fbed675e2a7f1183aaff23..5244693102ce0778964ce2e25b61c377b1b2bf8a 100644
--- a/server/conf/sieve_filter_1.2.master
+++ b/server/conf/sieve_filter_1.2.master
@@ -1,8 +1,8 @@
-require ["fileinto", "regex", "date", "relational", "vacation", "imap4flags", "envelope", "subaddress"];
+require ["fileinto", "regex", "date", "relational", "vacation", "imap4flags", "envelope", "subaddress", "copy", "reject"];
# Move spam to spam folder
-if header :contains "X-Spam-Flag" "YES" {
+if anyof (header :contains "X-Spam-Flag" "YES", header :contains "X-Spam" "Yes", header :contains "subject" "*** SPAM ***", header :contains "subject" "***SPAM***") {
fileinto "Junk";
# Stop here so that we do not reply on spams
stop;
@@ -26,7 +26,7 @@ keep;
#################################################################
# Move spam to spam folder
-if header :contains "X-Spam-Flag" "YES" {
+if anyof (header :contains "X-Spam-Flag" "YES", header :contains "X-Spam" "Yes", header :contains "subject" "*** SPAM ***", header :contains "subject" "***SPAM***") {
# Stop here so that we do not reply on spams
stop;
}
diff --git a/server/mods-available/mail_module.inc.php b/server/mods-available/mail_module.inc.php
index 8460d5d96a6f1a7b58cdee2837840f72378e5038..ffb72d68f428c4b934e85678ba8acda3d0c95d85 100644
--- a/server/mods-available/mail_module.inc.php
+++ b/server/mods-available/mail_module.inc.php
@@ -56,6 +56,12 @@ class mail_module {
'mail_mailinglist_insert',
'mail_mailinglist_update',
'mail_mailinglist_delete',
+ 'spamfilter_users_insert',
+ 'spamfilter_users_update',
+ 'spamfilter_users_delete',
+ 'spamfilter_wblist_insert',
+ 'spamfilter_wblist_update',
+ 'spamfilter_wblist_delete',
'mail_ml_member_insert',
'mail_ml_member_update',
'mail_ml_member_delete');
@@ -107,6 +113,10 @@ class mail_module {
$app->modules->registerTableHook('mail_mailinglist', 'mail_module', 'process');
$app->modules->registerTableHook('mail_ml_membership', 'mail_module', 'process');
+ $app->modules->registerTableHook('spamfilter_users', 'mail_module', 'process');
+ $app->modules->registerTableHook('spamfilter_wblist', 'mail_module', 'process');
+
+ $app->services->registerService('rspamd', 'mail_module', 'restartRspamd');
}
/*
@@ -163,9 +173,36 @@ class mail_module {
if($action == 'u') $app->plugins->raiseEvent('mail_ml_member_update', $data);
if($action == 'd') $app->plugins->raiseEvent('mail_ml_member_delete', $data);
break;
+ case 'spamfilter_users':
+ if($action == 'i') $app->plugins->raiseEvent('spamfilter_users_insert', $data);
+ if($action == 'u') $app->plugins->raiseEvent('spamfilter_users_update', $data);
+ if($action == 'd') $app->plugins->raiseEvent('spamfilter_users_delete', $data);
+ break;
+ case 'spamfilter_wblist':
+ if($action == 'i') $app->plugins->raiseEvent('spamfilter_wblist_insert', $data);
+ if($action == 'u') $app->plugins->raiseEvent('spamfilter_wblist_update', $data);
+ if($action == 'd') $app->plugins->raiseEvent('spamfilter_wblist_delete', $data);
+ break;
} // end switch
} // end function
+ function restartRspamd($action = 'reload') {
+ global $app;
+
+ $app->uses('system');
+
+ $daemon = 'rspamd';
+
+ $retval = array('output' => '', 'retval' => 0);
+ if($action == 'restart') {
+ exec($app->system->getinitcommand($daemon, 'restart').' 2>&1', $retval['output'], $retval['retval']);
+ } else {
+ exec($app->system->getinitcommand($daemon, 'reload').' 2>&1', $retval['output'], $retval['retval']);
+ }
+ return $retval;
+ }
+
+
} // end class
?>
diff --git a/server/plugins-available/apps_vhost_plugin.inc.php b/server/plugins-available/apps_vhost_plugin.inc.php
index b843e3c8a4e45f86adedf8106207d79e1c4b586f..32a62174ffc15681633fcb9c39f30f1639f06d01 100644
--- a/server/plugins-available/apps_vhost_plugin.inc.php
+++ b/server/plugins-available/apps_vhost_plugin.inc.php
@@ -106,6 +106,16 @@ class apps_vhost_plugin {
$vhost_port_listen = '#';
}
$tpl->setVar('vhost_port_listen', $vhost_port_listen);
+
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+ if($mail_config['content_filter'] == 'rspamd'){
+ $use_rspamd = true;
+ exec('/usr/sbin/a2enmod proxy');
+ exec('/usr/sbin/a2enmod proxy_http');
+ } else {
+ $use_rspamd = false;
+ }
+ $tpl->setVar('use_rspamd', $use_rspamd);
$content = $tpl->grab();
@@ -184,6 +194,14 @@ class apps_vhost_plugin {
$content = str_replace('{use_tcp}', $use_tcp, $content);
$content = str_replace('{use_socket}', $use_socket, $content);
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+ if($mail_config['content_filter'] == 'rspamd'){
+ $use_rspamd = '';
+ } else {
+ $use_rspamd = '#';
+ }
+ $content = str_replace('{use_rspamd}', $use_rspamd, $content);
+
// Fix socket path on PHP 7 systems
if(file_exists('/var/run/php/php7.0-fpm.sock')) $content = str_replace('/var/run/php5-fpm.sock', '/var/run/php/php7.0-fpm.sock', $content);
if(file_exists('/var/run/php/php7.1-fpm.sock')) $content = str_replace('/var/run/php5-fpm.sock', '/var/run/php/php7.1-fpm.sock', $content);
@@ -221,7 +239,3 @@ class apps_vhost_plugin {
} // end class
-
-
-
-?>
diff --git a/server/plugins-available/postfix_server_plugin.inc.php b/server/plugins-available/postfix_server_plugin.inc.php
index 64c557139088088f21dd35c547a9462361c6162a..ea0c951dcf2d94a161d4b49ed12966f293805e32 100644
--- a/server/plugins-available/postfix_server_plugin.inc.php
+++ b/server/plugins-available/postfix_server_plugin.inc.php
@@ -60,15 +60,15 @@ class postfix_server_plugin {
Register for the events
*/
- $app->plugins->registerEvent('server_insert', 'postfix_server_plugin', 'insert');
- $app->plugins->registerEvent('server_update', 'postfix_server_plugin', 'update');
-
-
+ $app->plugins->registerEvent('server_insert', $this->plugin_name, 'insert');
+ $app->plugins->registerEvent('server_update', $this->plugin_name, 'update');
+ $app->plugins->registerEvent('server_ip_insert', $this->plugin_name, 'server_ip');
+ $app->plugins->registerEvent('server_ip_update', $this->plugin_name, 'server_ip');
+ $app->plugins->registerEvent('server_ip_delete', $this->plugin_name, 'server_ip');
}
function insert($event_name, $data) {
- global $app, $conf;
$this->update($event_name, $data);
@@ -116,7 +116,7 @@ class postfix_server_plugin {
if($rbl_hosts != ''){
$rbl_hosts = explode(",", $rbl_hosts);
}
- $options = explode(", ", exec("postconf -h smtpd_recipient_restrictions"));
+ $options = preg_split("/,\s*/", exec("postconf -h smtpd_recipient_restrictions"));
$new_options = array();
foreach ($options as $key => $value) {
if (!preg_match('/reject_rbl_client/', $value)) {
@@ -162,7 +162,8 @@ class postfix_server_plugin {
}
if($app->system->is_installed('dovecot')) {
- $temp = exec("postconf -n virtual_transport", $out);
+ $out = null;
+ exec("postconf -n virtual_transport", $out);
if ($mail_config["mailbox_virtual_uidgid_maps"] == 'y') {
// If dovecot switch to lmtp
if($out[0] != "virtual_transport = lmtp:unix:private/dovecot-lmtp") {
@@ -182,12 +183,139 @@ class postfix_server_plugin {
}
}
- exec("postconf -e 'mailbox_size_limit = ".intval($mail_config['mailbox_size_limit']*1024*1024)."'"); //TODO : no reload?
- exec("postconf -e 'message_size_limit = ".intval($mail_config['message_size_limit']*1024*1024)."'"); //TODO : no reload?
+ if($mail_config['content_filter'] != $old_ini_data['mail']['content_filter']) {
+ if($mail_config['content_filter'] == 'rspamd'){
+ exec("postconf -X 'receive_override_options'");
+ exec("postconf -X 'content_filter'");
+
+ exec("postconf -e 'smtpd_milters = inet:localhost:11332'");
+ exec("postconf -e 'milter_protocol = 6'");
+ exec("postconf -e 'milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}'");
+ exec("postconf -e 'milter_default_action = accept'");
+
+ exec("postconf -e 'smtpd_sender_restrictions = check_sender_access mysql:/etc/postfix/mysql-virtual_sender.cf, permit_mynetworks, permit_sasl_authenticated'");
+
+ $new_options = array();
+ $options = preg_split("/,\s*/", exec("postconf -h smtpd_recipient_restrictions"));
+ foreach ($options as $key => $value) {
+ if (!preg_match('/check_policy_service\s+inet:127.0.0.1:10023/', $value)) {
+ $new_options[] = $value;
+ }
+ }
+ exec("postconf -e 'smtpd_recipient_restrictions = ".implode(", ", $new_options)."'");
+
+ if(!is_dir('/etc/rspamd/local.d/')){
+ $app->system->mkdirpath('/etc/rspamd/local.d/');
+ }
+
+ $this->server_ip($event_name, $data);
+
+ if(file_exists($conf['rootpath'].'/conf-custom/rspamd_antivirus.conf.master')) {
+ exec('cp '.$conf['rootpath'].'/conf-custom/rspamd_antivirus.conf.master /etc/rspamd/local.d/antivirus.conf');
+ } else {
+ exec('cp '.$conf['rootpath'].'/conf/rspamd_antivirus.conf.master /etc/rspamd/local.d/antivirus.conf');
+ }
+
+ if(file_exists($conf['rootpath'].'/conf-custom/rspamd_classifier-bayes.conf.master')) {
+ exec('cp '.$conf['rootpath'].'/conf-custom/rspamd_classifier-bayes.conf.master /etc/rspamd/local.d/classifier-bayes.conf');
+ } else {
+ exec('cp '.$conf['rootpath'].'/conf/rspamd_classifier-bayes.conf.master /etc/rspamd/local.d/classifier-bayes.conf');
+ }
+
+ if(file_exists($conf['rootpath'].'/conf-custom/rspamd_greylist.conf.master')) {
+ exec('cp '.$conf['rootpath'].'/conf-custom/rspamd_greylist.conf.master /etc/rspamd/local.d/greylist.conf');
+ } else {
+ exec('cp '.$conf['rootpath'].'/conf/rspamd_greylist.conf.master /etc/rspamd/local.d/greylist.conf');
+ }
+
+ if(file_exists($conf['rootpath'].'/conf-custom/rspamd_metrics.conf.master')) {
+ exec('cp '.$conf['rootpath'].'/conf-custom/rspamd_metrics.conf.master /etc/rspamd/local.d/metrics.conf');
+ } else {
+ exec('cp '.$conf['rootpath'].'/conf/rspamd_metrics.conf.master /etc/rspamd/local.d/metrics.conf');
+ }
+
+ if(file_exists($conf['rootpath'].'/conf-custom/rspamd_metrics_override.conf.master')) {
+ exec('cp '.$conf['rootpath'].'/conf-custom/rspamd_metrics_override.conf.master /etc/rspamd/override.d/metrics.conf');
+ } else {
+ exec('cp '.$conf['rootpath'].'/conf/rspamd_metrics_override.conf.master /etc/rspamd/override.d/metrics.conf');
+ }
+
+ if(file_exists($conf['rootpath'].'/conf-custom/rspamd_mx_check.conf.master')) {
+ exec('cp '.$conf['rootpath'].'/conf-custom/rspamd_mx_check.conf.master /etc/rspamd/local.d/mx_check.conf');
+ } else {
+ exec('cp '.$conf['rootpath'].'/conf/rspamd_mx_check.conf.master /etc/rspamd/local.d/mx_check.conf');
+ }
+
+ if(file_exists($conf['rootpath'].'/conf-custom/rspamd.local.lua.master')) {
+ exec('cp '.$conf['rootpath'].'/conf-custom/rspamd.local.lua.master /etc/rspamd/rspamd.local.lua');
+ } else {
+ exec('cp '.$conf['rootpath'].'/conf/rspamd.local.lua.master /etc/rspamd/rspamd.local.lua');
+ }
+
+ $tpl = new tpl();
+ $tpl->newTemplate('rspamd_dkim_signing.conf.master');
+ $tpl->setVar('dkim_path', $mail_config['dkim_path']);
+ $app->system->file_put_contents('/etc/rspamd/local.d/dkim_signing.conf', $tpl->grab());
+
+ $app->system->add_user_to_group('amavis', '_rspamd');
+
+ if(strpos($app->system->file_get_contents('/etc/rspamd/rspamd.conf'), '.include "$LOCAL_CONFDIR/local.d/users.conf"') === false){
+ $app->uses('file');
+ $app->file->af('/etc/rspamd/rspamd.conf', '.include "$LOCAL_CONFDIR/local.d/users.conf"');
+ }
+
+ if(is_file('/etc/init.d/rspamd')) $app->services->restartServiceDelayed('rspamd', 'reload');
+ }
+ if($mail_config['content_filter'] == 'amavisd'){
+ exec("postconf -X 'smtpd_milters'");
+ exec("postconf -X 'milter_protocol'");
+ exec("postconf -X 'milter_mail_macros'");
+ exec("postconf -X 'milter_default_action'");
+
+ exec("postconf -e 'receive_override_options = no_address_mappings'");
+ exec("postconf -e 'content_filter = amavis:[127.0.0.1]:10024'");
+
+ exec("postconf -e 'smtpd_sender_restrictions = check_sender_access mysql:/etc/postfix/mysql-virtual_sender.cf regexp:/etc/postfix/tag_as_originating.re, permit_mynetworks, permit_sasl_authenticated, check_sender_access regexp:/etc/postfix/tag_as_foreign.re'");
+ }
+ }
+ if($mail_config['content_filter'] == 'rspamd' && ($mail_config['rspamd_password'] != $old_ini_data['mail']['rspamd_password'] || $mail_config['content_filter'] != $old_ini_data['mail']['content_filter'])) {
+ $tpl = new tpl();
+ $tpl->newTemplate('rspamd_worker-controller.inc.master');
+ $tpl->setVar('rspamd_password', $mail_config['rspamd_password']);
+ $app->system->file_put_contents('/etc/rspamd/local.d/worker-controller.inc', $tpl->grab());
+ if(is_file('/etc/init.d/rspamd')) $app->services->restartServiceDelayed('rspamd', 'reload');
+ }
+ exec("postconf -e 'mailbox_size_limit = ".intval($mail_config['mailbox_size_limit']*1024*1024)."'"); //TODO : no reload?
+ exec("postconf -e 'message_size_limit = ".intval($mail_config['message_size_limit']*1024*1024)."'"); //TODO : no reload?
+
}
-} // end class
+ function server_ip($event_name, $data) {
+ global $app, $conf;
+
+ // get the config
+ $app->uses("getconf,system");
+ $app->load('tpl');
-?>
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+
+ if($mail_config['content_filter'] == 'rspamd'){
+ $tpl = new tpl();
+ $tpl->newTemplate('rspamd_users.conf.master');
+
+ $whitelist_ips = array();
+ $ips = $app->db->queryAllRecords("SELECT * FROM server_ip WHERE server_id = ?", $conf['server_id']);
+ if(is_array($ips) && !empty($ips)){
+ foreach($ips as $ip){
+ $whitelist_ips[] = array('ip' => $ip['ip_address']);
+ }
+ }
+ $tpl->setLoop('whitelist_ips', $whitelist_ips);
+ $app->system->file_put_contents('/etc/rspamd/local.d/users.conf', $tpl->grab());
+
+ if(is_file('/etc/init.d/rspamd')) $app->services->restartServiceDelayed('rspamd', 'reload');
+ }
+ }
+} // end class
diff --git a/server/plugins-available/rspamd_plugin.inc.php b/server/plugins-available/rspamd_plugin.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..e3fb16b800fc292949f9f899b5999462ea94288e
--- /dev/null
+++ b/server/plugins-available/rspamd_plugin.inc.php
@@ -0,0 +1,210 @@
+plugins->registerEvent('spamfilter_users_insert', $this->plugin_name, 'spamfilter_users_insert');
+ $app->plugins->registerEvent('spamfilter_users_update', $this->plugin_name, 'spamfilter_users_update');
+ $app->plugins->registerEvent('spamfilter_users_delete', $this->plugin_name, 'spamfilter_users_delete');
+
+ //* spamfilter_wblist
+ $app->plugins->registerEvent('spamfilter_wblist_insert', $this->plugin_name, 'spamfilter_wblist_insert');
+ $app->plugins->registerEvent('spamfilter_wblist_update', $this->plugin_name, 'spamfilter_wblist_update');
+ $app->plugins->registerEvent('spamfilter_wblist_delete', $this->plugin_name, 'spamfilter_wblist_delete');
+ }
+
+ function spamfilter_users_insert($event_name, $data) {
+ global $app, $conf;
+
+ $this->action = 'insert';
+ // just run the spamfilter_users_update function
+ $this->spamfilter_users_update($event_name, $data);
+ }
+
+ function spamfilter_users_update($event_name, $data) {
+ global $app, $conf;
+
+ // get the config
+ $app->uses('getconf,system,functions');
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+
+ if($mail_config['content_filter'] == 'rspamd'){
+ $policy = $app->db->queryOneRecord("SELECT * FROM spamfilter_policy WHERE id = ?", intval($data['new']['policy_id']));
+
+ //* Create the config file
+ $user_file = $this->users_config_dir.'spamfilter_user_'.intval($data['new']['id']).'.conf';
+
+ if($data['new']['local'] == 'Y' && is_array($policy) && !empty($policy)){
+ if(!is_dir($this->users_config_dir)){
+ $app->system->mkdirpath($this->users_config_dir);
+ }
+
+ $app->load('tpl');
+
+ $tpl = new tpl();
+ $tpl->newTemplate('rspamd_users.inc.conf.master');
+ $tpl->setVar('record_id', intval($data['new']['id']));
+ $tpl->setVar('priority', intval($data['new']['priority']));
+ $tpl->setVar('recipient', $app->functions->idn_encode($data['new']['email']));
+
+ $tpl->setVar('rspamd_greylisting', $policy['rspamd_greylisting']);
+ $tpl->setVar('rspamd_spam_greylisting_level', floatval($policy['rspamd_spam_greylisting_level']));
+
+ $tpl->setVar('rspamd_spam_tag_level', floatval($policy['rspamd_spam_tag_level']));
+ $tpl->setVar('rspamd_spam_tag_method', $policy['rspamd_spam_tag_method']);
+
+ $tpl->setVar('rspamd_spam_kill_level', floatval($policy['rspamd_spam_kill_level']));
+ $tpl->setVar('rspamd_virus_kill_level', floatval($policy['rspamd_spam_kill_level']) + 1000);
+
+ $spam_lover_virus_lover = '';
+ if($policy['spam_lover'] == 'Y' && $policy['virus_lover'] == 'Y') $spam_lover_virus_lover = 'spam_lover_AND_virus_lover';
+ if($policy['spam_lover'] == 'Y' && $policy['virus_lover'] != 'Y') $spam_lover_virus_lover = 'spam_lover_AND_NOTvirus_lover';
+ if($policy['spam_lover'] != 'Y' && $policy['virus_lover'] == 'Y') $spam_lover_virus_lover = 'NOTspam_lover_AND_virus_lover';
+ if($policy['spam_lover'] != 'Y' && $policy['virus_lover'] != 'Y') $spam_lover_virus_lover = 'NOTspam_lover_AND_NOTvirus_lover';
+
+ $tpl->setVar('spam_lover_virus_lover', $spam_lover_virus_lover);
+
+ //$groups_disabled = array();
+ //if($policy['virus_lover'] == 'Y') $groups_disabled[] = '';
+
+ $app->system->file_put_contents($user_file, $tpl->grab());
+ } else {
+ if(is_file($user_file)) unlink($user_file);
+ }
+ //if(is_file('/etc/init.d/rspamd')) exec('/etc/init.d/rspamd reload &> /dev/null');
+ if(is_file('/etc/init.d/rspamd')) $app->services->restartServiceDelayed('rspamd', 'reload');
+ }
+ }
+
+ function spamfilter_users_delete($event_name, $data) {
+ global $app, $conf;
+
+ // get the config
+ $app->uses('getconf');
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+
+ if($mail_config['content_filter'] == 'rspamd'){
+ //* delete the config file
+ $user_file = $this->users_config_dir.'spamfilter_user_'.intval($data['old']['id']).'.conf';
+ if(is_file($user_file)) unlink($user_file);
+ //if(is_file('/etc/init.d/rspamd')) exec('/etc/init.d/rspamd reload &> /dev/null');
+ if(is_file('/etc/init.d/rspamd')) $app->services->restartServiceDelayed('rspamd', 'reload');
+ }
+ }
+
+ function spamfilter_wblist_insert($event_name, $data) {
+ global $app, $conf;
+
+ $this->action = 'insert';
+ // just run the spamfilter_wblist_update function
+ $this->spamfilter_wblist_update($event_name, $data);
+ }
+
+ function spamfilter_wblist_update($event_name, $data) {
+ global $app, $conf;
+
+ $app->uses('getconf,system,functions');
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+
+ if($mail_config['content_filter'] == 'rspamd'){
+ $recipient = $app->db->queryOneRecord("SELECT email FROM spamfilter_users WHERE id = ?", intval($data['new']['rid']));
+ //* Create the config file
+ $wblist_file = $this->users_config_dir.'spamfilter_wblist_'.intval($data['new']['wblist_id']).'.conf';
+
+ if($data['new']['active'] == 'y' && is_array($recipient) && !empty($recipient)){
+ if(!is_dir($this->users_config_dir)){
+ $app->system->mkdirpath($this->users_config_dir);
+ }
+
+ $app->load('tpl');
+
+ $tpl = new tpl();
+ $tpl->newTemplate('rspamd_wblist.inc.conf.master');
+ $tpl->setVar('record_id', intval($data['new']['wblist_id']));
+ $tpl->setVar('priority', intval($data['new']['priority']));
+ $tpl->setVar('from', $app->functions->idn_encode($data['new']['email']));
+ $tpl->setVar('recipient', $app->functions->idn_encode($recipient['email']));
+ //$tpl->setVar('action', ($data['new']['wb'] == 'W'? 'want_spam = yes;' : 'action = "reject";'));
+ $tpl->setVar('wblist', $data['new']['wb']);
+
+ $app->system->file_put_contents($wblist_file, $tpl->grab());
+ } else {
+ if(is_file($wblist_file)) unlink($wblist_file);
+ }
+ //if(is_file('/etc/init.d/rspamd')) exec('/etc/init.d/rspamd reload &> /dev/null');
+ if(is_file('/etc/init.d/rspamd')) $app->services->restartServiceDelayed('rspamd', 'reload');
+ }
+ }
+
+ function spamfilter_wblist_delete($event_name, $data) {
+ global $app, $conf;
+
+ $app->uses('getconf');
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+
+ if($mail_config['content_filter'] == 'rspamd'){
+ //* delete the config file
+ $wblist_file = $this->users_config_dir.'spamfilter_wblist_'.intval($data['old']['wblist_id']).'.conf';
+ if(is_file($wblist_file)) unlink($wblist_file);
+ //if(is_file('/etc/init.d/rspamd')) exec('/etc/init.d/rspamd reload &> /dev/null');
+ if(is_file('/etc/init.d/rspamd')) $app->services->restartServiceDelayed('rspamd', 'reload');
+ }
+ }
+
+} // end class
+?>
\ No newline at end of file