settings.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <?php
  2. /*
  3. The match section performs AND operation on different matches: for example, if you have from and rcpt in the same rule,
  4. then the rule matches only when from AND rcpt match. For similar matches, the OR rule applies: if you have multiple rcpt matches,
  5. then any of these will trigger the rule. If a rule is triggered then no more rules are matched.
  6. */
  7. function parse_email($email) {
  8. if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
  9. $a = strrpos($email, '@');
  10. return array('local' => substr($email, 0, $a), 'domain' => substr($email, $a));
  11. }
  12. header('Content-Type: text/plain');
  13. require_once "vars.inc.php";
  14. ini_set('error_reporting', 0);
  15. $dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
  16. $opt = [
  17. PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  18. PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
  19. PDO::ATTR_EMULATE_PREPARES => false,
  20. ];
  21. try {
  22. $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
  23. $stmt = $pdo->query("SELECT * FROM `filterconf`");
  24. }
  25. catch (PDOException $e) {
  26. echo 'settings { }';
  27. exit;
  28. }
  29. ?>
  30. settings {
  31. whitelist_forwarding_hosts {
  32. priority = high;
  33. <?php
  34. try {
  35. $stmt = $pdo->query("SELECT `host` FROM `forwarding_hosts`");
  36. $rows = $stmt->fetchAll(PDO::FETCH_COLUMN);
  37. }
  38. catch (PDOException $e) {
  39. $rows = array();
  40. }
  41. foreach ($rows as $host) {
  42. echo "\t\t" . 'ip = "' . $host . '";' . "\n";
  43. }
  44. ?>
  45. apply "default" {
  46. actions {
  47. reject = 999.9;
  48. }
  49. }
  50. symbols [
  51. "WHITELIST_FORWARDING_HOST"
  52. ]
  53. }
  54. <?php
  55. $stmt = $pdo->query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'highspamlevel' OR `option` = 'lowspamlevel'");
  56. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  57. while ($row = array_shift($rows)) {
  58. $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']);
  59. ?>
  60. score_<?=$username_sane;?> {
  61. priority = low;
  62. <?php
  63. $stmt = $pdo->prepare("SELECT `option`, `value` FROM `filterconf`
  64. WHERE (`option` = 'highspamlevel' OR `option` = 'lowspamlevel')
  65. AND `object`= :object");
  66. $stmt->execute(array(':object' => $row['object']));
  67. $spamscore = $stmt->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP);
  68. $stmt = $pdo->prepare("SELECT GROUP_CONCAT(REPLACE(`value`, '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf`
  69. WHERE (`object`= :object OR `object`= :object_domain)
  70. AND (`option` = 'blacklist_from' OR `option` = 'whitelist_from')");
  71. $stmt->execute(array(':object' => $row['object'], ':object_domain' => substr(strrchr($row['object'], "@"), 1)));
  72. $grouped_lists = $stmt->fetchAll(PDO::FETCH_ASSOC);
  73. array_filter($grouped_lists);
  74. while ($grouped_list = array_shift($grouped_lists)) {
  75. $value_sane = preg_replace("/\.\./", ".", (preg_replace("/\*/", ".*", $grouped_list['value'])));
  76. if (!empty($value_sane)) {
  77. ?>
  78. from = "/^((?!<?=$value_sane;?>).)*$/";
  79. <?php
  80. }
  81. }
  82. $local = parse_email($row['object'])['local'];
  83. $domain = parse_email($row['object'])['domain'];
  84. if (!empty($local) && !empty($local)) {
  85. ?>
  86. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  87. <?php
  88. }
  89. ?>
  90. rcpt = "<?=$row['object'];?>";
  91. <?php
  92. $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` LIKE :object_goto AND `address` NOT LIKE '@%' AND `address` != :object_address");
  93. $stmt->execute(array(':object_goto' => '%' . $row['object'] . '%', ':object_address' => $row['object']));
  94. $rows_aliases_1 = $stmt->fetchAll(PDO::FETCH_ASSOC);
  95. while ($row_aliases_1 = array_shift($rows_aliases_1)) {
  96. $local = parse_email($row_aliases_1['address'])['local'];
  97. $domain = parse_email($row_aliases_1['address'])['domain'];
  98. if (!empty($local) && !empty($local)) {
  99. ?>
  100. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  101. <?php
  102. }
  103. ?>
  104. rcpt = "<?=$row_aliases_1['address'];?>";
  105. <?php
  106. }
  107. $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `aliases` FROM `mailbox`
  108. LEFT OUTER JOIN `alias_domain` on `mailbox`.`domain` = `alias_domain`.`target_domain`
  109. WHERE `mailbox`.`username` = :object");
  110. $stmt->execute(array(':object' => $row['object']));
  111. $rows_aliases_2 = $stmt->fetchAll(PDO::FETCH_ASSOC);
  112. array_filter($rows_aliases_2);
  113. while ($row_aliases_2 = array_shift($rows_aliases_2)) {
  114. if (!empty($row_aliases_2['aliases'])) {
  115. $local = parse_email($row_aliases_2['aliases'])['local'];
  116. $domain = parse_email($row_aliases_2['aliases'])['domain'];
  117. if (!empty($local) && !empty($local)) {
  118. ?>
  119. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  120. <?php
  121. }
  122. ?>
  123. rcpt = "<?=$row_aliases_2['aliases'];?>";
  124. <?php
  125. }
  126. }
  127. ?>
  128. apply "default" {
  129. actions {
  130. reject = <?=$spamscore['highspamlevel'][0];?>;
  131. greylist = <?=$spamscore['lowspamlevel'][0] - 1;?>;
  132. "add header" = <?=$spamscore['lowspamlevel'][0];?>;
  133. }
  134. }
  135. }
  136. <?php
  137. }
  138. /*
  139. // Start whitelist
  140. */
  141. $stmt = $pdo->query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'whitelist_from'");
  142. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  143. while ($row = array_shift($rows)) {
  144. $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']);
  145. ?>
  146. whitelist_<?=$username_sane;?> {
  147. <?php
  148. $stmt = $pdo->prepare("SELECT GROUP_CONCAT(REPLACE(`value`, '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf`
  149. WHERE `object`= :object
  150. AND `option` = 'whitelist_from'");
  151. $stmt->execute(array(':object' => $row['object']));
  152. $grouped_lists = $stmt->fetchAll(PDO::FETCH_COLUMN);
  153. $value_sane = preg_replace("/\.\./", ".", (preg_replace("/\*/", ".*", $grouped_lists[0])));
  154. ?>
  155. from = "/(<?=$value_sane;?>)/";
  156. <?php
  157. if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
  158. ?>
  159. priority = medium;
  160. rcpt = "/.*@<?=$row['object'];?>/";
  161. <?php
  162. $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain`
  163. WHERE `target_domain` = :object");
  164. $stmt->execute(array(':object' => $row['object']));
  165. $rows_domain_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC);
  166. array_filter($rows_domain_aliases);
  167. while ($row_domain_aliases = array_shift($rows_domain_aliases)) {
  168. ?>
  169. rcpt = "/.*@<?=$row_domain_aliases['alias_domain'];?>/";
  170. <?php
  171. }
  172. }
  173. else {
  174. ?>
  175. priority = high;
  176. <?php
  177. $local = parse_email($row['object'])['local'];
  178. $domain = parse_email($row['object'])['domain'];
  179. if (!empty($local) && !empty($local)) {
  180. ?>
  181. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  182. <?php
  183. }
  184. ?>
  185. rcpt = "<?=$row['object'];?>";
  186. <?php
  187. }
  188. $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` LIKE :object_goto AND `address` NOT LIKE '@%' AND `address` != :object_address");
  189. $stmt->execute(array(':object_goto' => '%' . $row['object'] . '%', ':object_address' => $row['object']));
  190. $rows_aliases_wl_1 = $stmt->fetchAll(PDO::FETCH_ASSOC);
  191. array_filter($rows_aliases_wl_1);
  192. while ($row_aliases_wl_1 = array_shift($rows_aliases_wl_1)) {
  193. $local = parse_email($row_aliases_wl_1['address'])['local'];
  194. $domain = parse_email($row_aliases_wl_1['address'])['domain'];
  195. if (!empty($local) && !empty($local)) {
  196. ?>
  197. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  198. <?php
  199. }
  200. ?>
  201. rcpt = "<?=$row_aliases_wl_1['address'];?>";
  202. <?php
  203. }
  204. $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `aliases` FROM `mailbox`
  205. LEFT OUTER JOIN `alias_domain` on `mailbox`.`domain` = `alias_domain`.`target_domain`
  206. WHERE `mailbox`.`username` = :object");
  207. $stmt->execute(array(':object' => $row['object']));
  208. $rows_aliases_wl_2 = $stmt->fetchAll(PDO::FETCH_ASSOC);
  209. array_filter($rows_aliases_wl_2);
  210. while ($row_aliases_wl_2 = array_shift($rows_aliases_wl_2)) {
  211. if (!empty($row_aliases_wl_2['aliases'])) {
  212. $local = parse_email($row_aliases_wl_2['aliases'])['local'];
  213. $domain = parse_email($row_aliases_wl_2['aliases'])['domain'];
  214. if (!empty($local) && !empty($local)) {
  215. ?>
  216. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  217. <?php
  218. }
  219. ?>
  220. rcpt = "<?=$row_aliases_wl_2['aliases'];?>";
  221. <?php
  222. }
  223. }
  224. ?>
  225. apply "default" {
  226. MAILCOW_MOO = -999.0;
  227. }
  228. }
  229. <?php
  230. }
  231. /*
  232. // Start blacklist
  233. */
  234. $stmt = $pdo->query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'blacklist_from'");
  235. $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  236. while ($row = array_shift($rows)) {
  237. $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']);
  238. ?>
  239. blacklist_<?=$username_sane;?> {
  240. <?php
  241. $stmt = $pdo->prepare("SELECT GROUP_CONCAT(REPLACE(`value`, '*', '.*') SEPARATOR '|') AS `value` FROM `filterconf`
  242. WHERE `object`= :object
  243. AND `option` = 'blacklist_from'");
  244. $stmt->execute(array(':object' => $row['object']));
  245. $grouped_lists = $stmt->fetchAll(PDO::FETCH_COLUMN);
  246. $value_sane = preg_replace("/\.\./", ".", (preg_replace("/\*/", ".*", $grouped_lists[0])));
  247. ?>
  248. from = "/(<?=$value_sane;?>)/";
  249. <?php
  250. if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
  251. ?>
  252. priority = medium;
  253. rcpt = "/.*@<?=$row['object'];?>/";
  254. <?php
  255. $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain`
  256. WHERE `target_domain` = :object");
  257. $stmt->execute(array(':object' => $row['object']));
  258. $rows_domain_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC);
  259. array_filter($rows_domain_aliases);
  260. while ($row_domain_aliases = array_shift($rows_domain_aliases)) {
  261. ?>
  262. rcpt = "/.*@<?=$row_domain_aliases['alias_domain'];?>/";
  263. <?php
  264. }
  265. }
  266. else {
  267. ?>
  268. priority = high;
  269. <?php
  270. $local = parse_email($row['object'])['local'];
  271. $domain = parse_email($row['object'])['domain'];
  272. if (!empty($local) && !empty($local)) {
  273. ?>
  274. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  275. <?php
  276. }
  277. ?>
  278. rcpt = "<?=$row['object'];?>";
  279. <?php
  280. }
  281. $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` LIKE :object_goto AND `address` NOT LIKE '@%' AND `address` != :object_address");
  282. $stmt->execute(array(':object_goto' => '%' . $row['object'] . '%', ':object_address' => $row['object']));
  283. $rows_aliases_bl_1 = $stmt->fetchAll(PDO::FETCH_ASSOC);
  284. array_filter($rows_aliases_bl_1);
  285. while ($row_aliases_bl_1 = array_shift($rows_aliases_bl_1)) {
  286. $local = parse_email($row_aliases_bl_1['address'])['local'];
  287. $domain = parse_email($row_aliases_bl_1['address'])['domain'];
  288. if (!empty($local) && !empty($local)) {
  289. ?>
  290. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  291. <?php
  292. }
  293. ?>
  294. rcpt = "<?=$row_aliases_bl_1['address'];?>";
  295. <?php
  296. }
  297. $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `aliases` FROM `mailbox`
  298. LEFT OUTER JOIN `alias_domain` on `mailbox`.`domain` = `alias_domain`.`target_domain`
  299. WHERE `mailbox`.`username` = :object");
  300. $stmt->execute(array(':object' => $row['object']));
  301. $rows_aliases_bl_2 = $stmt->fetchAll(PDO::FETCH_ASSOC);
  302. array_filter($rows_aliases_bl_2);
  303. while ($row_aliases_bl_2 = array_shift($rows_aliases_bl_2)) {
  304. if (!empty($row_aliases_bl_2['aliases'])) {
  305. $local = parse_email($row_aliases_bl_2['aliases'])['local'];
  306. $domain = parse_email($row_aliases_bl_2['aliases'])['domain'];
  307. if (!empty($local) && !empty($local)) {
  308. ?>
  309. rcpt = "/<?=$local;?>\+.*<?=$domain;?>/";
  310. <?php
  311. }
  312. ?>
  313. rcpt = "<?=$row_aliases_bl_2['aliases'];?>";
  314. <?php
  315. }
  316. }
  317. ?>
  318. apply "default" {
  319. MAILCOW_MOO = 999.0;
  320. }
  321. }
  322. <?php
  323. }
  324. ?>
  325. }