mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2025-12-15 19:06:03 +00:00
[Web][Rspamd] implement custom mailbox attributes and improve domain wide footer
This commit is contained in:
89
data/conf/rspamd/dynmaps/footer.php
Normal file
89
data/conf/rspamd/dynmaps/footer.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?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("FOOTER: " . $e . PHP_EOL);
|
||||
http_response_code(501);
|
||||
exit;
|
||||
}
|
||||
|
||||
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 Domain
|
||||
$domain = $headers['Domain'];
|
||||
// Get Username
|
||||
$username = $headers['Username'];
|
||||
// define empty footer
|
||||
$empty_footer = json_encode(array(
|
||||
'html' => '',
|
||||
'plain' => '',
|
||||
'vars' => array()
|
||||
));
|
||||
|
||||
error_log("FOOTER: checking for domain " . $domain . " and user " . $username . PHP_EOL);
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `plain`, `html`, `mbox_exclude` FROM `domain_wide_footer`
|
||||
WHERE `domain` = :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => $domain
|
||||
));
|
||||
$footer = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (in_array($username, json_decode($footer['mbox_exclude']))){
|
||||
$footer = false;
|
||||
}
|
||||
if (empty($footer)){
|
||||
echo $empty_footer;
|
||||
exit;
|
||||
}
|
||||
error_log("FOOTER: " . json_encode($footer) . PHP_EOL);
|
||||
|
||||
$stmt = $pdo->prepare("SELECT `custom_attributes` FROM `mailbox` WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username
|
||||
));
|
||||
$custom_attributes = $stmt->fetch(PDO::FETCH_ASSOC)['custom_attributes'];
|
||||
if (empty($custom_attributes)){
|
||||
$custom_attributes = (object)array();
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
error_log("FOOTER: " . $e->getMessage() . PHP_EOL);
|
||||
http_response_code(502);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
// return footer
|
||||
$footer["vars"] = $custom_attributes;
|
||||
echo json_encode($footer);
|
||||
@@ -527,12 +527,11 @@ rspamd_config:register_symbol({
|
||||
name = 'MOO_FOOTER',
|
||||
type = 'prefilter',
|
||||
callback = function(task)
|
||||
local cjson = require "cjson"
|
||||
local lua_mime = require "lua_mime"
|
||||
local lua_util = require "lua_util"
|
||||
local rspamd_logger = require "rspamd_logger"
|
||||
local rspamd_redis = require "rspamd_redis"
|
||||
local ucl = require "ucl"
|
||||
local redis_params = rspamd_parse_redis_server('footer')
|
||||
local rspamd_http = require "rspamd_http"
|
||||
local envfrom = task:get_from(1)
|
||||
local uname = task:get_user()
|
||||
if not envfrom or not uname then
|
||||
@@ -541,6 +540,7 @@ rspamd_config:register_symbol({
|
||||
local uname = uname:lower()
|
||||
local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case
|
||||
|
||||
-- determine newline type
|
||||
local function newline(task)
|
||||
local t = task:get_newlines_type()
|
||||
|
||||
@@ -552,20 +552,19 @@ rspamd_config:register_symbol({
|
||||
|
||||
return '\r\n'
|
||||
end
|
||||
local function redis_cb_footer(err, data)
|
||||
-- retrieve footer
|
||||
local function footer_cb(err_message, code, data, headers)
|
||||
if err or type(data) ~= 'string' then
|
||||
rspamd_logger.infox(rspamd_config, "domain wide footer request for user %s returned invalid or empty data (\"%s\") or error (\"%s\")", uname, data, err)
|
||||
else
|
||||
|
||||
-- parse json string
|
||||
local parser = ucl.parser()
|
||||
local res,err = parser:parse_string(data)
|
||||
if not res then
|
||||
local footer = cjson.decode(data)
|
||||
if not footer then
|
||||
rspamd_logger.infox(rspamd_config, "parsing domain wide footer for user %s returned invalid or empty data (\"%s\") or error (\"%s\")", uname, data, err)
|
||||
else
|
||||
local footer = parser:get_object()
|
||||
|
||||
if footer and type(footer) == "table" and (footer.html and footer.html ~= "" or footer.plain and footer.plain ~= "") then
|
||||
rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s", uname, footer.html, footer.plain)
|
||||
rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s, vars=%s", uname, footer.html, footer.plain, footer.vars)
|
||||
|
||||
local envfrom_mime = task:get_from(2)
|
||||
local from_name = ""
|
||||
@@ -575,6 +574,7 @@ rspamd_config:register_symbol({
|
||||
from_name = envfrom[1].name
|
||||
end
|
||||
|
||||
-- default replacements
|
||||
local replacements = {
|
||||
auth_user = uname,
|
||||
from_user = envfrom[1].user,
|
||||
@@ -582,10 +582,20 @@ rspamd_config:register_symbol({
|
||||
from_addr = envfrom[1].addr,
|
||||
from_domain = envfrom[1].domain:lower()
|
||||
}
|
||||
if footer.html then
|
||||
-- add custom mailbox attributes
|
||||
if footer.vars and type(footer.vars) == "string" then
|
||||
local footer_vars = cjson.decode(footer.vars)
|
||||
|
||||
if type(footer_vars) == "table" then
|
||||
for key, value in pairs(footer_vars) do
|
||||
replacements[key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
if footer.html and footer.html ~= "" then
|
||||
footer.html = lua_util.jinja_template(footer.html, replacements, true)
|
||||
end
|
||||
if footer.plain then
|
||||
if footer.plain and footer.plain ~= "" then
|
||||
footer.plain = lua_util.jinja_template(footer.plain, replacements, true)
|
||||
end
|
||||
|
||||
@@ -653,17 +663,14 @@ rspamd_config:register_symbol({
|
||||
end
|
||||
end
|
||||
|
||||
local redis_ret_footer = rspamd_redis_make_request(task,
|
||||
redis_params, -- connect params
|
||||
env_from_domain, -- hash key
|
||||
false, -- is write
|
||||
redis_cb_footer, --callback
|
||||
'HGET', -- command
|
||||
{"DOMAIN_WIDE_FOOTER", env_from_domain} -- arguments
|
||||
)
|
||||
if not redis_ret_footer then
|
||||
rspamd_logger.infox(rspamd_config, "cannot make request to load footer for domain")
|
||||
end
|
||||
-- fetch footer
|
||||
rspamd_http.request({
|
||||
task=task,
|
||||
url='http://nginx:8081/footer.php',
|
||||
body='',
|
||||
callback=footer_cb,
|
||||
headers={Domain=env_from_domain,Username=uname},
|
||||
})
|
||||
|
||||
return true
|
||||
end,
|
||||
|
||||
Reference in New Issue
Block a user