Merge branch 'master' into mta-sts-support
This commit is contained in:
commit
83f87885bc
|
@ -10,12 +10,6 @@ permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
statuses: write
|
statuses: write
|
||||||
|
|
||||||
env:
|
|
||||||
# Assign commit authorship to official Github Actions bot:
|
|
||||||
GIT_USER: github-actions[bot]
|
|
||||||
GIT_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com
|
|
||||||
BRANCH_NAME: contributors-update
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
add-contributors:
|
add-contributors:
|
||||||
name: 'Add Contributors'
|
name: 'Add Contributors'
|
||||||
|
@ -24,64 +18,15 @@ jobs:
|
||||||
- name: 'Checkout'
|
- name: 'Checkout'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 'Checkout New Branch and Push It'
|
|
||||||
run: |
|
|
||||||
git checkout -b ${{ env.BRANCH_NAME }}
|
|
||||||
git push --force https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git HEAD:${{ env.BRANCH_NAME }}
|
|
||||||
git checkout master
|
|
||||||
|
|
||||||
# See https://github.com/marketplace/actions/auto-add-contributors for reference of the action.
|
|
||||||
#
|
|
||||||
# This action is not well documented, but it does the job for now. We pin the version in order
|
|
||||||
# to not have any issues in the future.
|
|
||||||
- name: 'Update CONTRIBUTORS.md'
|
- name: 'Update CONTRIBUTORS.md'
|
||||||
uses: BobAnkh/add-contributors@v0.2.2
|
uses: akhilmhdh/contributors-readme-action@v2.3.6
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
ACCESS_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
readme_path: CONTRIBUTORS.md
|
||||||
BRANCH: ${{ env.BRANCH_NAME }}
|
collaborators: all
|
||||||
COMMIT_MESSAGE: 'docs: update `CONTRIBUTORS.md`'
|
commit_message: 'docs: updated `CONTRIBUTORS.md`'
|
||||||
PATH: /CONTRIBUTORS.md
|
committer_username: github-actions[bot]
|
||||||
CONTRIBUTOR: '## Contributors'
|
committer_email: 41898282+github-actions[bot]@users.noreply.github.com
|
||||||
COLUMN_PER_ROW: 6
|
pr_title_on_protected: 'docs: update `CONTRIBUTORS.md'
|
||||||
IMG_WIDTH: 100
|
auto_detect_branch_protection: true
|
||||||
FONT_SIZE: 14
|
|
||||||
AVATAR_SHAPE: round
|
|
||||||
|
|
||||||
# See https://github.com/marketplace/actions/create-pull-request for reference of the action.
|
|
||||||
- name: 'Create Pull Request'
|
|
||||||
uses: peter-evans/create-pull-request@v5.0.2
|
|
||||||
id: create-pr
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
base: master
|
|
||||||
branch: ${{ env.BRANCH_NAME }}
|
|
||||||
title: 'docs: update `CONTRIBUTORS.md`'
|
|
||||||
commit-message: 'docs: update `CONTRIBUTORS.md`'
|
|
||||||
delete-branch: true
|
|
||||||
committer: ${{ env.GIT_USER }} <${{ env.GIT_EMAIL }}>
|
|
||||||
author: ${{ env.GIT_USER }} <${{ env.GIT_EMAIL }}>
|
|
||||||
signoff: true
|
|
||||||
body: |
|
|
||||||
Updated `CONTRIBUTORS.md` via the CI workflow: [`contributors.yml`][workflow].
|
|
||||||
|
|
||||||
[workflow]: https://github.com/docker-mailserver/docker-mailserver/blob/master/.github/workflows/contributors.yml
|
|
||||||
|
|
||||||
# See https://github.com/marketplace/actions/set-commit-status for reference of the action.
|
|
||||||
#
|
|
||||||
# GH Actions are limited when it comes to actions triggering other actions. Hence,
|
|
||||||
# this whole workflow will not trigger a `pull_request` event without a PAT. The lint
|
|
||||||
# workflow, which is required due to branch protection, is not important for this type
|
|
||||||
# of PR, so we skip it and pretend it was successful.
|
|
||||||
- name: 'Set Status for Linting Actions to Success (Skipped)'
|
|
||||||
uses: myrotvorets/set-commit-status-action@v2.0.0
|
|
||||||
continue-on-error: true
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
# Skipped workflows are still assigned a "success" status:
|
|
||||||
status: success
|
|
||||||
# This should be the correct commit SHA on ${{ env.BRANCH_NAME }}:
|
|
||||||
sha: ${{ steps.create-pr.outputs.pull-request-head-sha }}
|
|
||||||
# Name of status check to add/update:
|
|
||||||
context: lint
|
|
||||||
# Optional message/note we can inline to the right of the context name in the UI:
|
|
||||||
description: Lint skipped. Not relevant.
|
|
||||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -9,6 +9,19 @@ All notable changes to this project will be documented in this file. The format
|
||||||
### Breaking
|
### Breaking
|
||||||
|
|
||||||
- The environment variable `ENABLE_LDAP=1` has been changed to `ACCOUNT_PROVISIONER=LDAP`.
|
- The environment variable `ENABLE_LDAP=1` has been changed to `ACCOUNT_PROVISIONER=LDAP`.
|
||||||
|
- Postfix now defaults to supporting DSNs (_[Delivery Status Notifications](https://github.com/docker-mailserver/docker-mailserver/pull/3572#issuecomment-1751880574)_) only for authenticated users. This is a security measure to reduce spammer abuse of your DMS instance as a backscatter source.
|
||||||
|
- If you need to modify this change, please let us know by opening an issue / discussion.
|
||||||
|
- You can [opt-out (_enable DSNs_) via the `postfix-main.cf` override support](https://docker-mailserver.github.io/docker-mailserver/v12.1/config/advanced/override-defaults/postfix/) using the contents: `smtpd_discard_ehlo_keywords =`.
|
||||||
|
- Likewise for authenticated users, the submission(s) ports (465 + 587) are configured internally via `master.cf` to keep DSNs enabled (_since authentication protects from abuse_).
|
||||||
|
|
||||||
|
If necessary, DSNs for authenticated users can be disabled via the `postfix-master.cf` override with the following contents:
|
||||||
|
|
||||||
|
```cf
|
||||||
|
submission/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
|
||||||
|
submissions/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
|
||||||
|
```
|
||||||
|
|
||||||
|
- using the old path for the Rspamd custom commands file (`/tmp/docker-mailserver/rspamd-modules.conf`), which was deprecated, will now prevent startup; use `/tmp/docker-mailserver/rspamd/custom-commands.conf` instead
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
2294
CONTRIBUTORS.md
2294
CONTRIBUTORS.md
File diff suppressed because it is too large
Load Diff
|
@ -107,11 +107,11 @@ DMS brings sane default settings for Rspamd. They are located at `/etc/rspamd/lo
|
||||||
|
|
||||||
!!! question "What is [`docker-data/dms/config/`][docs-dms-config-volume]?"
|
!!! question "What is [`docker-data/dms/config/`][docs-dms-config-volume]?"
|
||||||
|
|
||||||
If you want to overwrite the default settings and / or provide your own settings, you can place files at `docker-data/dms/config/rspamd/override.d/` (a directory that is linked to `/etc/rspamd/override.d/`, if it exists) to override Rspamd and DMS default settings. This directory will not do a complete file override, but a [forced override of the specific settings in that file][rspamd-docs-override-dir].
|
If you want to overwrite the default settings and / or provide your own settings, you can place files at `docker-data/dms/config/rspamd/override.d/`. Files from this directory are copied to `/etc/rspamd/override.d/` during startup. These files [forcibly override][rspamd-docs-override-dir] Rspamd and DMS default settings.
|
||||||
|
|
||||||
!!! warning "Clashing Overrides"
|
!!! warning "Clashing Overrides"
|
||||||
|
|
||||||
Note that when also [using the `rspamd-commands` file](#with-the-help-of-a-custom-file), files in `override.d` may be overwritten in case you adjust them manually and with the help of the file.
|
Note that when also [using the `custom-commands.conf` file](#with-the-help-of-a-custom-file), files in `override.d` may be overwritten in case you adjust them manually and with the help of the file.
|
||||||
|
|
||||||
[rspamd-docs-override-dir]: https://www.rspamd.com/doc/faq.html#what-are-the-locald-and-overrided-directories
|
[rspamd-docs-override-dir]: https://www.rspamd.com/doc/faq.html#what-are-the-locald-and-overrided-directories
|
||||||
[docs-dms-config-volume]: ../../faq.md#what-about-the-docker-datadmsconfig-directory
|
[docs-dms-config-volume]: ../../faq.md#what-about-the-docker-datadmsconfig-directory
|
||||||
|
|
|
@ -33,6 +33,9 @@ ${ORANGE}EXAMPLES${RESET}
|
||||||
${LWHITE}./setup.sh alias add alias@example.com recipient@example.com${RESET}
|
${LWHITE}./setup.sh alias add alias@example.com recipient@example.com${RESET}
|
||||||
Add the alias 'alias@example.com' for the mail account 'recipient@example.com'.
|
Add the alias 'alias@example.com' for the mail account 'recipient@example.com'.
|
||||||
|
|
||||||
|
${LWHITE}./setup.sh alias add alias@example.com 'recipient@example.com, another-recipient@example.com'${RESET}
|
||||||
|
Multiple recipients are separated by comma.
|
||||||
|
|
||||||
${ORANGE}EXIT STATUS${RESET}
|
${ORANGE}EXIT STATUS${RESET}
|
||||||
Exit status is 0 if command was successful. If wrong arguments are provided
|
Exit status is 0 if command was successful. If wrong arguments are provided
|
||||||
or arguments contain errors, the script will exit early with exit status 1.
|
or arguments contain errors, the script will exit early with exit status 1.
|
||||||
|
|
|
@ -27,6 +27,7 @@ ${ORANGE}DESCRIPTION${RESET}
|
||||||
|
|
||||||
${ORANGE}OPTIONS${RESET}
|
${ORANGE}OPTIONS${RESET}
|
||||||
${BLUE}Generic Program Information${RESET}
|
${BLUE}Generic Program Information${RESET}
|
||||||
|
-f | --force Overwrite existing files if there are any
|
||||||
-v Enable verbose logging (setting the log level to 'debug').
|
-v Enable verbose logging (setting the log level to 'debug').
|
||||||
-vv Enable very verbose logging (setting the log level to 'trace').
|
-vv Enable very verbose logging (setting the log level to 'trace').
|
||||||
help Print the usage information.
|
help Print the usage information.
|
||||||
|
@ -69,6 +70,7 @@ function __do_as_rspamd_user() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _parse_arguments() {
|
function _parse_arguments() {
|
||||||
|
FORCE=0
|
||||||
KEYTYPE='rsa'
|
KEYTYPE='rsa'
|
||||||
KEYSIZE='2048'
|
KEYSIZE='2048'
|
||||||
SELECTOR='mail'
|
SELECTOR='mail'
|
||||||
|
@ -112,6 +114,12 @@ function _parse_arguments() {
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
( '-f' | '--force' )
|
||||||
|
FORCE=1
|
||||||
|
shift 1
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
|
||||||
( '-vv' )
|
( '-vv' )
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
LOG_LEVEL='trace'
|
LOG_LEVEL='trace'
|
||||||
|
@ -132,30 +140,36 @@ function _parse_arguments() {
|
||||||
__usage
|
__usage
|
||||||
_exit_with_error "Unknown option(s) '${1}' ${2:+"and '${2}'"}"
|
_exit_with_error "Unknown option(s) '${1}' ${2:+"and '${2}'"}"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
shift 2
|
shift 2
|
||||||
done
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function _preflight_checks() {
|
||||||
if [[ ${KEYTYPE} == 'ed25519' ]] && [[ ${KEYSIZE} -ne 2048 ]]; then
|
if [[ ${KEYTYPE} == 'ed25519' ]] && [[ ${KEYSIZE} -ne 2048 ]]; then
|
||||||
_exit_with_error "Chosen keytype does not accept the 'keysize' argument"
|
_exit_with_error "Chosen keytype does not accept the 'keysize' argument"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
if [[ ! -d /tmp/docker-mailserver ]]; then
|
||||||
|
_log 'warn' "The directory '/tmp/docker-mailserver' does not seem to be mounted by a volume - the Rspamd (DKIM) configuration will not be persisted"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_rspamd_get_envs
|
||||||
|
|
||||||
|
mkdir -p "${RSPAMD_DMS_DKIM_D}" "${RSPAMD_DMS_OVERRIDE_D}"
|
||||||
|
chown _rspamd:_rspamd "${RSPAMD_DMS_DKIM_D}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function _create_keys() {
|
function _create_keys() {
|
||||||
# Note: Variables not marked with `local` are used
|
|
||||||
# in other functions (after this function was called).
|
|
||||||
BASE_DIR='/tmp/docker-mailserver/rspamd/dkim'
|
|
||||||
|
|
||||||
if [[ ${KEYTYPE} == 'rsa' ]]; then
|
if [[ ${KEYTYPE} == 'rsa' ]]; then
|
||||||
local BASE_FILE_NAME="${BASE_DIR}/${KEYTYPE}-${KEYSIZE}-${SELECTOR}-${DOMAIN}"
|
local BASE_FILE_NAME="${RSPAMD_DMS_DKIM_D}/${KEYTYPE}-${KEYSIZE}-${SELECTOR}-${DOMAIN}"
|
||||||
KEYTYPE_OPTIONS=('-b' "${KEYSIZE}")
|
KEYTYPE_OPTIONS=('-b' "${KEYSIZE}")
|
||||||
_log 'info' "Creating DKIM keys of type '${KEYTYPE}' and length '${KEYSIZE}' with selector '${SELECTOR}' for domain '${DOMAIN}'"
|
_log 'info' "Creating DKIM keys of type '${KEYTYPE}' and length '${KEYSIZE}' with selector '${SELECTOR}' for domain '${DOMAIN}'"
|
||||||
else
|
else
|
||||||
local BASE_FILE_NAME="${BASE_DIR}/${KEYTYPE}-${SELECTOR}-${DOMAIN}"
|
local BASE_FILE_NAME="${RSPAMD_DMS_DKIM_D}/${KEYTYPE}-${SELECTOR}-${DOMAIN}"
|
||||||
KEYTYPE_OPTIONS=('-t' "${KEYTYPE}")
|
KEYTYPE_OPTIONS=('-t' "${KEYTYPE}")
|
||||||
_log 'info' "Creating DKIM keys of type '${KEYTYPE}' with selector '${SELECTOR}' for domain '${DOMAIN}'"
|
_log 'info' "Creating DKIM keys of type '${KEYTYPE}' with selector '${SELECTOR}' for domain '${DOMAIN}'"
|
||||||
fi
|
fi
|
||||||
|
@ -164,8 +178,15 @@ function _create_keys() {
|
||||||
PUBLIC_KEY_DNS_FILE="${BASE_FILE_NAME}.public.dns.txt"
|
PUBLIC_KEY_DNS_FILE="${BASE_FILE_NAME}.public.dns.txt"
|
||||||
PRIVATE_KEY_FILE="${BASE_FILE_NAME}.private.txt"
|
PRIVATE_KEY_FILE="${BASE_FILE_NAME}.private.txt"
|
||||||
|
|
||||||
mkdir -p "${BASE_DIR}"
|
if [[ -f ${PUBLIC_KEY_FILE} ]] || [[ -f ${PUBLIC_KEY_DNS_FILE} ]] || [[ -f ${PRIVATE_KEY_FILE} ]]; then
|
||||||
chown _rspamd:_rspamd "${BASE_DIR}"
|
if [[ ${FORCE} -eq 0 ]]; then
|
||||||
|
_log 'error' "Not overwriting existing files (use '--force' to overwrite existing files)"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
_log 'info' "Overwriting existing files as the '--force' option was supplied"
|
||||||
|
rm "${PUBLIC_KEY_FILE}" "${PUBLIC_KEY_DNS_FILE}" "${PRIVATE_KEY_FILE}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# shellcheck disable=SC2310
|
# shellcheck disable=SC2310
|
||||||
if __do_as_rspamd_user rspamadm \
|
if __do_as_rspamd_user rspamadm \
|
||||||
|
@ -186,8 +207,8 @@ function _create_keys() {
|
||||||
|
|
||||||
function _check_permissions() {
|
function _check_permissions() {
|
||||||
# shellcheck disable=SC2310
|
# shellcheck disable=SC2310
|
||||||
if ! __do_as_rspamd_user ls "${BASE_DIR}" >/dev/null; then
|
if ! __do_as_rspamd_user ls "${RSPAMD_DMS_DKIM_D}" >/dev/null; then
|
||||||
_log 'warn' "The Rspamd user ('_rspamd') seems to be unable to list files in the keys directory ('${BASE_DIR}') - Rspamd may experience permission errors later"
|
_log 'warn' "The Rspamd user ('_rspamd') seems to be unable to list files in the keys directory ('${RSPAMD_DMS_DKIM_D}') - Rspamd may experience permission errors later"
|
||||||
elif ! __do_as_rspamd_user cat "${PRIVATE_KEY_FILE}" >/dev/null; then
|
elif ! __do_as_rspamd_user cat "${PRIVATE_KEY_FILE}" >/dev/null; then
|
||||||
_log 'warn' "The Rspamd user ('_rspamd') seems to be unable to read the private key file - Rspamd may experience permission errors later"
|
_log 'warn' "The Rspamd user ('_rspamd') seems to be unable to read the private key file - Rspamd may experience permission errors later"
|
||||||
else
|
else
|
||||||
|
@ -196,11 +217,11 @@ function _check_permissions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function _setup_default_signing_conf() {
|
function _setup_default_signing_conf() {
|
||||||
local DEFAULT_CONFIG_FILE='/etc/rspamd/override.d/dkim_signing.conf'
|
local DEFAULT_CONFIG_FILE="${RSPAMD_DMS_OVERRIDE_D}/dkim_signing.conf"
|
||||||
if [[ -f ${DEFAULT_CONFIG_FILE} ]]; then
|
if [[ -f ${DEFAULT_CONFIG_FILE} ]]; then
|
||||||
_log 'debug' "'${DEFAULT_CONFIG_FILE}' exists, not supplying a default"
|
_log 'info' "'${DEFAULT_CONFIG_FILE}' exists, not supplying a default ('--force' does not overwrite this file, manual adjustment required)"
|
||||||
else
|
else
|
||||||
_log 'info' "Supplying a default configuration ('${DEFAULT_CONFIG_FILE}')"
|
_log 'info' "Supplying a default configuration (to '${DEFAULT_CONFIG_FILE}')"
|
||||||
cat >"${DEFAULT_CONFIG_FILE}" << EOF
|
cat >"${DEFAULT_CONFIG_FILE}" << EOF
|
||||||
# documentation: https://rspamd.com/doc/modules/dkim_signing.html
|
# documentation: https://rspamd.com/doc/modules/dkim_signing.html
|
||||||
|
|
||||||
|
@ -225,7 +246,15 @@ domain {
|
||||||
}
|
}
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
chown _rspamd:_rspamd "${DEFAULT_CONFIG_FILE}"
|
|
||||||
|
# We copy here immediately in order to not rely on the changedetector - this way, users
|
||||||
|
# can immediately use the new keys. The file should not already exist in ${RSPAMD_OVERRIDE_D}
|
||||||
|
# since it would have been copied already.
|
||||||
|
cp "${DEFAULT_CONFIG_FILE}" "${RSPAMD_OVERRIDE_D}/dkim_signing.conf"
|
||||||
|
chown _rspamd:_rspamd "${DEFAULT_CONFIG_FILE}" "${RSPAMD_OVERRIDE_D}/dkim_signing.conf"
|
||||||
|
|
||||||
|
_log 'debug' 'Restarting Rspamd as initial DKIM configuration was suppplied'
|
||||||
|
supervisorctl restart rspamd
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +283,7 @@ function _final_steps() {
|
||||||
_obtain_hostname_and_domainname
|
_obtain_hostname_and_domainname
|
||||||
_require_n_parameters_or_print_usage 0 "${@}"
|
_require_n_parameters_or_print_usage 0 "${@}"
|
||||||
_parse_arguments "${@}"
|
_parse_arguments "${@}"
|
||||||
|
_preflight_checks
|
||||||
_create_keys
|
_create_keys
|
||||||
_check_permissions
|
_check_permissions
|
||||||
_setup_default_signing_conf
|
_setup_default_signing_conf
|
||||||
|
|
|
@ -54,6 +54,7 @@ smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_una
|
||||||
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain
|
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, reject_unauth_pipelining, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, reject_unknown_recipient_domain
|
||||||
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unauth_pipelining
|
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, reject_unauth_pipelining
|
||||||
smtpd_sender_restrictions = $dms_smtpd_sender_restrictions
|
smtpd_sender_restrictions = $dms_smtpd_sender_restrictions
|
||||||
|
smtpd_discard_ehlo_keywords = silent-discard, dsn
|
||||||
disable_vrfy_command = yes
|
disable_vrfy_command = yes
|
||||||
|
|
||||||
# Custom defined parameters for DMS:
|
# Custom defined parameters for DMS:
|
||||||
|
|
|
@ -24,6 +24,7 @@ submission inet n - n - - smtpd
|
||||||
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
|
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
|
||||||
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
|
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
|
||||||
-o smtpd_sender_restrictions=$mua_sender_restrictions
|
-o smtpd_sender_restrictions=$mua_sender_restrictions
|
||||||
|
-o smtpd_discard_ehlo_keywords=
|
||||||
-o milter_macro_daemon_name=ORIGINATING
|
-o milter_macro_daemon_name=ORIGINATING
|
||||||
-o cleanup_service_name=sender-cleanup
|
-o cleanup_service_name=sender-cleanup
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ submissions inet n - n - - smtpd
|
||||||
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
|
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
|
||||||
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
|
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
|
||||||
-o smtpd_sender_restrictions=$mua_sender_restrictions
|
-o smtpd_sender_restrictions=$mua_sender_restrictions
|
||||||
|
-o smtpd_discard_ehlo_keywords=
|
||||||
-o milter_macro_daemon_name=ORIGINATING
|
-o milter_macro_daemon_name=ORIGINATING
|
||||||
-o cleanup_service_name=sender-cleanup
|
-o cleanup_service_name=sender-cleanup
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,10 @@ source /etc/dms-settings
|
||||||
# usage with DMS_HOSTNAME, which should remove the need to call this:
|
# usage with DMS_HOSTNAME, which should remove the need to call this:
|
||||||
_obtain_hostname_and_domainname
|
_obtain_hostname_and_domainname
|
||||||
|
|
||||||
|
# This is a helper to properly set all Rspamd-related environment variables
|
||||||
|
# correctly and in one place.
|
||||||
|
_rspamd_get_envs
|
||||||
|
|
||||||
# verify checksum file exists; must be prepared by start-mailserver.sh
|
# verify checksum file exists; must be prepared by start-mailserver.sh
|
||||||
if [[ ! -f ${CHKSUM_FILE} ]]; then
|
if [[ ! -f ${CHKSUM_FILE} ]]; then
|
||||||
_exit_with_error "'${CHKSUM_FILE}' is missing" 0
|
_exit_with_error "'${CHKSUM_FILE}' is missing" 0
|
||||||
|
@ -49,6 +53,7 @@ function _check_for_changes() {
|
||||||
# Handle any changes
|
# Handle any changes
|
||||||
_ssl_changes
|
_ssl_changes
|
||||||
_postfix_dovecot_changes
|
_postfix_dovecot_changes
|
||||||
|
_rspamd_changes
|
||||||
|
|
||||||
_log_with_date 'debug' 'Reloading services due to detected changes'
|
_log_with_date 'debug' 'Reloading services due to detected changes'
|
||||||
|
|
||||||
|
@ -174,6 +179,33 @@ function _ssl_changes() {
|
||||||
# They presently have no special handling other than to trigger a change that will restart Postfix/Dovecot.
|
# They presently have no special handling other than to trigger a change that will restart Postfix/Dovecot.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _rspamd_changes() {
|
||||||
|
# RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd'
|
||||||
|
if [[ ${CHANGED} =~ ${RSPAMD_DMS_D}/.* ]]; then
|
||||||
|
|
||||||
|
# "${RSPAMD_DMS_D}/override.d"
|
||||||
|
if [[ ${CHANGED} =~ ${RSPAMD_DMS_OVERRIDE_D}/.* ]]; then
|
||||||
|
_log_with_date 'trace' 'Rspamd - Copying configuration overrides'
|
||||||
|
rm "${RSPAMD_OVERRIDE_D}"/*
|
||||||
|
cp "${RSPAMD_DMS_OVERRIDE_D}"/* "${RSPAMD_OVERRIDE_D}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# "${RSPAMD_DMS_D}/custom-commands.conf"
|
||||||
|
if [[ ${CHANGED} =~ ${RSPAMD_DMS_CUSTOM_COMMANDS_F} ]]; then
|
||||||
|
_log_with_date 'trace' 'Rspamd - Generating new configuration from custom commands'
|
||||||
|
_rspamd_handle_user_modules_adjustments
|
||||||
|
fi
|
||||||
|
|
||||||
|
# "${RSPAMD_DMS_D}/dkim"
|
||||||
|
if [[ ${CHANGED} =~ ${RSPAMD_DMS_DKIM_D} ]]; then
|
||||||
|
_log_with_date 'trace' 'Rspamd - DKIM files updated'
|
||||||
|
fi
|
||||||
|
|
||||||
|
_log_with_date 'debug' 'Rspamd configuration has changed - restarting service'
|
||||||
|
supervisorctl restart rspamd
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
_check_for_changes
|
_check_for_changes
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
|
@ -40,6 +40,12 @@ function _monitored_files_checksums() {
|
||||||
"${DMS_DIR}/dovecot-quotas.cf"
|
"${DMS_DIR}/dovecot-quotas.cf"
|
||||||
"${DMS_DIR}/dovecot-masters.cf"
|
"${DMS_DIR}/dovecot-masters.cf"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check whether Rspamd is used and if so, monitor it's changes as well
|
||||||
|
if [[ ${ENABLE_RSPAMD} -eq 1 ]] && [[ -d ${RSPAMD_DMS_D} ]]; then
|
||||||
|
readarray -d '' STAGING_FILES_RSPAMD < <(find "${RSPAMD_DMS_D}" -type f -name "*.sh" -print0)
|
||||||
|
STAGING_FILES+=("${STAGING_FILES_RSPAMD[@]}")
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# SSL certs:
|
# SSL certs:
|
||||||
|
|
|
@ -16,6 +16,7 @@ function _import_scripts() {
|
||||||
source "${PATH_TO_SCRIPTS}/network.sh"
|
source "${PATH_TO_SCRIPTS}/network.sh"
|
||||||
source "${PATH_TO_SCRIPTS}/postfix.sh"
|
source "${PATH_TO_SCRIPTS}/postfix.sh"
|
||||||
source "${PATH_TO_SCRIPTS}/relay.sh"
|
source "${PATH_TO_SCRIPTS}/relay.sh"
|
||||||
|
source "${PATH_TO_SCRIPTS}/rspamd.sh"
|
||||||
source "${PATH_TO_SCRIPTS}/ssl.sh"
|
source "${PATH_TO_SCRIPTS}/ssl.sh"
|
||||||
source "${PATH_TO_SCRIPTS}/utils.sh"
|
source "${PATH_TO_SCRIPTS}/utils.sh"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034 # VAR appears unused.
|
||||||
|
|
||||||
|
function _rspamd_get_envs() {
|
||||||
|
readonly RSPAMD_LOCAL_D='/etc/rspamd/local.d'
|
||||||
|
readonly RSPAMD_OVERRIDE_D='/etc/rspamd/override.d'
|
||||||
|
|
||||||
|
readonly RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd'
|
||||||
|
readonly RSPAMD_DMS_DKIM_D="${RSPAMD_DMS_D}/dkim"
|
||||||
|
readonly RSPAMD_DMS_OVERRIDE_D="${RSPAMD_DMS_D}/override.d"
|
||||||
|
|
||||||
|
readonly RSPAMD_DMS_CUSTOM_COMMANDS_F="${RSPAMD_DMS_D}/custom-commands.conf"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parses `RSPAMD_DMS_CUSTOM_COMMANDS_F` and executed the directives given by the file.
|
||||||
|
# To get a detailed explanation of the commands and how the file works, visit
|
||||||
|
# https://docker-mailserver.github.io/docker-mailserver/latest/config/security/rspamd/#with-the-help-of-a-custom-file
|
||||||
|
function _rspamd_handle_user_modules_adjustments() {
|
||||||
|
# Adds an option with a corresponding value to a module, or, in case the option
|
||||||
|
# is already present, overwrites it.
|
||||||
|
#
|
||||||
|
# @param ${1} = file name in ${RSPAMD_OVERRIDE_D}/
|
||||||
|
# @param ${2} = module name as it should appear in the log
|
||||||
|
# @param ${3} = option name in the module
|
||||||
|
# @param ${4} = value of the option
|
||||||
|
#
|
||||||
|
# ## Note
|
||||||
|
#
|
||||||
|
# While this function is currently bound to the scope of `_rspamd_handle_user_modules_adjustments`,
|
||||||
|
# it is written in a versatile way (taking 4 arguments instead of assuming `ARGUMENT2` / `ARGUMENT3`
|
||||||
|
# are set) so that it may be used elsewhere if needed.
|
||||||
|
function __add_or_replace() {
|
||||||
|
local MODULE_FILE=${1:?Module file name must be provided}
|
||||||
|
local MODULE_LOG_NAME=${2:?Module log name must be provided}
|
||||||
|
local OPTION=${3:?Option name must be provided}
|
||||||
|
local VALUE=${4:?Value belonging to an option must be provided}
|
||||||
|
# remove possible whitespace at the end (e.g., in case ${ARGUMENT3} is empty)
|
||||||
|
VALUE=${VALUE% }
|
||||||
|
local FILE="${RSPAMD_OVERRIDE_D}/${MODULE_FILE}"
|
||||||
|
|
||||||
|
readonly MODULE_FILE MODULE_LOG_NAME OPTION VALUE FILE
|
||||||
|
|
||||||
|
[[ -f ${FILE} ]] || touch "${FILE}"
|
||||||
|
|
||||||
|
if grep -q -E "${OPTION}.*=.*" "${FILE}"; then
|
||||||
|
__rspamd__log 'trace' "Overwriting option '${OPTION}' with value '${VALUE}' for ${MODULE_LOG_NAME}"
|
||||||
|
sed -i -E "s|([[:space:]]*${OPTION}).*|\1 = ${VALUE};|g" "${FILE}"
|
||||||
|
else
|
||||||
|
__rspamd__log 'trace' "Setting option '${OPTION}' for ${MODULE_LOG_NAME} to '${VALUE}'"
|
||||||
|
echo "${OPTION} = ${VALUE};" >>"${FILE}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# We check for usage of the previous location of the commands file.
|
||||||
|
# TODO This can be removed after the release of v14.0.0.
|
||||||
|
local RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD="${RSPAMD_DMS_D}-modules.conf"
|
||||||
|
readonly RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD
|
||||||
|
if [[ -f ${RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD} ]]; then
|
||||||
|
_dms_panic__general "Old custom command file location '${RSPAMD_DMS_CUSTOM_COMMANDS_F_OLD}' is deprecated (use '${RSPAMD_DMS_CUSTOM_COMMANDS_F}' now)" 'Rspamd setup'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "${RSPAMD_DMS_CUSTOM_COMMANDS_F}" ]]; then
|
||||||
|
__rspamd__log 'debug' "Found file '${RSPAMD_DMS_CUSTOM_COMMANDS_F}' - parsing and applying it"
|
||||||
|
|
||||||
|
local COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3
|
||||||
|
while read -r COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3; do
|
||||||
|
case "${COMMAND}" in
|
||||||
|
('disable-module')
|
||||||
|
__rspamd__helper__enable_disable_module "${ARGUMENT1}" 'false' 'override'
|
||||||
|
;;
|
||||||
|
|
||||||
|
('enable-module')
|
||||||
|
__rspamd__helper__enable_disable_module "${ARGUMENT1}" 'true' 'override'
|
||||||
|
;;
|
||||||
|
|
||||||
|
('set-option-for-module')
|
||||||
|
__add_or_replace "${ARGUMENT1}.conf" "module '${ARGUMENT1}'" "${ARGUMENT2}" "${ARGUMENT3}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
('set-option-for-controller')
|
||||||
|
__add_or_replace 'worker-controller.inc' 'controller worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
('set-option-for-proxy')
|
||||||
|
__add_or_replace 'worker-proxy.inc' 'proxy worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
('set-common-option')
|
||||||
|
__add_or_replace 'options.inc' 'common options' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
('add-line')
|
||||||
|
__rspamd__log 'trace' "Adding complete line to '${ARGUMENT1}'"
|
||||||
|
echo "${ARGUMENT2}${ARGUMENT3+ ${ARGUMENT3}}" >>"${RSPAMD_OVERRIDE_D}/${ARGUMENT1}"
|
||||||
|
;;
|
||||||
|
|
||||||
|
(*)
|
||||||
|
__rspamd__log 'warn' "Command '${COMMAND}' is invalid"
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done < <(_get_valid_lines_from_file "${RSPAMD_DMS_CUSTOM_COMMANDS_F}")
|
||||||
|
fi
|
||||||
|
}
|
|
@ -1,12 +1,17 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Function called during global setup to handle the complete setup of Rspamd.
|
# This file is executed during startup of DMS. Hence, the `index.sh` helper has already
|
||||||
|
# been sourced, and thus, all helper functions from `rspamd.sh` are available.
|
||||||
|
|
||||||
|
# Function called during global setup to handle the complete setup of Rspamd. Functions
|
||||||
|
# with a single `_` prefix are sourced from the `rspamd.sh` helper.
|
||||||
function _setup_rspamd() {
|
function _setup_rspamd() {
|
||||||
if _env_var_expect_zero_or_one 'ENABLE_RSPAMD' && [[ ${ENABLE_RSPAMD} -eq 1 ]]; then
|
if _env_var_expect_zero_or_one 'ENABLE_RSPAMD' && [[ ${ENABLE_RSPAMD} -eq 1 ]]; then
|
||||||
_log 'debug' 'Enabling and configuring Rspamd'
|
_log 'debug' 'Enabling and configuring Rspamd'
|
||||||
__rspamd__log 'trace' '---------- Setup started ----------'
|
__rspamd__log 'trace' '---------- Setup started ----------'
|
||||||
|
|
||||||
__rspamd__run_early_setup_and_checks # must run first
|
_rspamd_get_envs # must run first
|
||||||
|
__rspamd__run_early_setup_and_checks # must run second
|
||||||
__rspamd__setup_logfile
|
__rspamd__setup_logfile
|
||||||
__rspamd__setup_redis
|
__rspamd__setup_redis
|
||||||
__rspamd__setup_postfix
|
__rspamd__setup_postfix
|
||||||
|
@ -16,7 +21,7 @@ function _setup_rspamd() {
|
||||||
__rspamd__setup_greylisting
|
__rspamd__setup_greylisting
|
||||||
__rspamd__setup_hfilter_group
|
__rspamd__setup_hfilter_group
|
||||||
__rspamd__setup_check_authenticated
|
__rspamd__setup_check_authenticated
|
||||||
__rspamd__handle_user_modules_adjustments # must run last
|
_rspamd_handle_user_modules_adjustments # must run last
|
||||||
|
|
||||||
__rspamd__log 'trace' '---------- Setup finished ----------'
|
__rspamd__log 'trace' '---------- Setup finished ----------'
|
||||||
else
|
else
|
||||||
|
@ -64,25 +69,11 @@ EOF
|
||||||
# Run miscellaneous early setup tasks and checks, such as creating files needed at runtime
|
# Run miscellaneous early setup tasks and checks, such as creating files needed at runtime
|
||||||
# or checking for other anti-spam/anti-virus software.
|
# or checking for other anti-spam/anti-virus software.
|
||||||
function __rspamd__run_early_setup_and_checks() {
|
function __rspamd__run_early_setup_and_checks() {
|
||||||
# Note: Variables not marked with `local` are
|
|
||||||
# used in other functions as well.
|
|
||||||
readonly RSPAMD_LOCAL_D='/etc/rspamd/local.d'
|
|
||||||
readonly RSPAMD_OVERRIDE_D='/etc/rspamd/override.d'
|
|
||||||
readonly RSPAMD_DMS_D='/tmp/docker-mailserver/rspamd'
|
|
||||||
|
|
||||||
local RSPAMD_DMS_OVERRIDE_D="${RSPAMD_DMS_D}/override.d/"
|
|
||||||
readonly RSPAMD_DMS_OVERRIDE_D
|
|
||||||
|
|
||||||
mkdir -p /var/lib/rspamd/
|
mkdir -p /var/lib/rspamd/
|
||||||
: >/var/lib/rspamd/stats.ucl
|
: >/var/lib/rspamd/stats.ucl
|
||||||
|
|
||||||
if [[ -d ${RSPAMD_DMS_OVERRIDE_D} ]]; then
|
if [[ -d ${RSPAMD_DMS_OVERRIDE_D} ]]; then
|
||||||
__rspamd__log 'debug' "Found directory '${RSPAMD_DMS_OVERRIDE_D}' - linking it to '${RSPAMD_OVERRIDE_D}'"
|
cp "${RSPAMD_DMS_OVERRIDE_D}"/* "${RSPAMD_OVERRIDE_D}"
|
||||||
if rmdir "${RSPAMD_OVERRIDE_D}" 2>/dev/null; then
|
|
||||||
ln -s "${RSPAMD_DMS_OVERRIDE_D}" "${RSPAMD_OVERRIDE_D}"
|
|
||||||
else
|
|
||||||
__rspamd__log 'warn' "Could not remove '${RSPAMD_OVERRIDE_D}' (not empty?; not a directory?; did you restart properly?) - not linking '${RSPAMD_DMS_OVERRIDE_D}'"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${ENABLE_AMAVIS} -eq 1 ]] || [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]]; then
|
if [[ ${ENABLE_AMAVIS} -eq 1 ]] || [[ ${ENABLE_SPAMASSASSIN} -eq 1 ]]; then
|
||||||
|
@ -303,98 +294,3 @@ function __rspamd__setup_check_authenticated() {
|
||||||
"${MODULE_FILE}"
|
"${MODULE_FILE}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Parses `RSPAMD_CUSTOM_COMMANDS_FILE` and executed the directives given by the file.
|
|
||||||
# To get a detailed explanation of the commands and how the file works, visit
|
|
||||||
# https://docker-mailserver.github.io/docker-mailserver/edge/config/security/rspamd/#with-the-help-of-a-custom-file
|
|
||||||
function __rspamd__handle_user_modules_adjustments() {
|
|
||||||
# Adds an option with a corresponding value to a module, or, in case the option
|
|
||||||
# is already present, overwrites it.
|
|
||||||
#
|
|
||||||
# @param ${1} = file name in ${RSPAMD_OVERRIDE_D}/
|
|
||||||
# @param ${2} = module name as it should appear in the log
|
|
||||||
# @param ${3} = option name in the module
|
|
||||||
# @param ${4} = value of the option
|
|
||||||
#
|
|
||||||
# ## Note
|
|
||||||
#
|
|
||||||
# While this function is currently bound to the scope of `__rspamd__handle_user_modules_adjustments`,
|
|
||||||
# it is written in a versatile way (taking 4 arguments instead of assuming `ARGUMENT2` / `ARGUMENT3`
|
|
||||||
# are set) so that it may be used elsewhere if needed.
|
|
||||||
function __add_or_replace() {
|
|
||||||
local MODULE_FILE=${1:?Module file name must be provided}
|
|
||||||
local MODULE_LOG_NAME=${2:?Module log name must be provided}
|
|
||||||
local OPTION=${3:?Option name must be provided}
|
|
||||||
local VALUE=${4:?Value belonging to an option must be provided}
|
|
||||||
# remove possible whitespace at the end (e.g., in case ${ARGUMENT3} is empty)
|
|
||||||
VALUE=${VALUE% }
|
|
||||||
local FILE="${RSPAMD_OVERRIDE_D}/${MODULE_FILE}"
|
|
||||||
|
|
||||||
readonly MODULE_FILE MODULE_LOG_NAME OPTION VALUE FILE
|
|
||||||
|
|
||||||
[[ -f ${FILE} ]] || touch "${FILE}"
|
|
||||||
|
|
||||||
if grep -q -E "${OPTION}.*=.*" "${FILE}"; then
|
|
||||||
__rspamd__log 'trace' "Overwriting option '${OPTION}' with value '${VALUE}' for ${MODULE_LOG_NAME}"
|
|
||||||
sed -i -E "s|([[:space:]]*${OPTION}).*|\1 = ${VALUE};|g" "${FILE}"
|
|
||||||
else
|
|
||||||
__rspamd__log 'trace' "Setting option '${OPTION}' for ${MODULE_LOG_NAME} to '${VALUE}'"
|
|
||||||
echo "${OPTION} = ${VALUE};" >>"${FILE}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
local RSPAMD_CUSTOM_COMMANDS_FILE="${RSPAMD_DMS_D}/custom-commands.conf"
|
|
||||||
local RSPAMD_CUSTOM_COMMANDS_FILE_OLD="${RSPAMD_DMS_D}-modules.conf"
|
|
||||||
readonly RSPAMD_CUSTOM_COMMANDS_FILE RSPAMD_CUSTOM_COMMANDS_FILE_OLD
|
|
||||||
|
|
||||||
# We check for usage of the previous location of the commands file.
|
|
||||||
# This can be removed after the release of v14.0.0.
|
|
||||||
if [[ -f ${RSPAMD_CUSTOM_COMMANDS_FILE_OLD} ]]; then
|
|
||||||
__rspamd__log 'warn' "Detected usage of old file location for modules adjustment ('${RSPAMD_CUSTOM_COMMANDS_FILE_OLD}') - please use the new location ('${RSPAMD_CUSTOM_COMMANDS_FILE}')"
|
|
||||||
__rspamd__log 'warn' "Using old file location now (deprecated) - this will prevent startup in v13.0.0"
|
|
||||||
RSPAMD_CUSTOM_COMMANDS_FILE=${RSPAMD_CUSTOM_COMMANDS_FILE_OLD}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "${RSPAMD_CUSTOM_COMMANDS_FILE}" ]]; then
|
|
||||||
__rspamd__log 'debug' "Found file '${RSPAMD_CUSTOM_COMMANDS_FILE}' - parsing and applying it"
|
|
||||||
|
|
||||||
local COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3
|
|
||||||
while read -r COMMAND ARGUMENT1 ARGUMENT2 ARGUMENT3; do
|
|
||||||
case "${COMMAND}" in
|
|
||||||
('disable-module')
|
|
||||||
__rspamd__helper__enable_disable_module "${ARGUMENT1}" 'false' 'override'
|
|
||||||
;;
|
|
||||||
|
|
||||||
('enable-module')
|
|
||||||
__rspamd__helper__enable_disable_module "${ARGUMENT1}" 'true' 'override'
|
|
||||||
;;
|
|
||||||
|
|
||||||
('set-option-for-module')
|
|
||||||
__add_or_replace "${ARGUMENT1}.conf" "module '${ARGUMENT1}'" "${ARGUMENT2}" "${ARGUMENT3}"
|
|
||||||
;;
|
|
||||||
|
|
||||||
('set-option-for-controller')
|
|
||||||
__add_or_replace 'worker-controller.inc' 'controller worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}"
|
|
||||||
;;
|
|
||||||
|
|
||||||
('set-option-for-proxy')
|
|
||||||
__add_or_replace 'worker-proxy.inc' 'proxy worker' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}"
|
|
||||||
;;
|
|
||||||
|
|
||||||
('set-common-option')
|
|
||||||
__add_or_replace 'options.inc' 'common options' "${ARGUMENT1}" "${ARGUMENT2} ${ARGUMENT3}"
|
|
||||||
;;
|
|
||||||
|
|
||||||
('add-line')
|
|
||||||
__rspamd__log 'trace' "Adding complete line to '${ARGUMENT1}'"
|
|
||||||
echo "${ARGUMENT2}${ARGUMENT3+ ${ARGUMENT3}}" >>"${RSPAMD_OVERRIDE_D}/${ARGUMENT1}"
|
|
||||||
;;
|
|
||||||
|
|
||||||
(*)
|
|
||||||
__rspamd__log 'warn' "Command '${COMMAND}' is invalid"
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done < <(_get_valid_lines_from_file "${RSPAMD_CUSTOM_COMMANDS_FILE}")
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
smtpd_discard_ehlo_keywords =
|
|
@ -0,0 +1,2 @@
|
||||||
|
submission/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
|
||||||
|
submissions/inet/smtpd_discard_ehlo_keywords=silent-discard,dsn
|
|
@ -0,0 +1,14 @@
|
||||||
|
EHLO mail
|
||||||
|
AUTH LOGIN dXNlcjFAbG9jYWxob3N0LmxvY2FsZG9tYWlu
|
||||||
|
bXlwYXNzd29yZA==
|
||||||
|
MAIL FROM: user1@localhost.localdomain
|
||||||
|
RCPT TO: user1@localhost.localdomain NOTIFY=success,failure
|
||||||
|
DATA
|
||||||
|
From: Existing Local User <user1@localhost.localdomain>
|
||||||
|
To: Existing Local User <user1@localhost.localdomain>
|
||||||
|
Date: Sat, 22 May 2010 07:43:25 -0400
|
||||||
|
Subject: Test Message
|
||||||
|
This is a test mail.
|
||||||
|
|
||||||
|
.
|
||||||
|
QUIT
|
|
@ -0,0 +1,12 @@
|
||||||
|
HELO mail.external.tld
|
||||||
|
MAIL FROM: user@external.tld
|
||||||
|
RCPT TO: user1@localhost.localdomain NOTIFY=success,failure
|
||||||
|
DATA
|
||||||
|
From: Docker Mail Server <dockermailserver@external.tld>
|
||||||
|
To: Existing Local User <user1@localhost.localdomain>
|
||||||
|
Date: Sat, 22 May 2010 07:43:25 -0400
|
||||||
|
Subject: Test Message
|
||||||
|
This is a test mail.
|
||||||
|
|
||||||
|
.
|
||||||
|
QUIT
|
|
@ -4,8 +4,8 @@ load "${REPOSITORY_ROOT}/test/helper/setup"
|
||||||
BATS_TEST_NAME_PREFIX='[Rspamd] (DKIM) '
|
BATS_TEST_NAME_PREFIX='[Rspamd] (DKIM) '
|
||||||
CONTAINER_NAME='dms-test_rspamd-dkim'
|
CONTAINER_NAME='dms-test_rspamd-dkim'
|
||||||
|
|
||||||
DOMAIN_NAME='fixed.com'
|
DOMAIN_NAME='example.test'
|
||||||
SIGNING_CONF_FILE='/etc/rspamd/override.d/dkim_signing.conf'
|
SIGNING_CONF_FILE='/tmp/docker-mailserver/rspamd/override.d/dkim_signing.conf'
|
||||||
|
|
||||||
function setup_file() {
|
function setup_file() {
|
||||||
_init_with_defaults
|
_init_with_defaults
|
||||||
|
@ -59,7 +59,7 @@ function teardown_file() { _default_teardown ; }
|
||||||
__create_key
|
__create_key
|
||||||
assert_success
|
assert_success
|
||||||
__log_is_free_of_warnings_and_errors
|
__log_is_free_of_warnings_and_errors
|
||||||
assert_output --partial "Supplying a default configuration ('${SIGNING_CONF_FILE}')"
|
assert_output --partial "Supplying a default configuration (to '${SIGNING_CONF_FILE}')"
|
||||||
refute_output --partial "'${SIGNING_CONF_FILE}' exists, not supplying a default"
|
refute_output --partial "'${SIGNING_CONF_FILE}' exists, not supplying a default"
|
||||||
assert_output --partial "Finished DKIM key creation"
|
assert_output --partial "Finished DKIM key creation"
|
||||||
_run_in_container_bash "[[ -f ${SIGNING_CONF_FILE} ]]"
|
_run_in_container_bash "[[ -f ${SIGNING_CONF_FILE} ]]"
|
||||||
|
@ -68,8 +68,14 @@ function teardown_file() { _default_teardown ; }
|
||||||
local INITIAL_SHA512_SUM=$(_exec_in_container sha512sum "${SIGNING_CONF_FILE}")
|
local INITIAL_SHA512_SUM=$(_exec_in_container sha512sum "${SIGNING_CONF_FILE}")
|
||||||
|
|
||||||
__create_key
|
__create_key
|
||||||
|
assert_failure
|
||||||
|
assert_output --partial "Not overwriting existing files (use '--force' to overwrite existing files)"
|
||||||
|
|
||||||
|
# the same as before, but with the '--force' option
|
||||||
|
__create_key 'rsa' 'mail' "${DOMAIN_NAME}" '2048' '--force'
|
||||||
__log_is_free_of_warnings_and_errors
|
__log_is_free_of_warnings_and_errors
|
||||||
refute_output --partial "Supplying a default configuration ('${SIGNING_CONF_FILE}')"
|
refute_output --partial "Supplying a default configuration ('${SIGNING_CONF_FILE}')"
|
||||||
|
assert_output --partial "Overwriting existing files as the '--force' option was supplied"
|
||||||
assert_output --partial "'${SIGNING_CONF_FILE}' exists, not supplying a default"
|
assert_output --partial "'${SIGNING_CONF_FILE}' exists, not supplying a default"
|
||||||
assert_output --partial "Finished DKIM key creation"
|
assert_output --partial "Finished DKIM key creation"
|
||||||
local SECOND_SHA512_SUM=$(_exec_in_container sha512sum "${SIGNING_CONF_FILE}")
|
local SECOND_SHA512_SUM=$(_exec_in_container sha512sum "${SIGNING_CONF_FILE}")
|
||||||
|
@ -188,8 +194,12 @@ function __create_key() {
|
||||||
local SELECTOR=${2:-mail}
|
local SELECTOR=${2:-mail}
|
||||||
local DOMAIN=${3:-${DOMAIN_NAME}}
|
local DOMAIN=${3:-${DOMAIN_NAME}}
|
||||||
local KEYSIZE=${4:-2048}
|
local KEYSIZE=${4:-2048}
|
||||||
|
local FORCE=${5:-}
|
||||||
|
|
||||||
_run_in_container setup config dkim \
|
# Not quoting is intended here as we would othewise provide
|
||||||
|
# the argument "''" (empty string), which would cause errors
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
_run_in_container setup config dkim ${FORCE} \
|
||||||
keytype "${KEYTYPE}" \
|
keytype "${KEYTYPE}" \
|
||||||
keysize "${KEYSIZE}" \
|
keysize "${KEYSIZE}" \
|
||||||
selector "${SELECTOR}" \
|
selector "${SELECTOR}" \
|
||||||
|
|
|
@ -66,12 +66,9 @@ function teardown_file() { _default_teardown ; }
|
||||||
assert_output 'rspamd_milter = inet:localhost:11332'
|
assert_output 'rspamd_milter = inet:localhost:11332'
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "'/etc/rspamd/override.d/' is linked correctly" {
|
@test "contents of '/etc/rspamd/override.d/' are copied" {
|
||||||
local OVERRIDE_D='/etc/rspamd/override.d'
|
local OVERRIDE_D='/etc/rspamd/override.d'
|
||||||
|
|
||||||
_run_in_container_bash "[[ -h ${OVERRIDE_D} ]]"
|
|
||||||
assert_success
|
|
||||||
|
|
||||||
_run_in_container_bash "[[ -f ${OVERRIDE_D}/testmodule_complicated.conf ]]"
|
_run_in_container_bash "[[ -f ${OVERRIDE_D}/testmodule_complicated.conf ]]"
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
load "${REPOSITORY_ROOT}/test/helper/setup"
|
||||||
|
load "${REPOSITORY_ROOT}/test/helper/common"
|
||||||
|
|
||||||
|
BATS_TEST_NAME_PREFIX='[DSN] '
|
||||||
|
CONTAINER1_NAME='dms-test_dsn_send_always'
|
||||||
|
CONTAINER2_NAME='dms-test_dsn_send_auth'
|
||||||
|
CONTAINER3_NAME='dms-test_dsn_send_none'
|
||||||
|
# A similar line is added to the log when a DSN (Delivery Status Notification) is sent:
|
||||||
|
#
|
||||||
|
# postfix/bounce[1023]: C943BA6B46: sender delivery status notification: DBF86A6B4CO
|
||||||
|
#
|
||||||
|
LOG_DSN='delivery status notification'
|
||||||
|
|
||||||
|
function setup_file() {
|
||||||
|
local CUSTOM_SETUP_ARGUMENTS=(
|
||||||
|
# Required only for delivery via nc (_send_email)
|
||||||
|
--env PERMIT_DOCKER=container
|
||||||
|
)
|
||||||
|
|
||||||
|
export CONTAINER_NAME=${CONTAINER1_NAME}
|
||||||
|
_init_with_defaults
|
||||||
|
# Unset `smtpd_discard_ehlo_keywords` to allow DSNs by default on any `smtpd` service:
|
||||||
|
cp "${TEST_TMP_CONFIG}/dsn/postfix-main.cf" "${TEST_TMP_CONFIG}/postfix-main.cf"
|
||||||
|
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
||||||
|
_wait_for_service postfix
|
||||||
|
_wait_for_smtp_port_in_container
|
||||||
|
|
||||||
|
export CONTAINER_NAME=${CONTAINER2_NAME}
|
||||||
|
_init_with_defaults
|
||||||
|
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
||||||
|
_wait_for_service postfix
|
||||||
|
_wait_for_smtp_port_in_container
|
||||||
|
|
||||||
|
export CONTAINER_NAME=${CONTAINER3_NAME}
|
||||||
|
_init_with_defaults
|
||||||
|
# Mirror default main.cf (disable DSN on ports 465 + 587 too):
|
||||||
|
cp "${TEST_TMP_CONFIG}/dsn/postfix-master.cf" "${TEST_TMP_CONFIG}/postfix-master.cf"
|
||||||
|
_common_container_setup 'CUSTOM_SETUP_ARGUMENTS'
|
||||||
|
_wait_for_service postfix
|
||||||
|
_wait_for_smtp_port_in_container
|
||||||
|
}
|
||||||
|
|
||||||
|
function teardown_file() {
|
||||||
|
docker rm -f "${CONTAINER1_NAME}" "${CONTAINER2_NAME}" "${CONTAINER3_NAME}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "should always send a DSN when requested" {
|
||||||
|
export CONTAINER_NAME=${CONTAINER1_NAME}
|
||||||
|
|
||||||
|
_send_email 'email-templates/dsn-unauthenticated'
|
||||||
|
_send_email 'email-templates/dsn-authenticated' '0.0.0.0 465'
|
||||||
|
_send_email 'email-templates/dsn-authenticated' '0.0.0.0 587'
|
||||||
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
|
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
||||||
|
_should_output_number_of_lines 3
|
||||||
|
}
|
||||||
|
|
||||||
|
# Defaults test case
|
||||||
|
@test "should only send a DSN when requested from ports 465/587" {
|
||||||
|
export CONTAINER_NAME=${CONTAINER2_NAME}
|
||||||
|
|
||||||
|
_send_email 'email-templates/dsn-unauthenticated'
|
||||||
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
|
# DSN requests can now only be made on ports 465 and 587,
|
||||||
|
# so grep should not find anything.
|
||||||
|
#
|
||||||
|
# Although external requests are discarded, anyone who has requested a DSN
|
||||||
|
# will still receive it, but it will come from the sending mail server, not this one.
|
||||||
|
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
||||||
|
assert_failure
|
||||||
|
|
||||||
|
# These ports are excluded via master.cf.
|
||||||
|
_send_email 'email-templates/dsn-authenticated' '0.0.0.0 465'
|
||||||
|
_send_email 'email-templates/dsn-authenticated' '0.0.0.0 587'
|
||||||
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
|
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
||||||
|
_should_output_number_of_lines 2
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "should never send a DSN" {
|
||||||
|
export CONTAINER_NAME=${CONTAINER3_NAME}
|
||||||
|
|
||||||
|
_send_email 'email-templates/dsn-unauthenticated'
|
||||||
|
_send_email 'email-templates/dsn-authenticated' '0.0.0.0 465'
|
||||||
|
_send_email 'email-templates/dsn-authenticated' '0.0.0.0 587'
|
||||||
|
_wait_for_empty_mail_queue_in_container
|
||||||
|
|
||||||
|
# DSN requests are rejected regardless of origin.
|
||||||
|
# This is usually a bad idea, as you won't get them either.
|
||||||
|
_run_in_container grep "${LOG_DSN}" /var/log/mail/mail.log
|
||||||
|
assert_failure
|
||||||
|
}
|
Loading…
Reference in New Issue