mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2024-12-09 08:50:05 +08:00
[Rspamd] Create BCC plugin
This commit is contained in:
parent
735bcb2f55
commit
c8955284a2
@ -161,8 +161,9 @@ virtual_alias_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_alias_maps.
|
||||
virtual_gid_maps = static:5000
|
||||
virtual_mailbox_base = /var/vmail/
|
||||
virtual_mailbox_domains = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
|
||||
recipient_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf
|
||||
sender_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf
|
||||
# -- moved to rspamd on 2021-06-01
|
||||
#recipient_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf
|
||||
#sender_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf
|
||||
recipient_canonical_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
|
||||
recipient_canonical_classes = envelope_recipient
|
||||
virtual_mailbox_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
|
||||
|
88
data/conf/rspamd/dynmaps/bcc.php
Normal file
88
data/conf/rspamd/dynmaps/bcc.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
// File size is limited by Nginx site to 10M
|
||||
// To speed things up, we do not include prerequisites
|
||||
header('Content-Type: text/plain');
|
||||
require_once "vars.inc.php";
|
||||
// Do not show errors, we log to using error_log
|
||||
ini_set('error_reporting', 0);
|
||||
// Init database
|
||||
//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
|
||||
$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
|
||||
$opt = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
];
|
||||
try {
|
||||
$pdo = new PDO($dsn, $database_user, $database_pass, $opt);
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
error_log("BCC MAP SQL ERROR: " . $e . PHP_EOL);
|
||||
http_response_code(501);
|
||||
exit;
|
||||
}
|
||||
|
||||
function parse_email($email) {
|
||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
|
||||
$a = strrpos($email, '@');
|
||||
return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1));
|
||||
}
|
||||
if (!function_exists('getallheaders')) {
|
||||
function getallheaders() {
|
||||
if (!is_array($_SERVER)) {
|
||||
return array();
|
||||
}
|
||||
$headers = array();
|
||||
foreach ($_SERVER as $name => $value) {
|
||||
if (substr($name, 0, 5) == 'HTTP_') {
|
||||
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
|
||||
}
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
}
|
||||
|
||||
// Read headers
|
||||
$headers = getallheaders();
|
||||
// Get rcpt
|
||||
$rcpt = $headers['Rcpt'];
|
||||
// Get from
|
||||
$from = $headers['From'];
|
||||
// Remove tags
|
||||
$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt);
|
||||
$from = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $from);
|
||||
|
||||
try {
|
||||
if (!empty($rcpt)) {
|
||||
$stmt = $pdo->prepare("SELECT `bcc_dest` FROM `bcc_maps` WHERE `type` = 'rcpt' AND `local_dest` = :local_dest AND `active` = '1'");
|
||||
$stmt->execute(array(
|
||||
':local_dest' => $rcpt
|
||||
));
|
||||
$bcc_dest = $stmt->fetch(PDO::FETCH_ASSOC)['bcc_dest'];
|
||||
if (!empty($bcc_dest) && filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) {
|
||||
error_log("BCC MAP: returning ". $bcc_dest . " for " . $rcpt . PHP_EOL);
|
||||
http_response_code(201);
|
||||
echo trim($bcc_dest);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if (!empty($from)) {
|
||||
$stmt = $pdo->prepare("SELECT `bcc_dest` FROM `bcc_maps` WHERE `type` = 'sender' AND `local_dest` = :local_dest AND `active` = '1'");
|
||||
$stmt->execute(array(
|
||||
':local_dest' => $from
|
||||
));
|
||||
$bcc_dest = $stmt->fetch(PDO::FETCH_ASSOC)['bcc_dest'];
|
||||
if (!empty($bcc_dest) && filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) {
|
||||
error_log("BCC MAP: returning ". $bcc_dest . " for " . $from . PHP_EOL);
|
||||
http_response_code(201);
|
||||
echo trim($bcc_dest);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
error_log("BCC MAP SQL ERROR: " . $e->getMessage() . PHP_EOL);
|
||||
http_response_code(502);
|
||||
exit;
|
||||
}
|
||||
|
@ -320,6 +320,112 @@ rspamd_config:register_symbol({
|
||||
priority = 19
|
||||
})
|
||||
|
||||
rspamd_config:register_symbol({
|
||||
name = 'BCC',
|
||||
type = 'postfilter',
|
||||
callback = function(task)
|
||||
local util = require("rspamd_util")
|
||||
local rspamd_http = require "rspamd_http"
|
||||
local rspamd_logger = require "rspamd_logger"
|
||||
|
||||
local from_table = {}
|
||||
local rcpt_table = {}
|
||||
|
||||
local send_mail = function(task, bcc_dest)
|
||||
local lua_smtp = require "lua_smtp"
|
||||
local function sendmail_cb(ret, err)
|
||||
if not ret then
|
||||
rspamd_logger.errx(task, 'BCC SMTP ERROR: %s', err)
|
||||
else
|
||||
rspamd_logger.infox(rspamd_config, "BCC SMTP SUCCESS TO %s", bcc_dest)
|
||||
end
|
||||
end
|
||||
if not bcc_dest then
|
||||
return -- stop
|
||||
end
|
||||
lua_smtp.sendmail({
|
||||
task = task,
|
||||
host = 'postfix',
|
||||
port = 591,
|
||||
from = task:get_from(stp)[1].addr,
|
||||
recipients = bcc_dest,
|
||||
helo = 'bcc',
|
||||
timeout = 10,
|
||||
}, task:get_content(), sendmail_cb)
|
||||
end
|
||||
|
||||
-- determine from
|
||||
local from = task:get_from('smtp')
|
||||
if from then
|
||||
for _, a in ipairs(from) do
|
||||
table.insert(from_table, a['addr']) -- add this rcpt to table
|
||||
table.insert(from_table, '@' .. a['domain']) -- add this rcpts domain to table
|
||||
end
|
||||
else
|
||||
return -- stop
|
||||
end
|
||||
|
||||
-- determine rcpts
|
||||
local rcpts = task:get_recipients('smtp')
|
||||
if rcpts then
|
||||
for _, a in ipairs(rcpts) do
|
||||
table.insert(rcpt_table, a['addr']) -- add this rcpt to table
|
||||
table.insert(rcpt_table, '@' .. a['domain']) -- add this rcpts domain to table
|
||||
end
|
||||
else
|
||||
return -- stop
|
||||
end
|
||||
|
||||
local action = task:get_metric_action('default')
|
||||
rspamd_logger.infox("metric action now: %s", action)
|
||||
|
||||
local function rcpt_callback(err_message, code, body, headers)
|
||||
if err_message == nil and code == 201 and body ~= nil then
|
||||
if action == 'no action' or action == 'add header' or action == 'rewrite subject' then
|
||||
send_mail(task, body)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function from_callback(err_message, code, body, headers)
|
||||
if err_message == nil and code == 201 and body ~= nil then
|
||||
if action == 'no action' or action == 'add header' or action == 'rewrite subject' then
|
||||
send_mail(task, body)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if rcpt_table then
|
||||
for _,e in ipairs(rcpt_table) do
|
||||
rspamd_logger.infox(rspamd_config, "checking bcc for rcpt address %s", e)
|
||||
rspamd_http.request({
|
||||
task=task,
|
||||
url='http://nginx:8081/bcc.php',
|
||||
body='',
|
||||
callback=rcpt_callback,
|
||||
headers={Rcpt=e}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if from_table then
|
||||
for _,e in ipairs(from_table) do
|
||||
rspamd_logger.infox(rspamd_config, "checking bcc for from address %s", e)
|
||||
rspamd_http.request({
|
||||
task=task,
|
||||
url='http://nginx:8081/bcc.php',
|
||||
body='',
|
||||
callback=from_callback,
|
||||
headers={From=e}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
priority = 20
|
||||
})
|
||||
|
||||
rspamd_config:register_symbol({
|
||||
name = 'DYN_RL_CHECK',
|
||||
type = 'prefilter',
|
||||
|
Loading…
Reference in New Issue
Block a user