[Rspamd] add domain wide footer

This commit is contained in:
FreddleSpl0it
2023-05-08 12:55:38 +02:00
parent ee607dc3cc
commit f295b8cd91
7 changed files with 248 additions and 12 deletions

View File

@@ -47,6 +47,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
$quota_notification_bcc = quota_notification_bcc('get', $domain);
$rl = ratelimit('get', 'domain', $domain);
$rlyhosts = relayhost('get');
$domain_footer = mailbox('get', 'domain_wide_footer', $domain);
$template = 'edit/domain.twig';
$template_data = [
'acl' => $_SESSION['acl'],
@@ -56,6 +57,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
'rlyhosts' => $rlyhosts,
'dkim' => dkim('details', $domain),
'domain_details' => $result,
'domain_footer' => $domain_footer,
];
}
}

View File

@@ -3320,6 +3320,45 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
}
break;
case 'domain_wide_footer':
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
if (!is_valid_domain_name($domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'domain_invalid'
);
return false;
}
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'access_denied'
);
return false;
}
$footers = array();
$footers['html'] = isset($_data['footer_html']) ? $_data['footer_html'] : '';
$footers['plain'] = isset($_data['footer_plain']) ? $_data['footer_plain'] : '';
try {
$redis->hSet('DOMAIN_WIDE_FOOTER', $domain, json_encode($footers));
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('redis_error', $e)
);
return false;
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('domain_footer_modified', htmlspecialchars($domain))
);
break;
}
break;
case 'get':
@@ -4399,6 +4438,40 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
}
return $resourcedata;
break;
case 'domain_wide_footer':
$domain = idn_to_ascii(strtolower(trim($_data)), 0, INTL_IDNA_VARIANT_UTS46);
if (!is_valid_domain_name($domain)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'domain_invalid'
);
return false;
}
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'access_denied'
);
return false;
}
try {
$footers = $redis->hGet('DOMAIN_WIDE_FOOTER', $domain);
$footers = json_decode($footers, true);
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('redis_error', $e)
);
return false;
}
return $footers;
break;
}
break;
case 'delete':

View File

@@ -288,18 +288,18 @@ if (isset($_GET['query'])) {
case "domain-admin":
process_add_return(domain_admin('add', $attr));
break;
case "sso":
switch ($object) {
case "domain-admin":
$data = domain_admin_sso('issue', $attr);
if($data) {
echo json_encode($data);
exit(0);
}
process_add_return($data);
break;
}
break;
case "sso":
switch ($object) {
case "domain-admin":
$data = domain_admin_sso('issue', $attr);
if($data) {
echo json_encode($data);
exit(0);
}
process_add_return($data);
break;
}
break;
case "admin":
process_add_return(admin('add', $attr));
break;
@@ -1867,6 +1867,9 @@ if (isset($_GET['query'])) {
case "quota_notification_bcc":
process_edit_return(quota_notification_bcc('edit', $attr));
break;
case "domain-wide-footer":
process_edit_return(mailbox('edit', 'domain_wide_footer', $attr));
break;
case "mailq":
process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr)));
break;

View File

@@ -576,6 +576,10 @@
"disable_login": "Login verbieten (Mails werden weiterhin angenommen)",
"domain": "Domain bearbeiten",
"domain_admin": "Domain-Administrator bearbeiten",
"domain_footer": "Domain wide footer",
"domain_footer_html": "HTML footer",
"domain_footer_info": "Domain wide footer werden allen E-Mails hinzugefügt, die von der angegebenen Domain gesendet werden.",
"domain_footer_plain": "PLAIN footer",
"domain_quota": "Domain Speicherplatz gesamt (MiB)",
"domains": "Domains",
"dont_check_sender_acl": "Absender für Domain %s u. Alias-Domain nicht prüfen",
@@ -1011,6 +1015,7 @@
"domain_admin_added": "Domain-Administrator %s wurde angelegt",
"domain_admin_modified": "Änderungen an Domain-Administrator %s wurden gespeichert",
"domain_admin_removed": "Domain-Administrator %s wurde entfernt",
"domain_footer_modified": "Änderungen an Domain Footer %s wurden gespeichert",
"domain_modified": "Änderungen an Domain %s wurden gespeichert",
"domain_removed": "Domain %s wurde entfernt",
"dovecot_restart_success": "Dovecot wurde erfolgreich neu gestartet",

View File

@@ -576,6 +576,10 @@
"disable_login": "Disallow login (incoming mail is still accepted)",
"domain": "Edit domain",
"domain_admin": "Edit domain administrator",
"domain_footer": "Domain wide footer",
"domain_footer_html": "HTML footer",
"domain_footer_info": "Domain wide footers will be added to all emails sent from the specified domain.",
"domain_footer_plain": "PLAIN footer",
"domain_quota": "Domain quota",
"domains": "Domains",
"dont_check_sender_acl": "Disable sender check for domain %s (+ alias domains)",
@@ -1018,6 +1022,7 @@
"domain_admin_added": "Domain administrator %s has been added",
"domain_admin_modified": "Changes to domain administrator %s have been saved",
"domain_admin_removed": "Domain administrator %s has been removed",
"domain_footer_modified": "Changes to domain footer %s have been saved",
"domain_modified": "Changes to domain %s have been saved",
"domain_removed": "Domain %s has been removed",
"dovecot_restart_success": "Dovecot was restarted successfully",

View File

@@ -7,6 +7,7 @@
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dratelimit">{{ lang.edit.ratelimit }}</button></li>
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dspamfilter">{{ lang.edit.spam_filter }}</button></li>
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dqwbcc">{{ lang.edit.quota_warning_bcc }}</button></li>
<li role="presentation" class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#dfooter">{{ lang.edit.domain_footer }}</button></li>
</ul>
<hr>
<div class="tab-content">
@@ -229,6 +230,33 @@
</div>
</div>
</div>
<div id="dfooter" class="tab-pane fade" role="tabpanel" aria-labelledby="domain-footer">
<div class="row">
<div class="col-sm-12">
<h4>{{ lang.edit.domain_footer }}</h4>
<p>{{ lang.edit.domain_footer_info|raw }}</p>
<form class="form-horizontal" data-id="domain_footer">
<div class="row mb-2">
<label class="control-label col-sm-2" for="domain_footer_html">{{ lang.edit.domain_footer_html }}:</label>
<div class="col-sm-10">
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control" rows="10" id="domain_footer_html" name="footer_html">{{ domain_footer.html }}</textarea>
</div>
</div>
<div class="row mb-4">
<label class="control-label col-sm-2" for="domain_footer_plain">{{ lang.edit.domain_footer_plain }}:</label>
<div class="col-sm-10">
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control" rows="10" id="domain_footer_plain" name="footer_plain">{{ domain_footer.plain }}</textarea>
</div>
</div>
<div class="row">
<div class="offset-sm-2 col-sm-10">
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="domain_footer" data-item="domain_footer" data-api-url='edit/domain-wide-footer' data-api-attr='{"domain":"{{ domain }}"}' href="#">{{ lang.edit.save }}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% else %}
{{ parent() }}