Compare commits

..

33 Commits

Author SHA1 Message Date
b99844c1b5 install_postfixadmin.sh: remove space.. 2026-02-18 18:53:38 +01:00
691c34fa18 Merge branch 'master' of https://git.oopen.de/install/mailsystem 2026-02-18 18:48:01 +01:00
1ca6031fea install_postfixadmin.sh: fix error determin PFA configuration file. 2026-02-18 18:47:25 +01:00
8234254094 Merge branch 'master' of git.oopen.de:install/mailsystem 2026-02-18 12:38:47 +01:00
afff836253 install_postfix_advanced.sh: comment entries '127.0.0.1:10040_time_limit=3600' and 'policyd-spf_time_limit=3600'. 2026-02-18 12:38:33 +01:00
Christoph
7c05201520 install_postfix_advanced.sh: some changes of 'main.cf' in case of relay host only. 2026-02-18 01:48:45 +01:00
Christoph
0674fb1231 install_amavis.sh: fix entering procedure of variable 'SASL_AUTH_ENABLED'. 2026-02-18 01:33:55 +01:00
Christoph
32980f67de install_postfix_advanced.sh: fix handling of additional smtp port. 2026-02-18 01:32:08 +01:00
Christoph
7b9a6f52ca install_postfix_advanced.sh: add support for parameter 'smtpd_tls_eccert_file'. 2026-02-16 14:38:21 +01:00
5a8280b767 install_amavis.sh: in any case, IS_SYMPA_LIST_SERVER must be set to false except server ist a sympa listmanager. 2026-02-16 14:01:12 +01:00
7c99515e72 install_postfix_advanced.sh: some minor changes. 2026-02-16 13:32:21 +01:00
ef963e89fc install_amavis.sh: separate amavis inbound (port 10024) amd outbound (10029) in case of sympa listserver or 'only relay' server. 2026-02-16 00:17:56 +01:00
654e5738d4 install_postfix_advanced.sh: fix error - forgot 'fi'.. 2026-02-16 00:15:57 +01:00
6356876ab6 Change some settings, if Server is a listserver. 2026-02-15 14:37:19 +01:00
ee892a6b33 Add script 'set-policyd-spf-config-for-listserver.sh' - More relaxed settings for Listenserver. 2026-02-15 14:36:21 +01:00
7741803f71 install_amavis.sh: fix some error writing file '50-user'. 2026-02-13 23:46:22 +01:00
da1867ef91 install_amavis.sh: some minor changes.. 2026-02-13 22:47:16 +01:00
8dc105be68 install_amavis.sh: port 25 (smtp/inbound) → Amavis 10024 (NOT ORIGINATING); submission/smtps (outbound) → Amavis 10026 (ORIGINATING). 2026-02-13 21:50:15 +01:00
6bc490bfc1 add script 'set_amavis_local_domains_maps.sh'. 2026-02-13 21:43:42 +01:00
c6c6491ce0 install_postfix_advanced.sh: remove some commented lines written to master.cf file. 2026-02-13 15:02:45 +01:00
abb2941e4b install_postfix_advanced.sh: fix error checcking if 'policy-spf' is already present in master.cf file. 2026-02-13 14:59:58 +01:00
6d516ed25a install_postfix_advanced.sh: remove depredated parameter 'permit_mx_backup'. 2026-02-11 21:20:00 +01:00
c6909c937d Merge branch 'master' of git.oopen.de:install/mailsystem 2026-02-11 21:17:33 +01:00
9708c595c4 install_update_dovecot.conf.sample: fix parameter 'cert_base_dir'. 2026-02-11 21:16:37 +01:00
9c52e54182 install_postfixadmin.sh: configuration file at version 4.x is 'config.local.php'. 2026-02-11 00:47:05 +01:00
849cbfa2e4 install_postfixadmin.sh: some minor changes. 2026-02-10 23:58:58 +01:00
0a51e44b93 install_amavis.sh: some minor changes.. 2026-02-10 15:27:39 +01:00
16618f9949 install_opendmarc.sh: no opendmarc check on non_smtpd connections. 2026-02-10 15:02:05 +01:00
b4b47d5a79 install_amavis.sh: keine milters auf localhost:10025. install_postfix_advanced.sh: kein OpenDmarc bei non_smtpd_milters. (DMARC ist eine Inbound-Policy-Prüfung, nicht sinnvoll für lokal/originating.) 2026-02-10 14:14:53 +01:00
d1694bf3a4 install_postfix_advanced.sh: adjust '/etc/postfix/header_checks'. 2026-02-10 00:37:03 +01:00
ee1e2d0b7e install_amavis.sh: add spamassassin rule for Null sender ( (Return-Path: <>). 2026-02-10 00:35:10 +01:00
96a77260c3 Merge branch 'master' of https://git.oopen.de/install/mailsystem 2026-02-04 22:23:01 +01:00
71be7f0754 install_update_dovecot.sh: relax/defuse systemd-hardening 2026-02-04 22:22:31 +01:00
9 changed files with 1132 additions and 408 deletions

View File

@@ -145,7 +145,7 @@ dbhost=""
# - Cert/Key configurations # - Cert/Key configurations
# --- # ---
cert_base_dir="/etc/postfix/ssl" cert_base_dir="/etc/dovecot/ssl"
server_cert=${cert_base_dir}/mailserver.crt server_cert=${cert_base_dir}/mailserver.crt
server_key=${cert_base_dir}/mailserver.key server_key=${cert_base_dir}/mailserver.key
dh_pem_file="${cert_base_dir}/dh_4096.pem" dh_pem_file="${cert_base_dir}/dh_4096.pem"

View File

@@ -110,7 +110,8 @@ detect_os_1 () {
# --- Some default settings # --- Some default settings
# ------------- # -------------
DEFAULT_SASL_AUTH_ENABLED="no" DEFAULT_SASL_AUTH_ENABLED=false
DEFAULT_IS_SYMPA_LIST_SERVER=false
DEFAULT_QUARANTINE_DIR="/var/QUARANTINE" DEFAULT_QUARANTINE_DIR="/var/QUARANTINE"
DEFAULT_QUARANTINE_ADMIN='postmaster\@$mydomain' DEFAULT_QUARANTINE_ADMIN='postmaster\@$mydomain'
@@ -187,7 +188,9 @@ if [[ -z "$_HOSTNAME" ]] ; then
[[ "$_HOSTNAME" = "$_HOSTNAME_SHORT" ]] && _HOSTNAME="" [[ "$_HOSTNAME" = "$_HOSTNAME_SHORT" ]] && _HOSTNAME=""
fi fi
[[ -z "$_SASL_AUTH_ENABLED" ]] && _SASL_AUTH_ENABLED="$DEFAULT_SASL_AUTH_ENABLED" [[ -z "$_SASL_AUTH_ENABLED" ]] && _SASL_AUTH_ENABLED=${DEFAULT_SASL_AUTH_ENABLED}
[[ -z "${_IS_SYMPA_LIST_SERVER}" ]] && _IS_SYMPA_LIST_SERVER=${DEFAULT_IS_SYMPA_LIST_SERVER}
[[ -z "$_QUARANTINE_DIR" ]] && _QUARANTINE_DIR="$DEFAULT_QUARANTINE_DIR" [[ -z "$_QUARANTINE_DIR" ]] && _QUARANTINE_DIR="$DEFAULT_QUARANTINE_DIR"
@@ -375,9 +378,12 @@ SASL_AUTH_ENABLED=
echo "" echo ""
echo -e "\033[32m--\033[m" echo -e "\033[32m--\033[m"
echo "" echo ""
echo "Should this mail server support Cyrus SASL authentication?" echo "Should this mail server support Cyrus SASL authentication? [true/yes/false/no]"
echo "" echo ""
while [[ "$SASL_AUTH_ENABLED" != "yes" && "$SASL_AUTH_ENABLED" != "no" ]];do while [[ "$SASL_AUTH_ENABLED" != "yes" &&
"$SASL_AUTH_ENABLED" != "true" &&
"$SASL_AUTH_ENABLED" != "no" &&
"$SASL_AUTH_ENABLED" != "false" ]];do
if [[ -n "$_SASL_AUTH_ENABLED" ]]; then if [[ -n "$_SASL_AUTH_ENABLED" ]]; then
echononl "Support Cyrus SASL authentication [${_SASL_AUTH_ENABLED}]: " echononl "Support Cyrus SASL authentication [${_SASL_AUTH_ENABLED}]: "
@@ -390,13 +396,62 @@ while [[ "$SASL_AUTH_ENABLED" != "yes" && "$SASL_AUTH_ENABLED" != "no" ]];do
SASL_AUTH_ENABLED=${SASL_AUTH_ENABLED,,} SASL_AUTH_ENABLED=${SASL_AUTH_ENABLED,,}
fi fi
if [[ "$SASL_AUTH_ENABLED" != "yes" && "$SASL_AUTH_ENABLED" != "no" ]] ; then [[ -z "${SASL_AUTH_ENABLED}" ]] && SASL_AUTH_ENABLED=${_SASL_AUTH_ENABLED}
_SASL_AUTH_ENABLED=""
if [[ "$SASL_AUTH_ENABLED" != "yes" &&
"$SASL_AUTH_ENABLED" != "true" &&
"$SASL_AUTH_ENABLED" != "false" &&
"$SASL_AUTH_ENABLED" != "no" ]] ; then
SASL_AUTH_ENABLED=""
echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n Type 'yes' or 'no'" echo -e "\n\t\033[33m\033[1mWrong entry!\033[m\n Type 'yes' or 'no'"
fi fi
done done
[[ "$SASL_AUTH_ENABLED" = "yes" ]] && SASL_AUTH_ENABLED=true
[[ "$SASL_AUTH_ENABLED" = "no" ]] && SASL_AUTH_ENABLED=false
if ! ${SASL_AUTH_ENABLED} ; then
IS_SYMPA_LIST_SERVER=""
echo ""
echo -e "\033[32m--\033[m"
echo ""
echo "Are Sympa List Services provided? - [true/yes/false/no]"
echo ""
echononl "Sympa List Server? [$_IS_SYMPA_LIST_SERVER]: "
read IS_SYMPA_LIST_SERVER
if [[ -z "${IS_SYMPA_LIST_SERVER}" ]] ; then
IS_SYMPA_LIST_SERVER="$_IS_SYMPA_LIST_SERVER"
fi
IS_SYMPA_LIST_SERVER=${IS_SYMPA_LIST_SERVER,,}
while [[ "$IS_SYMPA_LIST_SERVER" != "yes" && \
"$IS_SYMPA_LIST_SERVER" != "true" && \
"$IS_SYMPA_LIST_SERVER" != "no" && \
"$IS_SYMPA_LIST_SERVER" != "false" ]]; do
echo -e "\n\t\033[33m\033[1mWrong value was given!!\033[m\n"
echononl "Sympa List Server? [$_IS_SYMPA_LIST_SERVER]: "
read IS_SYMPA_LIST_SERVER
if [[ -z "${IS_SYMPA_LIST_SERVER}" ]] ; then
IS_SYMPA_LIST_SERVER=false
fi
IS_SYMPA_LIST_SERVER=${IS_SYMPA_LIST_SERVER,,}
done
if [[ "$IS_SYMPA_LIST_SERVER" = 'yes' || "$IS_SYMPA_LIST_SERVER" = 'true' ]] ; then
IS_SYMPA_LIST_SERVER=true
else
IS_SYMPA_LIST_SERVER=false
fi
else
IS_SYMPA_LIST_SERVER=false
fi
echo "" echo ""
@@ -704,7 +759,6 @@ else
fi fi
if ! $DB_IN_USE ; then if ! $DB_IN_USE ; then
echo -e "[3] \033[37m\033[1mSkip (No Database in use)\033[m" echo -e "[3] \033[37m\033[1mSkip (No Database in use)\033[m"
_DB_TYPE="None"
else else
echo "[3] Skip (No Database in use)" echo "[3] Skip (No Database in use)"
fi fi
@@ -855,6 +909,7 @@ echo -e "\tIPv4 address...........................: $IPV4"
echo -e "\tIPv6 address...........................: $IPV6" echo -e "\tIPv6 address...........................: $IPV6"
echo "" echo ""
echo -e "\tSASL AUTH support......................: $SASL_AUTH_ENABLED" echo -e "\tSASL AUTH support......................: $SASL_AUTH_ENABLED"
echo -e "\tSupport sympa mailinglists.............: ${IS_SYMPA_LIST_SERVER}"
echo "" echo ""
echo -e "\tQuarantine Directory ..................: $QUARANTINE_DIR" echo -e "\tQuarantine Directory ..................: $QUARANTINE_DIR"
echo "" echo ""
@@ -906,6 +961,7 @@ _IPV4=$IPV4
_IPV6=$IPV6 _IPV6=$IPV6
_SASL_AUTH_ENABLED=$SASL_AUTH_ENABLED _SASL_AUTH_ENABLED=$SASL_AUTH_ENABLED
_IS_SYMPA_LIST_SERVER=${IS_SYMPA_LIST_SERVER}
_QUARANTINE_DIR=$QUARANTINE_DIR _QUARANTINE_DIR=$QUARANTINE_DIR
_QUARANTINE_ADMIN=$QUARANTINE_ADMIN _QUARANTINE_ADMIN=$QUARANTINE_ADMIN
@@ -2257,6 +2313,45 @@ if ! $installation_failed ; then
fi fi
fi fi
# Create /etc/spamassassin/99_nullsender.cf
#
# Spamassassin Regeln für Nullsender (Return-Path: <>)
#
# Problem:
# echte DSNs haben ebenfalls Return-Path: <>
#
# Aber:
# Echte DSNs sind i.d.R. multipart/report (delivery-status)
#
echononl " Create file \"/etc/spamassassin/99_nullsender.cf\".."
cat <<'EOF' > /etc/spamassassin/99_nullsender.cf 2> $tmp_err_msg
########################################################################
# Null-sender (Return-Path: <>) Behandlung
# Ziel: Fake-Bounces markieren, echte DSNs nicht treffen
########################################################################
# 1) Null-Envelope-From erkannt
header LOCAL_NULL_SENDER Return-Path =~ /^<>$/i
describe LOCAL_NULL_SENDER Null envelope-from (Return-Path <>)
score LOCAL_NULL_SENDER 0.1
# 2) Echte DSNs sind i.d.R. multipart/report (delivery-status)
header LOCAL_DSN_MULTIPART Content-Type =~ /^multipart\/report\b/i
describe LOCAL_DSN_MULTIPART Looks like a real DSN (multipart/report)
score LOCAL_DSN_MULTIPART -3.0
# 3) Fake-Bounce: Null-sender, aber NICHT multipart/report
meta LOCAL_NULL_NOT_DSN LOCAL_NULL_SENDER && !LOCAL_DSN_MULTIPART
describe LOCAL_NULL_NOT_DSN Null-sender but not a DSN (likely fake bounce spam)
score LOCAL_NULL_NOT_DSN 6.0
EOF
if [[ $? -eq 0 ]] ; then
echo_ok
else
echo_failed
error "$(cat $tmp_err_msg)"
fi
# - Enable nightly cronjob for spamassassin # - Enable nightly cronjob for spamassassin
# - # -
@@ -3260,6 +3355,18 @@ if $INSTALL_CLAMAV_UNOFFICIAL_SIGS ; then
if [[ "$?" -ne 0 ]] ; then if [[ "$?" -ne 0 ]] ; then
installation_failed=true installation_failed=true
error "$(cat $tmp_err_msg)" error "$(cat $tmp_err_msg)"
warn "command was:
git clone https://github.com/extremeshok/clamav-unofficial-sigs.git /tmp/clamav-unofficial-sigs"
echononl "continue anyway [yes/no]: "
read OK
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
echononl "Wrong entry! - repeat [yes/nno]: "
read OK
done
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
fi fi
if ! $installation_failed ; then if ! $installation_failed ; then
echo_ok echo_ok
@@ -4159,10 +4266,49 @@ use strict;
# !! smtpd_proxy_filter - see master.cf !! # !! smtpd_proxy_filter - see master.cf !!
# #
# #
#\$inet_socket_port = [10024, 10026]; EOF
if ${SASL_AUTH_ENABLED} ; then
cat << EOF >> "${_config_file}"
\$inet_socket_port = [10024, 10026];
#\$inet_socket_port = [10024, 10029]; #\$inet_socket_port = [10024, 10029];
#\$inet_socket_port = [10024, 10026, 10029]; #\$inet_socket_port = [10024, 10026, 10029];
\$interface_policy{'10026'} = 'ORIGINATING';
\$policy_bank{'ORIGINATING'} = {
originating => 1, # declare that mail was submitted by our smtp client
bypass_spam_checks_maps => (1),
bypass_virus_checks_maps => (0),
remove_existing_spam_headers => 1,
};
EOF
else
cat << EOF >> "${_config_file}"
#\$inet_socket_port = [10024, 10026];
\$inet_socket_port = [10024, 10029];
#\$inet_socket_port = [10024, 10026, 10029];
\$interface_policy{'10024'} = 'INBOUND';
\$interface_policy{'10029'} = 'VIRUSONLY';
# Inbound: Spam + Virus
\$policy_bank{'INBOUND'} = { };
# Outbound: nur Virus
\$policy_bank{'VIRUSONLY'} = {
bypass_spam_checks_maps => [1],
bypass_header_checks_maps => [1],
final_spam_destiny => D_PASS,
originating => 1,
};
EOF
fi
cat << EOF >> "${_config_file}"
# Bypass spam checking fro trusted networks # Bypass spam checking fro trusted networks
# #
#\$interface_policy{'10026'} = 'TRUSTED'; #\$interface_policy{'10026'} = 'TRUSTED';
@@ -4278,7 +4424,8 @@ read_hash(\%whitelist_sender, '/etc/postfix/sender_whitelist');
# Spam-Schwellwerte # Spam-Schwellwerte
# ---------------------------------------------------------- # ----------------------------------------------------------
\$sa_tag_level_deflt = 1.9; # ab hier Info-Header #\$sa_tag_level_deflt = 1.9; # ab hier Info-Header
\$sa_tag_level_deflt = -999; # immer header schreiben (Debug-freundlich)
\$sa_tag2_level_deflt = 5.1; # ab hier X-Spam-Flag: YES \$sa_tag2_level_deflt = 5.1; # ab hier X-Spam-Flag: YES
\$sa_kill_level_deflt = 9.51; # high-spam - final destiny (DISCARD) \$sa_kill_level_deflt = 9.51; # high-spam - final destiny (DISCARD)
\$sa_dsn_cutoff_level = 20.1; # ab hier keine DSN mehr \$sa_dsn_cutoff_level = 20.1; # ab hier keine DSN mehr
@@ -4376,15 +4523,99 @@ if (-r \$policy_banks_file) {
## - it which domains are local using the @local_domains_maps variable, ## - it which domains are local using the @local_domains_maps variable,
## - which by default is set to the value of \$mydomain & its subdomains: ## - which by default is set to the value of \$mydomain & its subdomains:
## - ## -
#@local_domains_maps = ( ["."] ); EOF
if [[ "$?" -ne 0 ]] ; then
installation_failed=true
fi
## - get rid of "Open Relay" warnings in amavis logfile. if [[ "${DB_TYPE}" = "PostgreSQL" ]] || \
## - [[ "${DB_TYPE}" = "MySQL" ]] && \
\$interface_policy{'10024'} = 'ORIGINATING'; ! ${IS_SYMPA_LIST_SERVER}; then
\$policy_bank{'ORIGINATING'} = {
originating => 1, # declare that mail was submitted by our smtp client if [[ "$DB_TYPE" = "PostgreSQL" ]]; then
}; _db="pgsql"
else
_db="mysql"
fi
cat >> /etc/amavis/conf.d/50-user <<EOF
@local_domains_maps = (
[qw(${HOSTNAME} localhost)],
EOF
if [[ "$?" -ne 0 ]] ; then
installation_failed=true
fi
if [[ -f "/etc/postfix/${_db}_virtual_domains_maps.cf" ]]; then
cat >> /etc/amavis/conf.d/50-user <<EOF
# Domains, die als virtuelle Mailbox-Domains gehostet sind:
'${_db}:/etc/postfix/${_db}_virtual_domains_maps.cf',
EOF
if [[ "$?" -ne 0 ]] ; then
installation_failed=true
fi
fi
if [[ -f "/etc/postfix/${_db}_relay-domain-maps.cf" ]]; then
cat >> /etc/amavis/conf.d/50-user <<EOF
# Domains, die als Relay Domains akzeptiert werden:
'${_db}:/etc/postfix/${_db}_relay-domain-maps.cf',
EOF
if [[ "$?" -ne 0 ]] ; then
installation_failed=true
fi
fi
if grep -iq -E "^\s*btree:/etc/postfix/relay_domains" "/etc/postfix/main.cf" > /dev/null 2>&1 ; then
cat >> /etc/amavis/conf.d/50-user <<EOF
# weiter Domains, die als Relay Domains akzeptiert werden
'btree:/etc/postfix/relay_domains',
EOF
if [[ "$?" -ne 0 ]] ; then
installation_failed=true
fi
fi
cat >> /etc/amavis/conf.d/50-user <<EOF
);
EOF
else
cat >> /etc/amavis/conf.d/50-user <<'EOF'
@local_domains_maps = ( ["."] );
EOF
if [[ "$?" -ne 0 ]] ; then
installation_failed=true
error "$(cat $tmp_err_msg)"
fi
fi
cat >> /etc/amavis/conf.d/50-user <<EOF
## - If you get am error like: ## - If you get am error like:
## - ## -
@@ -4396,6 +4627,7 @@ if (-r \$policy_banks_file) {
#\$inet_socket_bind = undef; #\$inet_socket_bind = undef;
EOF EOF
if [[ "$?" -ne 0 ]] ; then if [[ "$?" -ne 0 ]] ; then
installation_failed=true installation_failed=true
error "$(cat $tmp_err_msg)" error "$(cat $tmp_err_msg)"
@@ -4403,33 +4635,42 @@ fi
if [[ "$DB_TYPE" = "PostgreSQL" ]]; then if [[ "$DB_TYPE" = "PostgreSQL" ]]; then
cat >> /etc/amavis/conf.d/50-user <<EOF if [[ -n "${DB_NAME}" ]] && [[ -n "${DB_HOST}" ]] && [[ -n "${DB_USER}" ]] && [[ -n "${DB_PASS}" ]] ; then
cat >> /etc/amavis/conf.d/50-user <<EOF
## - lookup for local domains in PostgreSQL database ## - lookup for local domains in PostgreSQL database
## - ## -
@lookup_sql_dsn = ( #@lookup_sql_dsn = (
['DBI:Pg:database=${DB_NAME};host=${DB_HOST}', '$DB_USER', '$DB_PASS'] # ['DBI:Pg:database=${DB_NAME};host=${DB_HOST}', '$DB_USER', '$DB_PASS']
); #);
\$sql_select_policy = 'SELECT \\'Y\\' AS local FROM domain WHERE \\'@\\' || domain IN (%k);'; #\$sql_select_policy = 'SELECT \\'Y\\' AS local FROM domain WHERE \\'@\\' || domain IN (%k);';
EOF EOF
if [[ "$?" -ne 0 ]] ; then if [[ "$?" -ne 0 ]] ; then
installation_failed=true installation_failed=true
error "$(cat $tmp_err_msg)" error "$(cat $tmp_err_msg)"
fi
fi fi
elif [[ "$DB_TYPE" = "MySQL" ]];then elif [[ "$DB_TYPE" = "MySQL" ]];then
cat >> /etc/amavis/conf.d/50-user <<EOF
if [[ -n "${DB_NAME}" ]] && [[ -n "${DB_HOST}" ]] && [[ -n "${DB_USER}" ]] && [[ -n "${DB_PASS}" ]] ; then
cat >> /etc/amavis/conf.d/50-user <<EOF
## - lookup for local domains in MySQL database ## - lookup for local domains in MySQL database
## - ## -
@lookup_sql_dsn = ( #@lookup_sql_dsn = (
['DBI:mysql:database=${DB_NAME};host=${DB_HOST}', '$DB_USER', '$DB_PASS'] # ['DBI:mysql:database=${DB_NAME};host=${DB_HOST}', '$DB_USER', '$DB_PASS']
); #);
\$sql_select_policy = 'SELECT "Y" AS local FROM domain WHERE CONCAT("@", domain) IN (%k)'; #\$sql_select_policy = 'SELECT "Y" AS local FROM domain WHERE CONCAT("@", domain) IN (%k)';
EOF EOF
if [[ "$?" -ne 0 ]] ; then if [[ "$?" -ne 0 ]] ; then
installation_failed=true installation_failed=true
error "$(cat $tmp_err_msg)" error "$(cat $tmp_err_msg)"
fi
fi fi
fi fi
@@ -4957,6 +5198,7 @@ fi
## - localhost:10025 inet n - y - - smtpd ## - localhost:10025 inet n - y - - smtpd
## - -o content_filter= ## - -o content_filter=
## - -o smtpd_proxy_filter= ## - -o smtpd_proxy_filter=
## - -o smtpd_milters=
## - -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128 ## - -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128
## - -o smtpd_client_restrictions= ## - -o smtpd_client_restrictions=
## - -o smtpd_helo_restrictions= ## - -o smtpd_helo_restrictions=
@@ -5020,7 +5262,7 @@ while IFS='' read -r _line || [[ -n $_line ]] ; do
smtp inet n - y - - smtpd smtp inet n - y - - smtpd
-o content_filter=amavisfeed:[127.0.0.1]:10024 -o content_filter=amavisfeed:[127.0.0.1]:10024
EOF EOF
if [[ "$SASL_AUTH_ENABLED" = "no" ]] ; then if ! ${SASL_AUTH_ENABLED} ; then
cat >> $postfix_master_cf << EOF cat >> $postfix_master_cf << EOF
-o smtpd_sasl_auth_enable=no -o smtpd_sasl_auth_enable=no
EOF EOF
@@ -5031,6 +5273,8 @@ EOF
localhost:10025 inet n - y - - smtpd localhost:10025 inet n - y - - smtpd
-o content_filter= -o content_filter=
-o smtpd_proxy_filter= -o smtpd_proxy_filter=
-o smtpd_milters=
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128 -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128
-o smtpd_client_restrictions= -o smtpd_client_restrictions=
-o smtpd_helo_restrictions= -o smtpd_helo_restrictions=
@@ -5039,15 +5283,6 @@ localhost:10025 inet n - y - - smtpd
-o smtpd_data_restrictions= -o smtpd_data_restrictions=
-o mynetworks=127.0.0.0/8,[::1]/128 -o mynetworks=127.0.0.0/8,[::1]/128
-o receive_override_options=no_unknown_recipient_checks -o receive_override_options=no_unknown_recipient_checks
EOF
if [[-n "$(which opendmarc)" ]] ; then
cat >> $postfix_master_cf << EOF
# IMPORTANT: no opendmarc here!
#-o smtpd_milters=local:/opendmarc/opendmarc.sock
EOF
fi
cat >> $postfix_master_cf << EOF
#-o mynetworks=127.0.0.0/8,[::1]/128,${IPV4}/32
EOF EOF
fi fi
@@ -5061,7 +5296,7 @@ EOF
${additional_smtp_port} inet n - y - - smtpd ${additional_smtp_port} inet n - y - - smtpd
-o content_filter=amavisfeed:[127.0.0.1]:10024 -o content_filter=amavisfeed:[127.0.0.1]:10024
EOF EOF
if [[ "$SASL_AUTH_ENABLED" = "no" ]] ; then if ! ${SASL_AUTH_ENABLED} ; then
cat >> $postfix_master_cf << EOF cat >> $postfix_master_cf << EOF
-o smtpd_sasl_auth_enable=no -o smtpd_sasl_auth_enable=no
EOF EOF
@@ -5076,7 +5311,7 @@ EOF
_found=true _found=true
cat >> $postfix_master_cf << EOF cat >> $postfix_master_cf << EOF
submission inet n - y - 20 smtpd submission inet n - y - 20 smtpd
-o content_filter=amavisfeed:[127.0.0.1]:10024 -o content_filter=amavisfeed:[127.0.0.1]:10026
-o smtpd_tls_security_level=encrypt -o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes -o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_client_restrictions=permit_sasl_authenticated,reject
@@ -5093,6 +5328,8 @@ EOF
localhost:10025 inet n - y - - smtpd localhost:10025 inet n - y - - smtpd
-o content_filter= -o content_filter=
-o smtpd_proxy_filter= -o smtpd_proxy_filter=
-o smtpd_milters=
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128 -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128
-o smtpd_client_restrictions= -o smtpd_client_restrictions=
-o smtpd_helo_restrictions= -o smtpd_helo_restrictions=
@@ -5102,12 +5339,6 @@ localhost:10025 inet n - y - - smtpd
-o mynetworks=127.0.0.0/8,[::1]/128 -o mynetworks=127.0.0.0/8,[::1]/128
-o receive_override_options=no_unknown_recipient_checks -o receive_override_options=no_unknown_recipient_checks
EOF EOF
if [[ -n "$(which opendmarc)" ]] ; then
cat >> $postfix_master_cf << EOF
# IMPORTANT: no opendmarc here!
#-o smtpd_milters=local:/opendmarc/opendmarc.sock
EOF
fi
fi fi
if ! $amavisfeed_present ; then if ! $amavisfeed_present ; then
@@ -5128,7 +5359,7 @@ EOF
_found=true _found=true
cat >> $postfix_master_cf << EOF cat >> $postfix_master_cf << EOF
smtps inet n - y - - smtpd smtps inet n - y - - smtpd
-o content_filter=amavisfeed:[127.0.0.1]:10024 -o content_filter=amavisfeed:[127.0.0.1]:10026
-o smtpd_tls_wrappermode=yes -o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes -o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_client_restrictions=permit_sasl_authenticated,reject
@@ -5145,6 +5376,8 @@ EOF
localhost:10025 inet n - y - - smtpd localhost:10025 inet n - y - - smtpd
-o content_filter= -o content_filter=
-o smtpd_proxy_filter= -o smtpd_proxy_filter=
-o smtpd_milters=
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128 -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128
-o smtpd_client_restrictions= -o smtpd_client_restrictions=
-o smtpd_helo_restrictions= -o smtpd_helo_restrictions=
@@ -5154,12 +5387,6 @@ localhost:10025 inet n - y - - smtpd
-o mynetworks=127.0.0.0/8,[::1]/128 -o mynetworks=127.0.0.0/8,[::1]/128
-o receive_override_options=no_unknown_recipient_checks -o receive_override_options=no_unknown_recipient_checks
EOF EOF
if [[ -n "$(which opendmarc)" ]] ; then
cat >> $postfix_master_cf << EOF
# IMPORTANT: no opendmarc here!
#-o smtpd_milters=local:/opendmarc/opendmarc.sock
EOF
fi
fi fi
if ! $amavisfeed_present ; then if ! $amavisfeed_present ; then
@@ -5181,6 +5408,8 @@ EOF
localhost:10025 inet n - y - - smtpd localhost:10025 inet n - y - - smtpd
-o content_filter= -o content_filter=
-o smtpd_proxy_filter= -o smtpd_proxy_filter=
-o smtpd_milters=
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128 -o smtpd_authorized_xforward_hosts=127.0.0.0/8,[::1]/128
-o smtpd_client_restrictions= -o smtpd_client_restrictions=
-o smtpd_helo_restrictions= -o smtpd_helo_restrictions=
@@ -5190,12 +5419,6 @@ localhost:10025 inet n - y - - smtpd
-o mynetworks=127.0.0.0/8,[::1]/128 -o mynetworks=127.0.0.0/8,[::1]/128
-o receive_override_options=no_unknown_recipient_checks -o receive_override_options=no_unknown_recipient_checks
EOF EOF
if [[ -n "$(which opendmarc)" ]] ; then
cat >> $postfix_master_cf << EOF
# IMPORTANT: no opendmarc here!
#-o smtpd_milters=local:/opendmarc/opendmarc.sock
EOF
fi
continue continue
fi fi

View File

@@ -726,8 +726,11 @@ fi
if grep -q -E "^\s*#?\s*non_smtpd_milters\s*=" ${main_cf_file} ; then if grep -q -E "^\s*#?\s*non_smtpd_milters\s*=" ${main_cf_file} ; then
ensure_dkim_var "non_smtpd_milters" > "${tmp_main_cf_file}" # In case of sympa, DKIM signatures will be added by sympa list manager
cp "${tmp_main_cf_file}" "${main_cf_file}" if ! which sympa ; then
ensure_dkim_var "non_smtpd_milters" > "${tmp_main_cf_file}"
cp "${tmp_main_cf_file}" "${main_cf_file}"
fi
else else

View File

@@ -26,8 +26,15 @@ opendmarc_socket_file="${opendmarc_socket_dir}/opendmarc.sock"
config_file_name_value_parameters=" config_file_name_value_parameters="
AuthservID|HOSTNAME AuthservID|HOSTNAME
TrustedAuthservIDs|HOSTNAME TrustedAuthservIDs|HOSTNAME
PidFile|/run/opendmarc/opendmarc.pid PidFile|/run/opendmarc/opendmarc.pid"
RejectFailures|true if which sympa ; then
config_file_name_value_parameters="$config_file_name_value_parameters
RejectFailures|false"
else
config_file_name_value_parameters="$config_file_name_value_parameters
RejectFailures|true"
fi
config_file_name_value_parameters="$config_file_name_value_parameters
Syslog|true Syslog|true
SyslogFacility|mail SyslogFacility|mail
IgnoreHosts|${opendmarc_base_dir}/ignore.hosts IgnoreHosts|${opendmarc_base_dir}/ignore.hosts
@@ -881,26 +888,26 @@ else
error "$(cat $log_file)" error "$(cat $log_file)"
fi fi
echononl " Set Variable non_smtpd_milters at '/etc/postfix/main.cf'.." #echononl " Set Variable non_smtpd_milters at '/etc/postfix/main.cf'.."
if $(grep -q -E "^\s*non_smtpd_milters\s*=\s*.*opendkim.sock" /etc/postfix/main.cf 2> /dev/null) ; then #if $(grep -q -E "^\s*non_smtpd_milters\s*=\s*.*opendkim.sock" /etc/postfix/main.cf 2> /dev/null) ; then
if $(grep -q -E "^\s*non_smtpd_milters\s*=\s*.*$(basename "${opendmarc_socket_file}")" /etc/postfix/main.cf); then # if $(grep -q -E "^\s*non_smtpd_milters\s*=\s*.*$(basename "${opendmarc_socket_file}")" /etc/postfix/main.cf); then
echo_skipped # echo_skipped
else # else
perl -i -n -p -e "s&^\s*(non_smtpd_milters\s*=.*opendkim.sock)&\1,local:/$(basename "${opendmarc_socket_dir}")/$(basename "${opendmarc_socket_file}")&" \ # perl -i -n -p -e "s&^\s*(non_smtpd_milters\s*=.*opendkim.sock)&\1,local:/$(basename "${opendmarc_socket_dir}")/$(basename "${opendmarc_socket_file}")&" \
/etc/postfix/main.cf > $log_file 2>&1 # /etc/postfix/main.cf > $log_file 2>&1
if [[ $? -eq 0 ]] ; then # if [[ $? -eq 0 ]] ; then
echo_ok # echo_ok
postfix_needs_restart=true # postfix_needs_restart=true
else # else
echo_failed # echo_failed
error "$(cat $log_file)" # error "$(cat $log_file)"
fi # fi
fi # fi
else #else
#
echo_skipped # echo_skipped
warn "non_smtpd_milters is not adjusted. Complete Postfix configuration (main.cf) manually\!" # warn "non_smtpd_milters is not adjusted. Complete Postfix configuration (main.cf) manually\!"
fi #fi
echononl " Set Variable smtpd_milters at '/etc/postfix/main.cf'.." echononl " Set Variable smtpd_milters at '/etc/postfix/main.cf'.."
@@ -975,53 +982,53 @@ EOF
fi fi
if grep -q -E "^\s*#?\s*non_smtpd_milters\s*=" ${main_cf_file} ; then #if grep -q -E "^\s*#?\s*non_smtpd_milters\s*=" ${main_cf_file} ; then
ensure_dmarc_var "non_smtpd_milters" > "${tmp_main_cf_file}"
cp "${tmp_main_cf_file}" "${main_cf_file}"
else
cat <<EOF >> /etc/postfix/main.cf 2> $log_file
# Was sind non_smtpd_milters?
# #
# non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT # ensure_dmarc_var "non_smtpd_milters" > "${tmp_main_cf_file}"
# der smtpd-Daemon sind. # cp "${tmp_main_cf_file}" "${main_cf_file}"
# #
# Das betrifft z. B.: #else
# #
# cleanup Header/Content-Bereinigung # cat <<EOF >> /etc/postfix/main.cf 2> $log_file
# qmgr Queue-Manager
# lmtp / smtp Auslieferung nach extern
# local lokale Zustellung
# #
# Das sind z. B.: ## Was sind non_smtpd_milters?
# ##
# - interne Bounces (MAILER-DAEMON) ## non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT
# ## der smtpd-Daemon sind.
# - Cron-Mails vom Server ##
# ## Das betrifft z. B.:
# - Weiterleitungen, die Postfix selbst generiert ##
# ## cleanup Header/Content-Bereinigung
# - Mails, die über sendmail CLI gesendet werden ## qmgr Queue-Manager
# ## lmtp / smtp Auslieferung nach extern
# - Mails, die Amavis über LMTP zurückgibt ## local lokale Zustellung
# ##
# - etc. ## Das sind z. B.:
# ##
# ## - interne Bounces (MAILER-DAEMON)
# DKIM soll auch die ausgehenden Mails signieren, die nicht über smtpd daemon versendet werden. ##
non_smtpd_milters = $opendmarc_socket_string ## - Cron-Mails vom Server
EOF ##
fi ## - Weiterleitungen, die Postfix selbst generiert
postfix_needs_restart=true ##
if [[ $? -eq 0 ]] ; then ## - Mails, die über sendmail CLI gesendet werden
echo_ok ##
else ## - Mails, die Amavis über LMTP zurückgibt
echo_failed ##
error "$(cat $log_file)" ## - etc.
fi ##
##
## DKIM soll auch die ausgehenden Mails signieren, die nicht über smtpd daemon versendet werden.
#non_smtpd_milters = $opendmarc_socket_string
#EOF
#fi
#postfix_needs_restart=true
#if [[ $? -eq 0 ]] ; then
# echo_ok
#else
# echo_failed
# error "$(cat $log_file)"
#fi
echo "" echo ""

View File

@@ -171,8 +171,10 @@ fi
if [[ -z "$_RELAY_HOST" ]]; then if [[ -z "$_RELAY_HOST" ]]; then
_IS_RELAY_HOST=$DEFAULT_IS_RELAY_HOST _IS_RELAY_HOST=$DEFAULT_IS_RELAY_HOST
else else
_IS_RELAY_HOST="$_RELAY_HOST" _IS_RELAY_HOST="${_RELAY_HOST,,}"
fi fi
[[ "${_IS_RELAY_HOST}" == "yes" ]] && _IS_RELAY_HOST=true
[[ "${_IS_RELAY_HOST}" == "no" ]] && _IS_RELAY_HOST=false
if [[ -z "$_LISTEN_ON_ADDITIONAL_RELAY_PORT" ]] ; then if [[ -z "$_LISTEN_ON_ADDITIONAL_RELAY_PORT" ]] ; then
_LISTEN_ON_ADDITIONAL_RELAY_PORT=${DEFAULT_LISTEN_ON_ADDITIONAL_RELAY_PORT} _LISTEN_ON_ADDITIONAL_RELAY_PORT=${DEFAULT_LISTEN_ON_ADDITIONAL_RELAY_PORT}
@@ -466,7 +468,7 @@ if ! ${IS_RELAY_HOST} ; then
fi fi
if [[ "${INPUT,,}" == "yes" || "${INPUT,,}" == "true" ]]; then if [[ "${INPUT,,}" == "yes" || "${INPUT,,}" == "true" ]]; then
INSTALL_DMARC_REPORT_SUPPORT=true INSTALL_DMARC_REPORT_SUPPORT=true
fi fi
fi fi
@@ -1071,7 +1073,18 @@ debugLevel = 1
# HELO_reject = Null - Only reject HELO Fail for Null sender (SPF Classic) # HELO_reject = Null - Only reject HELO Fail for Null sender (SPF Classic)
# HELO_reject = False - Never reject/defer on HELO, append header only. # HELO_reject = False - Never reject/defer on HELO, append header only.
# HELO_reject = No_Check - Never check HELO. # HELO_reject = No_Check - Never check HELO.
EOF
if ${IS_SYMPA_LIST_SERVER} ; then
cat <<EOF >> "${_file}"
HELO_reject = False
EOF
else
cat <<EOF >> "${_file}"
HELO_reject = SPF_Not_Pass HELO_reject = SPF_Not_Pass
EOF
fi
cat <<EOF >> "${_file}"
# Mail From rejection policy. Options are: # Mail From rejection policy. Options are:
# Mail_From_reject = SPF_Not_Pass - Reject if result not Pass/None/Tempfail. # Mail_From_reject = SPF_Not_Pass - Reject if result not Pass/None/Tempfail.
@@ -1084,7 +1097,18 @@ HELO_reject = SPF_Not_Pass
# MAIL FROM-Adresse reagiert. Ein Fehler tritt auf, wenn die IP-Adresse des sendenden # MAIL FROM-Adresse reagiert. Ein Fehler tritt auf, wenn die IP-Adresse des sendenden
# Servers nicht den SPF-Einträgen der Domain in der MAIL FROM-Adresse entspricht. # Servers nicht den SPF-Einträgen der Domain in der MAIL FROM-Adresse entspricht.
# #
EOF
if ${IS_SYMPA_LIST_SERVER} ; then
cat <<EOF >> "${_file}"
Mail_From_reject = False
EOF
else
cat <<EOF >> "${_file}"
Mail_From_reject = Fail Mail_From_reject = Fail
EOF
fi
cat <<EOF >> "${_file}"
# Policy for rejecting due to SPF PermError. Options are: # Policy for rejecting due to SPF PermError. Options are:
# PermError_reject = True # PermError_reject = True
@@ -1096,7 +1120,18 @@ Mail_From_reject = Fail
# #
# Wenn PermError_reject auf True gesetzt ist, wird die E-Mail abgewiesen (rejected), # Wenn PermError_reject auf True gesetzt ist, wird die E-Mail abgewiesen (rejected),
# #
EOF
if ${IS_SYMPA_LIST_SERVER} ; then
cat <<EOF >> "${_file}"
PermError_reject = False
EOF
else
cat <<EOF >> "${_file}"
PermError_reject = True PermError_reject = True
EOF
fi
cat <<EOF >> "${_file}"
# Policy for deferring messages due to SPF TempError. Options are: # Policy for deferring messages due to SPF TempError. Options are:
# TempError_Defer = True # TempError_Defer = True
@@ -1109,7 +1144,7 @@ PermError_reject = True
# Wenn TempError_Defer auf True gesetzt ist, wird die E-Mail vorübergehend zurückgewiesen # Wenn TempError_Defer auf True gesetzt ist, wird die E-Mail vorübergehend zurückgewiesen
# (deferred), und der empfangende Server versucht später erneut, die E-Mail zuzustelle # (deferred), und der empfangende Server versucht später erneut, die E-Mail zuzustelle
# #
TempError_Defer = Defer TempError_Defer = True
# Type of header to insert to document SPF result. Can be Received-SPF (SPF) # Type of header to insert to document SPF result. Can be Received-SPF (SPF)
# or Authentication Results (AR). It cannot be both. # or Authentication Results (AR). It cannot be both.
@@ -2111,9 +2146,24 @@ smtp_tls_security_level=dane
smtpd_tls_loglevel = 1 smtpd_tls_loglevel = 1
smtp_tls_loglevel = 1 smtp_tls_loglevel = 1
# TLS RSA keys path
smtpd_tls_cert_file = $_TLS_CERT_FILE smtpd_tls_cert_file = $_TLS_CERT_FILE
smtpd_tls_key_file = $_TLS_KEY_FILE smtpd_tls_key_file = $_TLS_KEY_FILE
EOF
if [[ -f "/etc/postfix/ssl/mailserver-ecdsa.crt" &&
-f "/etc/postfix/ssl/mailserver-ecdsa.key" ]] ; then
cat <<EOF >> /etc/postfix/main.cf
# TLS ECDSA keys path
smtpd_tls_eccert_file = /etc/postfix/ssl/mailserver-ecdsa.crt
smtpd_tls_eckey_file = /etc/postfix/ssl/mailserver-ecdsa.key
EOF
fi
cat <<EOF >> /etc/postfix/main.cf
## - File with DH parameters that the Postfix SMTP server should use with EDH ciphers. ## - File with DH parameters that the Postfix SMTP server should use with EDH ciphers.
## - ## -
@@ -2427,8 +2477,8 @@ virtual_alias_domains =
#======= Postfix DSN Support ============ #======= Postfix DSN Support ============
# #
# Use the smtpd_discard_ehlo_keyword_address_maps feature if you wish to allow DSN # Use the smtpd_discard_ehlo_keyword_address_maps feature if you wish to allow DSN
# requests from trusted clients but not from random strangers # requests from trusted clients but not from random strangers
# #
# smtpd_discard_ehlo_keyword_address_maps = # smtpd_discard_ehlo_keyword_address_maps =
@@ -2443,15 +2493,15 @@ virtual_alias_domains =
#smtpd_discard_ehlo_keyword_address_maps = #smtpd_discard_ehlo_keyword_address_maps =
# If you want to disallow all use of DSN requests from the network, use the # If you want to disallow all use of DSN requests from the network, use the
# smtpd_discard_ehlo_keywords feature: # smtpd_discard_ehlo_keywords feature:
# #
# /etc/postfix/main.cf: # /etc/postfix/main.cf:
# smtpd_discard_ehlo_keywords = silent-discard, dsn # smtpd_discard_ehlo_keywords = silent-discard, dsn
# #
#
# #
# A case insensitive list of EHLO keywords (pipelining, starttls, auth, etc.) that #
# A case insensitive list of EHLO keywords (pipelining, starttls, auth, etc.) that
# the Postfix SMTP server will not send in the EHLO response to a remote SMTP client. # the Postfix SMTP server will not send in the EHLO response to a remote SMTP client.
# #
# #
@@ -2681,7 +2731,7 @@ EOF
if [[ -n "$(which postfwd)" ]] ; then if [[ -n "$(which postfwd)" ]] ; then
cat <<EOF >> /etc/postfix/main.cf cat <<EOF >> /etc/postfix/main.cf
127.0.0.1:10040_time_limit = 3600 #127.0.0.1:10040_time_limit = 3600
EOF EOF
else else
cat <<EOF >> /etc/postfix/main.cf cat <<EOF >> /etc/postfix/main.cf
@@ -2699,7 +2749,7 @@ if [[ -n "$(which policyd-spf)" ]] ; then
# policyd-spf unix - n n - 0 spawn # policyd-spf unix - n n - 0 spawn
# user=policyd-spf argv=/usr/bin/policyd-spf # user=policyd-spf argv=/usr/bin/policyd-spf
# #
policyd-spf_time_limit = 3600 #policyd-spf_time_limit = 3600
EOF EOF
fi fi
@@ -2876,6 +2926,16 @@ smtpd_recipient_restrictions =
# \$relay_recipient_maps, and \$relay_recipient_maps is not null. # \$relay_recipient_maps, and \$relay_recipient_maps is not null.
# #
reject_unlisted_recipient, reject_unlisted_recipient,
EOF
if [[ -n "$(which policyd-spf)" ]] ; then
cat <<EOF >> /etc/postfix/main.cf
# Check Postfix policy service ..
#
check_policy_service unix:private/policy-spf
EOF
fi
cat <<EOF >> /etc/postfix/main.cf
# reject_unauth_destination # reject_unauth_destination
# #
# Reject the request unless one of the following is true: # Reject the request unless one of the following is true:
@@ -2898,21 +2958,16 @@ smtpd_recipient_restrictions =
# managed by the verify(8) server; see http://www.postfix.org/ADDRESS_VERIFICATION_README.html # managed by the verify(8) server; see http://www.postfix.org/ADDRESS_VERIFICATION_README.html
# for more details # for more details
reject_unverified_recipient, reject_unverified_recipient,
EOF
if [[ -n "$(which policyd-spf)" ]] ; then
cat <<EOF >> /etc/postfix/main.cf
# Check Postfix policy service ..
#
check_policy_service unix:private/policy-spf
EOF
fi
cat <<EOF >> /etc/postfix/main.cf
# Policyd-Weight # Policyd-Weight
#check_policy_service inet:127.0.0.1:12525, #check_policy_service inet:127.0.0.1:12525,
# ---------------------------------------------------------------------------------
# DEPRECATED permit_mx_backup
#
# warning: support for restriction "permit_mx_backup" will be removed from Postfix;
# permit Backup MX # permit Backup MX
permit_mx_backup, # permit_mx_backup,
# ---------------------------------------------------------------------------------
# permit, if all restrictions so far passed # permit, if all restrictions so far passed
permit permit
@@ -2953,8 +3008,13 @@ smtpd_relay_restrictions =
# managed by the verify(8) server; see http://www.postfix.org/ADDRESS_VERIFICATION_README.html # managed by the verify(8) server; see http://www.postfix.org/ADDRESS_VERIFICATION_README.html
# for more details # for more details
reject_unverified_recipient, reject_unverified_recipient,
# ---------------------------------------------------------------------------------
# DEPRECATED permit_mx_backup
#
# warning: support for restriction "permit_mx_backup" will be removed from Postfix;
# permit Backup MX # permit Backup MX
permit_mx_backup, # permit_mx_backup,
# ---------------------------------------------------------------------------------
# permit, if all restrictions so far passed # permit, if all restrictions so far passed
permit permit
@@ -2989,6 +3049,16 @@ else
EOF EOF
fi fi
if ${IS_SYMPA_LIST_SERVER} || ${IS_RELAY_HOST}; then
cat <<EOF >> /etc/postfix/main.cf
# Default: alles was nicht explizit überschrieben wird (pickup/local/sympa/cron/...)
content_filter = amavisfeed:[127.0.0.1]:10029
EOF
fi
if [[ -n "$(which opendkim)" ]] || [[ -n "$(which opendmarc)" ]] ; then if [[ -n "$(which opendkim)" ]] || [[ -n "$(which opendmarc)" ]] ; then
cat <<EOF >> /etc/postfix/main.cf cat <<EOF >> /etc/postfix/main.cf
@@ -3030,7 +3100,7 @@ EOF
# Was sind non_smtpd_milters? # Was sind non_smtpd_milters?
# #
# non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT # non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT
# der smtpd-Daemon sind. # der smtpd-Daemon sind.
# #
# Das betrifft z. B.: # Das betrifft z. B.:
@@ -3058,20 +3128,24 @@ EOF
# #
EOF EOF
if [[ -n "$(which opendkim)" ]] && [[ -n "$(which opendmarc)" ]] ; then if ${IS_SYMPA_LIST_SERVER} ; then
cat <<EOF >> /etc/postfix/main.cf cat <<EOF >> /etc/postfix/main.cf
non_smtpd_milters = local:/opendkim/opendkim.sock,local:/opendmarc/opendmarc.sock # DKIM signing takes place in the Sympa list manager.
non_smtpd_milters =
EOF EOF
elif [[ -n "$(which opendkim)" ]] ; then elif [[ -n "$(which opendkim)" ]] ; then
cat <<EOF >> /etc/postfix/main.cf cat <<EOF >> /etc/postfix/main.cf
non_smtpd_milters = local:/opendkim/opendkim.sock non_smtpd_milters = local:/opendkim/opendkim.sock
EOF EOF
else else
cat <<EOF >> /etc/postfix/main.cf cat <<EOF >> /etc/postfix/main.cf
non_smtpd_milters = local:/opendmarc/opendmarc.sock non_smtpd_milters =
EOF EOF
fi fi
else else
cat <<EOF >> /etc/postfix/main.cf cat <<EOF >> /etc/postfix/main.cf
@@ -3616,41 +3690,58 @@ fi
_file="/etc/postfix/header_checks.pcre" _file="/etc/postfix/header_checks.pcre"
echononl " Create file '$_file' used for header replacing" echononl " Create file '$_file' used for header replacing"
if [[ ! -f "$_file" ]]; then if [[ ! -f "$_file" ]]; then
cat << EOF > "$_file" cat << 'EOF' > "$_file"
# --- # ---
# - Replace headers # - Header Checks - /etc/postfix/header_checks
# --- # ---
#
# Ziel: offensichtlich kaputte RFC-Header ablehnen (wenig False Positives)
# - Replace recieved from ########################################
#/^Received: from (.* \\([-._[:alnum:]]+ \\[[.[:digit:]]{7,15}\\]\\)).*?([[:space:]]+).*\\(Authenticated sender: ([^)]+)\\)(.*)/ REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])\$2(Authenticated sender: \$3)\$4 # A) Kaputter From:-Header
########################################
# 1) From: ist leer
/^From:\s*$/ REJECT Invalid From header (empty) - Spamschutzregel FROM-1001
# 2) Mehr als ein '@' im From:-Header -> syntaktisch kaputt
/^From:.*@.*@/ REJECT Invalid From header (multiple @) - Spamschutzregel FROM-1002
# --- # 3) Mehrere Mailboxen durch Komma getrennt (wie: Die@..., Lions@..., ...)
# - Ignore Headers # (Legitime Fälle nutzen i.d.R. Display-Namen/Group-Syntax; dieses Muster ist in Spam sehr häufig)
# --- /^From:\s*[^<>,]+@[^,]+,\s*[^<>,]+@/ REJECT Invalid From header (multiple mailboxes) - Spamschutzregel FROM-1003
#/^\s*User-Agent/ IGNORE # 4) Typische kaputte UTF-8-Fragmente
#/^\s*X-Enigmail/ IGNORE /^From:.*\xC3\xA2/ REJECT Invalid UTF-8 in From header - Spamschutzregel FROM-1004
#/^\s*X-Mailer/ IGNORE
#/^\s*X-Originating-IP/ IGNORE
# --- ########################################
# - Reject / Discard headers # B) Optional: sehr spezifische lokale Blacklist
# --- ########################################
/^To:.*<>/ REJECT Possible SPAM Blank email address To: header - Header-Spamschutzregel T0-1001 #/^Reply-To: .+\@inx1and1\..+/ REJECT Possible spam (local pattern)
/\(envelope-from <>\)/ REJECT Possible SPAM - Header-Spamschutzregel RECIEV-1001
/^Reply-To: .+\@inx1and1\..+/ REJECT Possible SPAM - Header-Spamschutzregel REPLY-1001 ########################################
# C) Warn
########################################
/^From:.*<>/ REJECT Possible SPAM - Header-Spamschutzregel FROM-1001 # Date-Rejects sind oft zu aggressiv -> wenn nötig: lieber taggen oder loggen statt reject
/^Date: .* 19[0-9][0-9]/ WARN Date far in the past Header-Spamschutzregel DATE-1001
/^Date: .* 200[0-9]/ WARN Date far in the past Header-Spamschutzregel DATE-1002
/^Date: .* 201[0-9]/ WARN Date far in the past Header-Spamschutzregel DATE-1003
########################################
# Bemerkungen
########################################
# (envelope-from <>) nicht pauschal rejecten:
# echte DSNs/Bounces haben legitimerweise MAIL FROM: <>
#/\(envelope-from <>\)/ REJECT Null envelope-from
/^Date: .* 19[0-9][0-9]/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1001
/^Date: .* 200[0-9]/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1002
/^Date: .* 201[0-9]/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1003
/^Date: .* 2020/ REJECT Date from the past. Fix your system clock. - Header-Spamschutzregel DATE-1004
EOF EOF
if [[ $? -eq 0 ]] ; then if [[ $? -eq 0 ]] ; then
echo_ok echo_ok
@@ -3915,10 +4006,10 @@ if ${INSTALL_DMARC_REPORT_SUPPORT} ; then
cat <<EOF >> /etc/postfix/transport 2> $log_file cat <<EOF >> /etc/postfix/transport 2> $log_file
# - Take care your master.cf file ($postfix_master_cf) contains: # - Take care your master.cf file ($postfix_master_cf) contains:
# - # -
# - dmarc-pipe unix - n n - - pipe # - dmarc-pipe unix - n n - - pipe
# - flags=Rq user=vmail argv=/usr/local/bin/dmarc-collect.sh # - flags=Rq user=vmail argv=/usr/local/bin/dmarc-collect.sh
# - # -
dmarc-reports@oopen.de dmarc-pipe: dmarc-reports@oopen.de dmarc-pipe:
EOF EOF
@@ -4007,7 +4098,7 @@ EOF
_failed=true _failed=true
fi fi
if ${_failed} ; then if ${_failed} ; then
echo_failed echo_failed
error "$(cat $log_file)" error "$(cat $log_file)"
@@ -4056,6 +4147,14 @@ else
dmarc_pipe_present=false dmarc_pipe_present=false
fi fi
if ${LISTEN_ON_ADDITIONAL_RELAY_PORT} ; then
if grep -iq -E "^${ADDITIONAL_RELAY_LISTEN_PORT}\s+" $postfix_master_cf > /dev/null 2>&1 ; then
additional_relay_port_present=true
else
additional_relay_port_present=false
fi
fi
_found=false _found=false
echononl " Create new file \"${postfix_master_cf}\"" echononl " Create new file \"${postfix_master_cf}\""
if [[ -f "${postfix_master_cf}.$backup_date" ]]; then if [[ -f "${postfix_master_cf}.$backup_date" ]]; then
@@ -4074,7 +4173,6 @@ submission inet n - y - 20 smtpd
-o smtpd_tls_security_level=encrypt -o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes -o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#-o milter_macro_daemon_name=ORIGINATING
EOF EOF
fi fi
if ! $smtps_present ; then if ! $smtps_present ; then
@@ -4083,13 +4181,14 @@ smtps inet n - y - - smtpd
-o smtpd_tls_wrappermode=yes -o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes -o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_client_restrictions=permit_sasl_authenticated,reject
#-o milter_macro_daemon_name=ORIGINATING
EOF EOF
fi fi
elif $LISTEN_ON_ADDITIONAL_RELAY_PORT ; then elif $LISTEN_ON_ADDITIONAL_RELAY_PORT ; then
cat >> $postfix_master_cf << EOF if ! ${additional_relay_port_present} ; then
cat >> $postfix_master_cf << EOF
${ADDITIONAL_RELAY_LISTEN_PORT} inet n - y - - smtpd ${ADDITIONAL_RELAY_LISTEN_PORT} inet n - y - - smtpd
EOF EOF
fi
fi fi
continue continue
fi fi
@@ -4102,7 +4201,6 @@ submission inet n - y - 20 smtpd
-o smtpd_tls_security_level=encrypt -o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes -o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
EOF EOF
fi fi
continue continue
@@ -4116,7 +4214,6 @@ smtps inet n - y - - smtpd
-o smtpd_tls_wrappermode=yes -o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes -o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_client_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
EOF EOF
fi fi
continue continue
@@ -4139,7 +4236,7 @@ EOF
# - Add support for policyd-spf service # - Add support for policyd-spf service
# - # -
if ! $(grep -iq -E "^policyd-spf\s+" "$postfix_master_cf" 2> /dev/null) ; then if ! grep -iq -E "^policy-spf\s+" "$postfix_master_cf" 2> /dev/null ; then
cat <<EOF >> $postfix_master_cf cat <<EOF >> $postfix_master_cf
policy-spf unix - n n - 0 spawn policy-spf unix - n n - 0 spawn
@@ -4150,7 +4247,7 @@ EOF
# - Add transport definitions for only sending over IPv4/IPv6 # - Add transport definitions for only sending over IPv4/IPv6
# - # -
if ! $(grep -iq -E "^smtp-ipv4-only\s+" "$postfix_master_cf" 2> /dev/null) ; then if ! grep -iq -E "^smtp-ipv4-only\s+" "$postfix_master_cf" 2> /dev/null ; then
cat <<EOF >> $postfix_master_cf cat <<EOF >> $postfix_master_cf
smtp-ipv4-only unix - - n - - smtp smtp-ipv4-only unix - - n - - smtp
@@ -4158,7 +4255,7 @@ smtp-ipv4-only unix - - n - - smtp
EOF EOF
fi fi
if ! $(grep -iq -E "^smtp-ipv6-only\s+" "$postfix_master_cf" 2> /dev/null) ; then if ! grep -iq -E "^smtp-ipv6-only\s+" "$postfix_master_cf" 2> /dev/null ; then
cat <<EOF >> $postfix_master_cf cat <<EOF >> $postfix_master_cf
smtp-ipv6-only unix - - n - - smtp smtp-ipv6-only unix - - n - - smtp

View File

@@ -389,7 +389,7 @@ if [[ -z "$APACHE_VHOST_DIR" ]] ; then
fi fi
fi fi
[[ -n "${COMPOSER}" ]] || COMPOSER=${DEFAULT_COMPOSER} [[ -n "${COMPOSER}" ]] || COMPOSER=${DEFAULT_COMPOSER}
[[ -n "$POSTFIX_DB_TYPE" ]] || fatal "Database Type of Postfix Database (POSTFIX_DB_TYPE) not present!" [[ -n "$POSTFIX_DB_TYPE" ]] || fatal "Database Type of Postfix Database (POSTFIX_DB_TYPE) not present!"
[[ -n "$POSTFIX_DB_HOST_MYSQL" ]] || POSTFIX_DB_HOST_MYSQL="$DEFAULT_POSTFIX_DB_HOST_MYSQL" [[ -n "$POSTFIX_DB_HOST_MYSQL" ]] || POSTFIX_DB_HOST_MYSQL="$DEFAULT_POSTFIX_DB_HOST_MYSQL"
@@ -430,7 +430,7 @@ if [[ "$POSTFIX_DB_TYPE" = "mysql" ]] ; then
fi fi
else else
echononl "\tGet MySQL command.." echononl "\tGet MySQL command.."
mysql_command="$(which mysql)" mysql_command="$(which mysql)"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
@@ -453,9 +453,9 @@ if [[ "$POSTFIX_DB_TYPE" = "mysql" ]] ; then
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf" MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
else else
fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated. fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated.
Use configuration file "$conf_file" to set Use configuration file "$conf_file" to set
parameter manually." parameter manually."
fi fi
fi fi
@@ -475,7 +475,7 @@ fi
if [[ "$ENCRYPTION_METHOD" =~ dovecot ]]; then if [[ "$ENCRYPTION_METHOD" =~ dovecot ]]; then
[[ -n "$DOVEADM_PW" ]] || DOVEADM_PW=$DEFAULT_DOVEADM_PW [[ -n "$DOVEADM_PW" ]] || DOVEADM_PW=$DEFAULT_DOVEADM_PW
fi fi
[[ -n "$DELETED_MAILBOX_DIR" ]] || DELETED_MAILBOX_DIR=$DEFAULT_DELETED_MAILBOX_DIR [[ -n "$DELETED_MAILBOX_DIR" ]] || DELETED_MAILBOX_DIR=$DEFAULT_DELETED_MAILBOX_DIR
[[ -n "$DELETED_DOMAINS_DIR" ]] || DELETED_DOMAINS_DIR=$DEFAULT_DELETED_DOMAINS_DIR [[ -n "$DELETED_DOMAINS_DIR" ]] || DELETED_DOMAINS_DIR=$DEFAULT_DELETED_DOMAINS_DIR
@@ -767,7 +767,7 @@ fi
if ! $database_exists ; then if ! $database_exists ; then
echononl "\tCreate Postfix Database '$POSTFIX_DB_NAME'" echononl "\tCreate Postfix Database '$POSTFIX_DB_NAME'"
if [ "$POSTFIX_DB_TYPE" = "mysql" ]; then if [ "$POSTFIX_DB_TYPE" = "mysql" ]; then
echo -n " (MySQL).." echo -n " (MySQL).."
mysql $MYSQL_CREDENTIALS -N -s -e \ mysql $MYSQL_CREDENTIALS -N -s -e \
"CREATE DATABASE IF NOT EXISTS $POSTFIX_DB_NAME CHARACTER SET utf8 COLLATE utf8_general_ci" >> $log_file 2>&1 "CREATE DATABASE IF NOT EXISTS $POSTFIX_DB_NAME CHARACTER SET utf8 COLLATE utf8_general_ci" >> $log_file 2>&1
@@ -817,7 +817,7 @@ else
else else
_db_backup_file_name="${POSTFIX_DB_NAME}-pfa.${backup_date}.sql" _db_backup_file_name="${POSTFIX_DB_NAME}-pfa.${backup_date}.sql"
fi fi
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then
echo -n " (MySQL).." echo -n " (MySQL).."
mysqldump $MYSQL_CREDENTIALS --opt $POSTFIX_DB_NAME > ${WEBSITE_BASEDIR}/${_db_backup_file_name} 2> $log_file mysqldump $MYSQL_CREDENTIALS --opt $POSTFIX_DB_NAME > ${WEBSITE_BASEDIR}/${_db_backup_file_name} 2> $log_file
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
@@ -938,6 +938,16 @@ done
if $_failed ; then if $_failed ; then
echo_failed echo_failed
error "$(cat $log_file)" error "$(cat $log_file)"
echononl "\tcontinue anyway [yes/no]: "
read OK
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
echononl "Wrong entry! - repeat [yes/nno]: "
read OK
done
[[ $OK = "yes" ]] || fatal "Script terminated by user input.."
else else
echo_ok echo_ok
fi fi
@@ -1001,7 +1011,7 @@ else
fi fi
echo -e "\n\n\t\033[37m\033[1mBase install Postfixadmin..\033[m\n" echo -e "\n\n\t\033[37m\033[1mBase install Postfixadmin..\033[m\n"
@@ -1348,13 +1358,13 @@ if [[ "$PHP_TYPE" = "fcgid" ]] ; then
#!/bin/sh #!/bin/sh
export PHPRC="${WEBSITE_BASEDIR}/conf/" export PHPRC="${WEBSITE_BASEDIR}/conf/"
export TMPDIR="${WEBSITE_BASEDIR}/tmp" export TMPDIR="${WEBSITE_BASEDIR}/tmp"
# PHP child process management (PHP_FCGI_CHILDREN) should # PHP child process management (PHP_FCGI_CHILDREN) should
# always be disabled with mod_fcgid, which will only route one # always be disabled with mod_fcgid, which will only route one
# request at a time to application processes it has spawned; # request at a time to application processes it has spawned;
# thus, any child processes created by PHP will not be used # thus, any child processes created by PHP will not be used
# effectively. (Additionally, the PHP child processes may not # effectively. (Additionally, the PHP child processes may not
# be terminated properly.) By default, and with the environment # be terminated properly.) By default, and with the environment
# variable setting PHP_FCGI_CHILDREN=0, PHP child process # variable setting PHP_FCGI_CHILDREN=0, PHP child process
# management is disabled. # management is disabled.
PHP_FCGI_CHILDREN=0 PHP_FCGI_CHILDREN=0
export PHP_FCGI_CHILDREN export PHP_FCGI_CHILDREN
@@ -1687,17 +1697,17 @@ EOF
# - X-Frame-Options # - X-Frame-Options
# - # -
# - The X-Frame-Options header (RFC), or XFO header, protects your visitors # - The X-Frame-Options header (RFC), or XFO header, protects your visitors
# - against clickjacking attacks. An attacker can load up an iframe on their # - against clickjacking attacks. An attacker can load up an iframe on their
# - site and set your site as the source, it's quite easy: # - site and set your site as the source, it's quite easy:
# - # -
# - <iframe src="https://scotthelme.co.uk"></iframe> # - <iframe src="https://scotthelme.co.uk"></iframe>
# - # -
# - Using some crafty CSS they can hide your site in the background and create some # - Using some crafty CSS they can hide your site in the background and create some
# - genuine looking overlays. When your visitors click on what they think is a harmless # - genuine looking overlays. When your visitors click on what they think is a harmless
# - link, they're actually clicking on links on your website in the background. That # - link, they're actually clicking on links on your website in the background. That
# - might not seem so bad until we realise that the browser will execute those requests # - might not seem so bad until we realise that the browser will execute those requests
# - in the context of the user, which could include them being logged in and authenticated # - in the context of the user, which could include them being logged in and authenticated
# - to your site! # - to your site!
# - # -
# - Troy Hunt has a great blog on 'Clickjack attack the hidden threat right in front : # - Troy Hunt has a great blog on 'Clickjack attack the hidden threat right in front :
@@ -1705,49 +1715,49 @@ EOF
# - # -
# - http://www.troyhunt.com/2013/05/clickjack-attack-hidden-threat-right-in.html # - http://www.troyhunt.com/2013/05/clickjack-attack-hidden-threat-right-in.html
# - # -
# - Valid values include DENY meaning your site can't be framed, SAMEORIGIN which allows # - Valid values include DENY meaning your site can't be framed, SAMEORIGIN which allows
# - you to frame your own site or ALLOW-FROM https://example.com/ which lets you specify # - you to frame your own site or ALLOW-FROM https://example.com/ which lets you specify
# -sites that are permitted to frame your own site. # -sites that are permitted to frame your own site.
# - # -
Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Frame-Options "SAMEORIGIN"
# - X-Xss-Protection # - X-Xss-Protection
# - # -
# - This header is used to configure the built in reflective XSS protection found # - This header is used to configure the built in reflective XSS protection found
# - in Internet Explorer, Chrome and Safari (Webkit). Valid settings for the header # - in Internet Explorer, Chrome and Safari (Webkit). Valid settings for the header
# - are 0, which disables the protection, 1 which enables the protection # - are 0, which disables the protection, 1 which enables the protection
# - and 1; mode=block which tells the browser to block the response if it # - and 1; mode=block which tells the browser to block the response if it
# - detects an attack rather than sanitising the script. # - detects an attack rather than sanitising the script.
# - # -
Header always set X-Xss-Protection "1; mode=block" Header always set X-Xss-Protection "1; mode=block"
# - X-Content-Type-Options # - X-Content-Type-Options
# - # -
# - Nice and easy to configure, this header only has one valid value, nosniff. # - Nice and easy to configure, this header only has one valid value, nosniff.
# - It prevents Google Chrome and Internet Explorer from trying to mime-sniff # - It prevents Google Chrome and Internet Explorer from trying to mime-sniff
# - the content-type of a response away from the one being declared by the server. # - the content-type of a response away from the one being declared by the server.
# - It reduces exposure to drive-by downloads and the risks of user uploaded content # - It reduces exposure to drive-by downloads and the risks of user uploaded content
# - that, with clever naming, could be treated as a different content-type, like # - that, with clever naming, could be treated as a different content-type, like
# - an executable. # - an executable.
# - # -
Header always set X-Content-Type-Options "nosniff" Header always set X-Content-Type-Options "nosniff"
# - Content Security Policy # - Content Security Policy
# - # -
# - The CSP header allows you to define a whitelist of approved sources of content # - The CSP header allows you to define a whitelist of approved sources of content
# - for your site. By restricting the assets that a browser can load for your site, # - for your site. By restricting the assets that a browser can load for your site,
# - like js and css, CSP can act as an effective countermeasure to XSS attacks. I # - like js and css, CSP can act as an effective countermeasure to XSS attacks. I
# - have covered CSP in a lot more detail in my blog Content Security Policy - An # - have covered CSP in a lot more detail in my blog Content Security Policy - An
# - Introduction (https://scotthelme.co.uk/content-security-policy-an-introduction/). # - Introduction (https://scotthelme.co.uk/content-security-policy-an-introduction/).
# - # -
# - Here is a basic policy to enforce TLS on all assets and prevent # - Here is a basic policy to enforce TLS on all assets and prevent
# - mixed content warnings. # - mixed content warnings.
# - # -
# - Allow Google Analytics, Google AJAX CDN and Same Origin # - Allow Google Analytics, Google AJAX CDN and Same Origin
# - script-src 'self' www.google-analytics.com ajax.googleapis.com; # - script-src 'self' www.google-analytics.com ajax.googleapis.com;
# - # -
# - Emmbedding Google Fonts # - Emmbedding Google Fonts
# - style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; # - style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
# - # -
# - Allow YouTube Videos (iframe embedded) # - Allow YouTube Videos (iframe embedded)
# - frame-src 'self' https://www.youtube.com # - frame-src 'self' https://www.youtube.com
@@ -1757,9 +1767,9 @@ EOF
# - Referrer-Policy # - Referrer-Policy
# - # -
# - The HTTP referer (originally a misspelling of referrer[1]) is an HTTP header # - The HTTP referer (originally a misspelling of referrer[1]) is an HTTP header
# - field that identifies the address of the webpage (i.e. the URI or IRI) that # - field that identifies the address of the webpage (i.e. the URI or IRI) that
# - linked to the resource being requested. By checking the referrer, the new # - linked to the resource being requested. By checking the referrer, the new
# - webpage can see where the request originated. # - webpage can see where the request originated.
# - # -
Header set Referrer-Policy "strict-origin-when-cross-origin" Header set Referrer-Policy "strict-origin-when-cross-origin"
@@ -1879,7 +1889,7 @@ fi
echononl "\tCreate system user '$VACATION_USER'" echononl "\tCreate system user '$VACATION_USER'"
if ! grep -q "$VACATION_USER" /etc/passwd > /dev/null 2>&1 ; then if ! grep -q "$VACATION_USER" /etc/passwd > /dev/null 2>&1 ; then
adduser --system --home /var/spool/vacation --no-create-home --uid 65501 --gid 65501 --shell /usr/sbin/nologin $VACATION_USER > "$log_file" 2>&1 adduser --system --home /var/spool/vacation --no-create-home --uid 65501 --gid 65501 --shell /usr/sbin/nologin $VACATION_USER > "$log_file" 2>&1
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
echo_failed echo_failed
error "$(cat $log_file)" error "$(cat $log_file)"
@@ -1950,7 +1960,7 @@ fi
# - # -
#echononl "\tWorkaround, because encoding does not work as exspected." #echononl "\tWorkaround, because encoding does not work as exspected."
## - Vacation script changed. Since Version 3.2 we need another perl regexp. ## - Vacation script changed. Since Version 3.2 we need another perl regexp.
## - The old one was: ## - The old one was:
## - perl -i -n -p -e "s/(\s*\'ctype\'\s* =>\s*)\'text\/plain.*$/\1\'text\/plain; charset=iso-8859-1\',/" \ ## - perl -i -n -p -e "s/(\s*\'ctype\'\s* =>\s*)\'text\/plain.*$/\1\'text\/plain; charset=iso-8859-1\',/" \
## - ## -
##perl -i -n -p -e "s/(\s*\'Content-Type\'\s* =>\s*)\"text\/plain.*$/\1\"text\/plain; charset=iso-8859-1\",/" \ ##perl -i -n -p -e "s/(\s*\'Content-Type\'\s* =>\s*)\"text\/plain.*$/\1\"text\/plain; charset=iso-8859-1\",/" \
@@ -1985,7 +1995,7 @@ fi
# - /etc/mail/postfixadmin/vacation.conf # - /etc/mail/postfixadmin/vacation.conf
# - /etc/postfixadmin/vacation.conf # - /etc/postfixadmin/vacation.conf
# - # -
# - Instead of changing this script, we put the needed entries # - Instead of changing this script, we put the needed entries
# - to file /etc/postfixadmin/vacation.conf: # - to file /etc/postfixadmin/vacation.conf:
# - # -
echononl "\tCreate directory '/etc/postfixadmin' " echononl "\tCreate directory '/etc/postfixadmin' "
@@ -2091,15 +2101,15 @@ fi
# - Create an entry in /etc/hosts for the (non-existant domain) # - Create an entry in /etc/hosts for the (non-existant domain)
# - $AUTOREPLY_HOSTNAME # - $AUTOREPLY_HOSTNAME
# - # -
# - add: # - add:
# - # -
# - 127.0.0.1 $AUTOREPLY_HOSTNAME # - 127.0.0.1 $AUTOREPLY_HOSTNAME
# - # -
echononl "\tCreate entry in /etc/hosts for '$AUTOREPLY_HOSTNAME'" echononl "\tCreate entry in /etc/hosts for '$AUTOREPLY_HOSTNAME'"
if ! grep -q "$AUTOREPLY_HOSTNAME" /etc/hosts > $log_file 2>&1 ; then if ! grep -q "$AUTOREPLY_HOSTNAME" /etc/hosts > $log_file 2>&1 ; then
perl -i -n -p -e"s#(^\s*127.0.0.1\s+localhost.*)#\1\n\n127.0.0.1 ${AUTOREPLY_HOSTNAME}#" /etc/hosts > $log_file 2>&1 perl -i -n -p -e"s#(^\s*127.0.0.1\s+localhost.*)#\1\n\n127.0.0.1 ${AUTOREPLY_HOSTNAME}#" /etc/hosts > $log_file 2>&1
if [[ $? -eq 0 ]] ; then if [[ $? -eq 0 ]] ; then
echo_ok echo_ok
else else
@@ -2110,7 +2120,7 @@ else
echo_skipped echo_skipped
fi fi
# - Define the transport type in the Postfix master file # - Define the transport type in the Postfix master file
# - /etc/postfix/master.cf # - /etc/postfix/master.cf
# - # -
# - vacation unix - n n - - pipe # - vacation unix - n n - - pipe
@@ -2198,15 +2208,18 @@ fi
echo -e "\n\n\t\033[37m\033[1mConfigure Postfix Admin\033[m\n" echo -e "\n\n\t\033[37m\033[1mConfigure Postfix Admin\033[m\n"
if [[ $MAJOR_VERSION -eq 3 ]] && [[ $MINOR_VERSION -gt 0 ]]; then if [[ $MAJOR_VERSION -gt 3 ]] ; then
pfa_conf_file="${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.local.php"
cp -a "${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.inc.php" "$pfa_conf_file"
elif [[ $MAJOR_VERSION -eq 3 ]] && [[ $MINOR_VERSION -gt 0 ]] ; then
pfa_conf_file="${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.local.php" pfa_conf_file="${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.local.php"
cp -a "${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.inc.php" "$pfa_conf_file" cp -a "${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.inc.php" "$pfa_conf_file"
else else
pfa_conf_file="${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.inc.php" pfa_conf_file="${WEBSITE_BASEDIR}/postfixadmin-${PF_ADMIN_VERSION}/config.inc.php"
cp -a "$pfa_conf_file" "${pfa_conf_file}.ORIG" cp -a "$pfa_conf_file" "${pfa_conf_file}.ORIG"
fi fi
# - Use 'Re: $SUBJECT' as the default subject template for vacation # - Use 'Re: $SUBJECT' as the default subject template for vacation
# - in postfixadmin # - in postfixadmin
@@ -2267,26 +2280,26 @@ else
fi fi
> $log_file > $log_file
perl -i -n -p -e "s#^(\s*\\\$CONF\['default_language'\]\s*=.*)#//!\1\n\\\$CONF['default_language'] = 'de';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['default_language'\]\s*=.*)#//!\1\n\\\$CONF['default_language'] = 'de';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['database_type'\]\s*=.*)#//!\1\n\\\$CONF['database_type'] = '$_database_type';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['database_type'\]\s*=.*)#//!\1\n\\\$CONF['database_type'] = '$_database_type';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['database_host'\]\s*=.*)#//!\1\n\\\$CONF['database_host'] = 'localhost';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['database_host'\]\s*=.*)#//!\1\n\\\$CONF['database_host'] = 'localhost';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['database_user'\]\s*=.*)#//!\1\n\\\$CONF['database_user'] = '$POSTFIX_DB_USER';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['database_user'\]\s*=.*)#//!\1\n\\\$CONF['database_user'] = '$POSTFIX_DB_USER';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['database_password'\]\s*=.*)#//!\1\n\\\$CONF['database_password'] = '$POSTFIX_DB_PASS';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['database_password'\]\s*=.*)#//!\1\n\\\$CONF['database_password'] = '$POSTFIX_DB_PASS';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['database_name'\]\s*=.*)#//!\1\n\\\$CONF['database_name'] = '$POSTFIX_DB_NAME';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['database_name'\]\s*=.*)#//!\1\n\\\$CONF['database_name'] = '$POSTFIX_DB_NAME';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['database_prefix'\]\s*=.*)#//!\1\n\\\$CONF['database_prefix'] = '';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['database_prefix'\]\s*=.*)#//!\1\n\\\$CONF['database_prefix'] = '';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['admin_email'\]\s*=.*)#//!\1\n\\\$CONF['admin_email'] = '$WEBMASTER_EMAIL';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['admin_email'\]\s*=.*)#//!\1\n\\\$CONF['admin_email'] = '$WEBMASTER_EMAIL';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['encrypt'\]\s*=.*)#//!\1\n\\\$CONF['encrypt'] = '$ENCRYPTION_METHOD';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['encrypt'\]\s*=.*)#//!\1\n\\\$CONF['encrypt'] = '$ENCRYPTION_METHOD';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
if grep -q -E "^\\\$CONF\['dovecotpw'\]\s*=.*" "$pfa_conf_file" 2> /dev/null ; then if grep -q -E "^\\\$CONF\['dovecotpw'\]\s*=.*" "$pfa_conf_file" 2> /dev/null ; then
perl -i -n -p -e "s#^(\\\$CONF\['dovecotpw'\]\s*=.*)#//!\1\n\\\$CONF['dovecotpw'] = '$DOVEADM_PW';#" \ perl -i -n -p -e "s#^(\\\$CONF\['dovecotpw'\]\s*=.*)#//!\1\n\\\$CONF['dovecotpw'] = '$DOVEADM_PW';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
else else
cat <<EOF >> $pfa_conf_file cat <<EOF >> $pfa_conf_file
@@ -2325,7 +2338,7 @@ echononl "\tAdjust Postfix Admin's Configuration - Part 2"
_failed=false _failed=false
> $log_file > $log_file
perl -i -n -p -e "s#^(\s*\\\$CONF\['default_aliases'\]\s*=.*)#//\n//! 'default_aliases' will be overridden - see end of configfile\n//\n\1#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['default_aliases'\]\s*=.*)#//\n//! 'default_aliases' will be overridden - see end of configfile\n//\n\1#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
cat <<EOF >> $pfa_conf_file 2> $log_file cat <<EOF >> $pfa_conf_file 2> $log_file
@@ -2345,10 +2358,10 @@ EOF
perl -i -n -p -e "s#^(\s*\\\$CONF\['language_hook'\]\s*=.*)#//\n//! 'language_hook' will be overridden - see end of configfile\n//\n\1#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['language_hook'\]\s*=.*)#//\n//! 'language_hook' will be overridden - see end of configfile\n//\n\1#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['password_validation'\]\s*=.*)#//\n//! 'password_validation' will be overridden - see end of configfile\n//\n\1#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['password_validation'\]\s*=.*)#//\n//! 'password_validation' will be overridden - see end of configfile\n//\n\1#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
cat <<EOF >> $pfa_conf_file 2> $log_file cat <<EOF >> $pfa_conf_file 2> $log_file
// Password validation // Password validation
@@ -2374,19 +2387,19 @@ cat <<EOF >> $pfa_conf_file 2> $log_file
); );
/* /*
language_hook example function language_hook example function
Called if \$CONF['language_hook'] == '<name_of_the_function>' Called if \$CONF['language_hook'] == '<name_of_the_function>'
Allows to add or override \$PALANG interface texts. Allows to add or override \$PALANG interface texts.
If you add new texts, please always prefix them with 'x_' (for example If you add new texts, please always prefix them with 'x_' (for example
\$PALANG['x_mytext'] = 'foo') to avoid they clash with texts that might be \$PALANG['x_mytext'] = 'foo') to avoid they clash with texts that might be
added to languages/*.lang in future versions of PostfixAdmin. added to languages/*.lang in future versions of PostfixAdmin.
Please also make sure that all your added texts are included in all Please also make sure that all your added texts are included in all
sections - that includes all 'case "XY":' sections and the 'default:' sections - that includes all 'case "XY":' sections and the 'default:'
section (for users that don't have any of the languages specified section (for users that don't have any of the languages specified
in the 'case "XY":' section). in the 'case "XY":' section).
Usually the 'default:' section should contain english text. Usually the 'default:' section should contain english text.
If you modify an existing text/translation, please consider to report it If you modify an existing text/translation, please consider to report it
@@ -2432,23 +2445,23 @@ EOF
perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_path'\]\s*=.*)#//!\1\n\\\$CONF['domain_path'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_path'\]\s*=.*)#//!\1\n\\\$CONF['domain_path'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_in_mailbox'\]\s*=.*)#//!\1\n\\\$CONF['domain_in_mailbox'] = 'NO';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_in_mailbox'\]\s*=.*)#//!\1\n\\\$CONF['domain_in_mailbox'] = 'NO';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['aliases'\]\s*=.*)#//!\1\n\\\$CONF['aliases'] = '100';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['aliases'\]\s*=.*)#//!\1\n\\\$CONF['aliases'] = '100';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['mailboxes'\]\s*=.*)#//!\1\n\\\$CONF['mailboxes'] = '100';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['mailboxes'\]\s*=.*)#//!\1\n\\\$CONF['mailboxes'] = '100';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['maxquota'\]\s*=.*)#//!\1\n\\\$CONF['maxquota'] = '0';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['maxquota'\]\s*=.*)#//!\1\n\\\$CONF['maxquota'] = '0';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_quota_default'\]\s*=.*)#//!\1\n\\\$CONF['domain_quota_default'] = '0';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_quota_default'\]\s*=.*)#//!\1\n\\\$CONF['domain_quota_default'] = '0';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['quota'\]\s*=.*)#//!\1\n\\\$CONF['quota'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['quota'\]\s*=.*)#//!\1\n\\\$CONF['quota'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_quota'\]\s*=.*)#//!\1\n\\\$CONF['domain_quota'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['domain_quota'\]\s*=.*)#//!\1\n\\\$CONF['domain_quota'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['quota_multiplier'\]\s*=.*)#//!\1\n\\\$CONF['quota_multiplier'] = '1048576';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['quota_multiplier'\]\s*=.*)#//!\1\n\\\$CONF['quota_multiplier'] = '1048576';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
if $_failed ; then if $_failed ; then
echo_failed echo_failed
error "$(cat $log_file)" error "$(cat $log_file)"
@@ -2526,8 +2539,8 @@ cat <<EOF >> $pfa_conf_file 2> $log_file
// ReplyType options // ReplyType options
// If you want to define additional reply options put them in array below. // If you want to define additional reply options put them in array below.
// The array has the format seconds between replies => $PALANG text // The array has the format seconds between replies => $PALANG text
// Special values for seconds are: // Special values for seconds are:
// 0 => only reply to the first mail while on vacation // 0 => only reply to the first mail while on vacation
// 1 => reply on every mail // 1 => reply on every mail
// 60*60*24*7 => Reply if last autoreply was at least a week ago // 60*60*24*7 => Reply if last autoreply was at least a week ago
// //
@@ -2560,8 +2573,8 @@ fi
## - EOM; ## - EOM;
## - ## -
echononl "\tCreate welcome message.." echononl "\tCreate welcome message.."
if [[ -n "$WELCOME_MESSAGE" ]] ; then if [[ -n "$WELCOME_MESSAGE" ]] ; then
cat <<EOF >> $pfa_conf_file 2> $log_file cat <<EOF >> $pfa_conf_file 2> $log_file
// Welcome Message // Welcome Message
// This message is send to every newly created mailbox. // This message is send to every newly created mailbox.
@@ -2604,35 +2617,35 @@ echononl "\tAdjust Postfix Admin's Configuration - Part 5"
_failed=false _failed=false
> $log_file > $log_file
perl -i -n -p -e "s#^(\s*\\\$CONF\['alias_control_admin'\]\s+=.*)#//!\1\n\\\$CONF['alias_control_admin'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['alias_control_admin'\]\s+=.*)#//!\1\n\\\$CONF['alias_control_admin'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['alias_control'\]\s*=.*)#//!\1\n\\\$CONF['alias_control'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['alias_control'\]\s*=.*)#//!\1\n\\\$CONF['alias_control'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['special_alias_control'\]\s*=.*)#//!\1\n\\\$CONF['special_alias_control'] = 'NO';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['special_alias_control'\]\s*=.*)#//!\1\n\\\$CONF['special_alias_control'] = 'NO';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['backup'\]\s*=.*)#//!\1\n\\\$CONF['backup'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['backup'\]\s*=.*)#//!\1\n\\\$CONF['backup'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['fetchmail'\]\s*=.*)#//!\1\n\\\$CONF['fetchmail'] = 'NO';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['fetchmail'\]\s*=.*)#//!\1\n\\\$CONF['fetchmail'] = 'NO';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['user_footer_link'\]\s+=.*)#//!\1\n\\\$CONF['user_footer_link'] = 'https://${WEBSITE_NAME}/main.php';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['user_footer_link'\]\s+=.*)#//!\1\n\\\$CONF['user_footer_link'] = 'https://${WEBSITE_NAME}/main.php';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['footer_text'\]\s+=.*)#//!\1\n\\\$CONF['footer_text'] = 'Main Menu';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['footer_text'\]\s+=.*)#//!\1\n\\\$CONF['footer_text'] = 'Main Menu';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['footer_link'\]\s+=.*)#//!\1\n\\\$CONF['footer_link'] = 'http://${WEBSITE_NAME}/main.php';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['footer_link'\]\s+=.*)#//!\1\n\\\$CONF['footer_link'] = 'http://${WEBSITE_NAME}/main.php';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['emailcheck_resolve_domain'\]\s*=.*)#//!\1\n\\\$CONF['emailcheck_resolve_domain'] = 'NO';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['emailcheck_resolve_domain'\]\s*=.*)#//!\1\n\\\$CONF['emailcheck_resolve_domain'] = 'NO';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['show_status'\]\s*=.*)#//!\1\n\\\$CONF['show_status'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['show_status'\]\s*=.*)#//!\1\n\\\$CONF['show_status'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['show_status_key'\]\s*=.*)#//!\1\n\\\$CONF['show_status_key'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['show_status_key'\]\s*=.*)#//!\1\n\\\$CONF['show_status_key'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['show_undeliverable'\]\s*=.*)#//!\1\n\\\$CONF['show_undeliverable'] = 'NO';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['show_undeliverable'\]\s*=.*)#//!\1\n\\\$CONF['show_undeliverable'] = 'NO';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['show_popimap'\]\s*=.*)#//!\1\n\\\$CONF['show_popimap'] = 'NO';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['show_popimap'\]\s*=.*)#//!\1\n\\\$CONF['show_popimap'] = 'NO';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['used_quotas'\]\s*=.*)#//!\1\n\\\$CONF['used_quotas'] = 'NO';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['used_quotas'\]\s*=.*)#//!\1\n\\\$CONF['used_quotas'] = 'NO';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
perl -i -n -p -e "s#^(\s*\\\$CONF\['new_quota_table'\]\s*=.*)#//!\1\n\\\$CONF['new_quota_table'] = 'YES';#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['new_quota_table'\]\s*=.*)#//!\1\n\\\$CONF['new_quota_table'] = 'YES';#" \
$pfa_conf_file >> $log_file 2>&1 || _failed=true $pfa_conf_file >> $log_file 2>&1 || _failed=true
if $_failed ; then if $_failed ; then
echo_failed echo_failed
error "$(cat $log_file)" error "$(cat $log_file)"
@@ -2665,7 +2678,7 @@ fi
# - $CONF['configured'] = true; # - $CONF['configured'] = true;
echononl "\tSet '\$CONF['configured'] = true'" echononl "\tSet '\$CONF['configured'] = true'"
perl -i -n -p -e "s#^(\s*\\\$CONF\['configured'\]\s*=.*)#//!\1\n\\\$CONF['configured'] = true;#" \ perl -i -n -p -e "s#^(\s*\\\$CONF\['configured'\]\s*=.*)#//!\1\n\\\$CONF['configured'] = true;#" \
$pfa_conf_file > $log_file 2>&1 $pfa_conf_file > $log_file 2>&1
if [[ $? -eq 0 ]] ; then if [[ $? -eq 0 ]] ; then
echo_ok echo_ok
else else
@@ -2726,7 +2739,7 @@ echo ""
# - AFTER DELETION MAILBOX # - AFTER DELETION MAILBOX
# - # -
# - activate script for moving a mailbox from the mailboxdirectory # - activate script for moving a mailbox from the mailboxdirectory
# - and save it to the backupb directory /var/deleted-maildirs # - and save it to the backupb directory /var/deleted-maildirs
# - # -
@@ -2735,7 +2748,7 @@ echononl "\tCreate folder '${DELETED_MAILBOX_DIR}"
if [[ ! -d "${DELETED_MAILBOX_DIR}" ]] ; then if [[ ! -d "${DELETED_MAILBOX_DIR}" ]] ; then
mkdir $DELETED_MAILBOX_DIR > $log_file 2>&1 mkdir $DELETED_MAILBOX_DIR > $log_file 2>&1
if [[ $? -eq 0 ]] ; then if [[ $? -eq 0 ]] ; then
echo_ok echo_ok
else else
echo_failed echo_failed
error "$(cat $log_file)" error "$(cat $log_file)"
@@ -2789,11 +2802,11 @@ else
fi fi
# - Change the posdeletion scripts to your needs: # - Change the posdeletion scripts to your needs:
# - # -
# - set: # - set:
# - basedir=/var/vmail # - basedir=/var/vmail
# - trashbase=$DELETED_MAILBOX_DIR # - trashbase=$DELETED_MAILBOX_DIR
# - # -
# - trashdir="${trashbase}/$2/`date +%F_$H-%M`_${subdir}" # - trashdir="${trashbase}/$2/`date +%F_$H-%M`_${subdir}"
# - # -
echononl "\tAdjust 'postfixadmin-mailbox-postdeletion.sh'" echononl "\tAdjust 'postfixadmin-mailbox-postdeletion.sh'"
@@ -2815,9 +2828,9 @@ fi
# - Edit ${WEBSITE_BASEDIR}/htdocs/config.inc.php # - Edit ${WEBSITE_BASEDIR}/htdocs/config.inc.php
# - # -
# - in section add line # - in section add line
# - $CONF['mailbox_postdeletion_script']='sudo -u vmail /usr/local/bin/postfixadmin-mailbox-postdeletion.sh'; # - $CONF['mailbox_postdeletion_script']='sudo -u vmail /usr/local/bin/postfixadmin-mailbox-postdeletion.sh';
# - # -
echononl "\tAdjust 'config.inc.php' to make script available" echononl "\tAdjust 'config.inc.php' to make script available"
perl -i -n -p -e "s#^(\s*[/*]?\s*\\\$CONF\['mailbox_postdeletion_script'\]\s*=.*)#//!\1\n\\\$CONF['mailbox_postdeletion_script'] = 'sudo -u vmail /usr/local/bin/postfixadmin-mailbox-postdeletion.sh';#" \ perl -i -n -p -e "s#^(\s*[/*]?\s*\\\$CONF\['mailbox_postdeletion_script'\]\s*=.*)#//!\1\n\\\$CONF['mailbox_postdeletion_script'] = 'sudo -u vmail /usr/local/bin/postfixadmin-mailbox-postdeletion.sh';#" \
$pfa_conf_file > $log_file 2>&1 $pfa_conf_file > $log_file 2>&1
@@ -2880,7 +2893,7 @@ fi
# - AFTER DELETION MAILDOMIAN # - AFTER DELETION MAILDOMIAN
# - # -
# - activate script for moving a mailbox from the mailboxdirectory # - activate script for moving a mailbox from the mailboxdirectory
# - and save it to the backupb directory $DELETED_DOMAINS_DIR # - and save it to the backupb directory $DELETED_DOMAINS_DIR
# - # -
@@ -2889,7 +2902,7 @@ echononl "\tCreate folder '${DELETED_DOMAINS_DIR}"
if [[ ! -d "${DELETED_DOMAINS_DIR}" ]] ; then if [[ ! -d "${DELETED_DOMAINS_DIR}" ]] ; then
mkdir $DELETED_DOMAINS_DIR > $log_file 2>&1 mkdir $DELETED_DOMAINS_DIR > $log_file 2>&1
if [[ $? -eq 0 ]] ; then if [[ $? -eq 0 ]] ; then
echo_ok echo_ok
else else
echo_failed echo_failed
error "$(cat $log_file)" error "$(cat $log_file)"
@@ -2946,11 +2959,11 @@ fi
# - Change the posdeletion scripts to your needs: # - Change the posdeletion scripts to your needs:
# - # -
# - set: # - set:
# - basedir=/var/vmail # - basedir=/var/vmail
# - trashbase=$DELETED_DOMAINS_DIR # - trashbase=$DELETED_DOMAINS_DIR
# - # -
# - trashdir="${trashbase}/`date +%F_%H-%M`_$1" # - trashdir="${trashbase}/`date +%F_%H-%M`_$1"
# - # -
echononl "\tAdjust 'postfixadmin-domain-postdeletion.sh'" echononl "\tAdjust 'postfixadmin-domain-postdeletion.sh'"
@@ -2971,9 +2984,9 @@ fi
# - edit ${WEBSITE_BASEDIR}/htdocs/config.inc.php # - edit ${WEBSITE_BASEDIR}/htdocs/config.inc.php
# - # -
# - in section add line # - in section add line
# - $CONF['domain_postdeletion_script']='sudo -u vmail /usr/local/bin/postfixadmin-domain-postdeletion.sh'; # - $CONF['domain_postdeletion_script']='sudo -u vmail /usr/local/bin/postfixadmin-domain-postdeletion.sh';
# - # -
echononl "\tAdjust 'config.inc.php' to make script available" echononl "\tAdjust 'config.inc.php' to make script available"
perl -i -n -p -e "s#^(\s*[/*]?\s*\\\$CONF\['domain_postdeletion_script'\]\s*=.*)#//!\1\n\\\$CONF['domain_postdeletion_script'] = 'sudo -u vmail /usr/local/bin/postfixadmin-domain-postdeletion.sh';#" \ perl -i -n -p -e "s#^(\s*[/*]?\s*\\\$CONF\['domain_postdeletion_script'\]\s*=.*)#//!\1\n\\\$CONF['domain_postdeletion_script'] = 'sudo -u vmail /usr/local/bin/postfixadmin-domain-postdeletion.sh';#" \
$pfa_conf_file >> $log_file 2>&1 $pfa_conf_file >> $log_file 2>&1
@@ -3040,9 +3053,9 @@ fi
## - specified database. ## - specified database.
## - ## -
## - Now you have to setup Postfix to recognize all these entries. To do so, ## - Now you have to setup Postfix to recognize all these entries. To do so,
## - you must specify database requests (in different files) and load them ## - you must specify database requests (in different files) and load them
## - into Postfix configuration. In particular that are the following files: ## - into Postfix configuration. In particular that are the following files:
## - ## -
## - pgsql_relay-domain-maps.cf ## - pgsql_relay-domain-maps.cf
## - pgsql_sender_login_maps.cf ## - pgsql_sender_login_maps.cf
## - pgsql_transport_maps.cf ## - pgsql_transport_maps.cf
@@ -3484,7 +3497,7 @@ echononl "\tCreate file '/etc/postfix/${POSTFIX_DB_TYPE}_virtual_alias_address_r
if [ "$POSTFIX_DB_TYPE" = "pgsql" ]; then if [ "$POSTFIX_DB_TYPE" = "pgsql" ]; then
cat <<EOF > /etc/postfix/${POSTFIX_DB_TYPE}_virtual_alias_address_rewriting.cf cat <<EOF > /etc/postfix/${POSTFIX_DB_TYPE}_virtual_alias_address_rewriting.cf
## - this address rewriting acts as address extension ## - this address rewriting acts as address extension
## - with delimeter "-" ## - with delimeter "-"
## - ## -
hosts = $POSTFIX_DB_HOST_PGSQL hosts = $POSTFIX_DB_HOST_PGSQL
@@ -3676,14 +3689,14 @@ info "Browse to \033[1mhttps://${WEBSITE_NAME}/setup.php\033[m to create a 'setu
\t Instructions on how to do this are pointed out at the setup site, maybe like this: \t Instructions on how to do this are pointed out at the setup site, maybe like this:
\t - Generate setup_password hash and set \033[1m$CONF['setup_password']\033[m \t - Generate setup_password hash and set \033[1m$CONF['setup_password']\033[m
\t in file \033[1mconfig.local.php\033[m as printed out. \t in file \033[1mconfig.local.php\033[m as printed out.
\t - Browse to \033[1mhttp://${WEBSITE_NAME}/setup.php\033[m once again to update \t - Browse to \033[1mhttp://${WEBSITE_NAME}/setup.php\033[m once again to update
\t the database \t the database
\t Browse to \033[1mhttp://${WEBSITE_NAME}\033[m and login using an existent admin account \t Browse to \033[1mhttp://${WEBSITE_NAME}\033[m and login using an existent admin account
\t[ \033[33m\033[1mNotice\033[m ]: \033[1mScroll back to see if all seems to be fine!\033[m \t[ \033[33m\033[1mNotice\033[m ]: \033[1mScroll back to see if all seems to be fine!\033[m
@@ -3737,7 +3750,7 @@ dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s' AND active = true query = SELECT quota FROM mailbox WHERE username='%s' AND active = true
EOF EOF
## - add configuration parameter virtual_mailbox_limit_maps ## - add configuration parameter virtual_mailbox_limit_maps
## - in Postfix /etc/postfix/main.cf ## - in Postfix /etc/postfix/main.cf
## - ## -
## - add: ## - add:

View File

@@ -184,7 +184,7 @@ else
fi fi
if [[ -z "$systemd_support" ]] ; then if [[ -z "$systemd_support" ]] ; then
if $SYSTEMD_EXISTS ; then if $SYSTEMD_EXISTS ; then
systemd_support=true systemd_support=true
else else
systemd_support=false systemd_support=false
@@ -305,7 +305,7 @@ _version_short="${_version%-*}"
#clean_up 0 #clean_up 0
# 'expire plugin'was rRemoved in version 2.3.14: This plugin is not needed. # 'expire plugin'was rRemoved in version 2.3.14: This plugin is not needed.
# Use mailbox { autoexpunge } Mailbox settings instead. # Use mailbox { autoexpunge } Mailbox settings instead.
# #
if [[ $dovecot_major_version -gt 2 ]] \ if [[ $dovecot_major_version -gt 2 ]] \
@@ -362,12 +362,12 @@ if [[ -n "$_update" ]]; then
echo -e "[1] Update" echo -e "[1] Update"
echo -e "\033[37m\033[1m[2] New Installation\033[m" echo -e "\033[37m\033[1m[2] New Installation\033[m"
fi fi
echo "" echo ""
echononl "Choose a number or press <RETURN> for highlighted value: " echononl "Choose a number or press <RETURN> for highlighted value: "
else else
echo -e "[1] Update" echo -e "[1] Update"
echo "[2] New Installation" echo "[2] New Installation"
echo "" echo ""
echononl "Choose a Number: " echononl "Choose a Number: "
fi fi
update="" update=""
@@ -392,13 +392,13 @@ while [[ "$update" != "true" && "$update" != "false" ]] ; do
fi fi
;; ;;
*) update="" *) update=""
echo "" echo ""
if [[ -n "$_IS_RELAY_HOST" ]]; then if [[ -n "$_IS_RELAY_HOST" ]]; then
echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ] or type <RETURN>" echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ] or type <RETURN>"
else else
echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ]" echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ]"
fi fi
echo "" echo ""
echononl "Reentry: " echononl "Reentry: "
;; ;;
esac esac
@@ -415,7 +415,7 @@ done
clear; clear;
echo "" echo ""
if $update ;then if $update ;then
echo -e "\tUpdate Dovecot................: $update" echo -e "\tUpdate Dovecot................: $update"
else else
echo -e "\tInstall Dovecot first time....: Yes" echo -e "\tInstall Dovecot first time....: Yes"
@@ -507,7 +507,7 @@ export MAKEFLAGS=-j$(expr `grep "^processor" /proc/cpuinfo | sort -u | wc -l` -
echo "" echo ""
if $update ;then if $update ;then
_new=false; _new=false;
else else
_new=true; _new=true;
@@ -683,7 +683,7 @@ mkdir -p $_log_dir
## ----------------- ## -----------------
## --- Download ## --- Download
cd ${_src_base_dir} cd ${_src_base_dir}
@@ -720,7 +720,7 @@ fi
## - Download Pigeonhole for Dovecot v2.2 ## - Download Pigeonhole for Dovecot v2.2
## - ## -
if [[ ${dovecot_major_version} -eq 2 ]] && [[ ${dovecot_minor_version} -lt 4 ]] ; then if [[ ${dovecot_major_version} -eq 2 ]] && [[ ${dovecot_minor_version} -lt 4 ]] ; then
echononl "\tDownload dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.." echononl "\tDownload dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.."
if [ ! -f "${_src_base_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz" ]; then if [ ! -f "${_src_base_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz" ]; then
wget --no-check-certificate https://pigeonhole.dovecot.org/releases/${dovecot_main_version}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz > /dev/null 2>&1 wget --no-check-certificate https://pigeonhole.dovecot.org/releases/${dovecot_main_version}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz > /dev/null 2>&1
@@ -730,7 +730,7 @@ if [[ ${dovecot_major_version} -eq 2 ]] && [[ ${dovecot_minor_version} -lt 4 ]]
echo -e "$rc_failed" echo -e "$rc_failed"
error "Direct download of 'dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz' failed error "Direct download of 'dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz' failed
Download \033[1mdovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz\033[m manually Download \033[1mdovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz\033[m manually
and proceed instllation." and proceed instllation."
echononl "\tProceed instllation [yes/no]: " echononl "\tProceed instllation [yes/no]: "
@@ -1071,7 +1071,7 @@ fi
## - if [ -d $checkdir ]; then ## - if [ -d $checkdir ]; then
## - PATH=$PATH:$checkdir ## - PATH=$PATH:$checkdir
## - fi ## - fi
## - ## -
echononl "\tAdd /usr/local/dovecot/bin to PATH variable.." echononl "\tAdd /usr/local/dovecot/bin to PATH variable.."
if ! grep "checkdir=\"/usr/local/dovecot/bin\"" /etc/profile > /dev/null ; then if ! grep "checkdir=\"/usr/local/dovecot/bin\"" /etc/profile > /dev/null ; then
perl -i -n -p -e "s#^(\s*)(export\ +PATH)#checkdir=\"/usr/local/dovecot/bin\"\nif [ -d \\\$checkdir ]; then\n PATH=\\\$PATH:\\\$checkdir\nfi\n\n\1\2#" /etc/profile perl -i -n -p -e "s#^(\s*)(export\ +PATH)#checkdir=\"/usr/local/dovecot/bin\"\nif [ -d \\\$checkdir ]; then\n PATH=\\\$PATH:\\\$checkdir\nfi\n\n\1\2#" /etc/profile
@@ -1166,9 +1166,9 @@ cp -r /usr/local/dovecot-${_version}/share/doc/dovecot/example-config/* \
## - base_dir =/run/dovecot/ ## - base_dir =/run/dovecot/
## - state_dir = /run/dovecot ## - state_dir = /run/dovecot
## - shutdown_clients = no ## - shutdown_clients = no
## - ## -
## - dict { ## - dict {
## - expire = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext ## - expire = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext
## - } ## - }
## - ## -
echononl "\tAdjust file dovecot.conf.." echononl "\tAdjust file dovecot.conf.."
@@ -1253,7 +1253,7 @@ if $_new ; then
echononl "\tCreate table expires in database ${dbname}.." echononl "\tCreate table expires in database ${dbname}.."
if $plugin_expire ; then if $plugin_expire ; then
cat << EOF | psql -U$dbuser $dbname > ${_log_dir}/error.log 2>&1 cat << EOF | psql -U$dbuser $dbname > ${_log_dir}/error.log 2>&1
CREATE TABLE IF NOT EXISTS expires ( CREATE TABLE IF NOT EXISTS expires (
username varchar(100) not null, username varchar(100) not null,
mailbox varchar(255) not null, mailbox varchar(255) not null,
@@ -1395,7 +1395,7 @@ EOF
echononl "\tCreate table expires in database ${dbname}.." echononl "\tCreate table expires in database ${dbname}.."
if $plugin_expire ; then if $plugin_expire ; then
cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1 cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1
CREATE TABLE IF NOT EXISTS expires ( CREATE TABLE IF NOT EXISTS expires (
username varchar(100) not null, username varchar(100) not null,
mailbox varchar(255) not null, mailbox varchar(255) not null,
@@ -1450,7 +1450,7 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
# END IF; # END IF;
# END; # END;
# \$\$ LANGUAGE plpgsql; # \$\$ LANGUAGE plpgsql;
# #
# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires # CREATE TRIGGER mergeexpires BEFORE INSERT ON expires
# FOR EACH ROW EXECUTE PROCEDURE merge_expires(); # FOR EACH ROW EXECUTE PROCEDURE merge_expires();
@@ -1505,7 +1505,7 @@ EOF
echo -e "$rc_failed" echo -e "$rc_failed"
fatal "Creating file sql-dict.conf.ext failed" fatal "Creating file sql-dict.conf.ext failed"
fi fi
fi fi
else else
echo -e "$rc_skipped" echo -e "$rc_skipped"
fi fi
@@ -1519,15 +1519,15 @@ fi
## - default_vsz_limit = 512M ## - default_vsz_limit = 512M
## - ## -
## - !! Bemerkung !! ## - !! Bemerkung !!
## - ## -
## - Das Hochsetzen des default_client_limit Parameters auf einen Wert größer ## - Das Hochsetzen des default_client_limit Parameters auf einen Wert größer
## - als 1024 geht nur dann wenn auch die Anzahl der zulässigen "open files" ## - als 1024 geht nur dann wenn auch die Anzahl der zulässigen "open files"
## - (default = 1024) geändert wird. ## - (default = 1024) geändert wird.
## - ## -
## - ## -
## - Systemd System: ## - Systemd System:
## - =============== ## - ===============
## - ## -
## - In der service datei (z.Bsp. /etc/systemd/system/multi-user.target.wants/dovecot.service) ## - In der service datei (z.Bsp. /etc/systemd/system/multi-user.target.wants/dovecot.service)
## - den Wert 'LimitNOFILE' hochsetzen: ## - den Wert 'LimitNOFILE' hochsetzen:
## - ## -
@@ -1536,15 +1536,15 @@ fi
## - systemctl daemon-reload ## - systemctl daemon-reload
## - systemctl restart dovecot.service ## - systemctl restart dovecot.service
## - ## -
## - Im Falle von LX containern muss zusätzlich auf dem hostsystem ## - Im Falle von LX containern muss zusätzlich auf dem hostsystem
## - in der datei '/etc/systemd/system.conf' der Wert für 'DefaultLimitNOFILE' ## - in der datei '/etc/systemd/system.conf' der Wert für 'DefaultLimitNOFILE'
## - hochgesetzt werden. ## - hochgesetzt werden.
## - ## -
## - System V systems: ## - System V systems:
## - ================= ## - =================
## - Das Hochsetzen des default_client_limit Parameters auf einen Wert größer ## - Das Hochsetzen des default_client_limit Parameters auf einen Wert größer
## - als 1024 geht nur dann wenn auch die Anzahl der zulässigen "open files" ## - als 1024 geht nur dann wenn auch die Anzahl der zulässigen "open files"
## - (default = 1024) geändert wird. Z.Bsp. in der Datei /etc/init.d/dovecot ## - (default = 1024) geändert wird. Z.Bsp. in der Datei /etc/init.d/dovecot
## - durch Einfügen der zeile: ## - durch Einfügen der zeile:
## - ulimit -n 32768 ## - ulimit -n 32768
## - ## -
@@ -1596,10 +1596,10 @@ fi
## - address = $imaps_listener_adresses ## - address = $imaps_listener_adresses
## - .. ## - ..
## - } ## - }
## - ## -
## - process_min_avail = 16 ## - process_min_avail = 16
## - } ## - }
## - ## -
## - service pop3-login { ## - service pop3-login {
## - inet_listener pop3 { ## - inet_listener pop3 {
## - address = $pop_listener_adresses ## - address = $pop_listener_adresses
@@ -1678,7 +1678,7 @@ fi
## - permanently on filesystem. So we have to create such a file ## - permanently on filesystem. So we have to create such a file
## - ## -
## - openssl dhparam -out /etc/postfix/ssl/dh_4096.pem` ## - openssl dhparam -out /etc/postfix/ssl/dh_4096.pem`
## - ## -
if [[ $dovecot_major_version -ge 3 ]] \ if [[ $dovecot_major_version -ge 3 ]] \
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then || ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then
@@ -1687,7 +1687,7 @@ if [[ $dovecot_major_version -ge 3 ]] \
echo -en "$rc_wait" echo -en "$rc_wait"
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
openssl dhparam -out "$dh_pem_file" 4096 > /dev/null 2>&1 openssl dhparam -out "$dh_pem_file" 4096 > /dev/null 2>&1
else else
openssl dhparam -dsaparam -out "$dh_pem_file" 4096 > /dev/null 2>&1 openssl dhparam -dsaparam -out "$dh_pem_file" 4096 > /dev/null 2>&1
fi fi
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
@@ -1784,7 +1784,7 @@ fi
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf ## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
## - ## -
## - mail_location = maildir:/var/vmail/%d/%n/Maildir ## - mail_location = maildir:/var/vmail/%d/%n/Maildir
## - ## -
## - mail_uid = vmail ## - mail_uid = vmail
@@ -1794,7 +1794,7 @@ fi
## - last_valid_uid = 5000 ## - last_valid_uid = 5000
## - ## -
## - mail_temp_dir = /var/vmail/tmp ## - mail_temp_dir = /var/vmail/tmp
## - ## -
## - first_valid_gid = 5000 ## - first_valid_gid = 5000
## - last_valid_gid = 5000 ## - last_valid_gid = 5000
## - ## -
@@ -1842,7 +1842,7 @@ else
echo -e "$rc_failed" echo -e "$rc_failed"
fatal "Adjusting file '10-mail.conf' failed" fatal "Adjusting file '10-mail.conf' failed"
fi fi
echononl "\tCreate TEMP directory '/var/vmail/tmp' .." echononl "\tCreate TEMP directory '/var/vmail/tmp' .."
@@ -1937,7 +1937,7 @@ fi
## - ## -
## - Add namespaces type private ## - Add namespaces type private
## - ## -
## - Add: ## - Add:
## - namespace inbox { ## - namespace inbox {
## - type = private ## - type = private
## - separator = / ## - separator = /
@@ -1957,7 +1957,7 @@ namespace inbox {
# Hierarchy separator to use. You should use the same separator for all # Hierarchy separator to use. You should use the same separator for all
# namespaces or some clients get confused. '/' is usually a good one. # namespaces or some clients get confused. '/' is usually a good one.
# The default however depends on the underlying mail storage format. # The default however depends on the underlying mail storage format.
#separator = #separator =
separator = / separator = /
# Prefix required to access this namespace. This needs to be different for # Prefix required to access this namespace. This needs to be different for
@@ -2007,12 +2007,12 @@ fi
## - auto = subscribe ## - auto = subscribe
## - special_use = \Drafts ## - special_use = \Drafts
## - } ## - }
## - ## -
## - mailbox Trash { ## - mailbox Trash {
## - auto = subscribe ## - auto = subscribe
## - special_use = \Trash ## - special_use = \Trash
## - } ## - }
## - ## -
## - mailbox Sent { ## - mailbox Sent {
## - auto = subscribe ## - auto = subscribe
## - special_use = \Sent ## - special_use = \Sent
@@ -2072,7 +2072,7 @@ fi
## - ## -
## - disable_plaintext_auth = no ## - disable_plaintext_auth = no
## - auth_mechanisms = $auth_mechanisms ## - auth_mechanisms = $auth_mechanisms
## - !include auth-sql.conf.ext # comment all other includes ## - !include auth-sql.conf.ext # comment all other includes
## - auth_username_translation = "%@" ## - auth_username_translation = "%@"
## - ## -
_failed=false _failed=false
@@ -2101,14 +2101,14 @@ fi
## - ## -
## - passdb { ## - passdb {
## - driver = sql ## - driver = sql
## - ## -
## - ## -
## - # path for sql configuration file, see example-config/dovecot-sql.conf.ext ## - # path for sql configuration file, see example-config/dovecot-sql.conf.ext
## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext ## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
## - } ## - }
## - ## -
## - .. ## - ..
## - ## -
## - userdb { ## - userdb {
## - driver = sql ## - driver = sql
## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext ## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
@@ -2194,14 +2194,14 @@ fi
## - if running inetd-script: ## - if running inetd-script:
## - ## -
## - log_path = /var/log/dovecot/dovecot.log ## - log_path = /var/log/dovecot/dovecot.log
## - ## -
## - or for example ## - or for example
## - ## -
## - log_path = syslog ## - log_path = syslog
## - syslog_facility = local1 ## - syslog_facility = local1
## - auth_verbose = yes ## - auth_verbose = yes
## - auth_verbose_passwords = plain ## - auth_verbose_passwords = plain
## - ## -
## - in conjunction with the the following entries in /etc/rsyslog.conf ## - in conjunction with the the following entries in /etc/rsyslog.conf
## - ## -
## - local1.* -/var/log/dovecot.log ## - local1.* -/var/log/dovecot.log
@@ -2310,7 +2310,7 @@ fi
## - hostname = $hostname ## - hostname = $hostname
## - sendmail_path = /usr/sbin/sendmail ## - sendmail_path = /usr/sbin/sendmail
## - lda_mailbox_autocreate = no ## - lda_mailbox_autocreate = no
## - mail_plugins = $mail_plugins sieve ## - mail_plugins = $mail_plugins sieve
## - ## -
_failed=false _failed=false
echononl "\tAdjusting file 15-lda.conf" echononl "\tAdjusting file 15-lda.conf"
@@ -2406,7 +2406,7 @@ fi
## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-plugin.conf ## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-plugin.conf
## - ## -
## - Note: ## - Note:
## - Setting "autocreate", "autosubscribe" here is depricated. Use mailbox { auto } setting instead. ## - Setting "autocreate", "autosubscribe" here is depricated. Use mailbox { auto } setting instead.
## - ## -
## - expire = Trash ## - expire = Trash
## - expire2 = Trash/* ## - expire2 = Trash/*
@@ -2419,7 +2419,7 @@ fi
## - # it's better to enable it only after you've verified that the expire plugin is ## - # it's better to enable it only after you've verified that the expire plugin is
## - # working as wanted. (v2.2.16+) ## - # working as wanted. (v2.2.16+)
## - expire_cache = yes ## - expire_cache = yes
## - ## -
_failed=false _failed=false
echononl "\tAdjusting file 90-plugin.conf" echononl "\tAdjusting file 90-plugin.conf"
if $plugin_expire ; then if $plugin_expire ; then
@@ -2483,7 +2483,7 @@ while IFS='' read -r _line || [[ -n $_line ]] ; do
cat <<EOF >> "$_tmp_file" cat <<EOF >> "$_tmp_file"
# Add Setting 'sieve_vacation_send_from_recipient' from (included) # Add Setting 'sieve_vacation_send_from_recipient' from (included)
# #
# Pigeonhole Sieve: Vacation Extension # Pigeonhole Sieve: Vacation Extension
# ==================================== # ====================================
@@ -2563,7 +2563,7 @@ else
fi fi
## - NOTICE: if you pre-compile your (global) scripts, you will increase ## - NOTICE: if you pre-compile your (global) scripts, you will increase
## - performance ## - performance
## - ## -
echononl "\tPrecompile global sieve script" echononl "\tPrecompile global sieve script"
@@ -2597,12 +2597,14 @@ chown -R vmail:vmail /usr/local/dovecot-${_version}/etc/dovecot/sieve
if $systemd_support; then if $systemd_support; then
_folder_created=false
## - # - At time, we don't use private tmp directory for divecot. ## - # - At time, we don't use private tmp directory for divecot.
## - # - ## - # -
## - echononl "\tAdjust Systemd service file, set PrivateTmp=false.." ## - echononl "\tAdjust Systemd service file, set PrivateTmp=false.."
## - if [[ -f "/etc/systemd/system/dovecot.service" ]] ; then ## - if [[ -f "/etc/systemd/system/dovecot.service" ]] ; then
## - ## -
## - if $(grep -o -E "PrivateTmp\s*=\s*[^[:blank:]]+" /etc/systemd/system/dovecot.service | grep -q true 2> /dev/null ) ; then ## - if $(grep -o -E "PrivateTmp\s*=\s*[^[:blank:]]+" /etc/systemd/system/dovecot.service | grep -q true 2> /dev/null ) ; then
## - perl -i -n -p -e "s/(PrivateTmp\s*=\s*)true/\1false/" /etc/systemd/system/dovecot.service ## - perl -i -n -p -e "s/(PrivateTmp\s*=\s*)true/\1false/" /etc/systemd/system/dovecot.service
## - if [[ $? -eq 0 ]]; then ## - if [[ $? -eq 0 ]]; then
## - echo -e "$rc_done" ## - echo -e "$rc_done"
@@ -2620,9 +2622,16 @@ if $systemd_support; then
## - ## -
## - here: ## - here:
## - LimitNOFILE=32768 ## - LimitNOFILE=32768
## - ## -
if [[ -f "/lib/systemd/system/dovecot.service" ]] \ ## - zwei Bemerkungen:
&& $(grep -q -E "^LimitNOFILE=" /lib/systemd/system/dovecot.service) ; then ## - - keine runden Klammern notwendig, da die bash '&&' vor '||' auswertet
## - - hier auch keine backslah '\' am ende der zeile notwendig, da statement
## - offensichtlich noch nichzt abgeschlossen ist (die bash erkennt das)
## -
if [[ -f /lib/systemd/system/dovecot.service ]] &&
grep -qE '^[[:space:]]*LimitNOFILE=' /lib/systemd/system/dovecot.service ||
[[ -f /etc/systemd/system/dovecot.service ]] &&
grep -qE '^[[:space:]]*LimitNOFILE=' /etc/systemd/system/dovecot.service ; then
_LimitNOFILE="$(grep -E "^LimitNOFILE=[[:digit:]]+" /lib/systemd/system/dovecot.service | cut -d'=' -f2)" _LimitNOFILE="$(grep -E "^LimitNOFILE=[[:digit:]]+" /lib/systemd/system/dovecot.service | cut -d'=' -f2)"
@@ -2638,6 +2647,7 @@ if $systemd_support; then
mkdir "/etc/systemd/system/dovecot.service.d" > /dev/null 2>&1 mkdir "/etc/systemd/system/dovecot.service.d" > /dev/null 2>&1
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo -e "$rc_done" echo -e "$rc_done"
_folder_created=true
else else
echo -e "$rc_failed" echo -e "$rc_failed"
adjust_limit_nofile=false adjust_limit_nofile=false
@@ -2656,8 +2666,54 @@ LimitNOFILE=$service_limit_nofile
EOF EOF
echo -e "$rc_done" echo -e "$rc_done"
fi fi
fi fi
## - Adjust systemd hardening:
## -
## - Options such as ProtectSystem=full/strict make the service's mount namespace,
## - including /usr (and thus /usr/local/dovecote/..), read-only, even though it is w
## - ritable outside the service.
## -
## - However, we would like to allow dovecot to write to the directory
## - /usr/local/dovecot/etc/dovecot/sieve/.
## -
## - ProtectSystem=off
## -
## - zwei Bemerkungen:
## - - keine runden Klammern notwendig, da die bash '&&' vor '||' auswertet
## - - hier auch keine backslah '\' am ende der zeile notwendig, da statement
## - offensichtlich noch nichzt abgeschlossen ist (die bash erkennt das)
## -
if [[ -f /lib/systemd/system/dovecot.service ]] &&
grep -qE '^[[:space:]]*ProtectSystem=' /lib/systemd/system/dovecot.service ||
[[ -f /etc/systemd/system/dovecot.service ]] &&
grep -qE '^[[:space:]]*ProtectSystem=' /etc/systemd/system/dovecot.service ; then
if ! ${_folder_created} ; then
echononl "\tCreate Directory '/etc/systemd/system/dovecot.service.d'.."
if [[ -d "/etc/systemd/system/dovecot.service.d" ]] ; then
echo -e "$rc_skipped"
else
mkdir "/etc/systemd/system/dovecot.service.d" > /dev/null 2>&1
if [[ $? -eq 0 ]]; then
echo -e "$rc_done"
else
echo -e "$rc_failed"
fi
fi
fi
echononl "\tSet 'ProtectSystem=off' for 'dovecot.service'.."
cat <<EOF > /etc/systemd/system/dovecot.service.d/systemd-hardening.conf
[Service]
ProtectSystem=off
EOF
echo -e "$rc_done"
fi
echononl "\tReload systemd .." echononl "\tReload systemd .."
systemctl daemon-reload > /dev/null 2>&1 systemctl daemon-reload > /dev/null 2>&1
@@ -2692,7 +2748,7 @@ else
fi fi
fi fi
if $_new ; then if $_new ; then
@@ -2707,7 +2763,7 @@ if $_new ; then
## - running dovecot service via init-script ## - running dovecot service via init-script
## - ## -
cat <<EOF > /etc/init.d/dovecot cat <<EOF > /etc/init.d/dovecot
#! /bin/sh #! /bin/sh
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: dovecot # Provides: dovecot
# Required-Start: \$syslog \$postgresql # Required-Start: \$syslog \$postgresql
@@ -2899,7 +2955,7 @@ EOF
echo -e "$rc_failed" echo -e "$rc_failed"
fatal "Creating init script for dovecot failed" fatal "Creating init script for dovecot failed"
fi fi
chmod 755 /etc/init.d/dovecot chmod 755 /etc/init.d/dovecot
else else
@@ -2910,7 +2966,7 @@ EOF
fi fi
## - Add a cronjob to restart dovecot after booting the system. ## - Add a cronjob to restart dovecot after booting the system.
## - ## -
## - Notice: ## - Notice:
## - On normal start, dovecot started its service even if ipv6 is not ## - On normal start, dovecot started its service even if ipv6 is not
## - yet present and dovecot cannot bind to ipv6 listeners. ## - yet present and dovecot cannot bind to ipv6 listeners.
@@ -2964,10 +3020,10 @@ EOF
## - add/uncomment: ## - add/uncomment:
## - ## -
## - smtpd_tls_auth_only ## - smtpd_tls_auth_only
## - ## -
## - smtpd_sasl_type = dovecot ## - smtpd_sasl_type = dovecot
## - smtpd_sasl_path = private/dovecot-auth ## - smtpd_sasl_path = private/dovecot-auth
## - ## -
## - virtual_transport = dovecot ## - virtual_transport = dovecot
## - dovecot_destination_recipient_limit = 1 ## - dovecot_destination_recipient_limit = 1
## - ## -
@@ -3172,22 +3228,22 @@ echo -e "\033[1mConfigure quota support for dovecot\033[m"
## - take care quota plugins (quota,imap-quota) will ## - take care quota plugins (quota,imap-quota) will
## - be loaded: ## - be loaded:
## - ## -
## - there are two quota related plugins: ## - there are two quota related plugins:
## - ## -
## - * quota: implements the actual quota handling and includes also all the quota backends. ## - * quota: implements the actual quota handling and includes also all the quota backends.
## - * imap_quota: for reporting quota information via imap. ## - * imap_quota: for reporting quota information via imap.
## - ## -
## - enable them in configuration files, e.g.: ## - enable them in configuration files, e.g.:
## - ## -
## - conf.d/10-mail.conf: ## - conf.d/10-mail.conf:
## - ## -
## - # space separated list of plugins to load for all services. plugins specific to ## - # space separated list of plugins to load for all services. plugins specific to
## - # imap, lda, etc. are added to this list in their own .conf files. ## - # imap, lda, etc. are added to this list in their own .conf files.
## - mail_plugins = $mail_plugins quota ## - mail_plugins = $mail_plugins quota
## - ## -
## - conf.d/20-imap.conf: ## - conf.d/20-imap.conf:
## - ## -
## - protocol imap { ## - protocol imap {
## - # space separated list of plugins to load (default is global mail_plugins). ## - # space separated list of plugins to load (default is global mail_plugins).
## - mail_plugins = $mail_plugins imap_quota ## - mail_plugins = $mail_plugins imap_quota
@@ -3222,7 +3278,7 @@ fi
## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf ## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf
## - ## -
## - add: ## - add:
## - ## -
## - dict { ## - dict {
@@ -3369,7 +3425,7 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
# END IF; # END IF;
# return NEW; # return NEW;
# END IF; # END IF;
# #
# LOOP # LOOP
# UPDATE quota2 SET bytes = bytes + NEW.bytes, # UPDATE quota2 SET bytes = bytes + NEW.bytes,
# messages = messages + NEW.messages # messages = messages + NEW.messages
@@ -3377,7 +3433,7 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
# IF found THEN # IF found THEN
# RETURN NULL; # RETURN NULL;
# END IF; # END IF;
# #
# BEGIN # BEGIN
# IF NEW.messages = 0 THEN # IF NEW.messages = 0 THEN
# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username); # INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username);
@@ -3391,10 +3447,10 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
# END LOOP; # END LOOP;
# END; # END;
# \$\$; # \$\$;
# #
# #
# ALTER FUNCTION public.merge_quota2() OWNER TO postfix; # ALTER FUNCTION public.merge_quota2() OWNER TO postfix;
# #
# CREATE TRIGGER mergequota2 # CREATE TRIGGER mergequota2
# BEFORE INSERT ON quota2 # BEFORE INSERT ON quota2
# FOR EACH ROW # FOR EACH ROW
@@ -3444,7 +3500,7 @@ EOF
# END IF; # END IF;
# END; # END;
# \$\$ LANGUAGE plpgsql; # \$\$ LANGUAGE plpgsql;
# #
# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires # CREATE TRIGGER mergeexpires BEFORE INSERT ON expires
# FOR EACH ROW EXECUTE PROCEDURE merge_expires(); # FOR EACH ROW EXECUTE PROCEDURE merge_expires();
@@ -3473,7 +3529,7 @@ EOF
fi fi
## - you also have to update the userdb's query in file ## - you also have to update the userdb's query in file
## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to ## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to
## - support extra variable "quota_rule" ## - support extra variable "quota_rule"
## - ## -
echononl "\tRenew file sql-connect.conf.ext" echononl "\tRenew file sql-connect.conf.ext"
@@ -3570,7 +3626,7 @@ EOF
fi fi
## - you also have to update the userdb's query in file ## - you also have to update the userdb's query in file
## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to ## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to
## - support extra variable "quota_rule" ## - support extra variable "quota_rule"
## - ## -
echononl "\tRenew file sql-connect.conf.ext" echononl "\tRenew file sql-connect.conf.ext"
@@ -3697,20 +3753,20 @@ fi
## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-quota.conf ## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-quota.conf
## - ## -
## - add to the end of file or in seperate plugin-blocks ## - add to the end of file or in seperate plugin-blocks
## - as designed in that file: ## - as designed in that file:
## - plugin { ## - plugin {
## - # sql backend: ## - # sql backend:
## - quota = dict:user quota::proxy::quota ## - quota = dict:user quota::proxy::quota
## - ## -
## - quota_rule = *:storage=1g ## - quota_rule = *:storage=1g
## - quota_rule2 = trash:storage=+100m ## - quota_rule2 = trash:storage=+100m
## - ## -
## - quota_warning = storage=80%% quota-warning 80 %u ## - quota_warning = storage=80%% quota-warning 80 %u
## - quota_warning2 = storage=95%% quota-warning 95 %u ## - quota_warning2 = storage=95%% quota-warning 95 %u
## - } ## - }
## - ## -
## - service quota-warning { ## - service quota-warning {
## - executable = script /usr/local/bin/quota-warning.sh ## - executable = script /usr/local/bin/quota-warning.sh
## - user = vmail ## - user = vmail
@@ -3725,7 +3781,7 @@ cp -a /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf \
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf.ORIG /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf.ORIG
cat <<EOF >>/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf cat <<EOF >>/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf
## - ## -
plugin { plugin {
# SQL backend: # SQL backend:
quota = dict:User quota::proxy::quota quota = dict:User quota::proxy::quota
@@ -3832,7 +3888,7 @@ fi
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf ## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
## - ## -
## - Add namespaces type shared to 10-mail.conf ## - Add namespaces type shared to 10-mail.conf
## - Take care to enable ACL plugin also, otherwise all users can access all the shared ## - Take care to enable ACL plugin also, otherwise all users can access all the shared
## - mailboxes, assuming they have permissions on filesystem level to do so. ## - mailboxes, assuming they have permissions on filesystem level to do so.
## - we will do that later.. ## - we will do that later..
## - namespace { ## - namespace {
@@ -3894,7 +3950,7 @@ else
fi fi
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf ## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
## - ## -
## - mail_plugins = quota expire acl ## - mail_plugins = quota expire acl
## - ## -
_failed=false _failed=false
@@ -3961,7 +4017,7 @@ fi
## - ## -
## - plugin { ## - plugin {
## - ## acl = vfile:/etc/dovecot/global-acls:cache_secs=300 ## - ## acl = vfile:/etc/dovecot/global-acls:cache_secs=300
## - ## -
## - # Without global ACLs: ## - # Without global ACLs:
## - acl = vfile ## - acl = vfile
## - .. ## - ..
@@ -4094,8 +4150,8 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
## - NOTE: ## - NOTE:
## - ## -
## - All changes on database (CREATE TABLE / CREATE TRIGGER / what else..) ## - All changes on database (CREATE TABLE / CREATE TRIGGER / what else..)
## - need to be done as the dbuser (here postfix) under whom dovecot ## - need to be done as the dbuser (here postfix) under whom dovecot
## - accesses the database. If not, you have to change the permissiond to allow ## - accesses the database. If not, you have to change the permissiond to allow
## - dovecot dbuser to access the createt table/trigger/... ## - dovecot dbuser to access the createt table/trigger/...
## - ## -
@@ -4125,7 +4181,7 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
# END IF; # END IF;
# return NEW; # return NEW;
# END IF; # END IF;
# #
# LOOP # LOOP
# UPDATE quota2 SET bytes = bytes + NEW.bytes, # UPDATE quota2 SET bytes = bytes + NEW.bytes,
# messages = messages + NEW.messages # messages = messages + NEW.messages
@@ -4133,7 +4189,7 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
# IF found THEN # IF found THEN
# RETURN NULL; # RETURN NULL;
# END IF; # END IF;
# #
# BEGIN # BEGIN
# IF NEW.messages = 0 THEN # IF NEW.messages = 0 THEN
# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username); # INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username);
@@ -4147,10 +4203,10 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
# END LOOP; # END LOOP;
# END; # END;
# \$\$; # \$\$;
# #
# #
# ALTER FUNCTION public.merge_quota2() OWNER TO postfix; # ALTER FUNCTION public.merge_quota2() OWNER TO postfix;
# #
# CREATE TRIGGER mergequota2 # CREATE TRIGGER mergequota2
# BEFORE INSERT ON quota2 # BEFORE INSERT ON quota2
# FOR EACH ROW # FOR EACH ROW
@@ -4200,7 +4256,7 @@ EOF
# END IF; # END IF;
# END; # END;
# \$\$ LANGUAGE plpgsql; # \$\$ LANGUAGE plpgsql;
# #
# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires # CREATE TRIGGER mergeexpires BEFORE INSERT ON expires
# FOR EACH ROW EXECUTE PROCEDURE merge_expires(); # FOR EACH ROW EXECUTE PROCEDURE merge_expires();
@@ -4230,7 +4286,7 @@ EOF
# primary key (from_user, to_user) # primary key (from_user, to_user)
# ); # );
# COMMENT ON TABLE user_shares IS 'User from_user shares folders to user to_user.'; # COMMENT ON TABLE user_shares IS 'User from_user shares folders to user to_user.';
# #
# CREATE TABLE anyone_shares ( # CREATE TABLE anyone_shares (
# from_user varchar(100) not null, # from_user varchar(100) not null,
# dummy char(1) DEFAULT '1', -- always '1' currently # dummy char(1) DEFAULT '1', -- always '1' currently
@@ -4336,7 +4392,7 @@ EOF
# dummy char(1) DEFAULT '1', -- always '1' currently # dummy char(1) DEFAULT '1', -- always '1' currently
# primary key (from_user, to_user) # primary key (from_user, to_user)
# ) COMMENT = 'User from_user shares folders to user to_user.'; # ) COMMENT = 'User from_user shares folders to user to_user.';
# #
# CREATE TABLE anyone_shares ( # CREATE TABLE anyone_shares (
# from_user varchar(100) not null, # from_user varchar(100) not null,
# dummy char(1) DEFAULT '1', -- always '1' currently # dummy char(1) DEFAULT '1', -- always '1' currently
@@ -4576,7 +4632,7 @@ fi
blank_line blank_line
echononl "\tSet '_update=true' in file '$(basename "$conf_file")'.." echononl "\tSet '_update=true' in file '$(basename "$conf_file")'.."
if grep -q -E "^\s*_update=false" "$conf_file" 2> /dev/null ; then if grep -q -E "^\s*_update=false" "$conf_file" 2> /dev/null ; then
perl -i -n -p -e "s/^\s*_update=.*/_update=true/" "$conf_file" perl -i -n -p -e "s/^\s*_update=.*/_update=true/" "$conf_file"
if [ "$?" = 0 ]; then if [ "$?" = 0 ]; then
echo -e "$rc_done" echo -e "$rc_done"
else else

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -euo pipefail
CONF="/etc/postfix-policyd-spf-python/policyd-spf.conf"
BACKUP="${CONF}.$(date +%Y%m%d-%H%M%S).bak"
if [[ ! -f "$CONF" ]]; then
echo "ERROR: Config not found: $CONF" >&2
exit 1
fi
cp -a -- "$CONF" "$BACKUP"
ensure_kv() {
local key="$1"
local value="$2"
# Prüfen ob es eine AKTIVE (nicht auskommentierte) Zeile gibt
if grep -Eq "^[[:space:]]*${key}[[:space:]]*=" "$CONF"; then
# Nur erste aktive Zeile ersetzen
sed -ri "0,/^[[:space:]]*${key}[[:space:]]*=.*/s//${key} = ${value}/" "$CONF"
else
# Anfügen mit Leerzeile + Kommentar
cat >>"$CONF" <<EOF
# --- Mailinglist-friendly SPF policy (added by script) ---
${key} = ${value}
EOF
fi
}
ensure_kv "HELO_reject" "False"
ensure_kv "Mail_From_reject" "False"
ensure_kv "PermError_reject" "False"
ensure_kv "TempError_Defer" "True"
echo "Updated: $CONF"
echo "Backup : $BACKUP"
exit

285
set_amavis_local_domains_maps.sh Executable file
View File

@@ -0,0 +1,285 @@
#!/usr/bin/env bash
# amavis-local-domains-auto.sh
#
# Zweck
# -----
# Ersetzt in /etc/amavis/conf.d/50-user die lokale Domains-Definition
#
# @local_domains_maps = ( ["."] );
#
# durch eine dynamische Definition, die aus der (effektiv aktiven) Postfix-
# Konfiguration ermittelt wird (pgsql oder mysql). Damit werden Spam-Header
# nur für Domains geschrieben, die Postfix tatsächlich als "lokal/relay" kennt.
#
# WICHTIG:
# - Das Skript ändert NUR dann etwas, wenn die Zeile exakt ( ["."] ); ist.
# - Backups werden IMMER nach /etc/amavis/ geschrieben (nicht neben die Datei).
# - DB-Typ wird automatisch aus "postconf -n" erkannt (robust inkl. includes).
#
# Features
# --------
# - Auto-Detect Backend: pgsql | mysql (aus Postfix-Maps)
# - Optionaler Fallback: wenn DB nicht erkennbar, dann auf ( ["."] ); setzen
# (standardmäßig AUS, weil produktiver Betrieb)
# - Dry-run Modus
# - Optional reload/restart von amavis
# - Atomare Aktualisierung (schreibt erst tmp, dann mv)
#
# Nutzung
# -------
# sudo ./amavis-local-domains-auto.sh --dry-run
# sudo ./amavis-local-domains-auto.sh --apply --reload
# sudo ./amavis-local-domains-auto.sh --apply --restart
#
# Optional:
# sudo ./amavis-local-domains-auto.sh --apply --allow-fallback-all
#
set -euo pipefail
# ----------------------------
# Konfigurierbare Pfade
# ----------------------------
AMAVIS_50="${AMAVIS_50:-/etc/amavis/conf.d/50-user}"
# Backup-Verzeichnis (gewünscht: /etc/amavis/)
BACKUP_DIR="${BACKUP_DIR:-/etc/amavis}"
# Optional: Dateimap für relay_domains (falls vorhanden)
RELAY_BTREE_DEFAULT="/etc/postfix/relay_domains"
# ----------------------------
# Schalter / Optionen
# ----------------------------
DO_APPLY=false
DO_DRY_RUN=false
DO_RESTART=false
DO_RELOAD=false
ALLOW_FALLBACK_ALL=false
# Optional overrides
HOST_FQDN_OVERRIDE=""
RELAY_BTREE_OVERRIDE=""
usage() {
cat <<'EOF'
Usage:
amavis-local-domains-auto.sh [OPTIONS]
Options:
--dry-run Show what would change, do not modify files
--apply Apply change (only if @local_domains_maps is exactly ( ["."] );)
--restart Restart amavis after apply
--reload Reload amavis after apply (preferred if supported)
--allow-fallback-all If DB backend not detectable, replace with ( ["."] ); anyway
(default: fail safely / do nothing)
--host-fqdn FQDN Override hostname -f used in the block
--relay-btree PATH Override btree file path (default: /etc/postfix/relay_domains)
-h, --help Show this help
Examples:
sudo ./amavis-local-domains-auto.sh --dry-run
sudo ./amavis-local-domains-auto.sh --apply --reload
EOF
}
die(){ echo "ERROR: $*" >&2; exit 1; }
log(){ echo "INFO: $*" >&2; }
# ----------------------------
# Argumente parsen
# ----------------------------
while [[ $# -gt 0 ]]; do
case "$1" in
--dry-run) DO_DRY_RUN=true; shift ;;
--apply) DO_APPLY=true; shift ;;
--restart) DO_RESTART=true; shift ;;
--reload) DO_RELOAD=true; shift ;;
--allow-fallback-all) ALLOW_FALLBACK_ALL=true; shift ;;
--host-fqdn) HOST_FQDN_OVERRIDE="${2:-}"; shift 2 ;;
--relay-btree) RELAY_BTREE_OVERRIDE="${2:-}"; shift 2 ;;
-h|--help) usage; exit 0 ;;
*) die "Unknown option: $1" ;;
esac
done
if ! $DO_DRY_RUN && ! $DO_APPLY; then
die "Choose one: --dry-run or --apply"
fi
if $DO_RESTART && $DO_RELOAD; then
die "Choose only one: --restart or --reload"
fi
# ----------------------------
# Sanity Checks
# ----------------------------
command -v postconf >/dev/null || die "postconf not found"
[[ -r "$AMAVIS_50" ]] || die "Missing $AMAVIS_50"
[[ -d "$BACKUP_DIR" ]] || die "Backup dir missing: $BACKUP_DIR"
[[ -w "$BACKUP_DIR" ]] || die "Backup dir not writable: $BACKUP_DIR"
HOST_FQDN="${HOST_FQDN_OVERRIDE:-$(hostname -f 2>/dev/null || hostname)}"
RELAY_BTREE="${RELAY_BTREE_OVERRIDE:-$RELAY_BTREE_DEFAULT}"
# Regex: exakt @local_domains_maps = ( ["."] );
DOTLINE_REGEX='^[[:space:]]*@local_domains_maps[[:space:]]*=[[:space:]]*\([[:space:]]*\[[[:space:]]*"\."[[:space:]]*\][[:space:]]*\)[[:space:]]*;[[:space:]]*$'
if ! grep -qE "$DOTLINE_REGEX" "$AMAVIS_50"; then
log "No change: @local_domains_maps is not exactly ( [\".\"] );"
exit 0
fi
# ----------------------------
# DB-Typ + Map-Dateien aus Postfix ermitteln
# (postconf -n berücksichtigt includes, master.d, etc.)
# ----------------------------
VMD_LINE="$(postconf -n virtual_mailbox_domains 2>/dev/null || true)"
RD_LINE="$(postconf -n relay_domains 2>/dev/null || true)"
extract_db_map() {
# Findet den ersten Token, der :pgsql: oder :mysql: enthält
# und gibt "scheme|/path/to/map.cf" aus.
local line="$1"
for tok in $line; do
tok="${tok%,}"
if [[ "$tok" == *":pgsql:"* ]]; then
echo "pgsql|${tok##*:pgsql:}"
return 0
elif [[ "$tok" == *":mysql:"* ]]; then
echo "mysql|${tok##*:mysql:}"
return 0
fi
done
return 1
}
DB_SCHEME=""
VDOM_CF=""
RELAY_CF=""
if out="$(extract_db_map "$VMD_LINE")"; then
DB_SCHEME="${out%%|*}"
VDOM_CF="${out##*|}"
else
if $ALLOW_FALLBACK_ALL; then
DB_SCHEME="all"
else
die "Could not detect pgsql/mysql from postfix virtual_mailbox_domains. Use --allow-fallback-all to force."
fi
fi
if [[ "$DB_SCHEME" != "all" ]]; then
if out="$(extract_db_map "$RD_LINE")"; then
rd_scheme="${out%%|*}"
rd_cf="${out##*|}"
if [[ "$rd_scheme" == "$DB_SCHEME" ]]; then
RELAY_CF="$rd_cf"
fi
fi
[[ -r "$VDOM_CF" ]] || die "Detected map not readable: $VDOM_CF"
if [[ -n "$RELAY_CF" ]]; then
[[ -r "$RELAY_CF" ]] || die "Detected relay map not readable: $RELAY_CF"
fi
fi
# ----------------------------
# Replacement-Block bauen (in temp Datei)
# ----------------------------
TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT
BLOCKFILE="$TMPDIR/block.txt"
if [[ "$DB_SCHEME" == "all" ]]; then
cat >"$BLOCKFILE" <<'EOF'
@local_domains_maps = ( ["."] );
EOF
else
{
echo "@local_domains_maps = ("
echo " [qw(${HOST_FQDN} localhost)],"
echo ""
echo " # Domains, die als virtuelle Mailbox-Domains gehostet sind:"
echo " '${DB_SCHEME}:${VDOM_CF}',"
if [[ -n "$RELAY_CF" ]]; then
echo ""
echo " # Domains, die als relay_domains akzeptiert werden:"
echo " '${DB_SCHEME}:${RELAY_CF}',"
else
echo ""
echo " # relay_domains DB-map nicht erkannt wird übersprungen"
fi
echo " 'btree:${RELAY_BTREE}',"
echo ");"
} >"$BLOCKFILE"
fi
# ----------------------------
# Geplante Änderung anzeigen
# ----------------------------
log "Detected backend: ${DB_SCHEME}"
if [[ "$DB_SCHEME" != "all" ]]; then
log "virtual_mailbox_domains map: ${DB_SCHEME}:${VDOM_CF}"
if [[ -n "$RELAY_CF" ]]; then
log "relay_domains map: ${DB_SCHEME}:${RELAY_CF}"
else
log "relay_domains map: (not detected / not used)"
fi
log "btree relay domains: btree:${RELAY_BTREE}"
fi
if $DO_DRY_RUN; then
echo "----- Would replace this line in $AMAVIS_50 -----"
echo '@local_domains_maps = ( ["."] );'
echo "----- With this block -----"
cat "$BLOCKFILE"
exit 0
fi
# ----------------------------
# Backup in /etc/amavis/ erstellen
# ----------------------------
STAMP="$(date +%F_%H%M%S)"
BACKUP_FILE="${BACKUP_DIR}/50-user.bak.${STAMP}"
cp -a "$AMAVIS_50" "$BACKUP_FILE"
log "Backup created: $BACKUP_FILE"
# ----------------------------
# Datei neu schreiben (atomar)
# - Wir ersetzen nur die exakt passende (["."]) Zeile durch den neuen Block.
# ----------------------------
OUTFILE="$TMPDIR/50-user.new"
awk -v blockfile="$BLOCKFILE" '
BEGIN {
while ((getline line < blockfile) > 0) {
newblock = newblock line "\n"
}
close(blockfile)
}
{
if ($0 ~ /^[[:space:]]*@local_domains_maps[[:space:]]*=[[:space:]]*\([[:space:]]*\[[[:space:]]*"\."[[:space:]]*\][[:space:]]*\)[[:space:]]*;[[:space:]]*$/) {
printf "%s", newblock
} else {
print
}
}
' "$AMAVIS_50" > "$OUTFILE"
mv "$OUTFILE" "$AMAVIS_50"
log "Updated $AMAVIS_50"
# ----------------------------
# Optionaler Reload/Restart von amavis
# ----------------------------
if $DO_RELOAD; then
log "Reloading amavis..."
systemctl reload amavis || die "amavis reload failed"
elif $DO_RESTART; then
log "Restarting amavis..."
systemctl restart amavis || die "amavis restart failed"
else
log "No service action requested (--reload/--restart)."
fi
log "Done."