[Rspamd] Create BCC plugin
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_gid_maps = static:5000
|
||||||
virtual_mailbox_base = /var/vmail/
|
virtual_mailbox_base = /var/vmail/
|
||||||
virtual_mailbox_domains = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
|
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
|
# -- moved to rspamd on 2021-06-01
|
||||||
sender_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_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
|
||||||
recipient_canonical_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
|
recipient_canonical_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
|
||||||
recipient_canonical_classes = envelope_recipient
|
recipient_canonical_classes = envelope_recipient
|
||||||
virtual_mailbox_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
|
virtual_mailbox_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
|
||||||
|
|
|
@ -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
|
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({
|
rspamd_config:register_symbol({
|
||||||
name = 'DYN_RL_CHECK',
|
name = 'DYN_RL_CHECK',
|
||||||
type = 'prefilter',
|
type = 'prefilter',
|
||||||
|
|
Loading…
Reference in New Issue