11100 lines
320 KiB
Bash
Executable File
11100 lines
320 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
|
||
## ===================================================================
|
||
## - Install/Update Dovecot Server
|
||
## ===================================================================
|
||
|
||
|
||
## -----------------------------------------------------------------
|
||
## ----------------------------------------------------------------
|
||
## ---
|
||
## --- For configurations see file conf/install_update_dovecot.conf
|
||
## ---
|
||
## --- Dont make changes here!
|
||
## ---
|
||
## -----------------------------------------------------------------
|
||
## -----------------------------------------------------------------
|
||
|
||
# -------------
|
||
# - Settings
|
||
# -------------
|
||
|
||
_src_base_dir="$(realpath $(dirname $0))"
|
||
conf_file="${_src_base_dir}/conf/install_update_dovecot.conf"
|
||
curdir=`pwd`
|
||
|
||
log_file="$(mktemp)"
|
||
|
||
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||
|
||
_backup_crontab_file="/tmp/crontab_root.${backup_date}"
|
||
|
||
rc_done="\033[71G[ \033[32mdone\033[m ]"
|
||
rc_failed="\033[71G[ \033[31m\033[1mfailed\033[m ]"
|
||
#rc_skipped="\033[71G[ \033[33m\033[1mskipped\033[m ]"
|
||
rc_skipped="\033[71G[ \033[1;37mskipped\033[m ]"
|
||
rc_wait="\033[71G[ \033[5m\033[1m..\033[m ]"
|
||
|
||
rc_not_yet_implemented="\033[71G[ \033[1;33mNot Yet Implemented\033[m ]"
|
||
rc_already_done="\033[71G[ \033[32mAlready Done\033[m ]"
|
||
rc_not_needed_anymore="\033[71G[ \033[1;37mNot Needed Anymore\033[m ]"
|
||
|
||
|
||
# -------------
|
||
# - Functions an Variable
|
||
# -------------
|
||
clean_up() {
|
||
|
||
|
||
if [[ -f "$_backup_crontab_file" ]]; then
|
||
|
||
echononl "(Re)Install previously saved crontab from '$_backup_crontab_file'.."
|
||
|
||
crontab $_backup_crontab_file >> $log_file 2>&1
|
||
|
||
if [[ $? -eq 0 ]]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
fi
|
||
|
||
fi
|
||
|
||
# Perform program exit housekeeping
|
||
rm -f $log_file
|
||
blank_line
|
||
exit $1
|
||
}
|
||
|
||
|
||
echononl(){
|
||
echo X\\c > /tmp/shprompt$$
|
||
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
|
||
echo -e "$*\\c" 1>&2
|
||
else
|
||
echo -en "$*" 1>&2
|
||
fi
|
||
rm /tmp/shprompt$$
|
||
}
|
||
|
||
fatal(){
|
||
echo ""
|
||
echo -e "\t[ \033[31m\033[1mFatal\033[m ]: \033[37m\033[1m$*\033[m"
|
||
echo ""
|
||
echo -e "\t\033[31m\033[1m Skript wird abgebrochen\033[m\033[m\n"
|
||
rm -f $log_file
|
||
clean_up 1
|
||
}
|
||
|
||
error(){
|
||
echo ""
|
||
echo -e "\t[ \033[31m\033[1mError\033[m ]: $*"
|
||
echo ""
|
||
}
|
||
|
||
warn(){
|
||
echo ""
|
||
echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*"
|
||
echo ""
|
||
}
|
||
|
||
info(){
|
||
echo ""
|
||
echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*"
|
||
echo ""
|
||
}
|
||
|
||
|
||
blank_line() {
|
||
echo ""
|
||
}
|
||
|
||
echo_ok() {
|
||
echo -e "\033[71G[ \033[32mok\033[m ]"
|
||
}
|
||
echo_failed(){
|
||
echo -e "\033[71G[ \033[1;31mfailed\033[m ]"
|
||
}
|
||
echo_skipped() {
|
||
echo -e "\033[71G[ \033[37m\033[1mskipped\033[m ]"
|
||
}
|
||
|
||
detect_os_1 () {
|
||
|
||
if $(which lsb_release > /dev/null 2>&1) ; then
|
||
|
||
os_dist="$(lsb_release -i | awk '{print tolower($3)}')"
|
||
os_version="$(lsb_release -r | awk '{print tolower($2)}')"
|
||
os_codename="$(lsb_release -c | awk '{print tolower($2)}')"
|
||
|
||
if [[ "$os_dist" = "debian" ]]; then
|
||
if $(echo "$os_version" | grep -q '\.') ; then
|
||
os_version=$(echo "$os_version" | cut --delimiter='.' -f1)
|
||
fi
|
||
fi
|
||
|
||
elif [[ -e "/etc/os-release" ]]; then
|
||
|
||
. /etc/os-release
|
||
|
||
os_dist=$ID
|
||
os_version=${VERSION_ID}
|
||
|
||
fi
|
||
|
||
# remove whitespace from os_dist and os_version
|
||
os_dist="${os_dist// /}"
|
||
os_version="${os_version// /}"
|
||
|
||
}
|
||
|
||
replace_code_block() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_dovecot_block \"blockname\" \"neuer_block\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 1
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
print new_block
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
}
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
return 0
|
||
}
|
||
|
||
replace_or_append_code_block() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_dovecot_block \"blockname\" \"neuer_block\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
local block_found=0
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
print new_block
|
||
block_found = 1
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
}
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
|
||
END {
|
||
if (!block_found) {
|
||
print new_block > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" 1>"$tmp_file" 2>_new_block_to_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
# Block nicht gefunden neuen Block anhängen
|
||
echo "" >> "$file"
|
||
cat _new_block_to_append.tmp >> "$file"
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde nicht gefunden und deshalb am Ende der Datei angehängt."
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde ersetzt."
|
||
return 0
|
||
}
|
||
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# Funktion: replace_or_append_code_block_if_keyval
|
||
#
|
||
# Beschreibung:
|
||
# Ersetzt einen benannten Codeblock in einer Konfigurationsdatei durch einen
|
||
# neuen Block, **aber nur**, wenn im Hauptblock (nicht in Unterblöcken)
|
||
# ein bestimmtes Key-Value-Paar (z. B. "type = shared") vorhanden ist.
|
||
#
|
||
# Wenn kein passender Block gefunden wird (also kein Block mit dem Namen existiert),
|
||
# wird der neue Block **am Ende der Datei angehängt**.
|
||
#
|
||
# Wenn der Block vorhanden ist, das Key-Value-Paar aber **nicht** mit dem
|
||
# erwarteten Wert übereinstimmt, bleibt der Originalblock **unverändert**
|
||
# und der neue Block wird trotzdem **angehängt**.
|
||
#
|
||
# Parameter:
|
||
# $1 - Name des Blocks (z. B. "mailbox INBOX")
|
||
# $2 - Neuer Blockinhalt (als String)
|
||
# $3 - Pfad zur Datei, in der der Block ersetzt werden soll
|
||
# $4 - Schlüssel, nach dem im Hauptblock gesucht werden soll
|
||
# $5 - Erwarteter Wert des Schlüssels
|
||
#
|
||
# Rückgabewerte:
|
||
# 0 - Erfolgreich ersetzt oder angehängt
|
||
# 1 - Ungültige Parameter
|
||
# 2 - Datei existiert nicht
|
||
# 3 - Kein passender Block gefunden → wurde angehängt
|
||
#
|
||
# Hinweise:
|
||
# - Die Prüfung auf key = value erfolgt nur auf oberster Blockebene.
|
||
# - Diese Funktion ist großzügiger als "replace_code_block_if_keyval_strict":
|
||
# Sie ersetzt, wenn Bedingung erfüllt ist – hängt aber auch an, wenn nicht.
|
||
# ------------------------------------------------------------------------------
|
||
replace_or_append_code_block_if_keyval() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
local required_key="$4"
|
||
local required_value="$5"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" || -z "$required_key" || -z "$required_value" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_or_append_code_block_if_keyval \"blockname\" \"neuer_block\" \"/pfad/zur/datei\" \"key\" \"value\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
local block_found=0
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" \
|
||
-v req_key="$required_key" -v req_val="$required_value" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = $0 "\n"
|
||
found_keyval = 0
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = block_buffer $0 "\n"
|
||
|
||
# Prüfe nur im obersten Block-Level auf key = value
|
||
if (brace_depth == 1 && $0 ~ "^\\s*" req_key "\\s*=\\s*" req_val "\\s*$") {
|
||
found_keyval = 1
|
||
}
|
||
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
if (found_keyval) {
|
||
print new_block
|
||
block_found = 1
|
||
} else {
|
||
printf "%s", block_buffer
|
||
}
|
||
next
|
||
}
|
||
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
|
||
END {
|
||
if (!block_found) {
|
||
print new_block > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" 1>"$tmp_file" 2>_new_block_to_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
echo "" >> "$file"
|
||
cat _new_block_to_append.tmp >> "$file"
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde nicht gefunden oder Bedingung nicht erfüllt und daher am Ende angehängt."
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde ersetzt (Bedingung erfüllt)."
|
||
return 0
|
||
}
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# Funktion: replace_code_block_if_keyval
|
||
#
|
||
# Beschreibung:
|
||
# Ersetzt einen benannten Codeblock in einer Konfigurationsdatei durch einen
|
||
# neuen Block, aber **nur**, wenn innerhalb des Hauptblocks (nicht in Unterblöcken)
|
||
# ein bestimmtes Key-Value-Paar vorhanden ist (z.B. "type = shared").
|
||
#
|
||
# Wenn der Block nicht vorhanden ist oder das Key-Value-Paar nicht übereinstimmt,
|
||
# wird **nichts verändert**.
|
||
#
|
||
# Parameter:
|
||
# $1 - Name des Blocks (z.B. "mailbox INBOX")
|
||
# $2 - Neuer Blockinhalt (als String)
|
||
# $3 - Pfad zur Datei, in der der Block ersetzt werden soll
|
||
# $4 - Schlüssel, nach dem im Hauptblock gesucht werden soll
|
||
# $5 - Erwarteter Wert des Schlüssels
|
||
#
|
||
# Rückgabewert:
|
||
# 0 - Erfolgreich ersetzt oder keine Änderung nötig
|
||
# 1 - Ungültige Parameter
|
||
# 2 - Datei existiert nicht
|
||
#
|
||
# Hinweis:
|
||
# Der neue Block muss korrekt formatiert sein (einschließlich öffnender Klammer).
|
||
# Der Block wird **nicht** angehängt, falls er fehlt oder die Bedingung nicht zutrifft.
|
||
# ------------------------------------------------------------------------------
|
||
replace_code_block_if_keyval() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
local required_key="$4"
|
||
local required_value="$5"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" || -z "$required_key" || -z "$required_value" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_code_block_if_keyval \"blockname\" \"neuer_block\" \"/pfad/zur/datei\" \"key\" \"value\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" \
|
||
-v req_key="$required_key" -v req_val="$required_value" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = $0 "\n"
|
||
found_keyval = 0
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = block_buffer $0 "\n"
|
||
|
||
# Nur im Hauptblock prüfen
|
||
if (brace_depth == 1 && $0 ~ "^\\s*" req_key "\\s*=\\s*" req_val "\\s*$") {
|
||
found_keyval = 1
|
||
}
|
||
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
if (found_keyval) {
|
||
print new_block
|
||
} else {
|
||
printf "%s", block_buffer
|
||
}
|
||
next
|
||
}
|
||
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Ersetzung abgeschlossen (nur wenn Bedingung erfüllt war)."
|
||
return 0
|
||
}
|
||
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# Funktion: replace_or_appen_dcode_block_if_keyval_strict
|
||
#
|
||
# Beschreibung:
|
||
# Ersetzt einen benannten Codeblock in einer Konfigurationsdatei durch einen
|
||
# neuen Block, aber **nur**, wenn innerhalb des Hauptblocks ein bestimmtes
|
||
# Key-Value-Paar (z. B. "type = shared") vorhanden ist.
|
||
#
|
||
# Wenn ein Block mit dem gesuchten Namen vorhanden ist, der angegebene Key aber
|
||
# einen **abweichenden Wert** hat (z. B. "type = private"), wird **nichts verändert**
|
||
# und der Block **wird nicht ersetzt und nicht angehängt**.
|
||
#
|
||
# Wenn kein passender Block vorhanden ist (also weder mit noch ohne Key),
|
||
# wird der neue Block **am Ende der Datei angehängt**.
|
||
#
|
||
# Parameter:
|
||
# $1 - Name des Blocks (z. B. "mailbox INBOX")
|
||
# $2 - Neuer Blockinhalt (als String)
|
||
# $3 - Pfad zur Datei, in der der Block ersetzt werden soll
|
||
# $4 - Schlüssel, nach dem im Hauptblock gesucht werden soll
|
||
# $5 - Erwarteter Wert des Schlüssels
|
||
#
|
||
# Rückgabewerte:
|
||
# 0 - Block ersetzt oder angehängt oder keine Änderung (weil Bedingung nicht erfüllt)
|
||
# 1 - Ungültige Parameter
|
||
# 2 - Datei existiert nicht
|
||
# 3 - Kein Block gefunden → wurde am Ende angehängt
|
||
# 4 - Block gefunden, aber Bedingung nicht erfüllt → keine Änderung vorgenommen
|
||
#
|
||
# Hinweise:
|
||
# - Die Bedingung wird nur im äußeren Block-Level geprüft (nicht in Unterblöcken).
|
||
# - Falls du mehrere Bedingungen prüfen willst, muss die Funktion erweitert werden.
|
||
# ------------------------------------------------------------------------------
|
||
replace_or_append_code_block_if_keyval_strict() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
local required_key="$4"
|
||
local required_value="$5"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" || -z "$required_key" || -z "$required_value" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_code_block_if_keyval_strict \"blockname\" \"neuer_block\" \"/pfad/zur/datei\" \"key\" \"value\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" \
|
||
-v req_key="$required_key" -v req_val="$required_value" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = $0 "\n"
|
||
found_key = 0
|
||
matching_keyval = 0
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = block_buffer $0 "\n"
|
||
|
||
if (brace_depth == 1 && match($0, "^\\s*" req_key "\\s*=\\s*")) {
|
||
found_key = 1
|
||
if ($0 ~ "^\\s*" req_key "\\s*=\\s*" req_val "\\s*$") {
|
||
matching_keyval = 1
|
||
}
|
||
}
|
||
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
block_seen = 1
|
||
if (found_key) {
|
||
if (matching_keyval) {
|
||
print new_block
|
||
block_replaced = 1
|
||
} else {
|
||
printf "%s", block_buffer
|
||
block_invalid = 1
|
||
}
|
||
} else {
|
||
printf "%s", block_buffer
|
||
}
|
||
next
|
||
}
|
||
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
|
||
END {
|
||
if (!block_seen) {
|
||
print new_block > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
if (block_invalid && !block_replaced) {
|
||
print "WARNUNG: Block vorhanden, aber Bedingung nicht erfüllt. Kein Ersetzen und kein Anhängen." > "/dev/stderr"
|
||
exit 4
|
||
}
|
||
}
|
||
' "$file" 1>"$tmp_file" 2>_new_block_to_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
# Kein passender Block gefunden -> Anfügen
|
||
echo "" >> "$file"
|
||
cat _new_block_to_append.tmp >> "$file"
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
echo "Block '$block_name' wurde nicht gefunden und wurde daher am Ende angehängt."
|
||
return 0
|
||
elif [[ $result -eq 4 ]]; then
|
||
# Block gefunden, aber Bedingung nicht erfüllt -> nichts tun
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
echo "Block '$block_name' vorhanden, aber Bedingung '$required_key = $required_value' nicht erfüllt. Keine Änderung vorgenommen."
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde ersetzt (Bedingung erfüllt)."
|
||
return 0
|
||
}
|
||
|
||
delete_code_block() {
|
||
local block_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$block_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_block \"blockname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
}
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Block '$block_name' wurde gelöscht."
|
||
return 0
|
||
}
|
||
|
||
delete_code_block_with_comments() {
|
||
local block_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$block_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_block_with_comments \"blockname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
lines[NR] = $0
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
# Rückwärts prüfen, ob vorherige Zeilen nur Kommentare oder leer sind
|
||
start = NR
|
||
for (i = NR - 1; i >= 1; i--) {
|
||
if (lines[i] ~ /^#|^\s*$/) {
|
||
start = i
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
skip_until = NR
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
for (i = start; i <= NR; i++) {
|
||
deleted[i] = 1
|
||
}
|
||
}
|
||
next
|
||
}
|
||
}
|
||
|
||
END {
|
||
for (i = 1; i <= NR; i++) {
|
||
if (!(i in deleted)) {
|
||
print lines[i]
|
||
}
|
||
}
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Block '$block_name' inkl. vorangehender Kommentare wurde gelöscht."
|
||
return 0
|
||
}
|
||
|
||
replace_variable() {
|
||
local var_name="$1"
|
||
local new_value="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$var_name" || -z "$new_value" || -z "$file" ]]; then
|
||
echo "Verwendung: replace_variable \"variablenname\" \"neuer_wert\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" -v new_value="$new_value" '
|
||
BEGIN {
|
||
replaced = 0
|
||
}
|
||
|
||
{
|
||
if ($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^[:alnum:]#])") {
|
||
# Ersetze gesamte Zeile durch normierte Form
|
||
print var_name " = " new_value
|
||
replaced = 1
|
||
} else {
|
||
print
|
||
}
|
||
}
|
||
|
||
END {
|
||
if (!replaced) {
|
||
print var_name " = " new_value > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" 1> "$tmp_file" 2> _missing_var.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
# Variable nicht gefunden → neue hinzufügen
|
||
echo "" >> "$file"
|
||
cat _missing_var.tmp >> "$file"
|
||
echo "➕ Variable '$var_name' wurde neu ans Ende angehängt."
|
||
rm -f "$tmp_file" _missing_var.tmp
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _missing_var.tmp
|
||
#echo "Variable '$var_name' wurde ersetzt."
|
||
return 0
|
||
}
|
||
|
||
replace_or_append_variable() {
|
||
local var_name="$1"
|
||
local new_value="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$var_name" || -z "$new_value" || -z "$file" ]]; then
|
||
echo "Verwendung: replace_variable \"variablenname\" \"neuer_wert\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" -v new_value="$new_value" '
|
||
BEGIN { replaced = 0 }
|
||
|
||
{
|
||
if ($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^[:alnum:]#])") {
|
||
print var_name " = " new_value
|
||
replaced = 1
|
||
} else {
|
||
print
|
||
}
|
||
}
|
||
|
||
END {
|
||
if (!replaced) {
|
||
printf("\n%s = %s\n", var_name, new_value) >> "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" > "$tmp_file" 2> _var_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
cat _var_append.tmp >> "$tmp_file"
|
||
#echo "Variable '$var_name' wurde neu ans Ende angehängt."
|
||
else
|
||
:
|
||
#echo "Variable '$var_name' wurde ersetzt."
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _var_append.tmp
|
||
|
||
return 0
|
||
}
|
||
|
||
|
||
delete_variable() {
|
||
local var_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$var_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_variable_only \"variablenname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" '
|
||
# match: key = val, key=val, key val
|
||
!($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^[:alnum:]#])") {
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Nur Variable '$var_name' wurde gelöscht (Kommentare erhalten)."
|
||
return 0
|
||
}
|
||
|
||
delete_variable_with_comments() {
|
||
local var_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$var_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_variable_with_comments \"variablenname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" '
|
||
{
|
||
lines[NR] = $0
|
||
|
||
if ($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^=[:alnum:]])") {
|
||
# Rückwärts: vorangehende Kommentarzeilen (ohne Leerzeile)
|
||
start = NR
|
||
for (i = NR - 1; i >= 1; i--) {
|
||
if (lines[i] ~ /^[[:space:]]*#/) {
|
||
start = i
|
||
} else if (lines[i] ~ /^[[:space:]]*$/) {
|
||
break
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
|
||
for (i = start; i <= NR; i++) {
|
||
delete lines[i]
|
||
}
|
||
}
|
||
}
|
||
|
||
END {
|
||
for (i = 1; i <= NR; i++) {
|
||
if (i in lines) {
|
||
print lines[i]
|
||
}
|
||
}
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Variable '$var_name' inkl. zugehöriger Kommentare wurde gelöscht."
|
||
return 0
|
||
}
|
||
|
||
|
||
|
||
# - Support systemd ?
|
||
# -
|
||
if [[ "X$(which systemd)" = "X" ]]; then
|
||
SYSTEMD_EXISTS=false
|
||
else
|
||
SYSTEMD_EXISTS=true
|
||
fi
|
||
|
||
if [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
||
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
||
else
|
||
DEFAULT_MYSQL_CREDENTIALS=""
|
||
fi
|
||
|
||
DEFAULT_SSL_CIPHER_LIST="ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305"
|
||
|
||
DEFAULT_VMAIL_UID=5000
|
||
DEFAULT_VMAIL_GID=5000
|
||
|
||
# - Detect OS - Set variable
|
||
# - os_dist
|
||
# - os_version
|
||
# - os_codename
|
||
# -
|
||
detect_os_1
|
||
|
||
|
||
echo
|
||
echononl " Include Configuration file.."
|
||
if [[ ! -f $conf_file ]]; then
|
||
echo -e "$rc_failed"
|
||
fatal "Missing configuration file '$conf_file'"
|
||
else
|
||
source $conf_file
|
||
echo -e "$rc_done"
|
||
fi
|
||
|
||
if [[ -z "$systemd_support" ]] ; then
|
||
if $SYSTEMD_EXISTS ; then
|
||
systemd_support=true
|
||
else
|
||
systemd_support=false
|
||
fi
|
||
fi
|
||
|
||
## - Required parameters
|
||
## -
|
||
[[ -n "$_update" ]] || fatal "Parameter "_update" not set."
|
||
[[ -n "$postmaster_address" ]] || postmaster_address="argus\@oopen.de"
|
||
[[ -n "$hostname" ]] || fatal "Missing value for parameter 'hostname'."
|
||
[[ -n "$ipv4" ]] || fatal "Missing value for parameter 'ipv4'."
|
||
[[ -n "$ipv6" ]] || warn "Missing value for parameter 'ipv6'."
|
||
|
||
[[ -n "$database" ]] || fatal "Parameter "database" not set."
|
||
|
||
if [[ "$database" != "postgres" ]] && [[ "$database" != "mysql" ]] ; then
|
||
fatal "Wrong value for parameter 'database' ({$database}). Only 'mysql' or 'postgres' is allowed."
|
||
fi
|
||
[[ -n "$dbpassword" ]] || fatal "Parameter "dbpassword" not set."
|
||
|
||
[[ -n "$from_address" ]] || fatal ""Parameter "from_address" not set.""
|
||
[[ -n "$reply_to" ]] || fatal ""Parameter "reply_to" not set.""
|
||
[[ -n "$webmailer" ]] || fatal ""Parameter "webmailer" not set.""
|
||
[[ -n "$salutation" ]] || fatal ""Parameter "salutation" not set.""
|
||
|
||
## - Some defaults if missing
|
||
## -
|
||
if [[ -n "$ipv6" ]] ; then
|
||
[[ -n "$imap_listener_adresses" ]] || imap_listener_adresses="127.0.0.1 $ipv4 $ipv6"
|
||
[[ -n "$imaps_listener_adresses" ]] || imaps_listener_adresses="127.0.0.1 $ipv4 $ipv6"
|
||
|
||
[[ -n "$pop_listener_adresses" ]] || pop_listener_adresses="$ipv4 $ipv6"
|
||
[[ -n "$pops_listener_adresses" ]] || pops_listener_adresses="127.0.0.1 $ipv4 $ipv6"
|
||
else
|
||
[[ -n "$imap_listener_adresses" ]] || imap_listener_adresses="127.0.0.1 $ipv4"
|
||
[[ -n "$imaps_listener_adresses" ]] || imaps_listener_adresses="127.0.0.1 $ipv4"
|
||
|
||
[[ -n "$pop_listener_adresses" ]] || pop_listener_adresses="$ipv4"
|
||
[[ -n "$pops_listener_adresses" ]] || pops_listener_adresses="127.0.0.1 $ipv4"
|
||
fi
|
||
|
||
[[ -n "$xmpp_listener" ]] || xmpp_listener=false
|
||
|
||
if $xmpp_listener ; then
|
||
# Be compartible with older installations
|
||
[[ -n "$xmpp_listener_address" ]] && xmpp_listener_addresses="$xmpp_listener_address"
|
||
[[ -n "$xmpp_listener_addresses" ]] || xmpp_listener_addresses="127.0.0.1 $ipv4"
|
||
[[ -n "$xmpp_listener_port" ]] || xmpp_listener_port="44444"
|
||
fi
|
||
|
||
[[ -n "$http_user" ]] || http_user="www-data"
|
||
[[ -n "$postfix_main_cf" ]] || postfix_main_cf="/etc/postfix/main.cf"
|
||
|
||
[[ -n "$dbname" ]] || dbname="postfix"
|
||
[[ -n "$dbuser" ]] || dbuser="postfix"
|
||
if [[ -z "$dbhost" ]] ; then
|
||
[[ "$database" = "mysql" ]] && dbhost="/run/mysqld/mysqld.sock"
|
||
[[ "$database" = "postgres" ]] && dbhost="/run/postgresql"
|
||
fi
|
||
|
||
[[ -n "$cert_base_dir" ]] || cert_base_dir="/etc/dovecot/ssl"
|
||
[[ -n "$server_cert" ]] || server_cert="${cert_base_dir}/mailserver.crt"
|
||
[[ -n "$server_key" ]] || server_key="${cert_base_dir}/mailserver.key"
|
||
[[ -n "$dh_pem_file" ]] || dh_pem_file="${cert_base_dir}/dh_4096.pem"
|
||
|
||
[[ -n "$ssl_cipher_list" ]] || ssl_cipher_list="${DEFAULT_SSL_CIPHER_LIST}"
|
||
|
||
[[ -n "$imap_cert" ]] || imap_cert="${cert_base_dir}/mailserver.crt"
|
||
[[ -n "$imap_key" ]] || imap_key="${cert_base_dir}/mailserver.key"
|
||
|
||
[[ -n "$pop_cert" ]] || pop_cert="${cert_base_dir}/mailserver.crt"
|
||
[[ -n "$pop_key" ]] || pop_key="${cert_base_dir}/mailserver.key"
|
||
|
||
[[ -n "$default_pass_scheme" ]] || default_pass_scheme="PLAIN"
|
||
|
||
[[ -n "$spam_folder" ]] || spam_folder="Spam"
|
||
|
||
[[ -n "$max_userip_connections" ]] || max_userip_connections=24
|
||
[[ -n "$auth_mechanisms" ]] || auth_mechanisms="plain login"
|
||
|
||
[[ -n "$service_limit_nofile" ]] || service_limit_nofile=524280
|
||
|
||
[[ -n "${vmail_uid}" ]] || vmail_uid=${DEFAULT_VMAIL_UID}
|
||
[[ -n "${vmail_gid}" ]] || vmail_gid=${DEFAULT_VMAIL_GID}
|
||
|
||
declare -i dovecot_major_version=0
|
||
declare -i dovecot_minor_version=0
|
||
declare -i dovecot_patch_level=0
|
||
|
||
echo -e "\033[32m--\033[m"
|
||
echo ""
|
||
echo "Version Number of Dovecot to install"
|
||
echo ""
|
||
echo ""
|
||
_version=
|
||
while [ "X$_version" = "X" ]
|
||
do
|
||
echononl "Dovecot Version: "
|
||
read _version
|
||
if [ "X$_version" = "X" ]; then
|
||
echo -e "\n\t\033[33m\033[1mA version number is required!\033[m\n"
|
||
fi
|
||
done
|
||
|
||
dovecot_main_version="$(echo $_version | cut -d '.' -f1,2)"
|
||
dovecot_major_version="$(echo $_version | cut -d '.' -f1)"
|
||
dovecot_minor_version="$(echo $_version | cut -d '.' -f2)"
|
||
dovecot_patch_level="$(echo $_version | cut -d '.' -f3)"
|
||
dovecot_minor_patch_level="$(echo $_version | cut -d '.' -f4)"
|
||
|
||
_version_short="${_version%-*}"
|
||
|
||
|
||
# 'expire plugin'was removed in version 2.3.14: This plugin is not needed.
|
||
# Use mailbox { autoexpunge } Mailbox settings instead.
|
||
#
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] \
|
||
&& [[ $dovecot_minor_version -gt 3 ]] \
|
||
) \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] \
|
||
&& [[ $dovecot_minor_version -eq 3 ]] \
|
||
&& [[ $dovecot_patch_level -gt 13 ]] \
|
||
) ; then
|
||
plugin_expire=false
|
||
else
|
||
plugin_expire=true
|
||
fi
|
||
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
postmaster_address="${postmaster_address/\\@/@}"
|
||
fi
|
||
|
||
#if $plugin_expire ; then
|
||
# info "Install plugin 'expire'.."
|
||
#else
|
||
# warn "Plugin 'expire' is no longer supported.."
|
||
#fi
|
||
|
||
#exit 0
|
||
|
||
_log_dir=${_src_base_dir}/log-dovecot-$_version
|
||
|
||
if [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -lt 4 ]] ; then
|
||
|
||
echo ""
|
||
echo -e "\033[32m--\033[m"
|
||
echo ""
|
||
echo "Version Number of Pigeonhole to install"
|
||
echo ""
|
||
echo ""
|
||
_pigeonhole=
|
||
while [ "X$_pigeonhole" = "X" ]
|
||
do
|
||
echononl "Pigeonhole Version: "
|
||
read _pigeonhole
|
||
if [ "X$_pigeonhole" = "X" ]; then
|
||
echo -e "\n\t\033[33m\033[1mA version number is required!\033[m\n"
|
||
fi
|
||
done
|
||
|
||
else
|
||
|
||
_pigeonhole=${_version}
|
||
|
||
fi
|
||
|
||
|
||
echo ""
|
||
echo -e "\033[32m--\033[m"
|
||
echo ""
|
||
echo "Is this a fresh new installation or an update?"
|
||
echo ""
|
||
echo ""
|
||
if [[ -n "$_update" ]]; then
|
||
if $_update || [[ "${_update,,}" = 'yes' ]] ; then
|
||
echo -e "\033[37m\033[1m[1] Update\033[m"
|
||
echo "[2] New Installation"
|
||
else
|
||
echo -e "[1] Update"
|
||
echo -e "\033[37m\033[1m[2] New Installation\033[m"
|
||
fi
|
||
echo ""
|
||
echononl "Choose a number or press <RETURN> for highlighted value: "
|
||
else
|
||
echo -e "[1] Update"
|
||
echo "[2] New Installation"
|
||
echo ""
|
||
echononl "Choose a Number: "
|
||
fi
|
||
update=""
|
||
while [[ "$update" != "true" && "$update" != "false" ]] ; do
|
||
read OPTION
|
||
case $OPTION in
|
||
1) update=true
|
||
;;
|
||
2) update=false
|
||
;;
|
||
'') if [[ -n "$_update" ]] ; then
|
||
if $_update || [[ "${_update,,}" = 'yes' ]] ; then
|
||
update=true
|
||
else
|
||
update=false
|
||
fi
|
||
else
|
||
echo ""
|
||
echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ]"
|
||
echo ""
|
||
echononl "Reentry: "
|
||
fi
|
||
;;
|
||
*) update=""
|
||
echo ""
|
||
if [[ -n "$_IS_RELAY_HOST" ]]; then
|
||
echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ] or type <RETURN>"
|
||
else
|
||
echo -e "\tWrong entry! [ 1 = Update ; 2 = New Installation ]"
|
||
fi
|
||
echo ""
|
||
echononl "Reentry: "
|
||
;;
|
||
esac
|
||
done
|
||
|
||
|
||
|
||
|
||
# -------------
|
||
# - List Script Configurations
|
||
# -------------
|
||
|
||
|
||
clear;
|
||
|
||
echo ""
|
||
if $update ;then
|
||
echo -e "\tUpdate Dovecot................: $update"
|
||
else
|
||
echo -e "\tInstall Dovecot first time....: Yes"
|
||
fi
|
||
echo ""
|
||
echo -e "\tDovecot (new) version.........: $_version"
|
||
echo -e "\t(Sieve) pigeonhole version....: $_pigeonhole"
|
||
echo ""
|
||
echo -e "\tSystemd support...............: $systemd_support"
|
||
echo ""
|
||
echo -e "\tSFolder containing sources....: $_src_base_dir"
|
||
echo ""
|
||
echo -e "\tPostmaser adress..............: $postmaster_address"
|
||
echo -e "\tHostname......................: $hostname"
|
||
echo ""
|
||
echo -e "\tIPv4 address..................: $ipv4"
|
||
echo -e "\tIPv6 address..................: $ipv6"
|
||
echo ""
|
||
echo -e "\tIMAP listener addresses.......: $imap_listener_adresses"
|
||
echo -e "\tIMAPS listener addresses......: $imaps_listener_adresses"
|
||
echo ""
|
||
echo -e "\tPOP3 listener addresses.......: $pop_listener_adresses"
|
||
echo -e "\tPOP3S listener addresses......: $pops_listener_adresses"
|
||
echo ""
|
||
echo -e "\tPostfix Configuration File....: $postfix_main_cf"
|
||
echo ""
|
||
echo -e "\tDatenbank.....................: $database"
|
||
echo ""
|
||
echo -e "\tPostfix database host.........: $dbhost"
|
||
echo -e "\tPostfix database name.........: $dbname"
|
||
echo -e "\tPostfix database user.........: $dbuser"
|
||
echo -e "\tPostfix database password.....: $dbpassword"
|
||
echo ""
|
||
echo -e "\tDefault password scheme.......: $default_pass_scheme"
|
||
echo ""
|
||
echo -e "\tCertificat base directory.....: $cert_base_dir"
|
||
echo -e "\tServer certificate............: $server_cert"
|
||
echo -e "\tServer key....................: $server_key"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then
|
||
echo -e "\tDH Parameters file............: $dh_pem_file"
|
||
fi
|
||
echo ""
|
||
echo -e "\tImap certificate..............: $imap_cert"
|
||
echo -e "\tImap key......................: $imap_key"
|
||
echo ""
|
||
echo -e "\tPop certificate...............: $pop_cert"
|
||
echo -e "\tPop key.......................: $pop_key"
|
||
echo ""
|
||
|
||
echo -e "\tSpan folder...................: $spam_folder"
|
||
echo -e "\tMax user connections per ip...: $max_userip_connections"
|
||
echo ""
|
||
echo -e "\tAuth Listener (Jabber)........: $xmpp_listener"
|
||
if $xmpp_listener ; then
|
||
echo -e "\t Auth Listener Addresses....: $xmpp_listener_addresses"
|
||
echo -e "\t AUTH Listener PORT.........: $xmpp_listener_port"
|
||
fi
|
||
echo ""
|
||
echo -e "\tInstall Plugin 'expire'.......: $plugin_expire"
|
||
echo ""
|
||
|
||
INSTALL_UPDATE_ENVIRONMENT_FILE="${_src_base_dir}/conf/install_update_dovecot-2.4.env"
|
||
cat <<EOF > ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
#!/usr/bin/env bash
|
||
|
||
|
||
log_file="${log_file}"
|
||
|
||
backup_date="${backup_date}"
|
||
|
||
_backup_crontab_file="${_backup_crontab_file}"
|
||
|
||
rc_done="${rc_done}"
|
||
rc_failed="${rc_failed}"
|
||
rc_skipped="${rc_skipped}"
|
||
rc_wait="${rc_wait}"
|
||
rc_not_yet_implemented="${rc_not_yet_implemented}"
|
||
|
||
EOF
|
||
|
||
cat <<'EOF' >> "${INSTALL_UPDATE_ENVIRONMENT_FILE}"
|
||
|
||
|
||
# -------------
|
||
# - Functions an Variable
|
||
# -------------
|
||
clean_up() {
|
||
|
||
|
||
if [[ -f "$_backup_crontab_file" ]]; then
|
||
|
||
echononl "(Re)Install previously saved crontab from '$_backup_crontab_file'.."
|
||
|
||
crontab $_backup_crontab_file >> $log_file 2>&1
|
||
|
||
if [[ $? -eq 0 ]]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
fi
|
||
|
||
fi
|
||
|
||
# Perform program exit housekeeping
|
||
rm -f $log_file
|
||
blank_line
|
||
exit $1
|
||
}
|
||
|
||
|
||
echononl(){
|
||
echo X\\c > /tmp/shprompt$$
|
||
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
|
||
echo -e "$*\\c" 1>&2
|
||
else
|
||
echo -en "$*" 1>&2
|
||
fi
|
||
rm /tmp/shprompt$$
|
||
}
|
||
|
||
fatal(){
|
||
echo ""
|
||
echo -e "\t[ \033[31m\033[1mFatal\033[m ]: \033[37m\033[1m$*\033[m"
|
||
echo ""
|
||
echo -e "\t\033[31m\033[1m Skript wird abgebrochen\033[m\033[m\n"
|
||
rm -f $log_file
|
||
clean_up 1
|
||
}
|
||
|
||
error(){
|
||
echo ""
|
||
echo -e "\t[ \033[31m\033[1mError\033[m ]: $*"
|
||
echo ""
|
||
}
|
||
|
||
warn(){
|
||
echo ""
|
||
echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*"
|
||
echo ""
|
||
}
|
||
|
||
info(){
|
||
echo ""
|
||
echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*"
|
||
echo ""
|
||
}
|
||
|
||
|
||
blank_line() {
|
||
echo ""
|
||
}
|
||
|
||
echo_ok() {
|
||
echo -e "\033[71G[ \033[32mok\033[m ]"
|
||
}
|
||
echo_failed(){
|
||
echo -e "\033[71G[ \033[1;31mfailed\033[m ]"
|
||
}
|
||
echo_skipped() {
|
||
echo -e "\033[71G[ \033[33m\033[1mskipped\033[m ]"
|
||
}
|
||
|
||
detect_os_1 () {
|
||
|
||
if $(which lsb_release > /dev/null 2>&1) ; then
|
||
|
||
os_dist="$(lsb_release -i | awk '{print tolower($3)}')"
|
||
os_version="$(lsb_release -r | awk '{print tolower($2)}')"
|
||
os_codename="$(lsb_release -c | awk '{print tolower($2)}')"
|
||
|
||
if [[ "$os_dist" = "debian" ]]; then
|
||
if $(echo "$os_version" | grep -q '\.') ; then
|
||
os_version=$(echo "$os_version" | cut --delimiter='.' -f1)
|
||
fi
|
||
fi
|
||
|
||
elif [[ -e "/etc/os-release" ]]; then
|
||
|
||
. /etc/os-release
|
||
|
||
os_dist=$ID
|
||
os_version=${VERSION_ID}
|
||
|
||
fi
|
||
|
||
# remove whitespace from os_dist and os_version
|
||
os_dist="${os_dist// /}"
|
||
os_version="${os_version// /}"
|
||
|
||
}
|
||
|
||
replace_code_block() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_dovecot_block \"blockname\" \"neuer_block\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 1
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
print new_block
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
}
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
return 0
|
||
}
|
||
|
||
replace_or_append_code_block() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_dovecot_block \"blockname\" \"neuer_block\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
local block_found=0
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
print new_block
|
||
block_found = 1
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
}
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
|
||
END {
|
||
if (!block_found) {
|
||
print new_block > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" 1>"$tmp_file" 2>_new_block_to_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
# Block nicht gefunden neuen Block anhängen
|
||
echo "" >> "$file"
|
||
cat _new_block_to_append.tmp >> "$file"
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde nicht gefunden und deshalb am Ende der Datei angehängt."
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde ersetzt."
|
||
return 0
|
||
}
|
||
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# Funktion: replace_or_append_code_block_if_keyval
|
||
#
|
||
# Beschreibung:
|
||
# Ersetzt einen benannten Codeblock in einer Konfigurationsdatei durch einen
|
||
# neuen Block, **aber nur**, wenn im Hauptblock (nicht in Unterblöcken)
|
||
# ein bestimmtes Key-Value-Paar (z. B. "type = shared") vorhanden ist.
|
||
#
|
||
# Wenn kein passender Block gefunden wird (also kein Block mit dem Namen existiert),
|
||
# wird der neue Block **am Ende der Datei angehängt**.
|
||
#
|
||
# Wenn der Block vorhanden ist, das Key-Value-Paar aber **nicht** mit dem
|
||
# erwarteten Wert übereinstimmt, bleibt der Originalblock **unverändert**
|
||
# und der neue Block wird trotzdem **angehängt**.
|
||
#
|
||
# Parameter:
|
||
# $1 - Name des Blocks (z. B. "mailbox INBOX")
|
||
# $2 - Neuer Blockinhalt (als String)
|
||
# $3 - Pfad zur Datei, in der der Block ersetzt werden soll
|
||
# $4 - Schlüssel, nach dem im Hauptblock gesucht werden soll
|
||
# $5 - Erwarteter Wert des Schlüssels
|
||
#
|
||
# Rückgabewerte:
|
||
# 0 - Erfolgreich ersetzt oder angehängt
|
||
# 1 - Ungültige Parameter
|
||
# 2 - Datei existiert nicht
|
||
# 3 - Kein passender Block gefunden → wurde angehängt
|
||
#
|
||
# Hinweise:
|
||
# - Die Prüfung auf key = value erfolgt nur auf oberster Blockebene.
|
||
# - Diese Funktion ist großzügiger als "replace_code_block_if_keyval_strict":
|
||
# Sie ersetzt, wenn Bedingung erfüllt ist – hängt aber auch an, wenn nicht.
|
||
# ------------------------------------------------------------------------------
|
||
replace_or_append_code_block_if_keyval() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
local required_key="$4"
|
||
local required_value="$5"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" || -z "$required_key" || -z "$required_value" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_or_append_code_block_if_keyval \"blockname\" \"neuer_block\" \"/pfad/zur/datei\" \"key\" \"value\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
local block_found=0
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" \
|
||
-v req_key="$required_key" -v req_val="$required_value" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = $0 "\n"
|
||
found_keyval = 0
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = block_buffer $0 "\n"
|
||
|
||
# Prüfe nur im obersten Block-Level auf key = value
|
||
if (brace_depth == 1 && $0 ~ "^\\s*" req_key "\\s*=\\s*" req_val "\\s*$") {
|
||
found_keyval = 1
|
||
}
|
||
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
if (found_keyval) {
|
||
print new_block
|
||
block_found = 1
|
||
} else {
|
||
printf "%s", block_buffer
|
||
}
|
||
next
|
||
}
|
||
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
|
||
END {
|
||
if (!block_found) {
|
||
print new_block > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" 1>"$tmp_file" 2>_new_block_to_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
echo "" >> "$file"
|
||
cat _new_block_to_append.tmp >> "$file"
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde nicht gefunden oder Bedingung nicht erfüllt und daher am Ende angehängt."
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde ersetzt (Bedingung erfüllt)."
|
||
return 0
|
||
}
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# Funktion: replace_code_block_if_keyval
|
||
#
|
||
# Beschreibung:
|
||
# Ersetzt einen benannten Codeblock in einer Konfigurationsdatei durch einen
|
||
# neuen Block, aber **nur**, wenn innerhalb des Hauptblocks (nicht in Unterblöcken)
|
||
# ein bestimmtes Key-Value-Paar vorhanden ist (z.B. "type = shared").
|
||
#
|
||
# Wenn der Block nicht vorhanden ist oder das Key-Value-Paar nicht übereinstimmt,
|
||
# wird **nichts verändert**.
|
||
#
|
||
# Parameter:
|
||
# $1 - Name des Blocks (z.B. "mailbox INBOX")
|
||
# $2 - Neuer Blockinhalt (als String)
|
||
# $3 - Pfad zur Datei, in der der Block ersetzt werden soll
|
||
# $4 - Schlüssel, nach dem im Hauptblock gesucht werden soll
|
||
# $5 - Erwarteter Wert des Schlüssels
|
||
#
|
||
# Rückgabewert:
|
||
# 0 - Erfolgreich ersetzt oder keine Änderung nötig
|
||
# 1 - Ungültige Parameter
|
||
# 2 - Datei existiert nicht
|
||
#
|
||
# Hinweis:
|
||
# Der neue Block muss korrekt formatiert sein (einschließlich öffnender Klammer).
|
||
# Der Block wird **nicht** angehängt, falls er fehlt oder die Bedingung nicht zutrifft.
|
||
# ------------------------------------------------------------------------------
|
||
replace_code_block_if_keyval() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
local required_key="$4"
|
||
local required_value="$5"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" || -z "$required_key" || -z "$required_value" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_code_block_if_keyval \"blockname\" \"neuer_block\" \"/pfad/zur/datei\" \"key\" \"value\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" \
|
||
-v req_key="$required_key" -v req_val="$required_value" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = $0 "\n"
|
||
found_keyval = 0
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = block_buffer $0 "\n"
|
||
|
||
# Nur im Hauptblock prüfen
|
||
if (brace_depth == 1 && $0 ~ "^\\s*" req_key "\\s*=\\s*" req_val "\\s*$") {
|
||
found_keyval = 1
|
||
}
|
||
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
if (found_keyval) {
|
||
print new_block
|
||
} else {
|
||
printf "%s", block_buffer
|
||
}
|
||
next
|
||
}
|
||
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Ersetzung abgeschlossen (nur wenn Bedingung erfüllt war)."
|
||
return 0
|
||
}
|
||
|
||
|
||
# ------------------------------------------------------------------------------
|
||
# Funktion: replace_or_appen_dcode_block_if_keyval_strict
|
||
#
|
||
# Beschreibung:
|
||
# Ersetzt einen benannten Codeblock in einer Konfigurationsdatei durch einen
|
||
# neuen Block, aber **nur**, wenn innerhalb des Hauptblocks ein bestimmtes
|
||
# Key-Value-Paar (z. B. "type = shared") vorhanden ist.
|
||
#
|
||
# Wenn ein Block mit dem gesuchten Namen vorhanden ist, der angegebene Key aber
|
||
# einen **abweichenden Wert** hat (z. B. "type = private"), wird **nichts verändert**
|
||
# und der Block **wird nicht ersetzt und nicht angehängt**.
|
||
#
|
||
# Wenn kein passender Block vorhanden ist (also weder mit noch ohne Key),
|
||
# wird der neue Block **am Ende der Datei angehängt**.
|
||
#
|
||
# Parameter:
|
||
# $1 - Name des Blocks (z. B. "mailbox INBOX")
|
||
# $2 - Neuer Blockinhalt (als String)
|
||
# $3 - Pfad zur Datei, in der der Block ersetzt werden soll
|
||
# $4 - Schlüssel, nach dem im Hauptblock gesucht werden soll
|
||
# $5 - Erwarteter Wert des Schlüssels
|
||
#
|
||
# Rückgabewerte:
|
||
# 0 - Block ersetzt oder angehängt oder keine Änderung (weil Bedingung nicht erfüllt)
|
||
# 1 - Ungültige Parameter
|
||
# 2 - Datei existiert nicht
|
||
# 3 - Kein Block gefunden → wurde am Ende angehängt
|
||
# 4 - Block gefunden, aber Bedingung nicht erfüllt → keine Änderung vorgenommen
|
||
#
|
||
# Hinweise:
|
||
# - Die Bedingung wird nur im äußeren Block-Level geprüft (nicht in Unterblöcken).
|
||
# - Falls du mehrere Bedingungen prüfen willst, muss die Funktion erweitert werden.
|
||
# ------------------------------------------------------------------------------
|
||
replace_or_append_code_block_if_keyval_strict() {
|
||
local block_name="$1"
|
||
local new_block="$2"
|
||
local file="$3"
|
||
local required_key="$4"
|
||
local required_value="$5"
|
||
|
||
if [[ -z "$block_name" || -z "$new_block" || -z "$file" || -z "$required_key" || -z "$required_value" ]]; then
|
||
echo "Fehler: Parameter fehlen."
|
||
echo "Verwendung: replace_code_block_if_keyval_strict \"blockname\" \"neuer_block\" \"/pfad/zur/datei\" \"key\" \"value\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Fehler: Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" -v new_block="$new_block" \
|
||
-v req_key="$required_key" -v req_val="$required_value" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = $0 "\n"
|
||
found_key = 0
|
||
matching_keyval = 0
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
block_buffer = block_buffer $0 "\n"
|
||
|
||
if (brace_depth == 1 && match($0, "^\\s*" req_key "\\s*=\\s*")) {
|
||
found_key = 1
|
||
if ($0 ~ "^\\s*" req_key "\\s*=\\s*" req_val "\\s*$") {
|
||
matching_keyval = 1
|
||
}
|
||
}
|
||
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
block_seen = 1
|
||
if (found_key) {
|
||
if (matching_keyval) {
|
||
print new_block
|
||
block_replaced = 1
|
||
} else {
|
||
printf "%s", block_buffer
|
||
block_invalid = 1
|
||
}
|
||
} else {
|
||
printf "%s", block_buffer
|
||
}
|
||
next
|
||
}
|
||
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
|
||
END {
|
||
if (!block_seen) {
|
||
print new_block > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
if (block_invalid && !block_replaced) {
|
||
print "WARNUNG: Block vorhanden, aber Bedingung nicht erfüllt. Kein Ersetzen und kein Anhängen." > "/dev/stderr"
|
||
exit 4
|
||
}
|
||
}
|
||
' "$file" 1>"$tmp_file" 2>_new_block_to_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
# Kein passender Block gefunden -> Anfügen
|
||
echo "" >> "$file"
|
||
cat _new_block_to_append.tmp >> "$file"
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde nicht gefunden und wurde daher am Ende angehängt."
|
||
return 0
|
||
elif [[ $result -eq 4 ]]; then
|
||
# Block gefunden, aber Bedingung nicht erfüllt -> nichts tun
|
||
rm -f "$tmp_file" _new_block_to_append.tmp
|
||
#echo "Block '$block_name' vorhanden, aber Bedingung '$required_key = $required_value' nicht erfüllt. Keine Änderung vorgenommen."
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _new_block_to_append.tmp
|
||
#echo "Block '$block_name' wurde ersetzt (Bedingung erfüllt)."
|
||
return 0
|
||
}
|
||
|
||
delete_code_block() {
|
||
local block_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$block_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_block \"blockname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
}
|
||
next
|
||
}
|
||
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Block '$block_name' wurde gelöscht."
|
||
return 0
|
||
}
|
||
|
||
delete_code_block_with_comments() {
|
||
local block_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$block_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_block_with_comments \"blockname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v block_name="$block_name" '
|
||
function count_char(str, c) {
|
||
n = 0
|
||
for (i = 1; i <= length(str); i++) {
|
||
if (substr(str, i, 1) == c) n++
|
||
}
|
||
return n
|
||
}
|
||
|
||
{
|
||
lines[NR] = $0
|
||
if (!in_block && $0 ~ "^\\s*" block_name "\\s*\\{") {
|
||
# Rückwärts prüfen, ob vorherige Zeilen nur Kommentare oder leer sind
|
||
start = NR
|
||
for (i = NR - 1; i >= 1; i--) {
|
||
if (lines[i] ~ /^#|^\s*$/) {
|
||
start = i
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
|
||
in_block = 1
|
||
brace_depth = count_char($0, "{") - count_char($0, "}")
|
||
skip_until = NR
|
||
next
|
||
}
|
||
|
||
if (in_block) {
|
||
brace_depth += count_char($0, "{") - count_char($0, "}")
|
||
if (brace_depth <= 0) {
|
||
in_block = 0
|
||
for (i = start; i <= NR; i++) {
|
||
deleted[i] = 1
|
||
}
|
||
}
|
||
next
|
||
}
|
||
}
|
||
|
||
END {
|
||
for (i = 1; i <= NR; i++) {
|
||
if (!(i in deleted)) {
|
||
print lines[i]
|
||
}
|
||
}
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Block '$block_name' inkl. vorangehender Kommentare wurde gelöscht."
|
||
return 0
|
||
}
|
||
|
||
replace_variable() {
|
||
local var_name="$1"
|
||
local new_value="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$var_name" || -z "$new_value" || -z "$file" ]]; then
|
||
echo "Verwendung: replace_variable \"variablenname\" \"neuer_wert\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" -v new_value="$new_value" '
|
||
BEGIN {
|
||
replaced = 0
|
||
}
|
||
|
||
{
|
||
if ($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^[:alnum:]#])") {
|
||
# Ersetze gesamte Zeile durch normierte Form
|
||
print var_name " = " new_value
|
||
replaced = 1
|
||
} else {
|
||
print
|
||
}
|
||
}
|
||
|
||
END {
|
||
if (!replaced) {
|
||
print var_name " = " new_value > "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" 1> "$tmp_file" 2> _missing_var.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
# Variable nicht gefunden → neue hinzufügen
|
||
echo "" >> "$file"
|
||
cat _missing_var.tmp >> "$file"
|
||
echo "➕ Variable '$var_name' wurde neu ans Ende angehängt."
|
||
rm -f "$tmp_file" _missing_var.tmp
|
||
return 0
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _missing_var.tmp
|
||
#echo "Variable '$var_name' wurde ersetzt."
|
||
return 0
|
||
}
|
||
|
||
replace_or_append_variable() {
|
||
local var_name="$1"
|
||
local new_value="$2"
|
||
local file="$3"
|
||
|
||
if [[ -z "$var_name" || -z "$new_value" || -z "$file" ]]; then
|
||
#echo "Verwendung: replace_variable \"variablenname\" \"neuer_wert\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" -v new_value="$new_value" '
|
||
BEGIN { replaced = 0 }
|
||
|
||
{
|
||
if ($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^[:alnum:]#])") {
|
||
print var_name " = " new_value
|
||
replaced = 1
|
||
} else {
|
||
print
|
||
}
|
||
}
|
||
|
||
END {
|
||
if (!replaced) {
|
||
printf("\n%s = %s\n", var_name, new_value) >> "/dev/stderr"
|
||
exit 3
|
||
}
|
||
}
|
||
' "$file" > "$tmp_file" 2> _var_append.tmp
|
||
|
||
result=$?
|
||
|
||
if [[ $result -eq 3 ]]; then
|
||
cat _var_append.tmp >> "$tmp_file"
|
||
#echo "Variable '$var_name' wurde neu ans Ende angehängt."
|
||
else
|
||
:
|
||
#echo "Variable '$var_name' wurde ersetzt."
|
||
fi
|
||
|
||
mv "$tmp_file" "$file"
|
||
rm -f _var_append.tmp
|
||
|
||
return 0
|
||
}
|
||
|
||
|
||
delete_variable() {
|
||
local var_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$var_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_variable_only \"variablenname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" '
|
||
# match: key = val, key=val, key val
|
||
!($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^[:alnum:]#])") {
|
||
print
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Nur Variable '$var_name' wurde gelöscht (Kommentare erhalten)."
|
||
return 0
|
||
}
|
||
|
||
delete_variable_with_comments() {
|
||
local var_name="$1"
|
||
local file="$2"
|
||
|
||
if [[ -z "$var_name" || -z "$file" ]]; then
|
||
echo "Verwendung: delete_variable_with_comments \"variablenname\" \"/pfad/zur/datei\""
|
||
return 1
|
||
fi
|
||
|
||
if [[ ! -f "$file" ]]; then
|
||
echo "Datei '$file' existiert nicht."
|
||
return 2
|
||
fi
|
||
|
||
local tmp_file
|
||
tmp_file=$(mktemp)
|
||
|
||
awk -v var_name="$var_name" '
|
||
{
|
||
lines[NR] = $0
|
||
|
||
if ($0 ~ "^[[:space:]]*" var_name "[[:space:]]*(=|[^=[:alnum:]])") {
|
||
# Rückwärts: vorangehende Kommentarzeilen (ohne Leerzeile)
|
||
start = NR
|
||
for (i = NR - 1; i >= 1; i--) {
|
||
if (lines[i] ~ /^[[:space:]]*#/) {
|
||
start = i
|
||
} else if (lines[i] ~ /^[[:space:]]*$/) {
|
||
break
|
||
} else {
|
||
break
|
||
}
|
||
}
|
||
|
||
for (i = start; i <= NR; i++) {
|
||
delete lines[i]
|
||
}
|
||
}
|
||
}
|
||
|
||
END {
|
||
for (i = 1; i <= NR; i++) {
|
||
if (i in lines) {
|
||
print lines[i]
|
||
}
|
||
}
|
||
}
|
||
' "$file" > "$tmp_file"
|
||
|
||
mv "$tmp_file" "$file"
|
||
#echo "Variable '$var_name' inkl. zugehöriger Kommentare wurde gelöscht."
|
||
return 0
|
||
}
|
||
|
||
|
||
EOF
|
||
|
||
echo "_version=\"${_version}\" # dovecot version" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "dovecot_main_version=${dovecot_main_version}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dovecot_major_version=${dovecot_major_version}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dovecot_minor_version=${dovecot_minor_version}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dovecot_patch_level=${dovecot_patch_level}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dovecot_minor_patch_level=${dovecot_minor_patch_level}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "_pigeonhole=\"${_pigeonhole}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "postmaster_address=\"${postmaster_address}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "systemd_support=${systemd_support}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "_src_base_dir=\"${_src_base_dir}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "postfix_main_cf=\"${postfix_main_cf}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "hostname=\"${hostname}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "ipv4=\"${ipv4}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "ipv6"=\"${ipv6}\" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "imap_listener_adresses=\"${imap_listener_adresses}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "imaps_listener_adresses=\"${imaps_listener_adresses}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "pop_listener_adresses=\"${pop_listener_adresses}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "pops_listener_adresses=\"${pops_listener_adresses}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "xmpp_listener=${xmpp_listener}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
if $xmpp_listener ; then
|
||
echo "xmpp_listener_addresses=\"${xmpp_listener_addresses}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "xmpp_listener_port=\"${xmpp_listener_port}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
fi
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "database=\"${database}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dbhost=\"${dbhost}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dbname=\"${dbuser}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dbuser=\"${dbuser}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "dbpassword=\"${dbpassword}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "PGPASSWORD=\"${dbpassword}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "MYSQL_CREDENTIALS=\"${DEFAULT_MYSQL_CREDENTIALS}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
|
||
echo "default_pass_scheme=\"${default_pass_scheme}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "cert_base_dir=\"${cert_base_dir}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "server_cert=\"${server_cert}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "server_key=\"${server_key}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
if [[ $dovecot_major_version -ge 3 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then
|
||
echo "dh_pem_file=\"${dh_pem_file}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
fi
|
||
echo "ssl_cipher_list=\"${ssl_cipher_list}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "imap_cert=\"${imap_cert}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "imap_key=\"${imap_key}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "pop_cert=\"${pop_cert}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "pop_key=\"${pop_key}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "spam_folder=\"${spam_folder}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
echo "max_userip_connections"=${max_userip_connections} >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
echo "plugin_expire=${plugin_expire}" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
#echo "" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
|
||
if ! $update ;then
|
||
if [[ "$database" = "psql" ]] || [[ "$database" = "postgres" ]]; then
|
||
warn "Take care, your PostgreSQL configuration (pg_hba.conf) contains the following line:\n\n\t pg_hba.conf:\n\t \033[1mlocal all postfix trust\033[m"
|
||
fi
|
||
fi
|
||
|
||
echononl "Sind die Angaben richtig [ja/nein]: "
|
||
read OK
|
||
while [ "X$OK" != "Xyes" -a "X$OK" != "XYes" -a "X$OK" != "Xja" -a "X$OK" != "XJa" \
|
||
-a "X$OK" != "XNo" -a "X$OK" != "Xno" -a "X$OK" != "Xn" -a "X$OK" != "Xnein" -a "X$OK" != "XNein" ]
|
||
do
|
||
echononl "falsche Angabe! [ja/nein] :"
|
||
read OK
|
||
done
|
||
|
||
[ $OK = "Yes" -o $OK = "yes" -o "$OK" = "ja" -o "$OK" = "Ja" ] || fatal "Edit '$(basename $conf_file)' and correct variables"
|
||
|
||
|
||
## - Let make use multiple cores (-j<number of cores +1>)
|
||
## -
|
||
export MAKEFLAGS=-j$(expr `grep "^processor" /proc/cpuinfo | sort -u | wc -l` - 1)
|
||
|
||
|
||
# -------------
|
||
# - Begin Install/Update
|
||
# -------------
|
||
|
||
echo ""
|
||
|
||
if $update ;then
|
||
_new=false;
|
||
else
|
||
_new=true;
|
||
fi
|
||
|
||
if [ "$database" = "mysql" ]; then
|
||
db_driver=mysql
|
||
else
|
||
db_driver=pgsql
|
||
fi
|
||
|
||
if $_new ; then
|
||
if [ "$database" = "mysql" ]; then
|
||
|
||
echo ""
|
||
echo "--"
|
||
echo ""
|
||
echo "Gib MySQL credentials für den root user an.."
|
||
echo ""
|
||
echo "Possible values could be:"
|
||
echo " -u root -p<Passwort>"
|
||
echo " -u root -S /run/mysqld/mysqld.sock"
|
||
echo " --login-path=local"
|
||
echo " --defaults-file=/usr/local/mysql/sys-maint.cnf"
|
||
echo " --defaults-file=/etc/mysql/debian.cnf"
|
||
echo " ..."
|
||
echo ""
|
||
echo -e " Type \"\033[33mNone\033[m\" if no credentials are needed for root user (MariaDB)"
|
||
echo ""
|
||
MYSQL_CREDENTIALS=""
|
||
if [[ -n "${DEFAULT_MYSQL_CREDENTIALS}" ]] ; then
|
||
while [[ -z "${MYSQL_CREDENTIALS}" ]] ; do
|
||
echononl "MySQL credentials [${DEFAULT_MYSQL_CREDENTIALS}]: "
|
||
read MYSQL_CREDENTIALS
|
||
if [[ -z "${MYSQL_CREDENTIALS}" ]] ;then
|
||
MYSQL_CREDENTIALS="${DEFAULT_MYSQL_CREDENTIALS}"
|
||
fi
|
||
done
|
||
else
|
||
while [[ -z "${MYSQL_CREDENTIALS}" ]] ; do
|
||
echononl "MySQL credentials: "
|
||
read MYSQL_CREDENTIALS
|
||
if "${MYSQL_CREDENTIALS}" ]] ; then
|
||
echo -e "\n\t\033[33m\033[1mMySQL credentials are required (or type\033[33mNone\033[m) : "
|
||
continue
|
||
fi
|
||
if [[ "$(trim ${MYSQL_CREDENTIALS,,})" = 'none' ]] ; then
|
||
MYSQL_CREDENTIALS=""
|
||
break
|
||
fi
|
||
done
|
||
fi
|
||
echo ""
|
||
echo "--"
|
||
echo ""
|
||
echo ""
|
||
|
||
if [[ "${MYSQL_CREDENTIALS}" != "${DEFAULT_MYSQL_CREDENTIALS}" ]] ; then
|
||
echo "MYSQL_CREDENTIALS=\"${MYSQL_CREDENTIALS}\"" >> ${INSTALL_UPDATE_ENVIRONMENT_FILE}
|
||
fi
|
||
|
||
fi
|
||
fi
|
||
|
||
export PGPASSWORD=$dbpassword
|
||
|
||
|
||
echo -e "\033[1mDoing some backups\033[m.."
|
||
|
||
echononl " Backup existing installation log directory.."
|
||
if [[ -d "${_log_dir}" ]]; then
|
||
mv "${_log_dir}" "${_log_dir}.${backup_date}"
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Cannot Backup (move) directory '${_log_dir}'"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Backup existing installation directory.."
|
||
if [[ -d "/usr/local/dovecot-${_version}" ]]; then
|
||
mv "/usr/local/dovecot-${_version}" "/usr/local/dovecot-${_version}.${backup_date}"
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Cannot Backup (move) directory '${_log_dir}'"
|
||
|
||
echononl "Proceed instllation [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Backup existing source directory.."
|
||
if [[ -d "${_src_base_dir}/dovecot-${_version}" ]]; then
|
||
mv "${_src_base_dir}/dovecot-${_version}" "${_src_base_dir}/dovecot-${_version}.${backup_date}"
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Cannot Backup (move) directory '${_src_base_dir}/dovecot-${_version}'"
|
||
|
||
echononl "Proceed instllation [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
mkdir -p $_log_dir
|
||
|
||
|
||
## -----------------
|
||
## --- Download
|
||
|
||
cd ${_src_base_dir}
|
||
|
||
echo ""
|
||
echo -e "\033[1mDownload sources\033[m.."
|
||
|
||
## - Downloud Dovecot 2.2.x
|
||
## -
|
||
echononl " Download dovecot-${_version}.tar.gz"
|
||
if [ ! -f "${_src_base_dir}/dovecot-${_version}.tar.gz" ]; then
|
||
wget --no-check-certificate https://dovecot.org/releases/${dovecot_main_version}/dovecot-${_version}.tar.gz > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Direct download of 'dovecot-${_version}.tar.gz' failed
|
||
|
||
Download \033[1mdovecot-${_version}.tar.gz\033[m manually and proceed instllation."
|
||
|
||
echononl "Proceed instllation [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
## - Download Pigeonhole for Dovecot v2.2
|
||
## -
|
||
if [[ ${dovecot_major_version} -eq 2 ]] && [[ ${dovecot_minor_version} -lt 4 ]] ; then
|
||
|
||
echononl " Download dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.."
|
||
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
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_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
|
||
and proceed instllation."
|
||
|
||
echononl " Proceed instllation [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
dovecot_pigeonhole_archiv="dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz"
|
||
|
||
else
|
||
|
||
echononl " Download dovecot-pigeonhole-${_pigeonhole}.tar.gz.."
|
||
if [ ! -f "${_src_base_dir}/dovecot-pigeonhole-${_pigeonhole}.tar.gz" ]; then
|
||
wget --no-check-certificate https://pigeonhole.dovecot.org/releases/${dovecot_main_version}/dovecot-pigeonhole-${_pigeonhole}.tar.gz > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
dovecot_pigeonhole_archiv="dovecot-pigeonhole-${_pigeonhole}.tar.gz"
|
||
else
|
||
echo -e "$rc_failed"
|
||
|
||
error "Direct download of 'Pigeonhole Sieve and ManageSieve' source archiv failed
|
||
|
||
Download Pigeonhole Sieve and ManageSieve manually and name it to
|
||
|
||
\033[1mdovecot-pigeonhole-${_pigeonhole}.tar.gz\033[m\n"
|
||
|
||
|
||
echononl " Proceed instllation [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
dovecot_pigeonhole_archiv="dovecot-pigeonhole-${_pigeonhole}.tar.gz"
|
||
fi
|
||
|
||
dovecot_pigeonhole_archiv_prefix="${dovecot_pigeonhole_archiv%.tar.gz}"
|
||
dovecot_pigeonhole_archiv_dir="${dovecot_pigeonhole_archiv%.tar.gz}"
|
||
|
||
|
||
if $_new ; then
|
||
## - Install reqired debian packages
|
||
## -
|
||
echo ""
|
||
echo -e "\033[1mInstalling required debian packages\033[m.."
|
||
echononl " Installing libpq5 libpq-dev .."
|
||
if ! dpkg -l libpq-dev | grep -e "^ii" | grep libpq-dev > /dev/null ; then
|
||
apt-get install libpq5 libpq-dev > ${_log_dir}/debian-install.log 2&>1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "installing debian package(s) failed"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
echononl " Installing libkrb5-dev .."
|
||
if ! dpkg -l libkrb5-dev | grep -e "^ii" | grep libkrb5-dev > /dev/null ; then
|
||
apt-get install libkrb5-dev >> ${_log_dir}/debian-install.log 2&>1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "installing debian package(s) failed"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
fi
|
||
|
||
|
||
## -----------------
|
||
## - Create Users/groups needed for dovecot
|
||
|
||
echo ""
|
||
echo -e "\033[1mCreate required users/groups\033[m.."
|
||
echononl " Create group dovecot.."
|
||
if ! grep dovecot /etc/group > /dev/null ; then
|
||
addgroup --system --gid 91 dovecot > ${_log_dir}/system.log 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Create group failed
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Create user dovecot.."
|
||
if ! grep dovecot /etc/passwd > /dev/null ; then
|
||
adduser --system --home /var/empty --no-create-home --shell /usr/sbin/nologin \
|
||
--ingroup dovecot --uid 91 dovecot > ${_log_dir}/system.log 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Create user failed
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Add Apache User (${http_user}) to group 'dovecot'.."
|
||
if getent group dovecot 2> /dev/null | grep -q "\b${http_user}\b" > /dev/null 2>&1 ; then
|
||
echo -e "$rc_skipped"
|
||
else
|
||
usermod -a -G dovecot $http_user > ${_log_dir}/system.log 2>&1
|
||
if [[ $? -eq 0 ]] ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Failed to add Apache User (${http_user}) to group 'dovecot'!"
|
||
fi
|
||
fi
|
||
|
||
|
||
echononl " Create group dovenull.."
|
||
if ! grep dovenull /etc/group > /dev/null ; then
|
||
addgroup --system --gid 65533 dovenull > ${_log_dir}/system.log 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Create group failed
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
echononl " Create user dovenull.."
|
||
if ! grep dovenull /etc/passwd > /dev/null ; then
|
||
adduser --system --home /var/empty --no-create-home --shell /usr/sbin/nologin \
|
||
--ingroup dovenull --uid 65533 dovenull > ${_log_dir}/system.log 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Create user failed
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
if $update ; then
|
||
|
||
# - Deaktiviere Cronjobs
|
||
# -
|
||
echo ""
|
||
echononl " Backup Crontab (user toot) to '$_backup_crontab_file'"
|
||
crontab -l > $_backup_crontab_file 2> $log_file
|
||
if [[ $? -eq 0 ]]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Backup Crontab to '$_backup_crontab_file' failed"
|
||
|
||
# If no crontab was present, the backup file contains
|
||
# th string "no crontab fo root". Better to delete the
|
||
# backup crontab file..
|
||
#
|
||
rm -f $_backup_crontab_file
|
||
fi
|
||
|
||
echononl " Remove crontab for user root.."
|
||
crontab -r > $log_file 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error ""
|
||
fi
|
||
|
||
fi
|
||
|
||
|
||
|
||
## -----------------
|
||
## --- Install Base System
|
||
|
||
echo ""
|
||
echo -e "\033[1mInstalling Base System\033[m.."
|
||
|
||
## - Unpack dovecot sources
|
||
## -
|
||
cd ${_src_base_dir}
|
||
echononl " Unpack dovecot-${_version}.tar.gz.."
|
||
tar -xzf dovecot-${_version}.tar.gz > /dev/null
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Extracting dovecot failed
|
||
fi
|
||
|
||
cd dovecot-${_version}
|
||
|
||
## - Configure dovecot
|
||
## -
|
||
config_params="
|
||
--prefix=/usr/local/dovecot-${_version} \
|
||
--with-${db_driver} \
|
||
--with-gssapi=yes
|
||
--with-ldap=yes
|
||
--with-rundir=/run/dovecot"
|
||
if $systemd_support ; then
|
||
config_params="$config_params \
|
||
--with-systemd"
|
||
fi
|
||
#--with-systemdsystemunitdir=/etc/systemd/system/"
|
||
|
||
echononl " Configure Dovecot.."
|
||
#./configure \
|
||
# --prefix=/usr/local/dovecot-${_version} \
|
||
# --with-${db_driver} \
|
||
# --with-gssapi=yes > ${_log_dir}/dovecot-${_version}-configure.log 2>&1
|
||
|
||
#--with-systemdsystemunitdir=/etc/systemd/system \
|
||
|
||
LDFLAGS="-s" \
|
||
./configure $config_params > ${_log_dir}/dovecot-${_version}-configure.log 2>&1
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Configuring dovecot failed
|
||
fi
|
||
|
||
## - Compile dovecot
|
||
## -
|
||
echononl " Compile Dovecot Sources.."
|
||
make > ${_log_dir}/dovecot-${_version}-make.log 2>&1 || clean_up 1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Compiling dovecot failed
|
||
fi
|
||
|
||
|
||
## -----------------
|
||
## --- Stop dovecot if running
|
||
|
||
echononl " Stop dovecot service.."
|
||
if ps ax 2> /dev/null | grep -q -E "/usr/local/dovecot[0-9.-]*/sbin/dovecot" > /dev/null 2>&1 ; then
|
||
if $systemd_support ; then
|
||
systemctl stop dovecot > /dev/null 2>&1
|
||
else
|
||
/etc/init.d/dovecot stop > /dev/null 2>&1
|
||
fi
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Stopping dovecot service failed"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Disable dovecot service.."
|
||
if systemctl list-units --full -all | grep -Fq "dovecot.service" 2> /dev/null ; then
|
||
if $systemd_support ; then
|
||
systemctl disable dovecot > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Stopping dovecot service failed"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
blank_line
|
||
|
||
echononl " Remove dovecot service file if exists.."
|
||
if [[ -f "/etc/systemd/system/dovecot.service" ]] ; then
|
||
rm -f "/etc/systemd/system/dovecot.service" > /dev/null 2>&1
|
||
if [[ "$?" -gt 0 ]]; then
|
||
echo -e "$rc_failed"
|
||
error "Removing file '/etc/systemd/system/dovecot.service' failed."
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
elif [[ -f "/usr/lib/systemd/system/dovecot.service" ]] ; then
|
||
rm -f "/usr/lib/systemd/system/dovecot.service" > /dev/null 2>&1
|
||
if [[ "$?" -gt 0 ]]; then
|
||
echo -e "$rc_failed"
|
||
error "Removing file '/usr/lib/systemd/system/dovecot.service' failed."
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Remove dovecot systemd's socket file if exists.."
|
||
if [[ -f "/etc/systemd/system/dovecot.socket" ]] ; then
|
||
rm -f "/etc/systemd/system/dovecot.socket" > /dev/null 2>&1
|
||
if [[ "$?" -gt 0 ]]; then
|
||
echo -e "$rc_failed"
|
||
error "Removing systemd's socket file '/etc/systemd/system/dovecot.socket' failed."
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
elif [[ -f "/usr/lib/systemd/system/dovecot.socket" ]] ; then
|
||
rm -f "/usr/lib/systemd/system/dovecot.socket" > /dev/null 2>&1
|
||
if [[ "$?" -gt 0 ]]; then
|
||
echo -e "$rc_failed"
|
||
error "Removing systemd's socket file '/usr/lib/systemd/system/dovecot.socket' failed."
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Remove directory '/etc/systemd/system/dovecot.service.d' if exists.."
|
||
if [[ -d "/etc/systemd/system/dovecot.service.d" ]] ; then
|
||
rm -rf "/etc/systemd/system/dovecot.service.d" > /dev/null 2>&1
|
||
if [[ "$?" -gt 0 ]]; then
|
||
echo -e "$rc_failed"
|
||
error "Removing directory '/etc/systemd/system/dovecot.service.d' failed."
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
blank_line
|
||
|
||
## - Install dovecot
|
||
## -
|
||
echononl " Install Dovecot into Folder /usr/local/dovecot-${_version}"
|
||
make install > ${_log_dir}/dovecot-${_version}-install.log 2>&1 || clean_up 1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Installing dovecot failed
|
||
fi
|
||
|
||
blank_line
|
||
|
||
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
echononl " Create Configuration Directory 'etc/dovecot/conf.d'.."
|
||
if [[ ! -d "/usr/local/dovecot-${_version}/etc/dovecot/conf.d" ]] ; then
|
||
mkdir -p "/usr/local/dovecot-${_version}/etc/dovecot/conf.d" > $log_file 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
touch "${_conf_file}" > ${log_file}
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating empty file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Mail Location ans Namespace Settigs
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## SSL settings
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Mailbox definitions
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Authentication processes
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/auth-sql.conf.ext"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Authentication for SQL users. Included from 10-auth.conf.
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Log destination.
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## LDA specific settings (also used by LMTP)
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## LMTP specific settings
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## IMAP specific settings
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## POP3 specific settings
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Settings for the Sieve interpreter
|
||
##
|
||
|
||
# see also: https://doc.dovecot.org/2.4.1/core/plugins/sieve.html
|
||
|
||
# To use Sieve, you will first need to make sure you are using Dovecot LDA or LMTP Server
|
||
# for delivering incoming mail to users' mailboxes.
|
||
#
|
||
# Then, you need to enable the Sieve plugin in your configuration:
|
||
#
|
||
# protocol lda {
|
||
# mail_plugins {
|
||
# sieve = yes
|
||
# }
|
||
# }
|
||
#
|
||
# protocol lmtp {
|
||
# mail_plugins {
|
||
# sieve = yes
|
||
# }
|
||
# }
|
||
|
||
# Script storage
|
||
# ==============
|
||
#
|
||
# Sieve scripts are retrieved from a script storage. This can currently be the local
|
||
# filesystem, an LDAP database or any dict storage. Depending on the storage
|
||
# implementation, its type and its configuration, storages can contain one script,
|
||
# several scripts identified by name, and a series of scripts in a well-defined order
|
||
# to be executed in sequence.
|
||
#
|
||
# Script storages are configured in a named sieve_script block:
|
||
#
|
||
# sieve_script personal {
|
||
# path = ~/.dovecot.sieve
|
||
# }
|
||
#
|
||
# The storage name (personal in the example) is used internally within configurations,
|
||
# as an identifier for logging, and as an identifier for command line tools. It also
|
||
# allows updating a storage that was defined earlier - by repeating the sieve_script
|
||
# block and adding additional configuration settings - or it allows userdb to override
|
||
# storage settings for specific users.
|
||
#
|
||
# Script storage types
|
||
# --------------------
|
||
#
|
||
# Sieve scripts can be evaluated at various stages in message delivery and for stored
|
||
# messages. The type of the Sieve script storage determines where it is applicable,
|
||
# how the storage is accessed and how the retrieved Sieve script is evaluated.
|
||
#
|
||
# The type of the Sieve script storage is configured using the sieve_script_type setting.
|
||
# The following types are currently recognized (others are defined by the sieve-imapsieve
|
||
# plugin):
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/95-sieve-vacation.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Settings for the Sieve Vacation Extension
|
||
##
|
||
|
||
# see also: https://doc.dovecot.org/2.4.1/core/config/sieve/extensions/vacation.html
|
||
|
||
# The Sieve vacation extension (RFC 5230) defines a mechanism to generate automatic
|
||
# replies to incoming email messages. It takes various precautions to make sure replies
|
||
# are only sent when appropriate.
|
||
#
|
||
# Script authors can specify how often replies can be sent to a particular contact.
|
||
# In the original vacation extension, this interval is specified in days with a minimum
|
||
# of one day. When more granularity is necessary and particularly when replies must be
|
||
# sent more frequently than one day, the vacation-seconds extension (RFC 6131) can be
|
||
# used. This allows specifying the minimum reply interval in seconds with a minimum of
|
||
# zero (a reply is then always sent), depending on administrator configuration.
|
||
#
|
||
# Configuration
|
||
# =============
|
||
#
|
||
# The vacation extension is available by default.
|
||
#
|
||
# In contrast, the vacation-seconds extension - which implies the vacation extension
|
||
# when used - is not available by default and needs to be enabled explicitly by adding
|
||
# it to sieve_extensions.
|
||
#
|
||
# The configuration also needs to be adjusted accordingly to allow a non-reply period of
|
||
# less than a day.
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Quota configuration.
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## Mailbox access control lists (ACL)
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf"
|
||
echononl " Create empty file '$(basename "${_conf_file}")'.."
|
||
if [[ ! -f "${_conf_file}" ]] ; then
|
||
_failed=false
|
||
cat <<'EOF' > "${_conf_file}" 2> "${log_file}"
|
||
##
|
||
## ManageSieve specific settings
|
||
##
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating file '${_conf_file}' failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
blank_line
|
||
|
||
fi
|
||
|
||
|
||
## - Add /usr/local/dovecot/bin to PATH variable
|
||
## -
|
||
## - Edit /etc/profile and add bevor "export PATH" directive:
|
||
## -
|
||
## - checkdir="/usr/local/dovecot/bin"
|
||
## - if [ -d $checkdir ]; then
|
||
## - PATH=$PATH:$checkdir
|
||
## - fi
|
||
## -
|
||
|
||
_file="/etc/profile"
|
||
|
||
_block='checkdir="/usr/local/dovecot/bin"
|
||
if [ -d "$checkdir" ]; then
|
||
PATH=${check_dir}:$PATH
|
||
fi'
|
||
|
||
echononl " Add /usr/local/dovecot/bin to PATH variable.."
|
||
|
||
|
||
if grep -Eq '^\s*checkdir="?/usr/local/dovecot/bin"?$' "${_file}"; then
|
||
echo -e "$rc_skipped"
|
||
else
|
||
cp "${_file}" "/tmp/etc_profile.${backup_date}" > "${log_file}" 2<&1
|
||
if [[ $? -gt 0 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
else
|
||
awk -v b="${_block}" '
|
||
/^export PATH/ {
|
||
print b;
|
||
print "";
|
||
}
|
||
{ print }
|
||
' "/tmp/etc_profile.${backup_date}" > "${_file}"
|
||
if [[ $? -gt 0 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "Adding /usr/local/dovecot/bin to PATH variable failed!"
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
#echononl " Add /usr/local/dovecot/bin to PATH variable.."
|
||
#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
|
||
#if [ "$?" = 0 ]; then
|
||
# echo -e "$rc_done"
|
||
#else
|
||
# echo -e "$rc_failed"
|
||
# fatal Adjusting /etc/profile failed
|
||
#fi
|
||
#else
|
||
# echo -e "$rc_skipped"
|
||
#fi
|
||
|
||
echononl " Copy Manpages if not exists.."
|
||
## - Manpages
|
||
## -
|
||
if ! grep /usr/local/dovecot/share/man /etc/manpath.config > /dev/null 2<&1 ; then
|
||
echo >> /etc/manpath.config
|
||
echo "MANDATORY_MANPATH /usr/local/dovecot/share/man /var/cache/man" >> /etc/manpath.config
|
||
echo "MANPATH_MAP /usr/local/dovecot/bin /usr/local/dovecot/share/man" >> /etc/manpath.config
|
||
echo "MANDB_MAP /usr/local/dovecot/share/man /var/cache/man" >> /etc/manpath.config
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
## -----------------
|
||
## --- Install Pigeonhole ManageSieve
|
||
|
||
cd ${_src_base_dir}
|
||
echo ""
|
||
echononl " Extracting ${dovecot_pigeonhole_archiv}.."
|
||
gunzip < ${_src_base_dir}/${dovecot_pigeonhole_archiv} | tar -C ${_src_base_dir} -xf -
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Extracting '${dovecot_pigeonhole_archiv}' failed
|
||
fi
|
||
cd ${dovecot_pigeonhole_archiv_dir}
|
||
|
||
|
||
echononl " Configure Pigeonhole ManageSieve.."
|
||
./configure \
|
||
--prefix=/usr/local/dovecot-${_version} \
|
||
--with-dovecot=/usr/local/dovecot-${_version}/lib/dovecot > ${_log_dir}/${dovecot_pigeonhole_archiv_prefix}-configure.log 2<&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Configuring Pigeonhole ManageSieve failed
|
||
fi
|
||
|
||
echononl " Compile Pigeonhole ManageSieve.."
|
||
make > ${_log_dir}/${dovecot_pigeonhole_archiv_prefix}-make.log 2<&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Compiling Pigeonhole ManageSieve failed
|
||
fi
|
||
|
||
echononl " Install Pigeonhole ManageSieve.."
|
||
make install > ${_log_dir}/${dovecot_pigeonhole_archiv_prefix}-install.log 2<&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Installing Pigeonhole ManageSieve failed
|
||
fi
|
||
|
||
|
||
## -----------------
|
||
## --- Configure dovecot services
|
||
|
||
#echo ""
|
||
#echo -e "\033[1mConfigure Dovecot\033[m.."
|
||
|
||
blank_line
|
||
|
||
|
||
## - Copy example config files to the config directory
|
||
## -
|
||
echononl " Copy example config files to the config directory.."
|
||
if [[ ${dovecot_major_version} -eq 2 ]] && [[ ${dovecot_minor_version} -lt 4 ]] ; then
|
||
cp -r /usr/local/dovecot-${_version}/share/doc/dovecot/example-config/* \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/ > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error Copying thr sample config files to the configuration directory failed.
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
echononl " Backup main configuration file 'dovecot.conf'.."
|
||
if [[ -f "/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf" ]] ; then
|
||
cp -a /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf.ORIG > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error The backup of the main configuration file failed.
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
blank_line
|
||
#echo -e "\033[1mBase install of Dovecot and Pigeonhole ManageSieve finished\033[m.."
|
||
#
|
||
#blank_line
|
||
#
|
||
#echononl "Proceed instllation [yes/no]: "
|
||
#read OK
|
||
#OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
#while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
# echononl "Wrong entry! - repeat [yes/no]: "
|
||
# read OK
|
||
#done
|
||
#[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# - edit /usr/local/dovecot/etc/dovecot/dovecot.conf
|
||
# -
|
||
# - protocols {
|
||
# - imap = yes
|
||
# - lmtp = yes
|
||
# - pop3 = yes
|
||
# - sieve = yes
|
||
# - }
|
||
# -
|
||
# - base_dir = /run/dovecot
|
||
# - state_dir = /run/dovecot
|
||
# -
|
||
# - listen = $ipv4 $ipv6
|
||
# -
|
||
# - mail_home = /var/vmail/%{user | domain}/%{user | username}
|
||
# - mail_path = ~/Maildir
|
||
# - mail_driver = maildir
|
||
# -
|
||
# - shutdown_clients = no
|
||
# -
|
||
# - ssl_server {
|
||
# - ssl = yes
|
||
# - cert_file = /etc/dovecot/ssl/mailserver.crt
|
||
# - key_file = /etc/dovecot/ssl/mailserver.key
|
||
# - }
|
||
# -
|
||
|
||
echononl " Delete block 'namespace inbox' in file '$(basename "${_conf_file}")'.."
|
||
if grep -qE '^\s*namespace\s+inbox\s*{' "${_conf_file}"; then
|
||
delete_code_block_with_comments "namespace inbox" "${_conf_file}"
|
||
if [[ $? -gt 1 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "Deleting block 'namespace inbox' in file '$(basename "${_conf_file}")' failed!"
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Delete block 'passdb pam' in file '$(basename "${_conf_file}")'.."
|
||
if grep -qE '^\s*passdb\s+pam\s*{' "${_conf_file}"; then
|
||
delete_code_block_with_comments "passdb pam" "${_conf_file}"
|
||
if [[ $? -gt 1 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "Deleting block 'passdb pam' in file '$(basename "${_conf_file}")' failed!"
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
_protocols_block="protocols {\n imap = yes\n lmtp = yes\n pop3 = yes\n sieve = yes\n}"
|
||
if [[ -n "$ipv6" ]]; then
|
||
_listen="$ipv4 $ipv6"
|
||
else
|
||
_listen="$ipv4"
|
||
fi
|
||
_base_dir="/run/dovecot"
|
||
_state_dir="/run/dovecot"
|
||
|
||
_mail_home="/var/vmail/%{user | domain}/%{user | username}"
|
||
_mail_driver="maildir"
|
||
_mail_path="~/Maildir"
|
||
|
||
_shutdown_clients="no"
|
||
|
||
_cert_file="/etc/dovecot/ssl/mailserver.crt"
|
||
_key_file="/etc/dovecot/ssl/mailserver.key"
|
||
_ssl_server_block="ssl_server {\n ssl = yes\n cert_file = ${_cert_file}\n key_file = ${_key_file}\n}"
|
||
|
||
echononl " Adjust file $(basename "${_conf_file}").."
|
||
|
||
# # Delete all lines that begin with !include and also delete the following line
|
||
# # if it is empty or contains only whitespace.
|
||
# #
|
||
# sed -i '/^!include/ {
|
||
# N
|
||
# /^\(!include.*\n[[:space:]]*\)$/d
|
||
# /^!include.*/d
|
||
# }' "${_conf_file}" || _failed=true
|
||
|
||
# Delete all lines beginning with !include, together with all comment lines
|
||
# directly preceding it (#...) - even several in a row, and also the line
|
||
# following it if it is empty or only contains whitespace.
|
||
#
|
||
awk '
|
||
{
|
||
zeile[NR] = $0
|
||
typ[NR] = "keep"
|
||
if ($0 ~ /^[[:space:]]*#/) typ[NR] = "comment"
|
||
if ($0 ~ /^[[:space:]]*$/) typ[NR] = "empty"
|
||
if ($0 ~ /^[[:space:]]*!include/) typ[NR] = "include"
|
||
}
|
||
|
||
END {
|
||
for (i = 1; i <= NR; i++) {
|
||
if (typ[i] == "include") {
|
||
# Vorherige Kommentarzeilen löschen
|
||
j = i - 1
|
||
while (j > 0 && typ[j] == "comment") {
|
||
typ[j] = "delete"
|
||
j--
|
||
}
|
||
# Include-Zeile löschen
|
||
typ[i] = "delete"
|
||
# Nachfolgende Leerzeile löschen (falls vorhanden)
|
||
if (typ[i+1] == "empty") {
|
||
typ[i+1] = "delete"
|
||
}
|
||
}
|
||
}
|
||
|
||
for (i = 1; i <= NR; i++) {
|
||
if (typ[i] != "delete") print zeile[i]
|
||
}
|
||
}
|
||
' "${_conf_file}" > "${_conf_file}.tmp" && mv "${_conf_file}.tmp" "${_conf_file}"
|
||
|
||
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
import_environment {
|
||
TZ = :/etc/localtime
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*quota \"User quota\"\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block 'quota "User quota"' "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# TZ (timezone) Environment Variable
|
||
#
|
||
# The use of the TZ environment variable can dramatically reduce the number
|
||
# of system calls and kernel context switches performed by the application.
|
||
#
|
||
# The localtime() function in glibc checks whether the TZ environment variable
|
||
# is set. If it is not set, then glibc will use the stat() system call every
|
||
# time localtime() is called, even with vDSO in place.
|
||
#
|
||
# Setting the TZ environment variable to :/etc/localtime (or some other
|
||
# timezone file of your choice) for a process will save glibc from making those
|
||
# extra unnecessary system calls (Notice the column : prefix before the file path).
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
|
||
|
||
if grep -qE '^\s*protocols\s*{' "${_conf_file}"; then
|
||
sed -i "/^\s*protocols\s*{/,/^}/c\
|
||
${_protocols_block}" ${_conf_file} || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Enable wanted protocols:
|
||
$(echo -e "${_protocols_block}")
|
||
EOF
|
||
#echo -e "\n${_protocols_block}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*listen\s*=' "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(listen\ ?=.*)#listen = ${_listen}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Enable wanted protocols:
|
||
listen = ${_listen}
|
||
EOF
|
||
#echo -e "\nlisten = ${_listen}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*base_dir\s*=' "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(base_dir\ ?=.*)#base_dir = ${_base_dir}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Base directory where to store runtime data.
|
||
base_dir = ${_base_dir}
|
||
EOF
|
||
#echo -e "\nbase_dir = ${_base_dir}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*state_dir\s*=' "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(state_dir\ ?=.*)#state_dir = ${_state_dir}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
echo -e "\nstate_dir = ${_state_dir}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*mail_home\s*=' "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(mail_home\ ?=.*)#mail_home = ${_mail_home}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
echo -e "\nmail_home = ${_mail_home}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*mail_path\s*=' "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(mail_path\ ?=.*)#mail_path = ${_mail_path}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
echo -e "\nmail_path = ${_mail_driver}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*mail_driver\s*=' "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(mail_driver\ ?=.*)#mail_driver = ${_mail_driver}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
echo -e "\nmail_driver = ${_mail_driver}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*shutdown_clients\s*=' "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(shutdown_clients\ ?=.*)#shutdown_clients = ${_shutdown_clients}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Should all processes be killed when Dovecot master process shuts down.
|
||
# Setting this to "no" means that Dovecot can be upgraded without
|
||
# forcing existing client connections to close (although that could also be
|
||
# a problem if the upgrade is e.g. because of a security fix).
|
||
shutdown_clients = ${_shutdown_clients}
|
||
EOF
|
||
#echo -e "\nshutdown_clients = ${_shutdown_clients}" >> "${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
if grep -qE '^\s*ssl_server\s*{' "${_conf_file}"; then
|
||
sed -i "/^\s*ssl_server\s*{/,/^}/c\
|
||
${_ssl_server_block}" ${_conf_file} || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# SSL/TLS Configuration
|
||
$(echo -e "${_ssl_server_block}")
|
||
EOF
|
||
fi
|
||
|
||
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Most of the actual configuration gets included below. The filenames are
|
||
# first sorted by their ASCII value and parsed in that order. The 00-prefixes
|
||
# in filenames are intended to make it easier to understand the ordering.
|
||
!include_try conf.d/*.conf
|
||
|
||
# A config file can also tried to be included without giving an error if
|
||
# it's not found:
|
||
!include_try local.conf
|
||
|
||
EOF
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf
|
||
## -
|
||
## - protocols = imap pop3 sieve
|
||
## - listen = $ipv4 $ipv6
|
||
## - base_dir =/run/dovecot/
|
||
## - state_dir = /run/dovecot
|
||
## - shutdown_clients = no
|
||
## -
|
||
## - dict {
|
||
## - expire = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext
|
||
## - }
|
||
## -
|
||
echononl " Adjust Main configuration ($(basename "${_conf_file}")).."
|
||
if [[ -n "$ipv6" ]]; then
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(listen\ ?=.*)#\1\#\# \2\n\1listen = $ipv4 $ipv6#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
else
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(listen\ ?=.*)#\1\#\# \2\n\1listen = $ipv4#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
fi
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(protocols\ ?=.*)#\1\#\# \2\n\1protocols = imap pop3 sieve#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(base_dir\ ?=.*)#\1\#\# \2\n\1base_dir = /run/dovecot/\n\nstate_dir = /run/dovecot#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(shutdown_clients\ ?=.*)#\1\#\# \2\n\1shutdown_clients = no#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
|
||
if $plugin_expire ; then
|
||
perl -i -n -p \
|
||
-e "s#^([ ]*)(dict\ +{.*)#\1\2\n\1 expire = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed"
|
||
fi
|
||
|
||
fi
|
||
|
||
blank_line
|
||
|
||
if $_new ; then
|
||
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
echononl " Check if database '$dbname' already exists.."
|
||
count=`su - postgres -c "psql -q -A -t -l" 2> ${_log_dir}/error.log | grep -c -e "^$dbname"`
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Checking existence of database '$dbname' failed!"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
|
||
if [ $count -eq 0 ];then
|
||
echononl " Create database user ${dbuser}.."
|
||
echo "CREATE ROLE $dbuser WITH LOGIN NOCREATEDB NOCREATEROLE NOSUPERUSER ENCRYPTED PASSWORD '$dbpassword'" \
|
||
| su - postgres -c "psql" > /dev/null 2>&1
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Creating database user $dbuser failed
|
||
fi
|
||
|
||
echononl " Create database ${dbname}.."
|
||
su - postgres -c "createdb -E utf8 -O ${dbuser} $dbname"
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal Creating database $dbname failed
|
||
fi
|
||
fi
|
||
|
||
## - Create table expires in database ${dbname}
|
||
## -
|
||
echononl " Create table expires in database ${dbname}.."
|
||
if $plugin_expire ; then
|
||
cat << EOF | psql -U$dbuser $dbname > ${_log_dir}/error.log 2>&1
|
||
|
||
CREATE TABLE IF NOT EXISTS expires (
|
||
username varchar(100) not null,
|
||
mailbox varchar(255) not null,
|
||
expire_stamp integer not null,
|
||
primary key (username, mailbox)
|
||
);
|
||
EOF
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat ${_log_dir}/error.log)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Create function merge_expires() / trigger mergeexpires.."
|
||
if $plugin_expire ; then
|
||
cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1
|
||
CREATE LANGUAGE plpgsql;
|
||
|
||
create or replace function merge_expires() returns trigger as \$\$
|
||
begin
|
||
update expires set expire_stamp = new.expire_stamp
|
||
where username = new.username and mailbox = new.mailbox;
|
||
if found then
|
||
return null;
|
||
else
|
||
return new;
|
||
end if;
|
||
end;
|
||
\$\$ language plpgsql;
|
||
|
||
create trigger mergeexpires before insert on expires
|
||
for each row execute procedure merge_expires();
|
||
EOF
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat ${_log_dir}/error.log)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
|
||
if ! mysql ${MYSQL_CREDENTIALS} -N -s -e \
|
||
"SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$dbname'" 2>/dev/null \
|
||
| grep $_db_name > /dev/null 2>&1 ; then
|
||
|
||
echononl " Create database ${dbname}.."
|
||
mysql ${MYSQL_CREDENTIALS} -N -s -e \
|
||
"CREATE DATABASE IF NOT EXISTS $dbname CHARACTER SET utf8 COLLATE utf8_general_ci" > ${_log_dir}/error.log 2>&1
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat ${_log_dir}/error.log)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
fi
|
||
|
||
echononl " Create database user ${dbuser}.."
|
||
mysql ${MYSQL_CREDENTIALS} -N -s -e \
|
||
"GRANT ALL ON ${dbname}.* TO '${dbuser}'@'localhost' IDENTIFIED BY '$dbpassword'" > ${_log_dir}/error.log 2>&1
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat ${_log_dir}/error.log)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
fi
|
||
|
||
echononl " Flushing database privileges.."
|
||
mysql ${MYSQL_CREDENTIALS} -N -s -e "FLUSH PRIVILEGES" > ${_log_dir}/error.log 2>&1
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat ${_log_dir}/error.log)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
fi
|
||
|
||
fi
|
||
|
||
|
||
## - Create table expires in database ${dbname}
|
||
## -
|
||
echononl " Create table expires in database ${dbname}.."
|
||
if $plugin_expire ; then
|
||
cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1
|
||
|
||
CREATE TABLE IF NOT EXISTS expires (
|
||
username varchar(100) not null,
|
||
mailbox varchar(255) not null,
|
||
expire_stamp integer not null,
|
||
primary key (username, mailbox)
|
||
);
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating table expires failed"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
|
||
## - create sql-dict.conf.ext file
|
||
## -
|
||
echononl " Create file sql-dict.conf.ext with plugin 'expire'.."
|
||
if $plugin_expire ; then
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
cat <<EOF >/usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
|
||
# CREATE TABLE expires (
|
||
# username varchar(100) not null,
|
||
# mailbox varchar(255) not null,
|
||
# expire_stamp integer not null,
|
||
# primary key (username, mailbox)
|
||
# );
|
||
|
||
## - if using postgres, you need also to create a trigger as follows:
|
||
## -
|
||
## - first create language plpgsql if not yet created:
|
||
## -
|
||
# CREATE LANGUAGE plpgsql;
|
||
#
|
||
# CREATE OR REPLACE FUNCTION merge_expires() RETURNS TRIGGER AS \$\$
|
||
# BEGIN
|
||
# UPDATE expires SET expire_stamp = NEW.expire_stamp
|
||
# WHERE username = NEW.username AND mailbox = NEW.mailbox;
|
||
# IF FOUND THEN
|
||
# RETURN NULL;
|
||
# ELSE
|
||
# RETURN NEW;
|
||
# END IF;
|
||
# END;
|
||
# \$\$ LANGUAGE plpgsql;
|
||
#
|
||
# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires
|
||
# FOR EACH ROW EXECUTE PROCEDURE merge_expires();
|
||
|
||
|
||
map {
|
||
pattern = shared/expire/\$user/\$mailbox
|
||
table = expires
|
||
value_field = expire_stamp
|
||
|
||
fields {
|
||
username = \$user
|
||
mailbox = \$mailbox
|
||
}
|
||
}
|
||
EOF
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Creating file sql-dict.conf.ext failed"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
|
||
## - create sql-dict.conf.ext file
|
||
## -
|
||
echononl " Create file sql-dict.conf.ext"
|
||
cat <<EOF >/usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
# CREATE TABLE expires (
|
||
# username varchar(100) not null,
|
||
# mailbox varchar(255) not null,
|
||
# expire_stamp integer not null,
|
||
# primary key (username, mailbox)
|
||
# );
|
||
|
||
|
||
map {
|
||
pattern = shared/expire/\$user/\$mailbox
|
||
table = expires
|
||
value_field = expire_stamp
|
||
|
||
fields {
|
||
username = \$user
|
||
mailbox = \$mailbox
|
||
}
|
||
}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Creating file sql-dict.conf.ext failed"
|
||
fi
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf"
|
||
: > "${log_file}"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
#
|
||
# default_process_limit = 1024
|
||
# default_client_limit = 10240
|
||
#
|
||
# default_vsz_limit = 512M
|
||
#
|
||
# !! Bemerkung !!
|
||
#
|
||
# 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"
|
||
# (default = 1024) geändert wird.
|
||
#
|
||
#
|
||
# Systemd System:
|
||
# ===============
|
||
#
|
||
# In der service datei (z.Bsp. /etc/systemd/system/multi-user.target.wants/dovecot.service)
|
||
# den Wert 'LimitNOFILE' hochsetzen:
|
||
#
|
||
# LimitNOFILE=32768 (must be greater or equal of 'default_client_limit')
|
||
#
|
||
# systemctl daemon-reload
|
||
# systemctl restart dovecot.service
|
||
#
|
||
# Im Falle von LX containern muss zusätzlich auf dem hostsystem
|
||
# in der datei '/etc/systemd/system.conf' der Wert für 'DefaultLimitNOFILE'
|
||
# hochgesetzt werden.
|
||
#
|
||
# System V systems:
|
||
# =================
|
||
# 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"
|
||
# (default = 1024) geändert wird. Z.Bsp. in der Datei /etc/init.d/dovecot
|
||
# durch Einfügen der zeile:
|
||
# ulimit -n 32768
|
||
#
|
||
# Linux VServer:
|
||
# put the following lines into /etc/security/limits.conf
|
||
#
|
||
# @staff hard nofile 32768
|
||
# root hard nofile 32768
|
||
#
|
||
# !! Mybe you have also create file /etc/vservers/*/ulimits/nofiles.hard
|
||
# with the same contents:
|
||
#
|
||
# @staff hard nofile 32768
|
||
# @adm hard nofile 32768
|
||
# root hard nofile 32768
|
||
#
|
||
# see also http://linux-vserver.org/Ulimit_Nofiles
|
||
#
|
||
#
|
||
# service imap-login {
|
||
# inet_listener imap {
|
||
# address = $imap_listener_adresses
|
||
# }
|
||
#
|
||
# inet_listener imaps {
|
||
# address = $imaps_listener_adresses
|
||
#
|
||
# }
|
||
#
|
||
# process_min_avail = 16
|
||
# }
|
||
#
|
||
# service pop3-login {
|
||
# inet_listener pop3 {
|
||
# address = $pop_listener_adresses
|
||
#
|
||
# }
|
||
# inet_listener pop3s {
|
||
# address = $pops_listener_adresses
|
||
#
|
||
# }
|
||
# }
|
||
#
|
||
# service submission-login {
|
||
#
|
||
# inet_listener submission {
|
||
# #port = 587
|
||
# }
|
||
#
|
||
# inet_listener submissions {
|
||
# #port = 465
|
||
# }
|
||
# }
|
||
#
|
||
# service lmtp {
|
||
#
|
||
# unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
||
# user = postfix
|
||
# group = postfix
|
||
# mode = 0660
|
||
# }
|
||
#
|
||
# # Create inet listener only if you can't use the above UNIX socket
|
||
# #inet_listener lmtp {
|
||
# # Avoid making LMTP visible for the entire internet
|
||
# #address =
|
||
# #port =
|
||
# #}
|
||
# }
|
||
#
|
||
# service imap {
|
||
#
|
||
# # tell imap to do post-login lookup using a socket called "imap-postlogin"
|
||
# executable = imap post-login
|
||
#
|
||
# # Most of the memory goes to mmap()ing files. You may need to increase this
|
||
# # limit if you have huge mailboxes.
|
||
# #vsz_limit = $default_vsz_limit
|
||
#
|
||
# # Max. number of IMAP processes (connections)
|
||
# #process_limit = 1024
|
||
# }
|
||
#
|
||
# service pop3 {
|
||
#
|
||
# # tell imap to do post-login lookup using a socket called "imap-postlogin"
|
||
# executable = pop3 post-login
|
||
#
|
||
# # Max. number of POP3 processes (connections)
|
||
# #process_limit = 1024
|
||
# }
|
||
#
|
||
# service submission {
|
||
#
|
||
# # Max. number of SMTP Submission processes (connections)
|
||
# #process_limit = 1024
|
||
# }
|
||
#
|
||
# service auth {
|
||
#
|
||
# # Auth Listener (XMPP - Jabber)
|
||
# inet_listener auth-xmpp {
|
||
# address = $xmpp_listener_addresses
|
||
# port = $xmpp_listener_port
|
||
# }
|
||
#
|
||
# unix_listener auth-userdb {
|
||
# mode = 0666
|
||
# user = dovecot
|
||
# group = dovecot
|
||
# }
|
||
#
|
||
# unix_listener /var/spool/postfix/private/dovecot-auth {
|
||
# mode = 0666
|
||
# user = postfix
|
||
# group = postfix
|
||
# }
|
||
#
|
||
# }
|
||
#
|
||
# service auth-worker {
|
||
# # Auth worker process is run as root by default, so that it can access
|
||
# # /etc/shadow. If this isn't necessary, the user should be changed to
|
||
# # $SET:default_internal_user.
|
||
# #user = root
|
||
# }
|
||
#
|
||
# service dict {
|
||
# # If dict proxy is used, mail processes should have access to its socket.
|
||
# # For example: mode=0660, group=vmail and global mail_access_groups=vmail
|
||
# unix_listener dict {
|
||
# #mode = 0600
|
||
# #user =
|
||
# #group =
|
||
# }
|
||
# }
|
||
#
|
||
echononl " Adjusting Services ($(basename "${_conf_file}")).."
|
||
:> "${_conf_file}"
|
||
|
||
_param="default_process_limit"
|
||
_val=1024
|
||
if grep -qE "^\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1 || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
# Default value for parameter 'service_process_limit', if not overridden by service-specific configuration.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
_param="default_client_limit"
|
||
_val=10240
|
||
if grep -qE "^\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1 || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Default value for service_client_limit, if not overridden by service-specific configuration.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
_param="default_vsz_limit"
|
||
_val="512M"
|
||
if grep -qE "^\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1 || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Default value for service_vsz_limit, if not overridden by service-specific configuration.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service imap-login {
|
||
|
||
inet_listener imap {
|
||
listen = $imap_listener_adresses
|
||
#port = 143
|
||
}
|
||
|
||
inet_listener imaps {
|
||
listen = $imaps_listener_adresses
|
||
#port = 993
|
||
#ssl = yes
|
||
}
|
||
|
||
# Minimum number of processes that always should be available to accept more client connections.
|
||
process_min_avail = 16
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service imap-login" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service pop3-login {
|
||
|
||
inet_listener pop3 {
|
||
listen = $pop_listener_adresses
|
||
#port = 110
|
||
}
|
||
|
||
inet_listener pop3s {
|
||
listen = $pops_listener_adresses
|
||
#port = 995
|
||
#ssl = yes
|
||
}
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service pop3-login" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service submission-login {
|
||
|
||
inet_listener submission {
|
||
#port = 587
|
||
}
|
||
|
||
inet_listener submissions {
|
||
#port = 465
|
||
}
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service submission-login" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service lmtp {
|
||
|
||
unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
||
user = postfix
|
||
group = postfix
|
||
mode = 0660
|
||
}
|
||
|
||
# Create inet listener only if you can't use the above UNIX socket
|
||
#inet_listener lmtp {
|
||
# Avoid making LMTP visible for the entire internet
|
||
#address =
|
||
#port =
|
||
#}
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service lmtp" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service imap {
|
||
|
||
# tell imap to do post-login lookup using a socket called "imap-postlogin"
|
||
#executable = imap post-login
|
||
|
||
# Most of the memory goes to mmap()ing files. You may need to increase this
|
||
# limit if you have huge mailboxes.
|
||
#vsz_limit = $default_vsz_limit
|
||
|
||
# Max. number of IMAP processes (connections)
|
||
#process_limit = 1024
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service imap" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service pop3 {
|
||
|
||
# tell imap to do post-login lookup using a socket called "imap-postlogin"
|
||
#executable = pop3 post-login
|
||
|
||
# Max. number of POP3 processes (connections)
|
||
#process_limit = 1024
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service pop3" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service submission {
|
||
|
||
# Max. number of SMTP Submission processes (connections)
|
||
#process_limit = 1024
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service submission" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if ${xmpp_listener} ; then
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service auth {
|
||
|
||
# Auth Listener (XMPP - Jabber)
|
||
inet_listener auth-xmpp {
|
||
listen = $xmpp_listener_addresses
|
||
port = $xmpp_listener_port
|
||
}
|
||
|
||
# auth_socket_path points to this userdb socket by default. It's typically
|
||
# used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
|
||
# full permissions to this socket are able to get a list of all usernames and
|
||
# get the results of everyone's userdb lookups.
|
||
#
|
||
# The default 0666 mode allows anyone to connect to the socket, but the
|
||
# userdb lookups will succeed only if the userdb returns an "uid" field that
|
||
# matches the caller process's UID. Also if caller's uid or gid matches the
|
||
# socket's uid or gid the lookup succeeds. Anything else causes a failure.
|
||
#
|
||
# To give the caller full permissions to lookup all users, set the mode to
|
||
# something else than 0666 and Dovecot lets the kernel enforce the
|
||
# permissions (e.g. 0777 allows everyone full permissions).
|
||
unix_listener auth-userdb {
|
||
mode = 0666
|
||
user = dovecot
|
||
group = dovecot
|
||
}
|
||
|
||
# Postfix smtp-auth
|
||
unix_listener /var/spool/postfix/private/dovecot-auth {
|
||
mode = 0666
|
||
user = postfix
|
||
group = postfix
|
||
}
|
||
}
|
||
EOF
|
||
else
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
service auth {
|
||
|
||
# auth_socket_path points to this userdb socket by default. It's typically
|
||
# used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
|
||
# full permissions to this socket are able to get a list of all usernames and
|
||
# get the results of everyone's userdb lookups.
|
||
#
|
||
# The default 0666 mode allows anyone to connect to the socket, but the
|
||
# userdb lookups will succeed only if the userdb returns an "uid" field that
|
||
# matches the caller process's UID. Also if caller's uid or gid matches the
|
||
# socket's uid or gid the lookup succeeds. Anything else causes a failure.
|
||
#
|
||
# To give the caller full permissions to lookup all users, set the mode to
|
||
# something else than 0666 and Dovecot lets the kernel enforce the
|
||
# permissions (e.g. 0777 allows everyone full permissions).
|
||
unix_listener auth-userdb {
|
||
mode = 0666
|
||
user = dovecot
|
||
group = dovecot
|
||
}
|
||
|
||
# Postfix smtp-auth
|
||
unix_listener /var/spool/postfix/private/dovecot-auth {
|
||
mode = 0666
|
||
user = postfix
|
||
group = postfix
|
||
}
|
||
}
|
||
EOF
|
||
fi
|
||
|
||
replace_or_append_code_block "service auth" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service auth-worker {
|
||
# Auth worker process is run as root by default, so that it can access
|
||
# /etc/shadow. If this isn't necessary, the user should be changed to
|
||
# $SET:default_internal_user.
|
||
#user = root
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service auth-worker" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service dict {
|
||
# If dict proxy is used, mail processes should have access to its socket.
|
||
# For example: mode=0660, group=vmail and global mail_access_groups=vmail
|
||
unix_listener dict {
|
||
mode = 0600
|
||
user = vmail
|
||
#group =
|
||
}
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "dict" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
# if grep -qE "^\s*service\s+auth\s*{" "${_conf_file}"; then
|
||
# replace_code_block "service auth" "${NEW_BLOCK}" "${_conf_file}"
|
||
#
|
||
# if [[ $? -gt 0 ]]; then
|
||
# _failed=true
|
||
# fi
|
||
# else
|
||
# echo -e "\n${NEW_BLOCK}" >> "${_conf_file}"
|
||
# fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${_conf_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
## -
|
||
## - default_process_limit = 1024
|
||
## - default_client_limit = 10240
|
||
## -
|
||
## - default_vsz_limit = 512M
|
||
## -
|
||
## - !! Bemerkung !!
|
||
## -
|
||
## - 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"
|
||
## - (default = 1024) geändert wird.
|
||
## -
|
||
## -
|
||
## - Systemd System:
|
||
## - ===============
|
||
## -
|
||
## - In der service datei (z.Bsp. /etc/systemd/system/multi-user.target.wants/dovecot.service)
|
||
## - den Wert 'LimitNOFILE' hochsetzen:
|
||
## -
|
||
## - LimitNOFILE=32768 (must be greater or equal of 'default_client_limit')
|
||
## -
|
||
## - systemctl daemon-reload
|
||
## - systemctl restart dovecot.service
|
||
## -
|
||
## - Im Falle von LX containern muss zusätzlich auf dem hostsystem
|
||
## - in der datei '/etc/systemd/system.conf' der Wert für 'DefaultLimitNOFILE'
|
||
## - hochgesetzt werden.
|
||
## -
|
||
## - System V systems:
|
||
## - =================
|
||
## - 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"
|
||
## - (default = 1024) geändert wird. Z.Bsp. in der Datei /etc/init.d/dovecot
|
||
## - durch Einfügen der zeile:
|
||
## - ulimit -n 32768
|
||
## -
|
||
## - Linux VServer:
|
||
## - put the following lines into /etc/security/limits.conf
|
||
## -
|
||
## - @staff hard nofile 32768
|
||
## - root hard nofile 32768
|
||
## -
|
||
## - !! Mybe you have also create file /etc/vservers/*/ulimits/nofiles.hard
|
||
## - with the same contents:
|
||
## -
|
||
## - @staff hard nofile 32768
|
||
## - @adm hard nofile 32768
|
||
## - root hard nofile 32768
|
||
## -
|
||
## - see also http://linux-vserver.org/Ulimit_Nofiles
|
||
## -
|
||
## -
|
||
## -
|
||
## - service auth {
|
||
## -
|
||
## - # Auth Listener (XMPP - Jabber)
|
||
## - inet_listener {
|
||
## - address = $xmpp_listener_addresses
|
||
## - port = $xmpp_listener_port
|
||
## - }
|
||
## - ..
|
||
## - unix_listener auth-userdb {
|
||
## - mode = 0666
|
||
## - user = dovecot
|
||
## - group = dovecot
|
||
## - }
|
||
## - ..
|
||
## - unix_listener /var/spool/postfix/private/dovecot-auth {
|
||
## - mode = 0666
|
||
## - user = postfix
|
||
## - group = postfix
|
||
## - }
|
||
## - ..
|
||
## - }
|
||
## -
|
||
## - service imap-login {
|
||
## - inet_listener imap {
|
||
## - address = $imap_listener_adresses
|
||
## - ..
|
||
## - }
|
||
## - inet_listener imaps {
|
||
## - address = $imaps_listener_adresses
|
||
## - ..
|
||
## - }
|
||
## -
|
||
## - process_min_avail = 16
|
||
## - }
|
||
## -
|
||
## - service pop3-login {
|
||
## - inet_listener pop3 {
|
||
## - address = $pop_listener_adresses
|
||
## - ..
|
||
## - }
|
||
## - inet_listener pop3s {
|
||
## - address = $pops_listener_adresses
|
||
## - ..
|
||
## - }
|
||
## - }
|
||
## -
|
||
echononl " Adjusting Services ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)(unix_listener\ +auth-userdb.*)#\1\2\n\1 mode = 0666\n\1 user = dovecot\n\1 group = dovecot#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(\#.*Postfix.*smtp-auth.*)#\1\2\n\1unix_listener /var/spool/postfix/private/dovecot-auth {\n\1 mode = 0666\n\1 user = postfix\n\1 group = postfix\n\1}#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(inet_listener\ +imap\ .*)#\1\2\n\1 address = $imap_listener_adresses#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(inet_listener\ +imaps.*)#\1\2\n\1 address = $imaps_listener_adresses#g#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(\#?process_min_avail\ ?=.*)#\1\#\# \2\n\1process_min_avail = 16#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(inet_listener\ +pop3\ .*)#\1\2\n\1 address = $pop_listener_adresses#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(inet_listener\ +pop3s.*)#\1\2\n\1 address = $pops_listener_adresses#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
|
||
if $xmpp_listener ; then
|
||
perl -i -n -p -e "s#^([ ]*)(service auth\s+\{.*)#\1\2\n\n \# Auth Listener (XMPP - Jabber)\n inet_listener {\n address = $xmpp_listener_addresses\n port = $xmpp_listener_port\n }\n#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
fi
|
||
|
||
## - setting default prozcess/client limit
|
||
## -
|
||
perl -i -n -p -e "s#^([ ]*\#?[ ]*)(default_process_limit.*)#\1\2\ndefault_process_limit = 1024#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*\#?[ ]*)(default_client_limit.*)#\1\2\ndefault_client_limit = 10240#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
|
||
perl -i -n -p -e "s#^([ ]*\#?[ ]*)(default_vsz_limit.*)#\1\2\ndefault_vsz_limit = 512M#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
|
||
blank_line
|
||
echononl " Create Cert/Key Directory '$cert_base_dir'.."
|
||
if [[ ! -d "$cert_base_dir" ]] ; then
|
||
mkdir -p "$cert_base_dir" > $log_file 2>&1
|
||
if [[ $? -eq 0 ]] ; then
|
||
echo -e "$rc_done"
|
||
|
||
echononl " Change Permissions for Cert/Key Directory '$cert_base_dir'.."
|
||
chmod 755 "$cert_base_dir" > $log_file 2>&1
|
||
if [[ $? -eq 0 ]] ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat "$log_file")"
|
||
fi
|
||
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat "$log_file")"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
## - Since dovecot version 2.3.x SSL DH parameters will be stored
|
||
## - permanently on filesystem. So we have to create such a file
|
||
## -
|
||
## - openssl dhparam -out /etc/postfix/ssl/dh_4096.pem`
|
||
## -
|
||
echononl " Create SSL DH parameters '$dh_pem_file'.."
|
||
if [[ $dovecot_major_version -ge 3 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then
|
||
|
||
if [[ ! -f "$dh_pem_file" ]] ; then
|
||
echo -en "$rc_wait"
|
||
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||
openssl dhparam -out "$dh_pem_file" 4096 > /dev/null 2>&1
|
||
else
|
||
openssl dhparam -dsaparam -out "$dh_pem_file" 4096 > /dev/null 2>&1
|
||
fi
|
||
if [[ $? -eq 0 ]]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating DH parameter file '$dh_pem_file' failed."
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-ssl.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf"
|
||
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-ssl.conf
|
||
#
|
||
# ssl_server {
|
||
#
|
||
# ssl = required
|
||
#
|
||
# # Preferred permissions: root:root 0444
|
||
# cert_file = $server_cert
|
||
#
|
||
# # Preferred permissions: root:root 0400
|
||
# key_file = $server_key
|
||
#
|
||
# # Path to the Diffie-Hellman parameters file. This setting isn't needed if using only ECDSA certificates.
|
||
# #
|
||
# # You can generate a new parameters file by, for example, running
|
||
# #
|
||
# # openssl dhparam -out dh.pem 4096
|
||
# #
|
||
# # on a machine with sufficient entropy (this may take some time).
|
||
# dh_file = $dh_pem_file
|
||
#
|
||
# # SSL ciphers to use
|
||
# ssl_cipher_list = ${ssl_cipher_list}
|
||
#
|
||
#
|
||
# # Whether to give preference to the server's cipher list over a client's list (server)
|
||
# # or vice versa (client)
|
||
# #
|
||
# # For TLSv1.3 server ciphers should not longer be preferred
|
||
# prefer_ciphers = client
|
||
#
|
||
# # The minimum SSL protocol version Dovecot accepts.
|
||
# #
|
||
# # This setting is used for both incoming and outgoing SSL connections.
|
||
# min_protocol = TLSv1.2
|
||
# }
|
||
|
||
echononl " Adjusting SSL ($(basename "${_conf_file}")).."
|
||
:> "${log_file}"
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
# Specifying SSL server settings.
|
||
ssl_server {
|
||
|
||
ssl = required
|
||
|
||
# Preferred permissions: root:root 0444
|
||
cert_file = $server_cert
|
||
|
||
# Preferred permissions: root:root 0400
|
||
key_file = $server_key
|
||
|
||
# Path to the Diffie-Hellman parameters file. This setting isn't needed if using only ECDSA certificates.
|
||
#
|
||
# You can generate a new parameters file by, for example, running
|
||
#
|
||
# openssl dhparam -out dh.pem 4096
|
||
#
|
||
# on a machine with sufficient entropy (this may take some time).
|
||
dh_file = $dh_pem_file
|
||
|
||
# SSL ciphers to use
|
||
ssl_cipher_list = ${ssl_cipher_list}
|
||
|
||
|
||
# Whether to give preference to the server's cipher list over a client's list (server)
|
||
# or vice versa (client)
|
||
#
|
||
# For TLSv1.3 server ciphers should not longer be preferred
|
||
prefer_ciphers = client
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "ssl_server" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
_param="ssl_min_protocol"
|
||
_val="TLSv1.2"
|
||
if grep -qE "^\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1 || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The minimum SSL protocol version Dovecot accepts.
|
||
#
|
||
# This setting is used for both incoming and outgoing SSL connections.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-ssl.conf
|
||
## -
|
||
## - ssl = required
|
||
## -
|
||
## - ssl_cert = <$server_cert
|
||
## - ssl_key = <$server_key
|
||
## -
|
||
## - # - 'ssl_dh_parameters_length' is obsolete and no longer needed
|
||
## - #ssl_dh_parameters_length = 2048
|
||
## -
|
||
## - # - 'ssl_protocols has been' replaced by ssl_min_protocol
|
||
## - #ssl_protocols = !SSLv3
|
||
## - ssl_min_protocol = TLSv1.2
|
||
## -
|
||
## - ssl_cipher_list = ${ssl_cipher_list}
|
||
## -
|
||
## - ssl_prefer_server_ciphers = yes
|
||
## -
|
||
## -
|
||
## - there are another possibilities to handle certs, but this did'nt work
|
||
## - as i expected..
|
||
## - #local_name imap.warenform.de {
|
||
## - # ssl_cert = <$imap_cert
|
||
## - # ssl_key = <$imap_key
|
||
## - #}
|
||
## - #local_name pop.warenform.de {
|
||
## - # ssl_cert = <$pop_cert
|
||
## - # ssl_key = <$pop_key
|
||
## - #}
|
||
## -
|
||
echononl " Backup file $(basename "${_conf_file}").."
|
||
|
||
if [[ ! -f "${_conf_file}.ORIG" ]] ; then
|
||
cp -a "${_conf_file}" "${_conf_file}.ORIG" > ${log_file} 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
:> "${log_file}"
|
||
|
||
echononl " Adjusting SSL ($(basename "${_conf_file}")).."
|
||
|
||
_param="ssl"
|
||
_val="required"
|
||
if grep -qE "^\s*#?\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# SSL/TLS support: yes, no, required.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
|
||
_param="ssl_cert"
|
||
_val="<$server_cert"
|
||
if grep -qE "^\s*#?\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# PEM encoded X.509 SSL/TLS certificate and private key. They're opened before
|
||
# dropping root privileges, so keep the key file unreadable by anyone but
|
||
# root. Included doc/mkcert.sh can be used to easily generate self-signed
|
||
# certificate, just make sure to update the domains in dovecot-openssl.cnf
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
|
||
_param="ssl_key"
|
||
_val="<$server_key"
|
||
if grep -qE "^\s*#?\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
|
||
if [[ $dovecot_major_version -ge 3 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -ge 3 ]] ); then
|
||
if [[ ! -f "$dh_pem_file" ]]; then
|
||
if [[ -f "/etc/postfix/ssl/dh_2048.pem" ]]; then
|
||
dh_pem_file="/etc/postfix/ssl/dh_2048.pem"
|
||
fi
|
||
fi
|
||
if [[ -f "$dh_pem_file" ]]; then
|
||
|
||
_param="ssl_dh"
|
||
_val="<$dh_pem_file"
|
||
if grep -qE "^\s*#?\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
# SSL DH parameters
|
||
# Generate new params with \`openssl dhparam -out /etc/dovecot/dh.pem 4096\`
|
||
# Or migrate from old ssl-parameters.dat file with the command dovecot
|
||
# gives on startup when ssl_dh is unset.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
else
|
||
_failed=true
|
||
fi
|
||
else
|
||
perl -i -n -p -e "s#^([ ]*)\#?(ssl_dh_parameters_length\ ?=.*)#\1\#\# \2\nssl_dh_parameters_length = 2048#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true
|
||
fi
|
||
|
||
_param="ssl_min_protocol"
|
||
_val="TLSv1.2"
|
||
if grep -qE "^\s*#?\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The minimum SSL protocol version Dovecot accepts.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
# - Replace only the first occurence of the match
|
||
# -
|
||
# - Example:
|
||
# - # Replace first occurence of 'width: .*' in file 'filename.css'
|
||
# -
|
||
# - perl -pi -e '$a=1 if(!$a && s/(width:).*;/$1 100%;/);' filename.css
|
||
# -
|
||
#perl -i -n -p -e "\$a=1 if(!\$a && s#^([ ]*)\#?(ssl_cipher_list\ ?=.*)#\1\#\# \2\nssl_cipher_list = ${ssl_cipher_list}#);" \
|
||
# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true
|
||
|
||
perl -i -n -p -e "\$a=1 if(!\$a && s#^([ ]*)\#?(ssl_cipher_list\ ?=.*)#ssl_cipher_list = ${ssl_cipher_list}#);" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-ssl.conf || _failed=true
|
||
|
||
|
||
_param="ssl_min_protocol"
|
||
_val="TLSv1.2"
|
||
if grep -qE "^\s*#?\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The minimum SSL protocol version Dovecot accepts.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
|
||
_param="ssl_prefer_server_ciphers"
|
||
_val="no"
|
||
if grep -qE "^\s*#?\s*${_param}\s*=" "${_conf_file}"; then
|
||
perl -i -n -p -e "s#^(\s*)\#?\ ?(${_param}\ ?=.*)#${_param} = ${_val}#g" \
|
||
"${_conf_file}" || _failed=true
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Prefer the server's order of ciphers over client's.
|
||
${_param} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting SSL ($(basename "${_conf_file}")) failed"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-ssl.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
#
|
||
# mail_home = /var/vmail/%{user | domain}/%{user | username}
|
||
# mail_driver = maildir
|
||
# mail_path = ~/Maildir
|
||
#
|
||
# mail_uid = vmail
|
||
# mail_gid = vmail
|
||
#
|
||
# first_valid_uid = ${vmail_uid}
|
||
# last_valid_uid = ${vmail_uid}
|
||
#
|
||
# first_valid_gid = ${vmail_gid}
|
||
# last_valid_gid = ${vmail_gid}
|
||
#
|
||
# mail_temp_dir = /var/vmail/tmp
|
||
#
|
||
# auth_socket_path = /run/dovecot/auth-userdb
|
||
#
|
||
# mail_plugins = quota acl
|
||
#
|
||
# mailbox_list_index
|
||
#
|
||
# maildir_broken_filename_sizes =
|
||
#
|
||
echononl " Adjusting base configurations ($(basename "${_conf_file}")).."
|
||
:> "${log_file}"
|
||
|
||
|
||
if grep -qE '^\s*mail_home\s*=' "${_conf_file}" \
|
||
|| grep -qE '^\s*mail_driver\s*=' "${_conf_file}" \
|
||
|| grep -qE '^\s*mail_path\s*=' "${_conf_file}" ; then
|
||
|
||
replace_variable \
|
||
"mail_home" \
|
||
'/var/vmail/%{user | domain}/%{user | username}' \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
replace_variable \
|
||
"mail_driver" \
|
||
'maildir' \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
replace_variable \
|
||
"mail_path" \
|
||
'~/Maildir' \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
mail_home= /var/vmail/%{user | domain}/%{user | username}'
|
||
mail_driver = maildir
|
||
mail_path = ~/Maildir
|
||
EOF
|
||
|
||
fi
|
||
|
||
if grep -qE '^\s*mail_uid\s*=' "${_conf_file}" \
|
||
|| grep -qE '^\s*mail_uid\s*=' "${_conf_file}" ; then
|
||
|
||
replace_variable \
|
||
"mail_uid" \
|
||
'vmail' \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
replace_variable \
|
||
"mail_gid" \
|
||
'vmail' \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# System user and group used to access mails.
|
||
mail_uid = vmail
|
||
mail_gid = vmail
|
||
EOF
|
||
|
||
fi
|
||
|
||
if grep -qE '^\s*first_valid_uid\s*=' "${_conf_file}" \
|
||
|| grep -qE '^\s*last_valid_uid\s*=' "${_conf_file}" ; then
|
||
|
||
replace_variable \
|
||
"first_valid_uid" \
|
||
"${vmail_uid}" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
replace_variable \
|
||
"last_valid_uid" \
|
||
"${vmail_uid}" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Valid UID range for users allowed to login
|
||
first_valid_uid = ${vmail_uid}
|
||
last_valid_uid = ${vmail_uid}
|
||
EOF
|
||
|
||
fi
|
||
|
||
if grep -qE '^\s*first_valid_gid\s*=' "${_conf_file}" \
|
||
|| grep -qE '^\s*last_valid_gid\s*=' "${_conf_file}" ; then
|
||
|
||
replace_variable \
|
||
"first_valid_gid" \
|
||
"${vmail_gid}" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
replace_variable \
|
||
"last_valid_gid" \
|
||
"${vmail_gid}" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Valid GID range for users allowed to login
|
||
first_valid_gid = ${vmail_gid}
|
||
last_valid_gid = ${vmail_gid}
|
||
EOF
|
||
|
||
fi
|
||
|
||
if grep -qE '^\s*mail_temp_dir\s*=' "${_conf_file}" ; then
|
||
replace_variable \
|
||
"mail_temp_dir" \
|
||
"/var/vmail/tmp" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The directory in which LDA/LMTP will temporarily store incoming message data
|
||
# that is above 128kB in size.
|
||
mail_temp_dir = /var/vmail/tmp
|
||
EOF
|
||
|
||
fi
|
||
|
||
if grep -qE '^\s*auth_socket_path\s*=' "${_conf_file}" ; then
|
||
replace_variable \
|
||
"auth_socket_path" \
|
||
"/run/dovecot/auth-userdb" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The UNIX socket path to the master authentication server for finding users.
|
||
auth_socket_path = /run/dovecot/auth-userdb
|
||
EOF
|
||
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
mail_plugins {
|
||
acl = yes
|
||
quota = yes
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*mail_plugins\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "mail_plugins" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# A list of mail plugins to load.
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
|
||
if grep -qE '^\s*mailbox_list_index\s*=' "${_conf_file}" ; then
|
||
replace_variable \
|
||
"mailbox_list_index" \
|
||
"yes" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot indexes live at the root of user's mailbox storage, and allows quick lookup
|
||
# of mailbox status instead of needing to open all mailbox indexes separately.
|
||
#
|
||
# Enabling this optimizes the server reply to IMAP STATUS commands, which are commonly
|
||
# issued by clients. This also needs to be enabled if you wish to enable the
|
||
# IMAP NOTIFY extension.
|
||
mailbox_list_index = yes
|
||
EOF
|
||
|
||
fi
|
||
|
||
|
||
if grep -qE '^\s*maildir_broken_filename_sizes\s*=' "${_conf_file}" ; then
|
||
replace_variable \
|
||
"maildir_broken_filename_sizes" \
|
||
"yes" \
|
||
"${_conf_file}" >> "${log_file}" 2>&1
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# maildir_broken_filename_sizes
|
||
#
|
||
# If enabled, Dovecot doesn't use the S=<size> in the Maildir filenames for
|
||
# getting the mail's physical size, except when recalculating Maildir++ quota.
|
||
# This can be useful in systems where a lot of the Maildir filenames have a
|
||
# broken size. The performance hit for enabling this is very small.
|
||
#maildir_broken_filename_sizes = no
|
||
maildir_broken_filename_sizes = yes
|
||
EOF
|
||
|
||
fi
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting '$(basename "${_conf_file}") failed"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
## -
|
||
## - mail_location = maildir:/var/vmail/%d/%n/Maildir
|
||
## -
|
||
## - mail_uid = vmail
|
||
## - mail_gid = vmail
|
||
## -
|
||
## - first_valid_uid = 5000
|
||
## - last_valid_uid = 5000
|
||
## -
|
||
## - mail_temp_dir = /var/vmail/tmp
|
||
## -
|
||
## - first_valid_gid = 5000
|
||
## - last_valid_gid = 5000
|
||
## -
|
||
## - auth_socket_path = /run/dovecot/auth-userdb
|
||
## - mail_plugins = quota acl | mail_plugins = quota acl expire
|
||
## -
|
||
## - mailbox_list_index = yes
|
||
## -
|
||
echononl " Adjusting base configurations ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(mail_location\ +=.*)#\1\#\# \2\n\1mail_location = maildir:/var/vmail/%d/%n/Maildir#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_uid.*)#\1\#\# \2\n\1mail_uid = vmail#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_gid.*)#\1\#\# \2\n\1mail_gid = vmail#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_temp_dir.*)#\1\#\# \2\n\1mail_temp_dir = /var/vmail/tmp#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(first_valid_uid.*)#\1\#\# \2\n\1first_valid_uid = 5000#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(last_valid_uid.*)#\1\#\# \2\n\1last_valid_uid = 5000#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(first_valid_gid.*)#\1\#\# \2\n\1first_valid_gid = 5000#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(last_valid_gid.*)#\1\#\# \2\n\1last_valid_gid = 5000#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_socket_path\ +=.*)#\1\#\# \2\n\1auth_socket_path = /run/dovecot/auth-userdb#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
if $plugin_expire ; then
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota acl expire#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
else
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota acl#g" \
|
||
"${_conf_file}" || _failed=true
|
||
fi
|
||
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mailbox_list_index\s*=.*)#\1\#\# \2\n\1mailbox_list_index = yes#g" \
|
||
${_conf_file} || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file '$(basename "${_conf_file}")' failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
|
||
|
||
echononl " Create TEMP directory '/var/vmail/tmp' .."
|
||
if [[ ! -d /var/vmail/tmp ]] ; then
|
||
mkdir /var/vmail/tmp > /dev/null 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating TEMP directory '/var/vmail/tmp' failed."
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echononl " Change ownerchip of directory '/var/vmail/tmp' .."
|
||
chown vmail:vmail /var/vmail/tmp > /dev/null 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Changing ownerchip of directory '/var/vmail/tmp' failed."
|
||
fi
|
||
|
||
blank_line
|
||
|
||
# modify /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
#
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Modify or add namespaces in file '$(basename "${_conf_file}")'.."
|
||
|
||
# modify /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
#
|
||
# namespace inbox {
|
||
# type = private
|
||
# separator = /
|
||
# hidden = no
|
||
# list = yes
|
||
# subscriptions = yes
|
||
# }
|
||
|
||
if grep -qE "^\s*namespace\s+inbox\s*{" "${_conf_file}"; then
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
namespace inbox {
|
||
# The namespace type. One of:
|
||
#
|
||
# public Contains public shared mailboxes.
|
||
# private Typically contains only user's own private mailboxes.
|
||
# shared Contains other users' user shared mailboxes.
|
||
#
|
||
# Default: private
|
||
type = private
|
||
|
||
# Specifies the hierarchy separator for the namespace.
|
||
#
|
||
# Default: "." for Maildir; "/" for other mbox formats
|
||
#
|
||
# The separator is a single character, which can't then otherwise be used in folder names.
|
||
# The commonly used separators are . and /, but other separators can be used as well. For
|
||
# example ^ is less likely to be found in normal folder names.
|
||
#
|
||
# Recommended value is to leave it empty and accept the default value.
|
||
separator = /
|
||
|
||
# Specifies prefix for namespace.
|
||
#
|
||
# Must end with namespace_separator.
|
||
#
|
||
# Default: [none]
|
||
#prefix =
|
||
|
||
# If yes, this namespace will be considered the one holding the INBOX folder.
|
||
#
|
||
# There can be only one namespace defined like this.
|
||
inbox = yes
|
||
|
||
# If yes, namespace will be hidden from IMAP NAMESPACE (RFC 2342) command.
|
||
hidden = no
|
||
|
||
# Include this namespace in LIST output when listing its parent's folders.
|
||
#
|
||
# One of:
|
||
# children Namespace prefix list listed only if it has child mailboxes.
|
||
#
|
||
# no Namespace and mailboxes not listed unless listing requests explicitly
|
||
# mailboxes under the namespace prefix.
|
||
#
|
||
# yes Namespace and mailboxes are always listed.
|
||
#
|
||
# It is still possible to list the namespace's folders by explicitly asking for them.
|
||
# For example, if this setting is no, using LIST "" * with namespace prefix "lazy-expunge/"
|
||
# won't list it, but using LIST "" lazy-expunge/* lists all folders under it.
|
||
#
|
||
# Default: yes
|
||
list = yes
|
||
|
||
# Whether subscriptions are stored in this namespace.
|
||
#
|
||
# This is usually no for shared namespaces so that the shared folders' subscriptions are
|
||
# stored in the user's primary subscriptions file. If no, the subscriptions are stored in
|
||
# the first parent namespace (based on the prefix) that has this setting enabled.
|
||
#
|
||
# Example: If this setting is no for a namespace with prefix=foo/bar/, Dovecot first sees
|
||
# if there's a prefix=foo/ namespace with subscriptions=yes and then a namespace with an
|
||
# empty prefix. If neither is found, an error is given.
|
||
#
|
||
# Default: yes
|
||
subscriptions = yes
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "namespace inbox" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2> "${log_file}"
|
||
|
||
# Namespaces
|
||
#
|
||
# Dovecot supports fully configurable, hierarchical namespaces, which can use different storage drivers.
|
||
#
|
||
# Their original and primary purpose is to provide Namespace IMAP extension (RFC 2342) support, which
|
||
# allows giving IMAP clients hints about where to locate mailboxes and whether they're private, shared
|
||
# or public.
|
||
#
|
||
# Dovecot namespaces can be used for several other purposes too:
|
||
#
|
||
# Changing the Hierarchy Separators
|
||
# Providing backwards compatibility when switching from another IMAP server
|
||
# Provides support for public shared mailboxes and user shared mailboxes mailboxes
|
||
# Allows having mails in multiple different locations with possibly different formats
|
||
#
|
||
# These different locations and drivers are presented to the client as a single tree.
|
||
#
|
||
# Each namespace has:
|
||
#
|
||
# prefix (usually empty or "INBOX.")
|
||
# namespace separator (usually '/' or '.')
|
||
# 0 or more folders
|
||
#
|
||
# There must be one namespace where the case-insensitive folder named INBOX exists.
|
||
#
|
||
# All visible namespaces must have the same separator.
|
||
#
|
||
# Inside each namespace there is a list of folders, which form a sub-hierarchy.
|
||
namespace inbox {
|
||
# The namespace type. One of:
|
||
#
|
||
# public Contains public shared mailboxes.
|
||
# private Typically contains only user's own private mailboxes.
|
||
# shared Contains other users' user shared mailboxes.
|
||
#
|
||
# Default: private
|
||
type = private
|
||
|
||
# Specifies the hierarchy separator for the namespace.
|
||
#
|
||
# Default: "." for Maildir; "/" for other mbox formats
|
||
#
|
||
# The separator is a single character, which can't then otherwise be used in folder names.
|
||
# The commonly used separators are . and /, but other separators can be used as well. For
|
||
# example ^ is less likely to be found in normal folder names.
|
||
#
|
||
# Recommended value is to leave it empty and accept the default value.
|
||
separator = /
|
||
|
||
# Specifies prefix for namespace.
|
||
#
|
||
# Must end with namespace_separator.
|
||
#prefix =
|
||
|
||
# If yes, this namespace will be considered the one holding the INBOX folder.
|
||
#
|
||
# There can be only one namespace defined like this.
|
||
inbox = yes
|
||
|
||
# If yes, namespace will be hidden from IMAP NAMESPACE (RFC 2342) command.
|
||
hidden = no
|
||
|
||
# Include this namespace in LIST output when listing its parent's folders.
|
||
#
|
||
# One of:
|
||
# children Namespace prefix list listed only if it has child mailboxes.
|
||
#
|
||
# no Namespace and mailboxes not listed unless listing requests explicitly
|
||
# mailboxes under the namespace prefix.
|
||
#
|
||
# yes Namespace and mailboxes are always listed.
|
||
#
|
||
# It is still possible to list the namespace's folders by explicitly asking for them.
|
||
# For example, if this setting is no, using LIST "" * with namespace prefix "lazy-expunge/"
|
||
# won't list it, but using LIST "" lazy-expunge/* lists all folders under it.
|
||
#
|
||
# Default: yes
|
||
list = yes
|
||
|
||
# Whether subscriptions are stored in this namespace.
|
||
#
|
||
# This is usually no for shared namespaces so that the shared folders' subscriptions are
|
||
# stored in the user's primary subscriptions file. If no, the subscriptions are stored in
|
||
# the first parent namespace (based on the prefix) that has this setting enabled.
|
||
#
|
||
# Example: If this setting is no for a namespace with prefix=foo/bar/, Dovecot first sees
|
||
# if there's a prefix=foo/ namespace with subscriptions=yes and then a namespace with an
|
||
# empty prefix. If neither is found, an error is given.
|
||
#
|
||
# Default: yes
|
||
subscriptions = yes
|
||
}
|
||
EOF
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi # if grep -qE "^\s*namespace\s+inbox\s*{" "${_conf_file}"; then
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
echononl " Modify or add namespaces in file '$(basename "${_conf_file}")'.."
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
## -
|
||
## - Add or Replace 'namespace inbox' type private
|
||
## -
|
||
## - namespace inbox {
|
||
## - # Namespace type: private, shared or public
|
||
## - type = private
|
||
## -
|
||
## - # Hierarchy separator to use. You should use the same separator for all
|
||
## - # namespaces or some clients get confused. '/' is usually a good one.
|
||
## - # The default however depends on the underlying mail storage format.
|
||
## - #separator =
|
||
## - separator = /
|
||
## -
|
||
## - # Prefix required to access this namespace. This needs to be different for
|
||
## - # all namespaces. For example "Public/".
|
||
## - #prefix =
|
||
## - prefix =
|
||
## -
|
||
## - # Physical location of the mailbox. This is in same format as
|
||
## - # mail_location, which is also the default for it.
|
||
## - #location =
|
||
## -
|
||
## - # There can be only one INBOX, and this setting defines which namespace
|
||
## - # has it.
|
||
## - #inbox = no
|
||
## - inbox = yes
|
||
## -
|
||
## - # If namespace is hidden, it's not advertised to clients via NAMESPACE
|
||
## - # extension. You'll most likely also want to set list=no. This is mostly
|
||
## - # useful when converting from another server with different namespaces which
|
||
## - # you want to deprecate but still keep working. For example you can create
|
||
## - # hidden namespaces with prefixes "~/mail/", "~%u/mail/" and "mail/".
|
||
## - #hidden = no
|
||
## -
|
||
## - # Show the mailboxes under this namespace with LIST command. This makes the
|
||
## - # namespace visible for clients that don't support NAMESPACE extension.
|
||
## - # "children" value lists child mailboxes, but hides the namespace prefix.
|
||
## - #list = yes
|
||
## -
|
||
## - # Namespace handles its own subscriptions. If set to "no", the parent
|
||
## - # namespace handles them (empty prefix should always have this as "yes")
|
||
## - #subscriptions = yes
|
||
## - }
|
||
|
||
if grep -qE "^\s*namespace\s+inbox\s*{" "${_conf_file}"; then
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
namespace inbox {
|
||
# Namespace type: private, shared or public
|
||
type = private
|
||
|
||
# Hierarchy separator to use. You should use the same separator for all
|
||
# namespaces or some clients get confused. '/' is usually a good one.
|
||
# The default however depends on the underlying mail storage format.
|
||
#separator =
|
||
separator = /
|
||
|
||
# Prefix required to access this namespace. This needs to be different for
|
||
# all namespaces. For example "Public/".
|
||
#prefix =
|
||
prefix =
|
||
|
||
# Physical location of the mailbox. This is in same format as
|
||
# mail_location, which is also the default for it.
|
||
#location =
|
||
|
||
# There can be only one INBOX, and this setting defines which namespace
|
||
# has it.
|
||
#inbox = no
|
||
inbox = yes
|
||
|
||
# If namespace is hidden, it's not advertised to clients via NAMESPACE
|
||
# extension. You'll most likely also want to set list=no. This is mostly
|
||
# useful when converting from another server with different namespaces which
|
||
# you want to deprecate but still keep working. For example you can create
|
||
# hidden namespaces with prefixes "~/mail/", "~%u/mail/" and "mail/".
|
||
#hidden = no
|
||
|
||
# Show the mailboxes under this namespace with LIST command. This makes the
|
||
# namespace visible for clients that don't support NAMESPACE extension.
|
||
# "children" value lists child mailboxes, but hides the namespace prefix.
|
||
#list = yes
|
||
|
||
# Namespace handles its own subscriptions. If set to "no", the parent
|
||
# namespace handles them (empty prefix should always have this as "yes")
|
||
#subscriptions = yes
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "namespace inbox" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2> "${log_file}"
|
||
|
||
# If you need to set multiple mailbox locations or want to change default
|
||
# namespace settings, you can do it by defining namespace sections.
|
||
#
|
||
# You can have private, shared and public namespaces. Private namespaces
|
||
# are for user's personal mails. Shared namespaces are for accessing other
|
||
# users' mailboxes that have been shared. Public namespaces are for shared
|
||
# mailboxes that are managed by sysadmin. If you create any shared or public
|
||
# namespaces you'll typically want to enable ACL plugin also, otherwise all
|
||
# users can access all the shared mailboxes, assuming they have permissions
|
||
# on filesystem level to do so.
|
||
namespace inbox {
|
||
# Namespace type: private, shared or public
|
||
type = private
|
||
|
||
# Hierarchy separator to use. You should use the same separator for all
|
||
# namespaces or some clients get confused. '/' is usually a good one.
|
||
# The default however depends on the underlying mail storage format.
|
||
#separator =
|
||
separator = /
|
||
|
||
# Prefix required to access this namespace. This needs to be different for
|
||
# all namespaces. For example "Public/".
|
||
#prefix =
|
||
prefix =
|
||
|
||
# Physical location of the mailbox. This is in same format as
|
||
# mail_location, which is also the default for it.
|
||
#location =
|
||
|
||
# There can be only one INBOX, and this setting defines which namespace
|
||
# has it.
|
||
#inbox = no
|
||
inbox = yes
|
||
|
||
# If namespace is hidden, it's not advertised to clients via NAMESPACE
|
||
# extension. You'll most likely also want to set list=no. This is mostly
|
||
# useful when converting from another server with different namespaces which
|
||
# you want to deprecate but still keep working. For example you can create
|
||
# hidden namespaces with prefixes "~/mail/", "~%u/mail/" and "mail/".
|
||
#hidden = no
|
||
|
||
# Show the mailboxes under this namespace with LIST command. This makes the
|
||
# namespace visible for clients that don't support NAMESPACE extension.
|
||
# "children" value lists child mailboxes, but hides the namespace prefix.
|
||
#list = yes
|
||
|
||
# Namespace handles its own subscriptions. If set to "no", the parent
|
||
# namespace handles them (empty prefix should always have this as "yes")
|
||
#subscriptions = yes
|
||
}
|
||
EOF
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi
|
||
|
||
cat <<EOF >> "${_conf_file}" 2> "${log_file}"
|
||
|
||
namespace {
|
||
type = shared
|
||
separator = /
|
||
|
||
# Mailboxes are visible under "shared/user@domain/"
|
||
# %%n, %%d and %%u are expanded to the destination user.
|
||
prefix = shared/%%u/
|
||
|
||
# Mail location for other users' mailboxes. Note that %variables and ~/
|
||
# expands to the logged in user's data. %%n, %%d, %%u and %%h expand to the
|
||
# destination user's data.
|
||
#location = maildir:%%h/Maildir:INDEX=~/Maildir/shared/%%u
|
||
location = maildir:/var/vmail/%%d/%%n/Maildir:INDEX=~/Maildir/shared/%%u
|
||
|
||
# Use the default namespace for saving subscriptions.
|
||
subscriptions = no
|
||
|
||
# Include this namespace in LIST output when listing its parent's folders.
|
||
#
|
||
# One of:
|
||
# children Namespace prefix list listed only if it has child mailboxes.
|
||
#
|
||
# no Namespace and mailboxes not listed unless listing requests explicitly
|
||
# mailboxes under the namespace prefix.
|
||
#
|
||
# yes Namespace and mailboxes are always listed.
|
||
#
|
||
# It is still possible to list the namespace's folders by explicitly asking for them.
|
||
# For example, if this setting is no, using LIST "" * with namespace prefix "lazy-expunge/"
|
||
# won't list it, but using LIST "" lazy-expunge/* lists all folders under it.
|
||
#
|
||
# Default: yes
|
||
list = children
|
||
}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adding namespaces to '${_conf_file}' failed"
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
fi # modify /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/15-mailboxes.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/15-mailboxes.conf
|
||
#
|
||
# namespace inbox {
|
||
# These mailboxes are widely used and could perhaps be created automatically:
|
||
# mailbox Drafts {
|
||
# auto = subscribe
|
||
# special_use = \Drafts
|
||
# }
|
||
# mailbox Spam {
|
||
# auto = subscribe
|
||
# autoexpunge = 30d
|
||
# special_use = \Junk
|
||
# }
|
||
# mailbox Junk {
|
||
# auto = no
|
||
# autoexpunge = 30d
|
||
# special_use = \Junk
|
||
# }
|
||
# mailbox Trash {
|
||
# auto = subscribe
|
||
# autoexpunge = 3d
|
||
# special_use = \Trash
|
||
# }
|
||
#
|
||
# # For \Sent mailboxes there are two widely used names. We'll mark both of
|
||
# # them as \Sent. User typically deletes one of them if duplicates are created.
|
||
# mailbox Sent {
|
||
# auto = subscribe
|
||
# special_use = \Sent
|
||
# }
|
||
# mailbox "Sent Messages" {
|
||
# auto = no
|
||
# special_use = \Sent
|
||
# }
|
||
# }
|
||
|
||
echononl " Adjusting Mailboxes ($(basename "${_conf_file}"))"
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
namespace inbox {
|
||
|
||
# These mailboxes are widely used and could perhaps be created automatically:
|
||
mailbox Drafts {
|
||
auto = subscribe
|
||
special_use = \Drafts
|
||
}
|
||
mailbox Spam {
|
||
auto = subscribe
|
||
autoexpunge = 30d
|
||
special_use = \Junk
|
||
}
|
||
mailbox Junk {
|
||
auto = no
|
||
autoexpunge = 30d
|
||
special_use = \Junk
|
||
}
|
||
mailbox Trash {
|
||
auto = subscribe
|
||
autoexpunge = 3d
|
||
special_use = \Trash
|
||
}
|
||
|
||
# For \Sent mailboxes there are two widely used names. We'll mark both of
|
||
# them as \Sent. User typically deletes one of them if duplicates are created.
|
||
mailbox Sent {
|
||
auto = subscribe
|
||
special_use = \Sent
|
||
}
|
||
mailbox "Sent Messages" {
|
||
auto = no
|
||
special_use = \Sent
|
||
}
|
||
}
|
||
EOF
|
||
|
||
if grep -qE "^\s*namespace\s+inbox\s*{" "${_conf_file}"; then
|
||
|
||
replace_code_block "inbox" "${NEW_BLOCK}" "${_conf_file}"
|
||
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2> "${log_file}"
|
||
|
||
# Each mailbox is specified in a separate mailbox section. The section name
|
||
# specifies the mailbox name. If it has spaces, you can put the name
|
||
# "in quotes". These sections can contain the following mailbox settings:
|
||
#
|
||
# auto:
|
||
# Indicates whether the mailbox with this name is automatically created
|
||
# implicitly when it is first accessed. The user can also be automatically
|
||
# subscribed to the mailbox after creation. The following values are
|
||
# defined for this setting:
|
||
#
|
||
# no - Never created automatically.
|
||
# create - Automatically created, but no automatic subscription.
|
||
# subscribe - Automatically created and subscribed.
|
||
#
|
||
# special_use:
|
||
# A space-separated list of SPECIAL-USE flags (RFC 6154) to use for the
|
||
# mailbox. There are no validity checks, so you could specify anything
|
||
# you want in here, but it's not a good idea to use flags other than the
|
||
# standard ones specified in the RFC:
|
||
#
|
||
# \All - This (virtual) mailbox presents all messages in the
|
||
# user's message store.
|
||
# \Archive - This mailbox is used to archive messages.
|
||
# \Drafts - This mailbox is used to hold draft messages.
|
||
# \Flagged - This (virtual) mailbox presents all messages in the
|
||
# user's message store marked with the IMAP \Flagged flag.
|
||
# \Important - This (virtual) mailbox presents all messages in the
|
||
# user's message store deemed important to user.
|
||
# \Junk - This mailbox is where messages deemed to be junk mail
|
||
# are held.
|
||
# \Sent - This mailbox is used to hold copies of messages that
|
||
# have been sent.
|
||
# \Trash - This mailbox is used to hold messages that have been
|
||
# deleted.
|
||
#
|
||
# comment:
|
||
# Defines a default comment or note associated with the mailbox. This
|
||
# value is accessible through the IMAP METADATA mailbox entries
|
||
# "/shared/comment" and "/private/comment". Users with sufficient
|
||
# privileges can override the default value for entries with a custom
|
||
# value.
|
||
|
||
# !! NOTE !!:
|
||
#
|
||
# Assumes "namespace inbox" has been defined (usally in 10-mail.conf).
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/15-mailboxes.conf
|
||
## -
|
||
## - Add definitions for mailbox Spam:
|
||
## -
|
||
## - mailbox Drafts {
|
||
## - auto = subscribe
|
||
## - special_use = \Drafts
|
||
## - }
|
||
## -
|
||
## - mailbox Trash {
|
||
## - auto = subscribe
|
||
## - special_use = \Trash
|
||
## - }
|
||
## -
|
||
## - mailbox Sent {
|
||
## - auto = subscribe
|
||
## - special_use = \Sent
|
||
## - }
|
||
## -
|
||
## - mailbox $spam_folder {
|
||
## - auto = subscribe
|
||
## - special_use = \Junk
|
||
## - }
|
||
## -
|
||
|
||
echononl " Adjusting Mailboxes ($(basename "${_conf_file}"))"
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)(mailbox\ +Drafts\ +{.*)#\1\2\n\1 auto = subscribe#g" \
|
||
${_conf_file} || _failed=true
|
||
if [ "$spam_folder" != "Junk" ]; then
|
||
if $plugin_expire ; then
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1mailbox $spam_folder {\n\1 auto = subscribe\n\1 special_use = \\\Junk\n\1}\n\1\2#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1\2\n\1 auto = no#g" \
|
||
${_conf_file} || _failed=true
|
||
else
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1mailbox $spam_folder {\n\1 auto = subscribe\n\1 autoexpunge = 30d\n\1 special_use = \\\Junk\n\1}\n\1\2#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1\2\n\1 auto = no\n\1 autoexpunge = 30d#g" \
|
||
${_conf_file} || _failed=true
|
||
fi
|
||
else
|
||
if $plugin_expire ; then
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +$spam_folder\ +{.*)#\1\2\n\1 auto = subscribe#g" \
|
||
${_conf_file} || _failed=true
|
||
else
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +$spam_folder\ +{.*)#\1\2\n\1 auto = subscribe\n\1 autoexpunge = 30d#g" \
|
||
${_conf_file} || _failed=true
|
||
fi
|
||
fi
|
||
if $plugin_expire ; then
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +Trash\ +{.*)#\1\2\n\1 auto = subscribe#g" \
|
||
${_conf_file} || _failed=true
|
||
else
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +Trash\ +{.*)#\1\2\n\1 auto = subscribe\n\1 autoexpunge = 3d#g" \
|
||
${_conf_file} || _failed=true
|
||
fi
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +Sent\ +{.*)#\1\2\n\1 auto = subscribe#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)(mailbox\ +\"Sent Messages\"\ +{.*)#\1\2\n\1 auto = no#g" \
|
||
${_conf_file} || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting ${_conf_file} failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/15-mailboxes.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-auth.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Adjusting Authentication ($(basename "${_conf_file}")).."
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-auth.conf
|
||
#
|
||
# auth_allow_cleartext = no
|
||
# auth_allow_weak_schemes = ys
|
||
# auth_username_translation = "%@"
|
||
# auth_mechanisms = $auth_mechanisms
|
||
# !include auth-sql.conf.ext # !! comment all other includes
|
||
#
|
||
|
||
if grep -qE "^\s*auth_allow_cleartext\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "auth_allow_cleartext" "no" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# If no, disables the LOGIN command and all other cleartext authentication unless
|
||
# SSL/TLS is used (LOGINDISABLED capability) or the connection is secured (see ssl).
|
||
#
|
||
# This setting replaces the 'disable_plaintext_auth' setting.
|
||
auth_allow_cleartext = no
|
||
EOF
|
||
fi
|
||
|
||
if grep -qE "^\s*auth_allow_weak_schemes\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "auth_allow_weak_schemes" "yes" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# auth_allow_weak_schemes
|
||
#
|
||
# Default no
|
||
# Value boolean
|
||
# Changes Added: 2.4.0
|
||
#
|
||
# Controls whether password schemes marked as weak are allowed to be used. See
|
||
# Password Schemes for disabled by default schemes.
|
||
#
|
||
# If enabled, will emit warning to logs. If a disabled scheme is used, an error
|
||
# is logged.
|
||
#
|
||
# Notably, any explicitly cleartext schemes (such as PLAIN), CRAM-MD5, and
|
||
# DIGEST-MD5 are not affected by this setting.
|
||
auth_allow_weak_schemes = yes
|
||
EOF
|
||
fi
|
||
|
||
if grep -qE "^\s*auth_username_translation\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "auth_username_translation" "%@" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# If set, performs username character translations before querying the auth database.
|
||
#
|
||
# The value is a string formed of sets of from and to characters alternating.
|
||
#
|
||
# A value of #@/@ means that # and / will both be translated to the @ character.
|
||
auth_username_translation ="%@"
|
||
EOF
|
||
fi
|
||
|
||
if grep -qE "^\s*auth_mechanisms\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "auth_mechanisms" "${auth_mechanisms}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Cleartext Authentication
|
||
#
|
||
# The simplest authentication mechanism is PLAIN. The client simply sends the password
|
||
# unencrypted to Dovecot. All clients support the PLAIN mechanism, but obviously there's
|
||
# the problem that anyone listening on the network can steal the password. For that
|
||
# reason (and some others) other mechanisms were implemented.
|
||
#
|
||
# Today however many people use SSL, and there's no problem with sending unencrypted
|
||
# password inside SSL secured connections. So if you're using SSL, you probably don't
|
||
# need to bother worrying about anything else than the PLAIN mechanism.
|
||
#
|
||
# Another cleartext mechanism is LOGIN. It's typically used only by SMTP servers to let
|
||
# Outlook clients perform SMTP authentication. Note that LOGIN mechanism is not the
|
||
# same as IMAP's LOGIN command. The LOGIN command is internally handled using PLAIN
|
||
# mechanism.
|
||
#
|
||
# see https://doc.dovecot.org/2.4.1/core/config/auth/mechanisms/overview.html for
|
||
# further (non-rcCleartext) Authentication.
|
||
auth_mechanisms = ${auth_mechanisms}
|
||
EOF
|
||
fi
|
||
|
||
if grep -qE "^\s*\!include\s+" "${_conf_file}"; then
|
||
|
||
sed -i "s|^!include[[:space:]]\+.*$|!include auth-sql.conf.ext|" "${_conf_file}"
|
||
|
||
else
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
##
|
||
## Password and user databases
|
||
##
|
||
|
||
#
|
||
# Password database is used to verify user's password (and nothing more).
|
||
# You can have multiple passdbs and userdbs. This is useful if you want to
|
||
# allow both system users (/etc/passwd) and virtual users to login without
|
||
# duplicating the system users into virtual database.
|
||
#
|
||
# <doc/wiki/PasswordDatabase.txt>
|
||
#
|
||
# User database specifies where mails are located and what user/group IDs
|
||
# own them. For single-UID configuration use "static" userdb.
|
||
#
|
||
# <doc/wiki/UserDatabase.txt>
|
||
|
||
!include auth-sql.conf.ext
|
||
EOF
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-auth.conf
|
||
## -
|
||
## - disable_plaintext_auth = no
|
||
## - auth_mechanisms = $auth_mechanisms
|
||
## - !include auth-sql.conf.ext # comment all other includes
|
||
## - auth_username_translation = "%@"
|
||
## -
|
||
echononl " Adjusting Authentication ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(disable_plaintext_auth\ +=.*)#\1\#\# \2\n\1disable_plaintext_auth = yes#" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_mechanisms\ +=.*)#\1\#\# \2\n\1auth_mechanisms = $auth_mechanisms#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^(\!include\ auth-.*)#\#\1#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^\#(\!include\ auth-sql.*)#\1#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_username_translation\ +=.*)#\1\#\# \2\n\1auth_username_translation = \"%@\"#g" \
|
||
${_conf_file} || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting ${_conf_file} failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-auth.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/auth-sql.conf.ext
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/auth-sql.conf.ext"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/auth-sql.conf.ext
|
||
#
|
||
# passdb_name = sql
|
||
# passdb sql {
|
||
# driver = sql
|
||
#
|
||
# # Path for SQL configuration file
|
||
# args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
|
||
# }
|
||
#
|
||
# userdb_name = sql
|
||
# passdb sql {
|
||
# driver = sql
|
||
#
|
||
# # Path for SQL configuration file
|
||
# args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
|
||
# }
|
||
#
|
||
# !! Note !!
|
||
#
|
||
# Ther above settings are equivalent to the following settins:
|
||
#
|
||
# passdb_name = sql
|
||
# passdb_driver = sql
|
||
# passdb_args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
|
||
#
|
||
# userdb_name = sql
|
||
# userdb_driver = sql
|
||
# userdb_args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
|
||
|
||
echononl " Adjusting SQL auth '$(basename "${_conf_file}")'.."
|
||
|
||
if [[ "$db_driver" = "pgsql" ]]; then
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
passdb sql {
|
||
|
||
# Load SQL connection data
|
||
!include /usr/local/dovecot-2.4.1-4/etc/dovecot/sql-connect.conf.ext
|
||
|
||
query = SELECT username AS user, password \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*passdb\s+sql\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "passdb sql" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot uses passdb and userdb as part of the authentication process.
|
||
#
|
||
# passdb authenticates the user. It also provides any other pre-login information
|
||
# needed for users, such as:
|
||
#
|
||
# - Which server user is proxied to.
|
||
# - If user should be allowed to log in at all (temporarily or permanently).
|
||
#
|
||
# Passdb Lookups Dovecot Proxy Dovecot Backend
|
||
# ----------------------------------------------------------
|
||
# IMAP & POP3 logins YES YES
|
||
# LMTP mail delivery YES YES
|
||
# doveadm commands YES YES
|
||
#
|
||
# see also: https://doc.dovecot.org/2.4.1/core/config/auth/passdb.html
|
||
#
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
userdb sql {
|
||
|
||
# Load SQL connection data
|
||
!include /usr/local/dovecot-2.4.1-4/etc/dovecot/sql-connect.conf.ext
|
||
|
||
query = SELECT '/var/vmail/' || maildir AS home, \\
|
||
'5000' AS uid, '5000' AS gid \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
#iterate_query = SELECT userid AS username, domain FROM mailbox
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*userdb sql\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "userdb" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot uses passdb and userdb as part of the authentication process.
|
||
#
|
||
# passdb authenticated the user. userdb lookup then retrieves post-login information
|
||
# specific to the authenticated user. This may include:
|
||
#
|
||
# - Mailbox location information
|
||
# - Quota limit
|
||
# - Overriding settings for the user (almost any setting can be overridden)
|
||
#
|
||
#
|
||
# Userdb Lookups Dovecot Proxy Dovecot Backend
|
||
# ----------------------------------------------------------
|
||
# IMAP & POP3 logins No YES
|
||
# LMTP mail delivery No YES
|
||
# doveadm commands No YES
|
||
#
|
||
# The userdb and passdb may be the same or they may be different depending on your needs.
|
||
# You can also have multiple authentication databases.
|
||
#
|
||
# see: https://doc.dovecot.org/2.4.1/core/config/auth/userdb.html
|
||
#
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
elif [[ "$db_driver" = "mysql" ]]; then
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
passdb sql {
|
||
|
||
# Load SQL connection data
|
||
!include /usr/local/dovecot-2.4.1-4/etc/dovecot/sql-connect.conf.ext
|
||
|
||
query = SELECT username AS user, password \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*passdb\s+sql\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "passdb sql" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot uses passdb and userdb as part of the authentication process.
|
||
#
|
||
# passdb authenticates the user. It also provides any other pre-login information
|
||
# needed for users, such as:
|
||
#
|
||
# - Which server user is proxied to.
|
||
# - If user should be allowed to log in at all (temporarily or permanently).
|
||
#
|
||
# Passdb Lookups Dovecot Proxy Dovecot Backend
|
||
# ----------------------------------------------------------
|
||
# IMAP & POP3 logins YES YES
|
||
# LMTP mail delivery YES YES
|
||
# doveadm commands YES YES
|
||
#
|
||
# see also: https://doc.dovecot.org/2.4.1/core/config/auth/passdb.html
|
||
#
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
userdb sql {
|
||
|
||
# Load SQL connection data
|
||
!include /usr/local/dovecot-2.4.1-4/etc/dovecot/sql-connect.conf.ext
|
||
|
||
query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\
|
||
'5000' AS uid, '5000' AS gid \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
#iterate_query = SELECT userid AS username, domain FROM mailbox
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*userdb sql\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "userdb" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot uses passdb and userdb as part of the authentication process.
|
||
#
|
||
# passdb authenticated the user. userdb lookup then retrieves post-login information
|
||
# specific to the authenticated user. This may include:
|
||
#
|
||
# - Mailbox location information
|
||
# - Quota limit
|
||
# - Overriding settings for the user (almost any setting can be overridden)
|
||
#
|
||
#
|
||
# Userdb Lookups Dovecot Proxy Dovecot Backend
|
||
# ----------------------------------------------------------
|
||
# IMAP & POP3 logins No YES
|
||
# LMTP mail delivery No YES
|
||
# doveadm commands No YES
|
||
#
|
||
# The userdb and passdb may be the same or they may be different depending on your needs.
|
||
# You can also have multiple authentication databases.
|
||
#
|
||
# see: https://doc.dovecot.org/2.4.1/core/config/auth/userdb.html
|
||
#
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
fi # if [[ "$db_driver" = "pgsql" ]]; then
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/auth-sql.conf.ext
|
||
## -
|
||
## - passdb {
|
||
## - driver = sql
|
||
## -
|
||
## -
|
||
## - # path for sql configuration file, see example-config/dovecot-sql.conf.ext
|
||
## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
|
||
## - }
|
||
## -
|
||
## - ..
|
||
## -
|
||
## - userdb {
|
||
## - driver = sql
|
||
## - args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext
|
||
## - }
|
||
## -
|
||
echononl " Adjusting SQL auth '$(basename "${_conf_file}")'.."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)(args\ ?=.*)#\1\#\# \2\n\1args = /usr/local/dovecot/etc/dovecot/sql-connect.conf.ext#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/auth-sql.conf.ext
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/auth-sql.conf.ext failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/auth-sql.conf.ext
|
||
|
||
# create file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Create sql configuration file '$(basename "${_conf_file}")'.."
|
||
|
||
if [[ "$db_driver" = "pgsql" ]]; then
|
||
|
||
cat <<EOF > /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext 2> ${log_file}
|
||
##
|
||
## SQL Connection Parameter
|
||
##
|
||
|
||
passdb_default_password_scheme = ${default_pass_scheme}
|
||
sql_driver = pgsql
|
||
|
||
# ----------
|
||
# if using unix-socket (host=/run/postgresql) ensure that
|
||
# coresponding entries in pg_hba.cof fits
|
||
# for example
|
||
# local all all md5
|
||
#
|
||
# ----------
|
||
|
||
pgsql localhost {
|
||
|
||
parameters {
|
||
user=${dbuser}
|
||
password=${dbpassword}
|
||
dbname=${dbname}
|
||
}
|
||
}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
|
||
|
||
cat <<EOF > /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext
|
||
##
|
||
## SQL Connection Parameter
|
||
##
|
||
|
||
passdb_default_password_scheme = ${default_pass_scheme}
|
||
sql_driver = mysql
|
||
|
||
mysql localhost {
|
||
|
||
parameters {
|
||
user=${dbuser}
|
||
password=${dbpassword}
|
||
dbname=${dbname}
|
||
}
|
||
}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
|
||
fi # if [[ "$db_driver" = "pgsql" ]]; then
|
||
|
||
else
|
||
|
||
## - create sql configuration file
|
||
## -
|
||
echononl " Create sql configuration file '$(basename "${_conf_file}")'.."
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
cat <<EOF > /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext
|
||
driver = $db_driver
|
||
## - if using unix-socket (host=/run/postgresql) ensure that
|
||
## - coresponding entries in pg_hba.cof fits
|
||
## - for example
|
||
## - local all all md5
|
||
## -
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
default_pass_scheme = $default_pass_scheme
|
||
password_query = SELECT username AS user, password \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
user_query = SELECT '/var/vmail/' || maildir AS home, \\
|
||
'5000' AS uid, '5000' AS gid \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
#WHERE username = substring ('%{user}' from '#"[^-]+#"_*@%%' for '#') || '@%d' and active = true
|
||
|
||
## - Query to get a list of all usernames.
|
||
## -
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
|
||
cat <<EOF > /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext
|
||
driver = $db_driver
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
default_pass_scheme = $default_pass_scheme
|
||
password_query = SELECT username AS user, password \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\
|
||
'5000' AS uid, '5000' AS gid \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
## - Query to get a list of all usernames.
|
||
## -
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed"
|
||
fi
|
||
fi
|
||
|
||
fi # create file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-logging.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-logging.conf
|
||
#
|
||
# log_path =syslog
|
||
# syslog_facility = local1
|
||
# auth_verbose = yes
|
||
# auth_verbose_passwords = plain
|
||
#
|
||
#
|
||
# in conjunction with the the following entries in /etc/rsyslog.conf
|
||
#
|
||
# local1.* -/var/log/dovecot.log
|
||
# local1.info -/var/log/dovecot.info
|
||
# local1.warn -/var/log/dovecot.warn
|
||
# local1.err -/var/log/dovecot.err
|
||
# :msg,contains,"stored mail into mailbox"\
|
||
# -/var/log/dovecot.lmtp
|
||
|
||
echononl " Configure logging ($(basename "${_conf_file}")).."
|
||
|
||
if grep -qE "^\s*log_path\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "log_path" "syslog" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# Specify the log file to use for error messages.
|
||
#
|
||
# Options:
|
||
#
|
||
# - syslog: Log to syslog
|
||
# - /dev/stderr: Log to stderr
|
||
#
|
||
# If you don't want to use syslog, or if you just can't find the Dovecot's error logs,
|
||
# you can make Dovecot log elsewhere as well:
|
||
#
|
||
# log_path = /var/log/dovecot.log
|
||
#
|
||
# If you don't want errors, info, and debug logs all in one file, specify
|
||
# info_log_path or debug_log_path as well:
|
||
#
|
||
# log_path = /var/log/dovecot.log
|
||
# info_log_path = /var/log/dovecot-info.log
|
||
#
|
||
log_path = syslog
|
||
EOF
|
||
fi
|
||
|
||
|
||
if grep -qE "^\s*syslog_facility\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "syslog_facility" "local1" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# The syslog facility used if you're logging to syslog
|
||
syslog_facility = local1
|
||
EOF
|
||
fi
|
||
|
||
|
||
if grep -qE "^\s*auth_verbose\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "auth_verbose" "yes" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# If yes, log unsuccessful authentication attempts and why they failed.
|
||
auth_verbose = yes
|
||
EOF
|
||
fi
|
||
|
||
|
||
if grep -qE "^\s*auth_verbose_passwords\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "auth_verbose_passwords" "yes" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<'EOF' >> "${_conf_file}" || _failed=true
|
||
|
||
# In case of password mismatches, log the attempted password. You can also truncate
|
||
# the logged password to n chars by appending :n (e.g. sha1:6).
|
||
#
|
||
#Available transformations:
|
||
#
|
||
# plain, yes: Output cleartext password (NOT RECOMMENDED)
|
||
# sha1: Output SHA1 hashed password
|
||
auth_verbose_passwords = plain
|
||
EOF
|
||
fi
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-logging.conf
|
||
## -
|
||
## -
|
||
## - if running inetd-script:
|
||
## -
|
||
## - log_path = /var/log/dovecot/dovecot.log
|
||
## -
|
||
## - or for example
|
||
## -
|
||
## - log_path = syslog
|
||
## - syslog_facility = local1
|
||
## - auth_verbose = yes
|
||
## - auth_verbose_passwords = plain
|
||
## -
|
||
## - in conjunction with the the following entries in /etc/rsyslog.conf
|
||
## -
|
||
## - local1.* -/var/log/dovecot.log
|
||
## - local1.info -/var/log/dovecot.info
|
||
## - local1.warn -/var/log/dovecot.warn
|
||
## - local1.err -/var/log/dovecot.err
|
||
## - :msg,contains,"stored mail into mailbox"\
|
||
## - -/var/log/dovecot.lmtp
|
||
## -
|
||
echononl " Configure logging ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(log_path\ ?=.*)#\1\#\# \2\n\1log_path = syslog#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(syslog_facility\ ?=.*)#\1\#\# \2\n\1syslog_facility = local1#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_verbose\ ?=.*)#\1\#\# \2\n\1auth_verbose = yes#g" \
|
||
${_conf_file} || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_verbose_passwords\ ?=.*)#\1\#\# \2\n\1auth_verbose_passwords = plain#g" \
|
||
${_conf_file} || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting ${_conf_file} failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-logging.conf
|
||
|
||
|
||
if $_new ; then
|
||
|
||
mkdir -p /var/log/dovecot
|
||
|
||
echo
|
||
echononl " Create file /etc/rsyslog.d/dovecot.conf"
|
||
cat <<EOF > /etc/rsyslog.d/dovecot.conf
|
||
|
||
## - dovecot
|
||
## -
|
||
local1.info -/var/log/dovecot/dovecot.info
|
||
local1.warn -/var/log/dovecot/dovecot.warn
|
||
local1.err -/var/log/dovecot/dovecot.err
|
||
:msg,contains,"stored mail into mailbox" \\
|
||
-/var/log/dovecot/dovecot.lmtp
|
||
local1.* -/var/log/dovecot/dovecot.log
|
||
& stop
|
||
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Creating file /etc/rsyslog.d/dovecot.conf failed"
|
||
fi
|
||
|
||
echononl " Restart rsyslog Servive"
|
||
if $systemd_support ; then
|
||
systemctl restart rsyslog.service > /dev/null 2>&1
|
||
else
|
||
/etc/init.d/rsyslog restart > /dev/null 2>&1
|
||
fi
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Restarting rsyslog failed"
|
||
fi
|
||
|
||
|
||
## - logrotate for dovecot log-files
|
||
## -
|
||
echononl " Create file /etc/logrotate.d/dovecot"
|
||
cat <<EOF > /etc/logrotate.d/dovecot
|
||
/var/log/dovecot/dovecot.log
|
||
/var/log/dovecot/dovecot.info
|
||
/var/log/dovecot/dovecot.warn
|
||
/var/log/dovecot/dovecot.err
|
||
/var/log/dovecot/dovecot.lmtp {
|
||
daily
|
||
start 0
|
||
rotate 7
|
||
missingok
|
||
notifempty
|
||
compress
|
||
delaycompress
|
||
create 640 root adm
|
||
copytruncate
|
||
#sharedscripts
|
||
#postrotate
|
||
#/etc/init.d/dovecot reload > /dev/null
|
||
#/bin/kill -usr1 'cat /run/dovecot/master.pid 2>/dev/null' 2>/dev/null || true
|
||
#endscript
|
||
}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Creating file /etc/logrotate.d/dovecot failed"
|
||
fi
|
||
echo
|
||
fi
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/15-lda.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/15-lda.conf
|
||
#
|
||
# postmaster_address = $postmaster_address
|
||
# hostname = $hostname
|
||
# sendmail_path = /usr/sbin/sendmail
|
||
# lda_mailbox_autocreate = no
|
||
#
|
||
# protocol lda {
|
||
# mail_plugins {
|
||
# sieve = yes
|
||
# quota = yes
|
||
# }
|
||
# }
|
||
#
|
||
|
||
echononl " Configure lda ($(basename "${_conf_file}")).."
|
||
|
||
if grep -qE "^\s*postmaster_address\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "postmaster_address" "${postmaster_address}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The From address from which email rejection messages (bounces) are sent.
|
||
#
|
||
# Default postmaster@%{user|domain|default(hostname)}
|
||
#
|
||
# As used here, %{user | domain} expands to the domain of the local user. Other Mail user
|
||
# variables can be used as well.
|
||
# see: https://doc.dovecot.org/2.4.1/core/settings/variables.html#mail-user-variables
|
||
postmaster_address = ${postmaster_address}
|
||
EOF
|
||
fi
|
||
|
||
|
||
if grep -qE "^\s*hostname\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "hostname" "${hostname}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The hostname to be used in email messages sent out by the local delivery agent
|
||
# (such as the Message-ID: header), in LMTP replies, and as the hostname advertised
|
||
# by submission SMTP service.
|
||
#
|
||
# Default: <system's real hostname@domain.tld>
|
||
hostname = ${hostname}
|
||
EOF
|
||
fi
|
||
|
||
|
||
if grep -qE "^\s*sendmail_path\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "sendmail_path" "/usr/sbin/sendmail" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The binary to use for sending email.
|
||
#
|
||
#Used only if submission_host is not set.
|
||
sendmail_path = /usr/sbin/sendmail
|
||
EOF
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
protocol lda {
|
||
|
||
mail_plugins {
|
||
sieve = yes
|
||
quota = yes
|
||
}
|
||
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "protocol lda" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/15-lda.conf
|
||
## -
|
||
## - postmaster_address = $postmaster_address
|
||
## - hostname = $hostname
|
||
## - sendmail_path = /usr/sbin/sendmail
|
||
## - lda_mailbox_autocreate = no
|
||
## - mail_plugins = $mail_plugins sieve
|
||
## -
|
||
echononl " Configure lda ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(postmaster_address\ +=.*)#\1\#\# \2\n\1postmaster_address = $postmaster_address#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(hostname\ +=.*)#\1\#\# \2\n\1hostname = $hostname#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(sendmail_path\ +=.*)#\1\#\# \2\n\1sendmail_path = /usr/sbin/sendmail#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(lda_mailbox_autocreate\ +=.*)#\1\#\# \2\n\1lda_mailbox_autocreate = no#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins sieve#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting '${_conf_file}' failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/15-lda.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-lmtp
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-lmtp
|
||
#
|
||
# lmtp_save_to_detail_mailbox = no
|
||
#
|
||
# protocol lmtp {
|
||
# postmaster_address = $postmaster_address
|
||
# mail_plugins {
|
||
# sieve = yes
|
||
# quota = yes
|
||
# }
|
||
# }
|
||
#
|
||
|
||
: > "${log_file}"
|
||
echononl " Configure lmtp ($(basename "${_conf_file}")).."
|
||
|
||
if grep -qE "^\s*lmtp_save_to_detail_mailbox\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "lmtp_save_to_detail_mailbox" "no" "${_conf_file}" 2> "${log_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# If the recipient address includes a detail element / role (as in user+detail format),
|
||
# save the message to the detail mailbox.
|
||
lmtp_save_to_detail_mailbox = no
|
||
EOF
|
||
fi
|
||
|
||
postmaster_address="argus@oopen.de"
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
protocol lmtp {
|
||
|
||
# The From address from which email rejection messages (bounces) are sent.
|
||
#
|
||
# Default postmaster@%{user|domain|default(hostname)}
|
||
#
|
||
# As used here, %{user | domain} expands to the domain of the local user. Other Mail user
|
||
# variables can be used as well.
|
||
# see: https://doc.dovecot.org/2.4.1/core/settings/variables.html#mail-user-variables
|
||
postmaster_address = ${postmaster_address}
|
||
|
||
mail_plugins {
|
||
sieve = yes
|
||
quota = yes
|
||
}
|
||
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "protocol lda" "${NEW_BLOCK}" "${_conf_file}" 2> "${log_file}" || _failed=true
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-lmtp
|
||
## -
|
||
## - lmtp_save_to_detail_mailbox = no
|
||
## - mail_plugins = $mail_plugins sieve
|
||
## -
|
||
echononl " Configure lmtp ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(lmtp_save_to_detail_mailbox\ +=.*)#\1\#\# \2\n\1lmtp_save_to_detail_mailbox = no#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins sieve#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting '${_conf_file}' failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-lmtp.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf
|
||
#
|
||
# imap_client_workarounds = delay-newmail
|
||
#
|
||
# protocol imap {
|
||
#
|
||
# mail_plugins = $mail_plugins imap_quota
|
||
# mail_max_userip_connections = $max_userip_connections
|
||
#
|
||
# ssl_client {
|
||
# cert_file = $imap_cert
|
||
# key_file = $imap_key
|
||
# }
|
||
#
|
||
# }
|
||
|
||
echononl " Configure imap protocol ($(basename "${_conf_file}")).."
|
||
|
||
if grep -qE "^\s*imap_client_workarounds\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "imap_client_workarounds" "delay-newmail" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
# Workarounds for various IMAP client bugs can be enabled here.
|
||
#
|
||
# The following values are currently supported:
|
||
#
|
||
# delay-newmail
|
||
# EXISTS/RECENT new-mail notifications are sent only in replies to NOOP and CHECK
|
||
# commands. Some clients, such as pre-2.1 versions of Mac OS X Mail, ignore them
|
||
# otherwise, and, worse, Outlook Express may report that the message is no longer
|
||
# on the server (note that the workaround does not help for OE6 if synchronization
|
||
# is set to Headers Only).
|
||
# tb-extra-mailbox-sep
|
||
# Because mailbox_list_layout = fs (mbox and dbox) confuses Thunderbird, causing
|
||
# extra / suffixes to mailbox names, Dovecot can be told to ignore the superfluous
|
||
# character instead of judging the mailbox name to be invalid.
|
||
# tb-lsub-flags
|
||
# Without this workaround, Thunderbird doesn't immediately recognize that LSUB
|
||
# replies with mailbox_list_layout = fs aren't selectable, and users may receive
|
||
# pop-ups with not selectable errors. Showing \Noselect flags for these replies
|
||
# (e.g., in mbox use) causes them to be grayed out.
|
||
imap_client_workarounds = delay-newmail
|
||
EOF
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
protocol imap {
|
||
|
||
# The maximum number of IMAP connections allowed for a user from each IP address.
|
||
#
|
||
# This setting is checked only by backends, not proxies.
|
||
#
|
||
# Note that for this to work, any username changes must be done already by
|
||
# passdb lookup (not by userdb lookup).
|
||
#
|
||
# Unique users are identified via case-sensitive comparison.
|
||
mail_max_userip_connections = $max_userip_connections
|
||
|
||
# A list of mail plugins to load.
|
||
mail_plugins {
|
||
acl = yes
|
||
quota = yes
|
||
imap_quota = yes
|
||
}
|
||
|
||
ssl_client {
|
||
cert_file = $imap_cert
|
||
key_file = $imap_key
|
||
}
|
||
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "protocol imap" "${NEW_BLOCK}" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf
|
||
## -
|
||
## - ssl_cert = <$imap_cert
|
||
## - ssl_key = <$imap_key
|
||
## - mail_max_userip_connections = $max_userip_connections
|
||
## - mail_plugins = $mail_plugins imap_quota
|
||
## - imap_client_workarounds = delay-newmail
|
||
## -
|
||
echononl " Configure imap protocol ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(protocol imap \{)#\1\2\n\n\1 ssl_cert = <$imap_cert\n\1 ssl_key = <$imap_key\n#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_max_userip_connections\ +=.*)#\1\#\# \2\n\1mail_max_userip_connections = $max_userip_connections#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins imap_quota#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(imap_client_workarounds\ +=.*)#\1\#\# \2\n\1imap_client_workarounds = delay-newmail#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting '${_conf_file}' failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-pop3.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Configure pop3 protocol ($(basename "${_conf_file}")).."
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-pop3.conf
|
||
#
|
||
# pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
|
||
#
|
||
# protocol pop3 {
|
||
# ssl_client {
|
||
# cert_file = $imap_cert
|
||
# key_file = $imap_key
|
||
# }
|
||
# }
|
||
|
||
if grep -qE "^\s*pop3_client_workarounds\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "pop3_client_workarounds" "outlook-no-nuls oe-ns-eoh" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
# Workarounds for various POP3 client bugs can be enabled here.
|
||
#
|
||
# The following values are currently supported:
|
||
#
|
||
# oe-ns-eoh
|
||
# Because Outlook Express and Netscape Mail expect an end-of-headers line,
|
||
# this option sends one explicitly if none has been sent.
|
||
# outlook-no-nuls
|
||
# Because Outlook and Outlook Express hang if messages contain NUL characters,
|
||
# this setting replaces each of them with a 0x80 character.
|
||
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
|
||
EOF
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
protocol pop3 {
|
||
|
||
# A list of mail plugins to load.
|
||
mail_plugins {
|
||
acl = yes
|
||
quota = yes
|
||
}
|
||
|
||
ssl_client {
|
||
cert_file = $pop_cert
|
||
key_file = $pop_key
|
||
}
|
||
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "protocol pop3" "${NEW_BLOCK}" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-pop3.conf
|
||
## -
|
||
## - ssl_cert = <$pop_cert
|
||
## - ssl_key = <$pop_key
|
||
## - mail_max_userip_connections = 24
|
||
## - pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
|
||
## -
|
||
echononl " Configure pop3 protocol ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(protocol pop3 \{)#\1\2\n\n\1 ssl_cert = <$pop_cert\n\1 ssl_key = <$pop_key\n#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_max_userip_connections\ +=.*)#\1\#\# \2\n\1mail_max_userip_connections = 24#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(pop3_client_workarounds\ +=.*)#\1\#\# \2\n\1pop3_client_workarounds = outlook-no-nuls oe-ns-eoh#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting '${_conf_file}' failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-pop3.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/90-plugin.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-plugin.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Adjusting expire plugin file '$(basename "${_conf_file}")'.."
|
||
echo -e "$rc_skipped"
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-plugin.conf
|
||
## -
|
||
## - Note:
|
||
## - Setting "autocreate", "autosubscribe" here is depricated. Use mailbox { auto } setting instead.
|
||
## -
|
||
## - expire = Trash
|
||
## - expire2 = Trash/*
|
||
## - expire3 = Spam
|
||
## -
|
||
## - expire_dict = proxy::expire
|
||
## -
|
||
## - # Enable caching of dict value in dovecot.index file. This significantly reduces
|
||
## - # the number of dict lookups. It makes initial testing more confusing though, so
|
||
## - # it's better to enable it only after you've verified that the expire plugin is
|
||
## - # working as wanted. (v2.2.16+)
|
||
## - expire_cache = yes
|
||
## -
|
||
echononl " Adjusting expire plugin file '$(basename "${_conf_file}")'.."
|
||
if $plugin_expire ; then
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)(\#?\ ?setting_name\ +=.*)#\1\2\n\n\1expire = Trash\n\1expire2 = Trash/*\n\1expire3 = $spam_folder\n\n\1expire_dict = proxy::expire\n\n\1\# Enable caching of dict value in dovecot.index file. This significantly reduces\n\1\# the number of dict lookups. It makes initial testing more confusing though, so\n\1\# it's better to enable it only after you've verified that the expire plugin is\n\1\# working as wanted. (v2.2.16+)\n\1expire_cache = yes#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting '${_conf_file}' failed"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/90-plugin.conf
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Adjusting sieve configuration ($(basename "${_conf_file}")).."
|
||
|
||
if grep -qE "^\s*sieve_script\s+personal\s*{" "${_conf_file}"; then
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
|
||
sieve_script personal {
|
||
driver = file
|
||
path = ~/sieve
|
||
active_path = ~/.dovecot.sieve
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "sieve_script personal" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2> "${log_file}"
|
||
|
||
# personal
|
||
# --------
|
||
#
|
||
# The personal storage serves as the user's main personal storage. Although more than a single
|
||
# personal storage can be defined, only the first one listed in the configuration is used.
|
||
#
|
||
# The LDA Sieve plugin uses the personal storage to find the active script for Sieve filtering
|
||
# at delivery. If the storage supports storing more than a single script (e.g. the file
|
||
# storage does), personal scripts can also be retrieved by name. The Sieve include extension
|
||
# will then use this storage for retrieving :personal scripts and the ManageSieve service will
|
||
# be able to store the user's scripts there.
|
||
#
|
||
# If the storage supports storing more than a single script, only one of those scripts will be
|
||
# the active script used at delivery. The active script can be managed by the user through the
|
||
# ManageSieve service. If the personal storage has no active script, the default script will
|
||
# be executed if configured.
|
||
#
|
||
# If no personal storage is defined explicitly, auto-detection will be attempted. This is
|
||
# currently only trying the [[link,sieve_storage_file,file storage driver], which looks for
|
||
# a ~/.dovecot.sieve script file or a directory at ~/sieve/ containing script files. In the
|
||
# latter case ~/.dovecot.sieve is expected to be a symbolic link pointing to the active script
|
||
# file. If auto-detection also finds no personal storage, Sieve processing will be skipped and
|
||
# no default script is executed.
|
||
|
||
sieve_script personal {
|
||
driver = file
|
||
path = ~/sieve
|
||
active_path = ~/.dovecot.sieve
|
||
}
|
||
EOF
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi
|
||
|
||
|
||
if grep -qE "^\s*sieve_script\s+before\s*{" "${_conf_file}"; then
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
|
||
sieve_script before {
|
||
driver = file
|
||
path = /usr/local/dovecot/etc/dovecot/sieve/
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "sieve_script before" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2> "${log_file}"
|
||
|
||
# after
|
||
# -----
|
||
#
|
||
# An after storage is the source of one script or several scripts that are to be executed after
|
||
# the user's personal script. If the storage supports storing more than a single script, these
|
||
# scripts will be executed in a well-defined order defined by the storage driver. Multiple after
|
||
# storages can be configured and each storage will be accessed in sequence to retrieve scripts
|
||
# for execution after the personal script. The storages will be accessed in the order these
|
||
# storages are defined in the configuration, unless the order is overridden by the
|
||
# sieve_script_precedence setting.
|
||
#
|
||
# This is usually a global script, so be sure to pre-compile the specified script manually in
|
||
# that case using the sievec command line tool, as explained by sievec(1).
|
||
#
|
||
# before
|
||
# ------
|
||
#
|
||
# A before storage behaves identical to an after storage, except the contained script or
|
||
# scripts are run before user's personal script (instead of after).
|
||
|
||
sieve_script before {
|
||
driver = file
|
||
path = /usr/local/dovecot/etc/dovecot/sieve/
|
||
}
|
||
EOF
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi
|
||
|
||
|
||
if grep -qE "^\s*sieve_script\s+global\s*{" "${_conf_file}"; then
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
|
||
sieve_script global {
|
||
driver = file
|
||
path = /usr/local/dovecot/etc/dovecot/sieve/global/
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "sieve_script global" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2> "${log_file}"
|
||
|
||
# default
|
||
# -------
|
||
#
|
||
# The default storage yields the sieve script that gets executed only if the user's personal
|
||
# Sieve script does not exist. Although more than a single default storage can be defined,
|
||
# only the first one listed in the configuration is used.
|
||
#
|
||
# If sieve_script_name is set for this script storage, the default script can be seen and
|
||
# accessed by this name through ManageSieve (and doveadm sieve). See below (Sieve visible
|
||
# default script).
|
||
#
|
||
# This is usually a global script, so be sure to pre-compile the specified script manually in
|
||
# that case using the sievec command line tool, as explained by sievec(1).
|
||
#
|
||
# discard
|
||
# -------
|
||
#
|
||
# The discard storage yields the sieve script that gets executed for any message that is about
|
||
# to be discarded; i.e., it is not delivered anywhere by the normal Sieve execution. Although
|
||
# more than a single discard storage can be defined, only the first one listed in the
|
||
# configuration is used. The discard storage is currently only applicable for message delivery.
|
||
#
|
||
# The script from the discard storage is only executed when the "implicit keep" is canceled,
|
||
# by e.g. the "discard" action, and no actions that deliver the message are executed. Delivery
|
||
# in this case means both local delivery to a mailbox and redirection to a remote recipient.
|
||
# This "discard script" can prevent discarding the message, by executing alternative actions.
|
||
# If the discard script does nothing, the message is still discarded as it would be when no
|
||
# scard script is configured.
|
||
#
|
||
# global
|
||
# -------
|
||
#
|
||
# A global storage is the source of :global include scripts for the Sieve include extension.
|
||
# Scripts are accessed by name, so if the storage yields only one script, a name must be
|
||
# defined for it; either implicitly by the storage driver or explicitly using sieve_script_name.
|
||
# Multiple global storages can be configured and each storage will be queried in sequence to
|
||
# retrieve the requested script by name. The storages will be queried in the order these
|
||
# storages are defined in the configuration until the script is found. The order can be
|
||
# overridden by the sieve_script_precedence setting.
|
||
|
||
sieve_script global {
|
||
driver = file
|
||
path = /usr/local/dovecot/etc/dovecot/sieve/global/
|
||
}
|
||
EOF
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf
|
||
## -
|
||
## - sieve = ~/.dovecot.sieve
|
||
## - #sieve_global_path = /usr/local/dovecot/etc/dovecot/sieve/default.sieve
|
||
## - sieve_before = /usr/local/dovecot/etc/dovecot/sieve/move-spam.sieve
|
||
## - sieve_dir = ~/sieve
|
||
## - sieve_global = /usr/local/dovecot/etc/dovecot/sieve/global/
|
||
## - recipient_delimiter =
|
||
## -
|
||
echononl " Adjusting sieve configuration ($(basename "${_conf_file}")).."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(sieve\ ?=.*)#\1\#\# \2\n\1sieve = ~/.dovecot.sieve#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(sieve_before\ ?=.*)#\1\#\# \2\n\1sieve_before =/usr/local/dovecot/etc/dovecot/sieve/move-spam.sieve#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(sieve_dir\ ?=.*)#\1\#\# \2\n\1sieve_dir = ~/sieve#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(sieve_global\ ?=.*)#\1\#\# \2\n\1sieve_global = /usr/local/dovecot/etc/dovecot/sieve/global/#g" \
|
||
"${_conf_file}" || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(recipient_delimiter\ ?=.*)#\1\#\# \2\n\1recipient_delimiter =#g" \
|
||
"${_conf_file}" || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting "${_conf_file}""
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf
|
||
|
||
|
||
# adjust /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf
|
||
#
|
||
# Add Setting for included Pigeonhole Sieve: Vacation Extension
|
||
#
|
||
_failed=false
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/95-sieve-vacation.conf"
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/95-sieve-vacation.conf
|
||
#
|
||
# sieve_extensions {
|
||
# vacation-seconds = yes
|
||
# }
|
||
#
|
||
# # One hour at minimum
|
||
# sieve_vacation_min_period = 1h
|
||
#
|
||
# # Ten days default
|
||
# sieve_vacation_default_period = 10d
|
||
#
|
||
# # Thirty days at maximum
|
||
# sieve_vacation_max_period = 30d
|
||
|
||
echononl " Add Setting for included Pigeonhole Sieve: Vacation Extension'.."
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
|
||
sieve_extensions {
|
||
vacation-seconds = yes
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "sieve_extensions" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
_replace_key="sieve_vacation_min_period"
|
||
_replace_val="1h"
|
||
|
||
read -r -d '' COMMENT_BLOCK <<EOF
|
||
# sieve_vacation_min_period
|
||
#
|
||
# Default 1d
|
||
# Value time
|
||
#
|
||
# Specifies the minimum period that can be specified for the :days and :seconds
|
||
# tags of the vacation command.
|
||
#
|
||
# A minimum of 0 indicates that users are allowed to make the Sieve interpreter send
|
||
# a vacation response message for every incoming message that meets the other reply
|
||
# criteria (refer to RFC 5230). A value of zero is not recommended.
|
||
|
||
EOF
|
||
|
||
|
||
if grep -qE "^\s*${_replace_key}\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "${_replace_key}" "${_replace_val}" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
${COMMENT_BLOCK}
|
||
${_replace_key} = ${_replace_val}
|
||
EOF
|
||
fi
|
||
|
||
_replace_key="sieve_vacation_default_period"
|
||
_replace_val="10d"
|
||
|
||
read -r -d '' COMMENT_BLOCK <<EOF
|
||
# sieve_vacation_min_period
|
||
#
|
||
# Default 7d
|
||
# Value time
|
||
#
|
||
# Specifies the default period that is used when no :days or :seconds tag is specified.
|
||
#
|
||
# The configured value must lie between sieve_vacation_min_period and
|
||
# sieve_vacation_max_period.
|
||
EOF
|
||
|
||
|
||
if grep -qE "^\s*${_replace_key}\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "${_replace_key}" "${_replace_val}" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
${COMMENT_BLOCK}
|
||
${_replace_key} = ${_replace_val}
|
||
EOF
|
||
fi
|
||
|
||
_replace_key="sieve_vacation_max_period"
|
||
_replace_val="60d"
|
||
|
||
read -r -d '' COMMENT_BLOCK <<EOF
|
||
# sieve_vacation_min_period
|
||
#
|
||
# Default 60d
|
||
# Value time
|
||
#
|
||
# Specifies the maximum period that can be specified for the :days tag of the
|
||
# vacation command.
|
||
#
|
||
# The configured value must be larger than sieve_vacation_min_period.
|
||
#
|
||
# A value of 0 has a special meaning: it indicates that there is no upper limit.
|
||
EOF
|
||
|
||
|
||
if grep -qE "^\s*${_replace_key}\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "${_replace_key}" "${_replace_val}" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
${COMMENT_BLOCK}
|
||
${_replace_key} = ${_replace_val}
|
||
EOF
|
||
fi
|
||
|
||
_replace_key="sieve_vacation_send_from_recipient"
|
||
_replace_val="yes"
|
||
|
||
read -r -d '' COMMENT_BLOCK <<EOF
|
||
# sieve_vacation_min_period
|
||
#
|
||
# Default no
|
||
# Value boolean
|
||
#
|
||
# This setting determines whether vacation messages are sent with the SMTP MAIL FROM
|
||
# envelope address set to the recipient address of the Sieve script owner.
|
||
#
|
||
# Normally this is set to <>, which is the default as recommended in the specification.
|
||
# This is meant to prevent mail loops. However, there are situations for which a valid
|
||
# sender address is required and this setting can be used to accommodate for those.
|
||
EOF
|
||
|
||
|
||
if grep -qE "^\s*${_replace_key}\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "${_replace_key}" "${_replace_val}" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
${COMMENT_BLOCK}
|
||
${_replace_key} = ${_replace_val}
|
||
EOF
|
||
fi
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
|
||
else
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf"
|
||
|
||
# - Add Setting from Pigeonhole Sieve: Vacation Extension
|
||
# -
|
||
echononl " Add Setting for included Pigeonhole Sieve: Vacation Extension"
|
||
|
||
_found=false
|
||
_tmp_file="/tmp/dovecot_conf_90-sieve.conf"
|
||
#cp -a "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" "$_tmp_file" > /dev/null 2>&1
|
||
:> $_tmp_file
|
||
while IFS='' read -r _line || [[ -n $_line ]] ; do
|
||
|
||
echo "$_line" >> "$_tmp_file"
|
||
|
||
if ! $_found && $(echo "$_line" | grep -i -E "^\s*plugin {" > /dev/null 2>&1) ; then
|
||
_found=true
|
||
|
||
cat <<EOF >> "$_tmp_file"
|
||
|
||
# Add Setting 'sieve_vacation_send_from_recipient' from (included)
|
||
#
|
||
# Pigeonhole Sieve: Vacation Extension
|
||
# ====================================
|
||
#
|
||
# sieve_vacation_send_from_recipient
|
||
#
|
||
# Default: no
|
||
#
|
||
# Values: Boolean
|
||
#
|
||
# This setting determines whether vacation messages are sent with the
|
||
# SMTP MAIL FROM envelope address set to the recipient address of the
|
||
# Sieve script owner.
|
||
#
|
||
# Normally this is set to <>, which is the default as recommended in the
|
||
# specification. This is meant to prevent mail loops. However, there are
|
||
# situations for which a valid sender address is required and this setting
|
||
# can be used to accommodate for those.
|
||
#
|
||
sieve_vacation_send_from_recipient = yes
|
||
|
||
EOF
|
||
fi
|
||
done < "${_conf_file}"
|
||
cp -a "$_tmp_file" "${_conf_file}" > /dev/null 2>&1
|
||
echo -e "$rc_done"
|
||
|
||
fi # adjust /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf
|
||
|
||
|
||
echononl " Create Directory for global sieve scripts"
|
||
mkdir -p "/usr/local/dovecot-${_version}/etc/dovecot/sieve/global/" > $log_file 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
|
||
|
||
## - ceate global sieve script
|
||
## -
|
||
echononl " Ceate global sieve script"
|
||
cat <<EOF > /usr/local/dovecot-${_version}/etc/dovecot/sieve/move-spam.sieve
|
||
require ["fileinto"];
|
||
# rule:[Move Spam]
|
||
# Move spam to spam folder
|
||
if header :contains "X-Spam-Flag" ["YES"] {
|
||
fileinto "$spam_folder";
|
||
#discard;
|
||
stop;
|
||
}
|
||
EOF
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating global sieve script failed"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
|
||
## - NOTICE: if you pre-compile your (global) scripts, you will increase
|
||
## - performance
|
||
## -
|
||
echononl " Precompile global sieve script"
|
||
cd /usr/local/dovecot-${_version}/etc/dovecot/sieve/
|
||
/usr/local/dovecot-${_version}/bin/sievec \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/sieve/move-spam.sieve > $log_file 2>&1
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat $log_file)"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
|
||
|
||
## - you can also give dovecot's delivery service (lda / lmtp) the permissions to write
|
||
## - into the sieve directory. then dovecots delivery service will compile the script
|
||
## - by first using..
|
||
## -
|
||
chown -R vmail:vmail /usr/local/dovecot-${_version}/etc/dovecot/sieve
|
||
|
||
if $systemd_support; then
|
||
|
||
## - # - At time, we don't use private tmp directory for divecot.
|
||
## - # -
|
||
## - echononl " Adjust Systemd service file, set PrivateTmp=false.."
|
||
## - 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
|
||
## - perl -i -n -p -e "s/(PrivateTmp\s*=\s*)true/\1false/" /etc/systemd/system/dovecot.service
|
||
## - if [[ $? -eq 0 ]]; then
|
||
## - echo -e "$rc_done"
|
||
## - else
|
||
## - echo -e "$rc_failed"
|
||
## - fi
|
||
## - else
|
||
## - echo -e "$rc_skipped"
|
||
## - fi
|
||
## - else
|
||
## - echo -e "$rc_skipped"
|
||
## - fi
|
||
|
||
## - Increase LimitNOFILE to fit dovecots setting for 'default_client_limit'.
|
||
## -
|
||
## - here:
|
||
## - LimitNOFILE=32768
|
||
## -
|
||
if [[ -f "/lib/systemd/system/dovecot.service" ]] \
|
||
&& $(grep -q -E "^LimitNOFILE=" /lib/systemd/system/dovecot.service) ; then
|
||
|
||
_LimitNOFILE="$(grep -E "^LimitNOFILE=[[:digit:]]+" /lib/systemd/system/dovecot.service | cut -d'=' -f2)"
|
||
|
||
adjust_limit_nofile=false
|
||
|
||
if [[ $service_limit_nofile -gt _LimitNOFILE ]] ; then
|
||
|
||
adjust_limit_nofile=true
|
||
echononl " Create 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"
|
||
adjust_limit_nofile=false
|
||
fi
|
||
fi
|
||
|
||
fi
|
||
|
||
echononl " Adjust 'LimitNOFILE' for 'dovecot.service'.."
|
||
if ! $adjust_limit_nofile ; then
|
||
echo -e "$rc_skipped"
|
||
else
|
||
cat <<EOF > /etc/systemd/system/dovecot.service.d/set-limit-nofile.conf
|
||
[Service]
|
||
LimitNOFILE=$service_limit_nofile
|
||
EOF
|
||
echo -e "$rc_done"
|
||
fi
|
||
fi
|
||
|
||
|
||
echononl " Reload systemd .."
|
||
systemctl daemon-reload > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fi
|
||
|
||
## - Make dovecot start at boot time
|
||
## -
|
||
echononl " Make dovecot start at boottime.."
|
||
systemctl enable dovecot > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Make dovecot start at boottime (systend service) failed"
|
||
fi
|
||
|
||
else
|
||
|
||
## - Make dovecot start at boot time
|
||
## -
|
||
echononl " Make dovecot start at boottime.."
|
||
update-rc.d dovecot defaults > /dev/null 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Make dovecot start at boottime (init script) failed"
|
||
fi
|
||
|
||
fi
|
||
|
||
|
||
if $_new ; then
|
||
|
||
if ! $systemd_support; then
|
||
|
||
_create_init=""
|
||
echo
|
||
echo -n "Create init script /etc/init.d/dovecot ? [y/n]: "
|
||
read _create_init
|
||
if [ "y" = "$_create_init" -o "Y" = "$_create_init" -o "Yes" = "$_create_init" -o "yes" = "$_create_init" ];then
|
||
echononl " Create init script for dovecot .."
|
||
## - running dovecot service via init-script
|
||
## -
|
||
cat <<EOF > /etc/init.d/dovecot
|
||
#! /bin/sh
|
||
### BEGIN INIT INFO
|
||
# Provides: dovecot
|
||
# Required-Start: \$syslog \$postgresql
|
||
# Required-Stop: \$syslog \$postgresql
|
||
# Should-Start: \$local_fs \$time ntp
|
||
# Should-Stop: \$local_fs
|
||
# Default-Start: 2 3 4 5
|
||
# Default-Stop: 0 1 6
|
||
# Short-Description: Dovecot init script
|
||
# Description: Init script for dovecot services
|
||
### END INIT INFO
|
||
|
||
# Author: Miquel van Smoorenburg <miquels@cistron.nl>.
|
||
# Modified for Debian GNU/Linux
|
||
# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
|
||
#
|
||
|
||
# Do NOT "set -e"
|
||
ulimit -n 32768
|
||
|
||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/dovecot/sbin/dovecot:/usr/local/dovecot/bin
|
||
DESC="IMAP/POP3 mail server"
|
||
NAME=dovecot
|
||
DAEMON=/usr/local/dovecot/sbin/dovecot
|
||
DAEMON_ARGS=""
|
||
SCRIPTNAME=/etc/init.d/\$NAME
|
||
CONF=/usr/local/dovecot/etc/dovecot/\${NAME}.conf
|
||
|
||
# Read configuration variable file if it is present
|
||
[ -r /etc/default/\$NAME ] && . /etc/default/\$NAME
|
||
|
||
# Exit if the package is not installed
|
||
[ -x "\$DAEMON" ] || exit 0
|
||
|
||
# Exit if the configuration file doesn't exist
|
||
[ -f "\$CONF" ] || exit 0
|
||
|
||
# Load the VERBOSE setting and other rcS variables
|
||
. /lib/init/vars.sh
|
||
|
||
# Define LSB log_* functions.
|
||
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
||
. /lib/lsb/init-functions
|
||
|
||
# cong file readable?
|
||
if [ ! -r \${CONF} ]; then
|
||
[ "\$VERBOSE" != no ] && log_daemon_msg "\${CONF}: not readable" "\$NAME" \\
|
||
&& log_end_msg 1;
|
||
exit 1;
|
||
fi
|
||
|
||
|
||
# The init script should do nothing if dovecot or another imap/pop3 server
|
||
# is being run from inetd, and dovecot is configured to run as an imap or
|
||
# pop3 service
|
||
if [ -r /etc/inetd.conf ]; then
|
||
for p in \`sed -r "s/^ *(([^:]+|\[[^]]+]|\*):)?(pop3s?|imaps?)[ \t].*/\3/;t;d" \\
|
||
/etc/inetd.conf\`
|
||
do
|
||
for q in \`sed -r "s/^[ \t]*protocols[ \t]*=[ \t]*(([^\"]*)|\"(.*)\")/\2\3/;t;d" \\
|
||
\${CONF}\`
|
||
do
|
||
if [ \$p = \$q ]; then
|
||
exit 0
|
||
fi
|
||
done
|
||
done
|
||
fi
|
||
|
||
# determine the location of the PID file
|
||
# overide by setting base_dir in conf file or PIDBASE in /etc/defaults/\$NAME
|
||
PIDBASE=\${PIDBASE:-\`sed -r "s/^[ \t]*base_dir[ \t]*=[ \t]*([^ \t]*)/\1/;t;d" \${CONF}\`}
|
||
PIDFILE=\${PIDBASE:-/run/dovecot/}master.pid
|
||
|
||
#
|
||
# Function that starts the daemon/service
|
||
#
|
||
do_start()
|
||
{
|
||
# Return
|
||
# 0 if daemon has been started
|
||
# 1 if daemon was already running
|
||
# 2 if daemon could not be started
|
||
start-stop-daemon --start --quiet --pidfile \$PIDFILE --exec \$DAEMON --test > /dev/null \\
|
||
|| return 1
|
||
start-stop-daemon --start --quiet --pidfile \$PIDFILE --exec \$DAEMON -- \\
|
||
\$DAEMON_ARGS \\
|
||
|| return 2
|
||
}
|
||
|
||
#
|
||
# Function that stops the daemon/service
|
||
#
|
||
do_stop()
|
||
{
|
||
# Return
|
||
# 0 if daemon has been stopped
|
||
# 1 if daemon was already stopped
|
||
# 2 if daemon could not be stopped
|
||
# other if a failure occurred
|
||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile \$PIDFILE --name \${DAEMON##*/}
|
||
RETVAL="\$?"
|
||
[ "\$RETVAL" = 2 ] && return 2
|
||
# Wait for children to finish too if this is a daemon that forks
|
||
# and if the daemon is only ever run from this initscript.
|
||
# If the above conditions are not satisfied then add some other code
|
||
# that waits for the process to drop all resources that could be
|
||
# needed by services started subsequently. A last resort is to
|
||
# sleep for some time.
|
||
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --pidfile \$PIDFILE --name \${DAEMON##*/}
|
||
[ "\$?" = 2 ] && return 2
|
||
# Many daemons don't delete their pidfiles when they exit.
|
||
rm -f \$PIDFILE
|
||
return "\$RETVAL"
|
||
}
|
||
|
||
#
|
||
# Function that sends a SIGHUP to the daemon/service
|
||
#
|
||
do_reload() {
|
||
#
|
||
# If the daemon can reload its configuration without
|
||
# restarting (for example, when it is sent a SIGHUP),
|
||
# then implement that here.
|
||
#
|
||
start-stop-daemon --stop --signal USR1 --quiet --pidfile \$PIDFILE --name \$NAME
|
||
return 0
|
||
}
|
||
|
||
|
||
case "\$1" in
|
||
start)
|
||
[ "\$VERBOSE" != no ] && log_daemon_msg "Starting \$DESC" "\$NAME"
|
||
do_start
|
||
case "\$?" in
|
||
0|1) [ "\$VERBOSE" != no ] && log_end_msg 0 ;;
|
||
2) [ "\$VERBOSE" != no ] && log_end_msg 1 ;;
|
||
esac
|
||
;;
|
||
stop)
|
||
[ "\$VERBOSE" != no ] && log_daemon_msg "Stopping \$DESC" "\$NAME"
|
||
do_stop
|
||
case "\$?" in
|
||
0|1) [ "\$VERBOSE" != no ] && log_end_msg 0 ;;
|
||
2) [ "\$VERBOSE" != no ] && log_end_msg 1 ;;
|
||
esac
|
||
;;
|
||
reload|force-reload)
|
||
log_daemon_msg "Reloading \$DESC" "\$NAME"
|
||
do_reload
|
||
log_end_msg \$?
|
||
;;
|
||
restart)
|
||
#
|
||
# If the "reload" option is implemented then remove the
|
||
# 'force-reload' alias
|
||
#
|
||
log_daemon_msg "Restarting \$DESC" "\$NAME"
|
||
do_stop
|
||
case "\$?" in
|
||
0|1)
|
||
do_start
|
||
case "\$?" in
|
||
0) log_end_msg 0 ;;
|
||
1) log_end_msg 1 ;; # Old process is still running
|
||
*) log_end_msg 1 ;; # Failed to start
|
||
esac
|
||
;;
|
||
*)
|
||
# Failed to stop
|
||
log_end_msg 1
|
||
;;
|
||
esac
|
||
;;
|
||
*)
|
||
#echo "Usage: \$SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||
echo "Usage: \$SCRIPTNAME {start|stop|restart|force-reload}" >&2
|
||
exit 3
|
||
;;
|
||
esac
|
||
|
||
exit 0
|
||
EOF
|
||
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Creating init script for dovecot failed"
|
||
fi
|
||
|
||
chmod 755 /etc/init.d/dovecot
|
||
|
||
else
|
||
echononl " Create init script for dovecot .."
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
fi
|
||
|
||
## - Add a cronjob to restart dovecot after booting the system.
|
||
## -
|
||
## - Notice:
|
||
## - On normal start, dovecot started its service even if ipv6 is not
|
||
## - yet present and dovecot cannot bind to ipv6 listeners.
|
||
## -
|
||
## - Doimg a restart (after ipv6 adresses are present) fixes this.
|
||
## -
|
||
echononl " Create cronjob to restart dovecot service after reboot.."
|
||
_crontab_tmp_file=/tmp/crontab_root.$$
|
||
crontab -l > $_crontab_tmp_file 2> /dev/null
|
||
|
||
if [[ ! -s $_crontab_tmp_file ]]; then
|
||
echo "PATH=/usr/local/dovecot/bin:$PATH" > $_crontab_tmp_file
|
||
fi
|
||
|
||
if ! grep -q -E "\s*@reboot.*systemctl\s+restart\s+dovecot.service" $_crontab_tmp_file ; then
|
||
echo "" >> $_crontab_tmp_file
|
||
echo "# - Restart dovecot after reboot" >> $_crontab_tmp_file
|
||
echo "# -" >> $_crontab_tmp_file
|
||
echo "@reboot sleep 15 ; /bin/systemctl restart dovecot.service" >> $_crontab_tmp_file
|
||
crontab $_crontab_tmp_file
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
rm -f $_crontab_tmp_file
|
||
|
||
|
||
## - update postfix configuration to play with dovecot lda
|
||
## -
|
||
|
||
## - /etc/postfix/master.cf
|
||
## -
|
||
## - add line
|
||
## - dovecot unix - n n - - pipe
|
||
## - flags=drhu user=vmail:vmail argv=/usr/local/dovecot/libexec/dovecot/dovecot-lda -f ${sender} -d ${user}@${nexthop}
|
||
if ! grep -e dovecot-lda /etc/postfix/master.cf > /dev/null ; then
|
||
cp -a "/etc/postfix/master.cf" "/etc/postfix/master.cf.$backup_date"
|
||
echononl " Configure /etc/postfix/master.cf to play with dovecot lda"
|
||
echo -e "\ndovecot unix - n n - - pipe\n flags=drhu user=vmail:vmail argv=/usr/local/dovecot/libexec/dovecot/dovecot-lda -f \${sender} -d \${user}@\${nexthop}" >> /etc/postfix/master.cf
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Configuring /etc/postfix/master.cf failed"
|
||
fi
|
||
fi
|
||
|
||
|
||
## - /etc/postfix/main.cf
|
||
## -
|
||
## - add/uncomment:
|
||
## -
|
||
## - smtpd_tls_auth_only
|
||
## -
|
||
## - smtpd_sasl_type = dovecot
|
||
## - smtpd_sasl_path = private/dovecot-auth
|
||
## -
|
||
## - virtual_transport = dovecot
|
||
## - dovecot_destination_recipient_limit = 1
|
||
## -
|
||
## - in section restrictions, parameter smtpd_recipient_restrictions
|
||
## - uncomment add
|
||
## -
|
||
## - permit_sasl_authenticated,
|
||
## -
|
||
_failed=false
|
||
echononl " Adjust /etc/postfix/main.cf"
|
||
|
||
perl -i.$backup_date -n -p -e "s#^(\s*)(smtpd_tls_auth_only\ *=.*)#smtpd_tls_auth_only = yes#" \
|
||
/etc/postfix/main.cf || _failed=true
|
||
perl -i -n -p -e "s#^(\s*)(smtpd_sasl_auth_enable\ *=.*)#smtpd_sasl_auth_enable = no#" \
|
||
/etc/postfix/main.cf || _failed=true
|
||
perl -i -n -p -e "s#^(\s*)(smtpd_sasl_type\ *=.*)#smtpd_sasl_type = dovecot#" \
|
||
/etc/postfix/main.cf || _failed=true
|
||
perl -i -n -p -e "s#^(\s*)(smtpd_sasl_path\ *=.*)#smtpd_sasl_path = private/dovecot-auth#" \
|
||
/etc/postfix/main.cf || _failed=true
|
||
|
||
perl -i -n -p -e "s#^(\s*)(virtual_transport\ *=.*)#virtual_transport = dovecot\ndovecot_destination_recipient_limit = 1#" \
|
||
/etc/postfix/main.cf || _failed=true
|
||
|
||
perl -i-n -p -e "s#^(\s*)\#?(permit_sasl_authenticated)#\1\2#" /etc/postfix/main.cf || _failed=true
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting /etc/postfix/main.cf failed"
|
||
fi
|
||
|
||
|
||
## - add a cronjob to run expunge scripts, to delete old mails
|
||
## - from users'mailbox. only cleanup spam and trash directories
|
||
## -
|
||
echononl " Create cronjob to run expunge scripts"
|
||
_crontab_tmp_file=/tmp/crontab_root.$$
|
||
crontab -l > $_crontab_tmp_file 2> /dev/null
|
||
|
||
if [[ ! -s $_crontab_tmp_file ]]; then
|
||
echo "PATH=/usr/local/dovecot/bin:$PATH" > $_crontab_tmp_file
|
||
fi
|
||
|
||
if ! grep -e "/usr/local/dovecot/bin/doveadm\ *expunge" $_crontab_tmp_file > /dev/null ; then
|
||
echo "" >> $_crontab_tmp_file
|
||
echo "# - cleanup spam and trash directories of users'mailboxes" >> $_crontab_tmp_file
|
||
echo "# -" >> $_crontab_tmp_file
|
||
echo "13 3 * * * /usr/local/dovecot/bin/doveadm expunge -A mailbox Trash* savedbefore 3d; /usr/local/dovecot/bin/doveadm expunge -A mailbox ${spam_folder}* savedbefore 30d" >> $_crontab_tmp_file
|
||
crontab $_crontab_tmp_file
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
rm -f $_crontab_tmp_file
|
||
|
||
fi # if $_new
|
||
|
||
|
||
echo
|
||
echo -e "\033[1mChange (from lda) to lmtp-service\033[m"
|
||
|
||
## -----------------
|
||
## --- Change (from lda) to lmtp-service
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf
|
||
## -
|
||
## - add "lmtp" to protocols
|
||
## -
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Add lmtp to protocols ($(basename "${_conf_file}"))"
|
||
echo -e "${rc_skipped}"
|
||
|
||
else
|
||
echononl " Add lmtp to protocols ($(basename "${_conf_file}"))"
|
||
perl -i -n -p -e "s#^([ ]*)(protocols\ +=\ +.*)#\1\2 lmtp#" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adding lmtp to protocols in file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed"
|
||
fi
|
||
fi
|
||
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
## -
|
||
## - unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
||
## - mode = 0600
|
||
## - user = postfix
|
||
## - group = postfix
|
||
## - }
|
||
## -
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf"
|
||
echononl " Adding dovecot-lmtp listener to file $(basename "${_conf_file}")"
|
||
perl -i -n -p -e "s#^([ ]*)(unix_listener\ +lmtp\ .*)#\1unix_listener /var/spool/postfix/private/dovecot-lmtp {\n user = postfix\n mode = 0660\n group = postfix#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf failed"
|
||
fi
|
||
|
||
|
||
# - /etc/postfix/main.cf
|
||
# -
|
||
# - comment in:
|
||
# - #virtual_transport = dovecot
|
||
# - #dovecot_destination_recipient_limit = ..
|
||
# -
|
||
# - change:
|
||
# - smtpd_sasl_auth_enable = yes
|
||
# - smtpd_sasl_type = dovecot
|
||
# - smtpd_sasl_path = private/dovecot-auth
|
||
# - virtual_transport = lmtp:unix:private/dovecot-lmtp
|
||
var="smtpd_sasl_auth_enable"
|
||
val="yes"
|
||
echononl " ${postfix_main_cf}: adjust '${var}'.."
|
||
if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then
|
||
perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \
|
||
/etc/postfix/main.cf > $log_file 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo_ok
|
||
changed=true
|
||
else
|
||
echo_failed
|
||
error "$(cat "$log_file")"
|
||
fi
|
||
else
|
||
echo_skipped
|
||
fi
|
||
|
||
var="smtpd_sasl_type"
|
||
val="dovecot"
|
||
echononl " ${postfix_main_cf}: adjust '${var}'.."
|
||
if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then
|
||
perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \
|
||
/etc/postfix/main.cf > $log_file 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo_ok
|
||
changed=true
|
||
else
|
||
echo_failed
|
||
error "$(cat "$log_file")"
|
||
fi
|
||
else
|
||
echo_skipped
|
||
fi
|
||
|
||
var="smtpd_sasl_path"
|
||
val="private/dovecot-auth"
|
||
echononl " ${postfix_main_cf}: adjust '${var}'.."
|
||
if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then
|
||
perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \
|
||
/etc/postfix/main.cf > $log_file 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo_ok
|
||
changed=true
|
||
else
|
||
echo_failed
|
||
error "$(cat "$log_file")"
|
||
fi
|
||
else
|
||
echo_skipped
|
||
fi
|
||
|
||
var="virtual_transport"
|
||
val="lmtp:unix:private/dovecot-lmtp"
|
||
echononl " ${postfix_main_cf}: adjust '${var}'.."
|
||
if ! $(grep -E -q "^\s*${var}\s*=\s*${val}" ${postfix_main_cf} 2> /dev/null) ; then
|
||
perl -i -n -p -e "s#^(\s*)(${var}\ *=.*)#${var} = ${val}#" \
|
||
/etc/postfix/main.cf > $log_file 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo_ok
|
||
else
|
||
echo_failed
|
||
changed=true
|
||
error "$(cat "$log_file")"
|
||
fi
|
||
else
|
||
echo_skipped
|
||
fi
|
||
|
||
|
||
echononl " Comment variable 'dovecot_destination_recipient_limit'.."
|
||
if $(grep -E -q "^\s*dovecot_destination_recipient_limit" ${postfix_main_cf} 2> /dev/null) ; then
|
||
perl -i-n -p -e "s/^(\s*)(dovecot_destination_recipient_limit.*)/\1\#\2/" /etc/postfix/main.cf > $log_file 2>&1
|
||
if [[ $? -eq 0 ]]; then
|
||
echo_ok
|
||
changed=true
|
||
else
|
||
echo_failed
|
||
error "$(cat "$log_file")"
|
||
fi
|
||
else
|
||
echo_skipped
|
||
fi
|
||
|
||
|
||
|
||
## -----------------
|
||
## --- Configure quota support for dovecot
|
||
|
||
echo
|
||
echo -e "\033[1mConfigure quota support for dovecot\033[m"
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
#
|
||
# add service dict
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Configure dict service ($(basename "${_conf_file}"))"
|
||
echo -e "${rc_already_done}"
|
||
|
||
else
|
||
## - take care quota plugins (quota,imap_quota) will
|
||
## - be loaded:
|
||
## -
|
||
## - there are two quota related plugins:
|
||
## -
|
||
## - * quota: implements the actual quota handling and includes also all the quota backends.
|
||
## - * imap_quota: for reporting quota information via imap.
|
||
## -
|
||
## - enable them in configuration files, e.g.:
|
||
## -
|
||
## - conf.d/10-mail.conf:
|
||
## -
|
||
## - # 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.
|
||
## - mail_plugins = $mail_plugins quota
|
||
## -
|
||
## - conf.d/20-imap.conf:
|
||
## -
|
||
## - protocol imap {
|
||
## - # space separated list of plugins to load (default is global mail_plugins).
|
||
## - mail_plugins = $mail_plugins imap_quota
|
||
## - }
|
||
## -
|
||
## - we have done it befor, at the basic configuration
|
||
## -
|
||
|
||
## - configure dict service
|
||
## -
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
## -
|
||
## - add:
|
||
## -
|
||
## - service dict {
|
||
## - unix_listener dict {
|
||
## - mode = 0600
|
||
## - user = vmail
|
||
## - }
|
||
## - }
|
||
## -
|
||
_failed=false
|
||
echononl " Configure dict service ($(basename "${_conf_file}"))"
|
||
perl -i -n -p -e "s#^([ ]*)(unix_listener\ +dict.*)#\1\2\n\1 mode = 0600\n\1 user = vmail#g" \
|
||
"${_conf_file}" || _failed=true
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf failed"
|
||
fi
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf
|
||
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf
|
||
## -
|
||
## - add:
|
||
## -
|
||
## - dict {
|
||
## - quota = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext
|
||
## - }
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Adjust file $(basename "${_conf_file}") for (dict) quota service"
|
||
echo -e "${rc_not_needed_anymore}"
|
||
|
||
else
|
||
echononl " Adjust file $(basename "${_conf_file}") for (dict) quota service"
|
||
perl -i -n -p -e "s#^([ ]*)(dict\ +{.*)#\1\2\n\1 quota = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext#g" \
|
||
"${_conf_file}" || _failed=true
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed"
|
||
fi
|
||
fi
|
||
|
||
|
||
if $_new ; then
|
||
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
echononl " Create table quota2 in database \"$dbname\".."
|
||
cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1
|
||
CREATE TABLE IF NOT EXISTS quota2 (
|
||
username varchar(100) not null,
|
||
bytes bigint not null default 0,
|
||
messages integer not null default 0,
|
||
primary key (username)
|
||
);
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating table quota2 in database \"$dbname\" failed"
|
||
fi
|
||
|
||
echononl " Create Trigger mergequota2.."
|
||
cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1
|
||
CREATE PROCEDURAL LANGUAGE plpgsql;
|
||
|
||
CREATE FUNCTION merge_quota2() RETURNS trigger
|
||
LANGUAGE plpgsql
|
||
AS \$\$
|
||
BEGIN
|
||
IF NEW.messages < 0 OR NEW.messages IS NULL THEN
|
||
-- ugly kludge: we came here from this function, really do try to insert
|
||
IF NEW.messages IS NULL THEN
|
||
NEW.messages = 0;
|
||
ELSE
|
||
NEW.messages = -NEW.messages;
|
||
END IF;
|
||
return NEW;
|
||
END IF;
|
||
|
||
LOOP
|
||
UPDATE quota2 SET bytes = bytes + NEW.bytes,
|
||
messages = messages + NEW.messages
|
||
WHERE username = NEW.username;
|
||
IF found THEN
|
||
RETURN NULL;
|
||
END IF;
|
||
|
||
BEGIN
|
||
IF NEW.messages = 0 THEN
|
||
INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username);
|
||
ELSE
|
||
INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, -NEW.messages, NEW.username);
|
||
END IF;
|
||
return NULL;
|
||
EXCEPTION WHEN unique_violation THEN
|
||
-- someone just inserted the record, update it
|
||
END;
|
||
END LOOP;
|
||
END;
|
||
\$\$;
|
||
CREATE TRIGGER mergequota2
|
||
BEFORE INSERT ON quota2
|
||
FOR EACH ROW
|
||
EXECUTE PROCEDURE merge_quota2();
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Creating function merge_quota2() / trigger merge_quota2 failed"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
echononl " Create table quota2 in database \"$dbname\".."
|
||
cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1
|
||
CREATE TABLE IF NOT EXISTS quota2 (
|
||
username varchar(100) not null,
|
||
bytes bigint not null default 0,
|
||
messages integer not null default 0,
|
||
primary key (username)
|
||
);
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating table quota2 in database \"$dbname\" failed"
|
||
fi
|
||
fi
|
||
|
||
fi # if new
|
||
|
||
|
||
# Renew file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Renew SQL dict file '$(basename "${_conf_file}")'.."
|
||
echo -e "${rc_not_needed_anymore}"
|
||
|
||
info "Since version 2.4 we will use quota driver 'count'.
|
||
No dict service is needed for quota"
|
||
|
||
else
|
||
|
||
echononl " Renew SQL dict file '$(basename "${_conf_file}")'.."
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
|
||
cat <<EOF > "${_conf_file}"
|
||
## - if using unix-socket (host=/run/postgresql) ensure that
|
||
## - coresponding entries in pg_hba.cof fits
|
||
## - for example
|
||
## - local all all md5
|
||
## -
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
# CREATE TABLE quota2 (
|
||
# username varchar(100) not null,
|
||
# bytes bigint not null default 0,
|
||
# messages integer not null default 0,
|
||
# primary key (username)
|
||
# );
|
||
#
|
||
## - if using postgres, you need also to create a trigger as follows:
|
||
## -
|
||
## - first create language plpgsql if not yet created:
|
||
## -
|
||
# CREATE PROCEDURAL LANGUAGE plpgsql;
|
||
#
|
||
# CREATE FUNCTION merge_quota2() RETURNS trigger
|
||
# LANGUAGE plpgsql
|
||
# AS \$\$
|
||
# BEGIN
|
||
# IF NEW.messages < 0 OR NEW.messages IS NULL THEN
|
||
# -- ugly kludge: we came here from this function, really do try to insert
|
||
# IF NEW.messages IS NULL THEN
|
||
# NEW.messages = 0;
|
||
# ELSE
|
||
# NEW.messages = -NEW.messages;
|
||
# END IF;
|
||
# return NEW;
|
||
# END IF;
|
||
#
|
||
# LOOP
|
||
# UPDATE quota2 SET bytes = bytes + NEW.bytes,
|
||
# messages = messages + NEW.messages
|
||
# WHERE username = NEW.username;
|
||
# IF found THEN
|
||
# RETURN NULL;
|
||
# END IF;
|
||
#
|
||
# BEGIN
|
||
# IF NEW.messages = 0 THEN
|
||
# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username);
|
||
# ELSE
|
||
# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, -NEW.messages, NEW.username);
|
||
# END IF;
|
||
# return NULL;
|
||
# EXCEPTION WHEN unique_violation THEN
|
||
# -- someone just inserted the record, update it
|
||
# END;
|
||
# END LOOP;
|
||
# END;
|
||
# \$\$;
|
||
#
|
||
#
|
||
# ALTER FUNCTION public.merge_quota2() OWNER TO postfix;
|
||
#
|
||
# CREATE TRIGGER mergequota2
|
||
# BEFORE INSERT ON quota2
|
||
# FOR EACH ROW
|
||
# EXECUTE PROCEDURE merge_quota2();
|
||
|
||
map {
|
||
pattern = priv/quota/storage
|
||
table = quota2
|
||
username_field = username
|
||
value_field = bytes
|
||
}
|
||
map {
|
||
pattern = priv/quota/messages
|
||
table = quota2
|
||
username_field = username
|
||
value_field = messages
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if $plugin_expire ; then
|
||
cat <<EOF >> "${_conf_file}"
|
||
|
||
# CREATE TABLE expires (
|
||
# username varchar(100) not null,
|
||
# mailbox varchar(255) not null,
|
||
# expire_stamp integer not null,
|
||
# primary key (username, mailbox)
|
||
# );
|
||
|
||
## - if using postgres, you need also to create a trigger as follows:
|
||
## -
|
||
## - first create language plpgsql if not yet created:
|
||
## -
|
||
# CREATE LANGUAGE plpgsql;
|
||
#
|
||
# CREATE OR REPLACE FUNCTION merge_expires() RETURNS TRIGGER AS \$\$
|
||
# BEGIN
|
||
# UPDATE expires SET expire_stamp = NEW.expire_stamp
|
||
# WHERE username = NEW.username AND mailbox = NEW.mailbox;
|
||
# IF FOUND THEN
|
||
# RETURN NULL;
|
||
# ELSE
|
||
# RETURN NEW;
|
||
# END IF;
|
||
# END;
|
||
# \$\$ LANGUAGE plpgsql;
|
||
#
|
||
# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires
|
||
# FOR EACH ROW EXECUTE PROCEDURE merge_expires();
|
||
|
||
map {
|
||
pattern = shared/expire/\$user/\$mailbox
|
||
table = expires
|
||
value_field = expire_stamp
|
||
|
||
fields {
|
||
username = \$user
|
||
mailbox = \$mailbox
|
||
}
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
cat <<EOF >/usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
# CREATE TABLE quota2 (
|
||
# username varchar(100) not null,
|
||
# bytes bigint not null default 0,
|
||
# messages integer not null default 0,
|
||
# primary key (username)
|
||
# );
|
||
|
||
map {
|
||
pattern = priv/quota/storage
|
||
table = quota2
|
||
username_field = username
|
||
value_field = bytes
|
||
}
|
||
map {
|
||
pattern = priv/quota/messages
|
||
table = quota2
|
||
username_field = username
|
||
value_field = messages
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if $plugin_expire ; then
|
||
cat <<EOF >> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
|
||
# CREATE TABLE expires (
|
||
# username varchar(100) not null,
|
||
# mailbox varchar(255) not null,
|
||
# expire_stamp integer not null,
|
||
# primary key (username, mailbox)
|
||
# );
|
||
|
||
map {
|
||
pattern = shared/expire/\$user/\$mailbox
|
||
table = expires
|
||
value_field = expire_stamp
|
||
|
||
fields {
|
||
username = \$user
|
||
mailbox = \$mailbox
|
||
}
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi # if $plugin_expire
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed"
|
||
fi
|
||
|
||
fi
|
||
|
||
fi # Renew file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
|
||
|
||
# In order to support extra variable "quota_rule", also userdb's and
|
||
# passdb's SQL query have to update
|
||
#
|
||
# Note:
|
||
# On versions 2.4.x and later, this happends in file'auth-sql.conf.ext'. On prior versions
|
||
# this happends in file 'sql-connect.conf.ext'
|
||
#
|
||
_failed=false
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/auth-sql.conf.ext"
|
||
|
||
echononl " Renew SQL connect file '$(basename "${_conf_file}")'.."
|
||
|
||
if [[ "$db_driver" = "pgsql" ]]; then
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
userdb sql {
|
||
|
||
# Load SQL connection data
|
||
!include /usr/local/dovecot-2.4.1-4/etc/dovecot/sql-connect.conf.ext
|
||
|
||
query = SELECT '/var/vmail/' || maildir AS home, \\
|
||
'5000' AS uid, '5000' AS gid, \\
|
||
quota || 'B'AS quota_storage_size \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
#iterate_query = SELECT userid AS username, domain FROM mailbox
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*userdb sql\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "userdb sql" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot uses passdb and userdb as part of the authentication process.
|
||
#
|
||
# passdb authenticated the user. userdb lookup then retrieves post-login information
|
||
# specific to the authenticated user. This may include:
|
||
#
|
||
# - Mailbox location information
|
||
# - Quota limit
|
||
# - Overriding settings for the user (almost any setting can be overridden)
|
||
#
|
||
#
|
||
# Userdb Lookups Dovecot Proxy Dovecot Backend
|
||
# ----------------------------------------------------------
|
||
# IMAP & POP3 logins No YES
|
||
# LMTP mail delivery No YES
|
||
# doveadm commands No YES
|
||
#
|
||
# The userdb and passdb may be the same or they may be different depending on your needs.
|
||
# You can also have multiple authentication databases.
|
||
#
|
||
# see: https://doc.dovecot.org/2.4.1/core/config/auth/userdb.html
|
||
#
|
||
${NEW_BLOCK}
|
||
EOF
|
||
fi
|
||
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
elif [[ "$db_driver" = "mysql" ]]; then
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
userdb sql {
|
||
|
||
# Load SQL connection data
|
||
!include /usr/local/dovecot-2.4.1-4/etc/dovecot/sql-connect.conf.ext
|
||
|
||
query = SELECT CONCAT('/var/vmail/',maildir) AS home, \
|
||
'5000' AS uid, '5000' AS gid, \
|
||
CONCAT(quota,'B') AS quota_storage_size \
|
||
FROM mailbox \
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
#iterate_query = SELECT userid AS username, domain FROM mailbox
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*userdb sql\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "userdb" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot uses passdb and userdb as part of the authentication process.
|
||
#
|
||
# passdb authenticated the user. userdb lookup then retrieves post-login information
|
||
# specific to the authenticated user. This may include:
|
||
#
|
||
# - Mailbox location information
|
||
# - Quota limit
|
||
# - Overriding settings for the user (almost any setting can be overridden)
|
||
#
|
||
#
|
||
# Userdb Lookups Dovecot Proxy Dovecot Backend
|
||
# ----------------------------------------------------------
|
||
# IMAP & POP3 logins No YES
|
||
# LMTP mail delivery No YES
|
||
# doveadm commands No YES
|
||
#
|
||
# The userdb and passdb may be the same or they may be different depending on your needs.
|
||
# You can also have multiple authentication databases.
|
||
#
|
||
# see: https://doc.dovecot.org/2.4.1/core/config/auth/userdb.html
|
||
#
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
fi # if [[ "$db_driver" = "pgsql" ]]; then
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
|
||
else
|
||
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext"
|
||
|
||
## - Update the userdb's query in file "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext"
|
||
## -
|
||
echononl " Renew SQL connect file '$(basename "${_conf_file}")'.."
|
||
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
cat <<EOF > /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext
|
||
driver = $db_driver
|
||
## - if using unix-socket (host=/run/postgresql) ensure that
|
||
## - coresponding entries in pg_hba.cof fits
|
||
## - for example
|
||
## - local all all md5
|
||
## -
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
default_pass_scheme = $default_pass_scheme
|
||
password_query = SELECT username AS user, password \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
user_query = SELECT '/var/vmail/' || maildir AS home, \\
|
||
'5000' AS uid, '5000' AS gid, \\
|
||
'*:bytes=' || quota AS quota_rule \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
## - Query to get a list of all usernames.
|
||
## -
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
|
||
cat <<EOF > /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext
|
||
driver = $db_driver
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
default_pass_scheme = $default_pass_scheme
|
||
password_query = SELECT username AS user, password \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\
|
||
'5000' AS uid, '5000' AS gid, \\
|
||
CONCAT('*:bytes=',quota) AS quota_rule \\
|
||
FROM mailbox \\
|
||
WHERE username = '%{user}' AND active = true
|
||
|
||
## - Query to get a list of all usernames.
|
||
## -
|
||
iterate_query = SELECT username AS user FROM mailbox
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext failed"
|
||
fi
|
||
fi
|
||
fi # Update the userdb's and passdb's SQL query
|
||
|
||
|
||
# Renew file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf
|
||
#
|
||
# Configur service stats
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Add 'service stats' to file '$(basename "${_conf_file}")'.."
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
service stats {
|
||
|
||
fifo_listener stats-mail {
|
||
user = vmail
|
||
group = dovecot
|
||
mode = 0660
|
||
}
|
||
|
||
unix_listener stats-reader {
|
||
user = vmail
|
||
group = dovecot
|
||
mode = 0660
|
||
}
|
||
|
||
unix_listener stats-writer {
|
||
user = vmail
|
||
group = dovecot
|
||
mode = 0660
|
||
}
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "service stats" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
else
|
||
|
||
## - configure stats service (10-master.conf)
|
||
## -
|
||
echononl " Add 'service stats' to file '$(basename "${_conf_file}")'.."
|
||
cat <<EOF >> "${_conf_file}"
|
||
|
||
service stats {
|
||
|
||
fifo_listener stats-mail {
|
||
user = vmail
|
||
group = dovecot
|
||
mode = 0660
|
||
}
|
||
|
||
unix_listener stats-reader {
|
||
user = vmail
|
||
group = dovecot
|
||
mode = 0660
|
||
}
|
||
|
||
unix_listener stats-writer {
|
||
user = vmail
|
||
group = dovecot
|
||
mode = 0660
|
||
}
|
||
}
|
||
EOF
|
||
if [[ $? -gt 0 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "Configure stats service ($(basename "${_conf_file}")) failed!"
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
|
||
fi # Renew file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf
|
||
|
||
|
||
|
||
## - Add script 'post-login.sh'
|
||
## -
|
||
## - see also: https://wiki.dovecot.org/PostLoginScripting
|
||
## -
|
||
echononl " Add script '/usr/local/dovecot-${_version}/bin/post-login.sh'.."
|
||
cat <<EOF > /usr/local/dovecot-${_version}/bin/post-login.sh
|
||
#!/usr/bin/env bash
|
||
|
||
touch ~/.last_login
|
||
|
||
exec "\$@"
|
||
EOF
|
||
if [[ $? -gt 0 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "Adding script '/usr/local/dovecot-${_version}/bin/post-login.sh' failed!"
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
|
||
echononl " Set Permissions of 'post-login.sh' .."
|
||
chmod 755 "/usr/local/dovecot-${_version}/bin/post-login.sh" > /dev/null 2>&1
|
||
if [[ $? -gt 0 ]] ; then
|
||
echo -e "$rc_failed"
|
||
error "Setting permissions to '/usr/local/dovecot-${_version}/bin/post-login.sh' failed!"
|
||
else
|
||
echo -e "$rc_done"
|
||
fi
|
||
|
||
|
||
# Configure post-login service (10-master.conf)
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Configure post-login service ($(basename "${_conf_file}")).."
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service imap {
|
||
|
||
# tell imap to do post-login lookup using a socket called "imap-postlogin"
|
||
executable = imap post-login
|
||
|
||
# Most of the memory goes to mmap()ing files. You may need to increase this
|
||
# limit if you have huge mailboxes.
|
||
#vsz_limit = $default_vsz_limit
|
||
|
||
# Max. number of IMAP processes (connections)
|
||
#process_limit = 1024
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service imap" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service pop3 {
|
||
|
||
# tell imap to do post-login lookup using a socket called "imap-postlogin"
|
||
executable = pop3 post-login
|
||
|
||
# Max. number of POP3 processes (connections)
|
||
#process_limit = 1024
|
||
}
|
||
EOF
|
||
replace_or_append_code_block "service pop3" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
service post-login {
|
||
# all post-login scripts are executed via script-login binary
|
||
executable = script-login /usr/local/dovecot/bin/post-login.sh
|
||
|
||
# the script process runs as the user specified here:
|
||
user = vmail
|
||
|
||
# this UNIX socket listener must use the same name as given to imap executable
|
||
unix_listener post-login {
|
||
}
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "service post-login" "${NEW_BLOCK}" "${_conf_file}" >> "${log_file}" 2>&1
|
||
if [[ $? -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Configure post-login service (10-master.conf) failed"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
|
||
fi
|
||
else
|
||
|
||
echononl " Configure post-login service (10-master.conf)"
|
||
perl -i -n -p -e "s#^(\s*)(service\s+imap\s+{.*)#\1\2\n\1 \# tell imap to do post-login lookup using a socket called \"imap-postlogin\"\n\1 executable = imap post-login\n#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
perl -i -n -p -e "s#^(\s*)(service\s+pop3\s+{.*)#\1\2\n\1 \# tell imap to do post-login lookup using a socket called \"imap-postlogin\"\n\1 executable = pop3 post-login\n#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf || _failed=true
|
||
cat <<EOF >> /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-master.conf
|
||
|
||
service post-login {
|
||
# all post-login scripts are executed via script-login binary
|
||
executable = script-login /usr/local/dovecot/bin/post-login.sh
|
||
|
||
# the script process runs as the user specified here:
|
||
user = vmail
|
||
|
||
# this UNIX socket listener must use the same name as given to imap executable
|
||
unix_listener post-login {
|
||
}
|
||
}
|
||
EOF
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Configuring 'post-login' service failed!"
|
||
fi
|
||
|
||
fi # Configure post-login service (10-master.conf)
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/90-quota.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Adjust quota file '$(basename "${_conf_file}")'.."
|
||
|
||
_key="mailbox_list_index"
|
||
_val="yes"
|
||
if grep -qE "^\s*${_key}\s*=" "${_conf_file}"; then
|
||
|
||
replace_variable "${_key}" "${_val}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Dovecot indexes live at the root of user's mailbox storage, and allows
|
||
# quick lookup of mailbox status instead of needing to open all mailbox
|
||
# indexes separately.
|
||
#
|
||
# Enabling this optimizes the server reply to IMAP STATUS commands, which
|
||
# are commonly issued by clients. This also needs to be enabled if you wish
|
||
# to enable the IMAP NOTIFY extension.
|
||
${_key} = ${_val}
|
||
EOF
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
protocol imap {
|
||
|
||
# Enable the IMAP QUOTA extension, allowing IMAP clients to ask for the
|
||
# current quota usage.
|
||
mail_plugins {
|
||
imap_quota = yes
|
||
}
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "protocol imap" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
quota "User quota" {
|
||
|
||
# quota_storage_size
|
||
#
|
||
# Default unlimited
|
||
# Value unsigned integer
|
||
#
|
||
# See Also:
|
||
# quota_storage_extra
|
||
# quota_storage_percentage
|
||
# quota_message_count
|
||
# Quota Root
|
||
#
|
||
# Quota storage size limit for the Quota Root. This value is still
|
||
# multiplied by quota_storage_percentage and then increased by
|
||
# 'quota_storage_extra' to get the final value (in this mailbox or
|
||
# namespace). This is reported as the STORAGE limit in IMAP GETQUOTA
|
||
# commands. Using 0 as the value means the same as unlimited.
|
||
#quota_storage_size = 0
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*quota \"User quota\"\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block 'quota "User quota"' "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Per-User Quota
|
||
# --------------
|
||
#
|
||
# You can override the quota settings in your userdb: Extra Fields. Keep global settings
|
||
# from below in configuration plugin section and override only those settings you need
|
||
# to in your userdb.
|
||
#
|
||
# Use doveadm user command to verify that the userdb returns the expected quota settings.
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
protocol !indexer-worker {
|
||
mail_vsize_bg_after_count = 100
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*protocol \!indexer-worker\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block 'protocol !indexer-worker' "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Avoid spending excessive time waiting for the quota calculation to finish
|
||
# when mails' vsizes aren't already cached. If this many mails are opened,
|
||
# finish the quota calculation on background in indexer-worker process. Mail
|
||
# deliveries will be assumed to succeed, and explicit quota lookups will
|
||
# return internal error.
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
quota user {
|
||
warning warn-95 {
|
||
quota_storage_percentage = 95
|
||
execute quota-warning {
|
||
args = 95 %{user}
|
||
}
|
||
}
|
||
warning warn-80 {
|
||
quota_storage_percentage = 80
|
||
execute quota-warning {
|
||
args = 80 %{user}
|
||
}
|
||
}
|
||
warning warn-under {
|
||
quota_storage_percentage = 100
|
||
# user is no longer over quota
|
||
threshold = under
|
||
execute quota-warn-under {
|
||
args = 100 %{user}
|
||
}
|
||
}
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*quota\s+user\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "quota user" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Then user's quota exceeds 80% quota-warning.sh is executed with parameter 80.
|
||
# The same goes for when quota exceeds 95%. If user suddenly receives a huge
|
||
# mail and the quota jumps from 70% to 99%, only the 95 script is executed.
|
||
$(echo -e "${NEW_BLOCK}")
|
||
EOF
|
||
fi
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
namespace inbox {
|
||
mailbox Trash {
|
||
quota_storage_extra = 100M
|
||
}
|
||
mailbox Spam {
|
||
quota_ignore = yes
|
||
}
|
||
}
|
||
|
||
EOF
|
||
|
||
replace_or_append_code_block "namespace inbox" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
|
||
if [[ $? -gt 0 ]] ; then
|
||
_failed=true
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
service quota-warning {
|
||
executable = script /usr/local/bin/quota-warning.sh
|
||
# use some unprivileged user for executing the quota warnings
|
||
user = vmail
|
||
unix_listener quota-warning {
|
||
user = vmail
|
||
mode = 0666
|
||
}
|
||
}
|
||
|
||
EOF
|
||
|
||
replace_or_append_code_block "service quota-warning" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
service quota-warn-under {
|
||
executable = script /usr/local/bin/quota-warn-under.sh
|
||
# use some unprivileged user for executing the quota warn-under script
|
||
user = vmail
|
||
unix_listener quota-warn-under {
|
||
user = vmail
|
||
mode = 0666
|
||
}
|
||
}
|
||
|
||
EOF
|
||
|
||
replace_or_append_code_block "service quota-warn-under" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-quota.conf
|
||
## -
|
||
## - add to the end of file or in seperate plugin-blocks
|
||
## - as designed in that file:
|
||
## - plugin {
|
||
## - # sql backend:
|
||
## - quota = dict:user quota::proxy::quota
|
||
## -
|
||
## - quota_rule = *:storage=1g
|
||
## - quota_rule2 = trash:storage=+100m
|
||
## -
|
||
## - quota_warning = storage=80%% quota-warning 80 %u
|
||
## - quota_warning2 = storage=95%% quota-warning 95 %u
|
||
## - }
|
||
## -
|
||
## - service quota-warning {
|
||
## - executable = script /usr/local/bin/quota-warning.sh
|
||
## - user = vmail
|
||
## - unix_listener quota-warning {
|
||
## - user = vmail
|
||
## - mode = 0666
|
||
## - }
|
||
## - }
|
||
## -
|
||
echononl " Adjust quota file '$(basename "${_conf_file}")'"
|
||
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
|
||
cat <<EOF >>/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf
|
||
|
||
## -
|
||
plugin {
|
||
# SQL backend:
|
||
quota = dict:User quota::proxy::quota
|
||
|
||
quota_rule = *:storage=1G
|
||
quota_rule2 = Trash:storage=+200M
|
||
|
||
quota_warning = storage=80%% quota-warning 80 %u
|
||
quota_warning2 = storage=95%% quota-warning 95 %u
|
||
}
|
||
|
||
service quota-warning {
|
||
executable = script /usr/local/bin/quota-warning.sh
|
||
user = vmail
|
||
unix_listener quota-warning {
|
||
user = vmail
|
||
mode = 0666
|
||
}
|
||
}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-quota.conf failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/90-quota.conf
|
||
|
||
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Create quota warning script.."
|
||
## - create the user-warning script
|
||
## -
|
||
cat <<EOF >/usr/local/bin/quota-warning.sh
|
||
#!/usr/bin/env bash
|
||
|
||
# author: zhang huangbin <michaelbibby (at) gmail.com>
|
||
# purpose: send mail to notify user when his mailbox quota exceeds a
|
||
# specified limit.
|
||
# project: iredmail (http://www.iredmail.org/)
|
||
|
||
LANG=en_US.UTF-8
|
||
|
||
percent=\$1
|
||
user=\$2
|
||
|
||
cat << EOF | /usr/local/dovecot/libexec/dovecot/dovecot-lda -d \${user} -o quota_enforce=no
|
||
Date: \`date +"%a, %e %b %Y %H:%M:%S %z"\`
|
||
From: $from_address
|
||
Reply-to: $reply_to
|
||
To:\${user}
|
||
Subject: mailbox quota warning: mehr \${percent}% belegt.
|
||
content-type: text/plain;
|
||
charset=utf-8
|
||
|
||
Hallo!
|
||
|
||
Deine Mailbox für das Postfach
|
||
\${user}
|
||
ist nun zu über \${percent}% voll. Damit Du weiterhin E-Mails
|
||
empfangen kannst, lösche bitte vorhandene E-Mails vom Server.
|
||
|
||
Dies geht zum Beispiel via Webmailer:
|
||
$webmailer
|
||
|
||
Achte darauf nach dem Löschen gegebenenfalls auch den Papierkorb zu leeren.
|
||
|
||
Viele Grüße
|
||
|
||
$salutation
|
||
${_EOF:-EOF}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Create quota warning script /usr/local/bin/quota-warning.sh failed"
|
||
fi
|
||
|
||
chmod 755 /usr/local/bin/quota-warning.sh
|
||
|
||
echononl " Create quota warn-under script.."
|
||
## - create the user-warning script
|
||
## -
|
||
cat <<EOF >/usr/local/bin/quota-warn-under.sh
|
||
#!/usr/bin/env bash
|
||
|
||
percent=\$1
|
||
user=\$2
|
||
|
||
cat << EOF | /usr/local/dovecot/libexec/dovecot/dovecot-lda -d \${user} -o quota_enforce=no
|
||
Date: \`date +"%a, %e %b %Y %H:%M:%S %z"\`
|
||
From: $from_address
|
||
Reply-to: $reply_to
|
||
To:\${user}
|
||
Subject: mailbox quota: Weniger als \${percent}% belegt.
|
||
content-type: text/plain;
|
||
charset=utf-8
|
||
|
||
Hallo!
|
||
|
||
Deine Mailbox
|
||
\${user}
|
||
kann nun wieder E-MAIL empfangen.
|
||
|
||
Beachte, dass, je nach dem wieviel Platz du frei gemacht hast, dein verfügbarer Speicher auch schnell wieder vollständig belegt sein kann.
|
||
|
||
Du kannst den aktuellen Füllstand in deinem Mailprogramm oder im Webmailer hier einsehen:
|
||
$webmailer
|
||
|
||
|
||
Viele Grüße
|
||
|
||
$salutation
|
||
${_EOF:-EOF}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Create quota warn-under script /usr/local/bin/quota-warn-under.sh failed"
|
||
fi
|
||
|
||
chmod 755 /usr/local/bin/quota-warn-under.sh
|
||
|
||
else
|
||
|
||
echononl " Create quota warning script.."
|
||
## - create the user-warning script
|
||
## -
|
||
cat <<EOF >/usr/local/bin/quota-warning.sh
|
||
#!/usr/bin/env bash
|
||
|
||
# author: zhang huangbin <michaelbibby (at) gmail.com>
|
||
# purpose: send mail to notify user when his mailbox quota exceeds a
|
||
# specified limit.
|
||
# project: iredmail (http://www.iredmail.org/)
|
||
|
||
LANG=en_US.UTF-8
|
||
|
||
percent=\$1
|
||
user=\$2
|
||
|
||
cat << EOF | /usr/local/dovecot/libexec/dovecot/deliver -d \${user} -c /usr/local/dovecot/etc/dovecot/dovecot.conf -o "plugin/quota=dict:User quota::noenforcing:proxy::quota"
|
||
date: \`date +"%a, %e %b %Y %H:%M:%S %z"\`
|
||
from: $from_address
|
||
reply-to: $reply_to
|
||
to:\${user}
|
||
subject: mailbox quota warning: \${percent}% belegt.
|
||
content-type: text/plain;
|
||
charset=utf-8
|
||
|
||
Hallo!
|
||
|
||
Deine Mailbox für das Postfach
|
||
\${user}
|
||
ist nun zu über \${percent}% belegt. Damit Du weiterhin E-Mails
|
||
empfangen kannst, lösche bitte vorhandene E-Mails vom Server.
|
||
|
||
Dies geht zum Beispiel via Webmailer:
|
||
$webmailer
|
||
|
||
Viele Grüße
|
||
|
||
$salutation
|
||
${_EOF:-EOF}
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Create quota warning script /usr/local/bin/quota-warning.sh failed"
|
||
fi
|
||
|
||
chmod 755 /usr/local/bin/quota-warning.sh
|
||
|
||
fi
|
||
|
||
|
||
## -----------------
|
||
## --- Configure ACL support for dovecot
|
||
|
||
echo
|
||
echo -e "\033[1mConfigure ACL support for dovecot\033[m"
|
||
|
||
## - What to do:
|
||
## -
|
||
## - 1.) Add shared namespace
|
||
## - 2.) Add plugins to the several plugin lists
|
||
## - - "acl" to variable mail_plugins in 10-mail.conf
|
||
## - - "acl-imap" to variable mail_plugins in 20-imap.conf
|
||
## -
|
||
## - 3.a) Add acl to the plugin part in 90-acl.conf
|
||
## -
|
||
## - 3.b) To make shared mailboxes visible a database (dict) is needed.
|
||
## - This can also be a dict file.
|
||
## - Add acl_shared_dict to the plugin part of 90-acl.conf
|
||
## -
|
||
## - 4.) If using SQL backend, also a rule "acl =" in "dict" section
|
||
## - of file dovecont.conf needed
|
||
## -
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf
|
||
#
|
||
# mail_plugins = $mail_plugins imap_quota imap_acl
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Add mail_plugin imap_acl to file '$(basename "${_conf_file}")'.."
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
protocol imap {
|
||
|
||
# The maximum number of IMAP connections allowed for a user from each IP address.
|
||
#
|
||
# This setting is checked only by backends, not proxies.
|
||
#
|
||
# Note that for this to work, any username changes must be done already by
|
||
# passdb lookup (not by userdb lookup).
|
||
#
|
||
# Unique users are identified via case-sensitive comparison.
|
||
mail_max_userip_connections = $max_userip_connections
|
||
|
||
# A list of mail plugins to load.
|
||
mail_plugins {
|
||
imap_acl = yes
|
||
imap_quota = yes
|
||
}
|
||
|
||
ssl_client {
|
||
cert_file = $imap_cert
|
||
key_file = $imap_key
|
||
}
|
||
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "protocol imap" "${NEW_BLOCK}" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf
|
||
## -
|
||
## - mail_plugins = $mail_plugins imap_quota imap_acl
|
||
## -
|
||
echononl " Add mail_plugin imap_acl to file '$(basename "${_conf_file}")'"
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins imap_quota imap_acl#g" \
|
||
"${_conf_file}" || _failed=true
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file '${_conf_file}' failed"
|
||
fi
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf
|
||
|
||
|
||
## - !! Notice !!
|
||
## - There a two possibilities, configuring acl backend:
|
||
## - - flat file
|
||
## - - SQL dictionary
|
||
## -
|
||
## - On rage.so36.net we actually uses SQL dictionary not a flat file
|
||
|
||
## -----------------
|
||
## - Using a flat file as dictionary backend
|
||
## -
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-acl.conf
|
||
## -
|
||
## - plugin {
|
||
## - # Without global ACLs:
|
||
## - acl = vfile
|
||
## -
|
||
## - # With global ACLs in /etc/dovecot/acls/ directory:
|
||
## - #acl = vfile:/etc/dovecot/acls
|
||
## - #acl = vfile:/etc/dovecot/acls:cache_secs=300
|
||
## - }
|
||
## -
|
||
## - plugin {
|
||
## - #acl_shared_dict = file:/run/dovecot/shared-mailboxes.db
|
||
## - acl_shared_dict = file:/var/vmail/shared-mailboxes.db
|
||
## - }
|
||
## -
|
||
#perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(acl\ +=.*)#\1\#\# \2\n\n\1\# Without global ACLs:\n\1acl = vfile\n\n\1\# With global ACLs in /etc/dovecot/acls/ directory:\n\1\#acl = vfile:/etc/dovecot/acls\n\1\#acl = vfile:/etc/dovecot/acls:cache_secs=300#g" \
|
||
# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf
|
||
#perl -i -n -p -e "s#^([ ]*)\#?\ ?(acl_shared_dict\ +=.*)#\1\#\# \2\n\1acl_shared_dict = file:/var/vmail/shared-mailboxes.db#g" \
|
||
# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf
|
||
|
||
## -
|
||
## - End: Using a flat file as dictionary backend
|
||
## ------------------------------------------------------------------------
|
||
|
||
|
||
## ------------------------------------------------------------------------
|
||
## - Using SQL dictionary
|
||
## -
|
||
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/90-acl.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Configure acl - file '$(basename "${_conf_file}")'.."
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
protocol imap {
|
||
mail_plugins {
|
||
imap_acl = yes
|
||
}
|
||
}
|
||
EOF
|
||
|
||
if grep -qE "^\s*protocol imap\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "protocol imap" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Enable the IMAP ACL commands
|
||
${NEW_BLOCK}
|
||
EOF
|
||
fi
|
||
|
||
if grep -qE "^\s*acl_driver\s+=" "${_conf_file}"; then
|
||
|
||
replace_variable "acl_driver" "vfile" "${_conf_file}" 2>> "${log_file}" || _failed=true
|
||
|
||
else
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# The ACL driver to use. This setting is REQUIRED - if empty, the
|
||
# acl plugin is disabled.
|
||
#
|
||
# Currently, there is a single driver available: vfile. This driver supports
|
||
# two ways of defining the ACL configuration:
|
||
#
|
||
# - global: ACL rules are applied to all users.
|
||
#
|
||
# - per-mailbox: Each mailbox has separate ACL rules. They are stored in a
|
||
# dovecot-acl file in each mailbox (or mail_control_path) directory. This
|
||
# is the default.
|
||
acl_driver = vfile
|
||
EOF
|
||
fi
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
namespace shared {
|
||
|
||
type = shared
|
||
separator = /
|
||
|
||
# Mailboxes are visible under "shared/user@domain/"
|
||
#
|
||
# Changed: 2.4.0 The shared namespaces now use $user,
|
||
# $username and $domain template variables, rather than
|
||
# the old %%u, %%n and %%d.
|
||
prefix = shared/$user/
|
||
|
||
# Mail location setting
|
||
mail_home = /var/vmail/%{user | domain}/%{user | username}
|
||
mail_driver = maildir
|
||
mail_path = ~/Maildir
|
||
mail_index_private_path = ~/Maildir/shared/%{owner_user}
|
||
|
||
# Use the default namespace for saving subscriptions.
|
||
subscriptions = no
|
||
|
||
# Include this namespace in LIST output when listing its parent's folders.
|
||
#
|
||
# One of:
|
||
# children Namespace prefix list listed only if it has child mailboxes.
|
||
#
|
||
# no Namespace and mailboxes not listed unless listing requests explicitly
|
||
# mailboxes under the namespace prefix.
|
||
#
|
||
# yes Namespace and mailboxes are always listed.
|
||
#
|
||
# It is still possible to list the namespace's folders by explicitly asking for them.
|
||
# For example, if this setting is no, using LIST "" * with namespace prefix "lazy-expunge/"
|
||
# won't list it, but using LIST "" lazy-expunge/* lists all folders under it.
|
||
#
|
||
# Default: yes
|
||
list = children
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*namespace\s+shared\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "namespace shared" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# This creates a shared/ namespace under which each user's mailboxes are.
|
||
${NEW_BLOCK}
|
||
EOF
|
||
fi
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/90-acl.conf
|
||
## -
|
||
## - plugin {
|
||
## - ## acl = vfile:/etc/dovecot/global-acls:cache_secs=300
|
||
## -
|
||
## - # Without global ACLs:
|
||
## - acl = vfile
|
||
## - ..
|
||
## - }
|
||
## - plugin {
|
||
## - acl_shared_dict = proxy::acl
|
||
## - }
|
||
## -
|
||
_failed=false
|
||
echononl " Configure acl file '$(basename "${_conf_file}")'"
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(acl\ +=.*)#\1\#\# \2\n\n\1\# Without global ACLs:\n\1acl = vfile\n\n\1\# With global ACLs in /etc/dovecot/acls/ directory:\n\1\#acl = vfile:/etc/dovecot/acls\n\1\#acl = vfile:/etc/dovecot/acls:cache_secs=300#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(acl_shared_dict\ +=.*)#\1\#\# \2\n\1acl_shared_dict = proxy::acl#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf || _failed=true
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-acl.conf failed"
|
||
fi
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/dovecot.conf
|
||
## -
|
||
## - dict {
|
||
## - acl = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext
|
||
## - ...
|
||
## - }
|
||
## -
|
||
_failed=false
|
||
echononl " Adjust file dovecot.conf for (dict) acl service"
|
||
perl -i -n -p -e "s#^([ ]*)(dict\ +{.*)#\1\2\n\1 acl = $db_driver:/usr/local/dovecot/etc/dovecot/sql-dict.conf.ext#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf || _failed=true
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/dovecot.conf failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/90-acl.conf
|
||
|
||
|
||
if $_new ; then
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
## - Create tables user_shares / anyone_shares
|
||
## -
|
||
echononl " Create table user_share"
|
||
cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1
|
||
CREATE TABLE IF NOT EXISTS user_shares (
|
||
from_user varchar(100) not null,
|
||
to_user varchar(100) not null,
|
||
dummy char(1) DEFAULT '1', -- always '1' currently
|
||
primary key (from_user, to_user)
|
||
);
|
||
COMMENT ON TABLE user_shares IS 'User from_user shares folders to user to_user.';
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating table user_shares failed"
|
||
fi
|
||
|
||
echononl " Create table anyone_shares"
|
||
cat << EOF | psql -U$dbuser $dbname > /dev/null 2>&1
|
||
CREATE TABLE IF NOT EXISTS anyone_shares (
|
||
from_user varchar(100) not null,
|
||
dummy char(1) DEFAULT '1', -- always '1' currently
|
||
primary key (from_user)
|
||
);
|
||
COMMENT ON TABLE anyone_shares IS 'User from_user shares folders to anyone.';
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating table anyone_shares failed"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
|
||
## - Create table user_shares / anyone_shares
|
||
## -
|
||
echononl " Create table user_share"
|
||
cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1
|
||
CREATE TABLE IF NOT EXISTS user_shares (
|
||
from_user varchar(100) not null,
|
||
to_user varchar(100) not null,
|
||
dummy char(1) DEFAULT '1', -- always '1' currently
|
||
primary key (from_user, to_user)
|
||
) COMMENT = 'User from_user shares folders to user to_user.';
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating table user_shares failed"
|
||
fi
|
||
|
||
echononl " Create table anyone_shares"
|
||
cat << EOF | mysql -u$dbuser -p$dbpassword $dbname > /dev/null 2>&1
|
||
CREATE TABLE IF NOT EXISTS anyone_shares (
|
||
from_user varchar(100) not null,
|
||
dummy char(1) DEFAULT '1', -- always '1' currently
|
||
primary key (from_user)
|
||
) COMMENT = 'User from_user shares folders to anyone.';
|
||
EOF
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Creating table anyone_shares failed"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
|
||
# Renew file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Renew SQL dict file '$(basename "${_conf_file}")'.."
|
||
echo -e "$rc_not_needed_anymore"
|
||
|
||
else
|
||
|
||
echononl " Renew SQL dict file '$(basename "${_conf_file}")'.."
|
||
|
||
if [ "$db_driver" = "pgsql" ]; then
|
||
|
||
## - adjust/renew file /usr/local/dovecot/etc/dovecot/sql-dict.conf.ext
|
||
## -
|
||
cat <<EOF >/usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
## - if using unix-socket (host=/run/postgresql) ensure that
|
||
## - coresponding entries in pg_hba.cof fits
|
||
## - for example
|
||
## - local all all md5
|
||
## -
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
## - NOTE:
|
||
## -
|
||
## - All changes on database (CREATE TABLE / CREATE TRIGGER / what else..)
|
||
## - 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
|
||
## - dovecot dbuser to access the createt table/trigger/...
|
||
## -
|
||
|
||
# CREATE TABLE quota2 (
|
||
# username varchar(100) not null,
|
||
# bytes bigint not null default 0,
|
||
# messages integer not null default 0,
|
||
# primary key (username)
|
||
# );
|
||
#
|
||
## - if using postgres, you need also to create a trigger as follows:
|
||
## -
|
||
## - first create language plpgsql if not yet created:
|
||
## -
|
||
# CREATE PROCEDURAL LANGUAGE plpgsql;
|
||
#
|
||
# CREATE FUNCTION merge_quota2() RETURNS trigger
|
||
# LANGUAGE plpgsql
|
||
# AS \$\$
|
||
# BEGIN
|
||
# IF NEW.messages < 0 OR NEW.messages IS NULL THEN
|
||
# -- ugly kludge: we came here from this function, really do try to insert
|
||
# IF NEW.messages IS NULL THEN
|
||
# NEW.messages = 0;
|
||
# ELSE
|
||
# NEW.messages = -NEW.messages;
|
||
# END IF;
|
||
# return NEW;
|
||
# END IF;
|
||
#
|
||
# LOOP
|
||
# UPDATE quota2 SET bytes = bytes + NEW.bytes,
|
||
# messages = messages + NEW.messages
|
||
# WHERE username = NEW.username;
|
||
# IF found THEN
|
||
# RETURN NULL;
|
||
# END IF;
|
||
#
|
||
# BEGIN
|
||
# IF NEW.messages = 0 THEN
|
||
# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username);
|
||
# ELSE
|
||
# INSERT INTO quota2 (bytes, messages, username) VALUES (NEW.bytes, -NEW.messages, NEW.username);
|
||
# END IF;
|
||
# return NULL;
|
||
# EXCEPTION WHEN unique_violation THEN
|
||
# -- someone just inserted the record, update it
|
||
# END;
|
||
# END LOOP;
|
||
# END;
|
||
# \$\$;
|
||
#
|
||
#
|
||
# ALTER FUNCTION public.merge_quota2() OWNER TO postfix;
|
||
#
|
||
# CREATE TRIGGER mergequota2
|
||
# BEFORE INSERT ON quota2
|
||
# FOR EACH ROW
|
||
# EXECUTE PROCEDURE merge_quota2();
|
||
|
||
map {
|
||
pattern = priv/quota/storage
|
||
table = quota2
|
||
username_field = username
|
||
value_field = bytes
|
||
}
|
||
map {
|
||
pattern = priv/quota/messages
|
||
table = quota2
|
||
username_field = username
|
||
value_field = messages
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if $plugin_expire ; then
|
||
cat <<EOF >> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
|
||
# CREATE TABLE expires (
|
||
# username varchar(100) not null,
|
||
# mailbox varchar(255) not null,
|
||
# expire_stamp integer not null,
|
||
# primary key (username, mailbox)
|
||
# );
|
||
|
||
## - if using postgres, you need also to create a trigger as follows:
|
||
## -
|
||
## - first create language plpgsql if not yet created:
|
||
## -
|
||
# CREATE LANGUAGE plpgsql;
|
||
#
|
||
# CREATE OR REPLACE FUNCTION merge_expires() RETURNS TRIGGER AS \$\$
|
||
# BEGIN
|
||
# UPDATE expires SET expire_stamp = NEW.expire_stamp
|
||
# WHERE username = NEW.username AND mailbox = NEW.mailbox;
|
||
# IF FOUND THEN
|
||
# RETURN NULL;
|
||
# ELSE
|
||
# RETURN NEW;
|
||
# END IF;
|
||
# END;
|
||
# \$\$ LANGUAGE plpgsql;
|
||
#
|
||
# CREATE TRIGGER mergeexpires BEFORE INSERT ON expires
|
||
# FOR EACH ROW EXECUTE PROCEDURE merge_expires();
|
||
|
||
|
||
map {
|
||
pattern = shared/expire/\$user/\$mailbox
|
||
table = expires
|
||
value_field = expire_stamp
|
||
|
||
fields {
|
||
username = \$user
|
||
mailbox = \$mailbox
|
||
}
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
fi
|
||
|
||
cat <<EOF >> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
|
||
|
||
# CREATE TABLE user_shares (
|
||
# from_user varchar(100) not null,
|
||
# to_user varchar(100) not null,
|
||
# dummy char(1) DEFAULT '1', -- always '1' currently
|
||
# primary key (from_user, to_user)
|
||
# );
|
||
# COMMENT ON TABLE user_shares IS 'User from_user shares folders to user to_user.';
|
||
#
|
||
# CREATE TABLE anyone_shares (
|
||
# from_user varchar(100) not null,
|
||
# dummy char(1) DEFAULT '1', -- always '1' currently
|
||
# primary key (from_user)
|
||
# );
|
||
# COMMENT ON TABLE anyone_shares IS 'User from_user shares folders to anyone.';
|
||
|
||
map {
|
||
pattern = shared/shared-boxes/user/\$to/\$from
|
||
table = user_shares
|
||
value_field = dummy
|
||
|
||
fields {
|
||
from_user = \$from
|
||
to_user = \$to
|
||
}
|
||
}
|
||
|
||
map {
|
||
pattern = shared/shared-boxes/anyone/\$from
|
||
table = anyone_shares
|
||
value_field = dummy
|
||
|
||
fields {
|
||
from_user = \$from
|
||
}
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed"
|
||
fi
|
||
|
||
elif [ "$db_driver" = "mysql" ]; then
|
||
|
||
## - adjust/renew file /usr/local/dovecot/etc/dovecot/sql-dict.conf.ext
|
||
## -
|
||
cat <<EOF >/usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname
|
||
|
||
# CREATE TABLE quota2 (
|
||
# username varchar(100) not null,
|
||
# bytes bigint not null default 0,
|
||
# messages integer not null default 0,
|
||
# primary key (username)
|
||
# );
|
||
|
||
map {
|
||
pattern = priv/quota/storage
|
||
table = quota2
|
||
username_field = username
|
||
value_field = bytes
|
||
}
|
||
map {
|
||
pattern = priv/quota/messages
|
||
table = quota2
|
||
username_field = username
|
||
value_field = messages
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
|
||
if $plugin_expire ; then
|
||
cat <<EOF >> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
|
||
# CREATE TABLE expires (
|
||
# username varchar(100) not null,
|
||
# mailbox varchar(255) not null,
|
||
# expire_stamp integer not null,
|
||
# primary key (username, mailbox)
|
||
# );
|
||
|
||
|
||
map {
|
||
pattern = shared/expire/\$user/\$mailbox
|
||
table = expires
|
||
value_field = expire_stamp
|
||
|
||
fields {
|
||
username = \$user
|
||
mailbox = \$mailbox
|
||
}
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
fi
|
||
cat <<EOF >> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext
|
||
|
||
|
||
# CREATE TABLE user_shares (
|
||
# from_user varchar(100) not null,
|
||
# to_user varchar(100) not null,
|
||
# dummy char(1) DEFAULT '1', -- always '1' currently
|
||
# primary key (from_user, to_user)
|
||
# ) COMMENT = 'User from_user shares folders to user to_user.';
|
||
#
|
||
# CREATE TABLE anyone_shares (
|
||
# from_user varchar(100) not null,
|
||
# dummy char(1) DEFAULT '1', -- always '1' currently
|
||
# primary key (from_user)
|
||
# ) COMMENT = 'User from_user shares folders to anyone.';
|
||
|
||
map {
|
||
pattern = shared/shared-boxes/user/\$to/\$from
|
||
table = user_shares
|
||
value_field = dummy
|
||
|
||
fields {
|
||
from_user = \$from
|
||
to_user = \$to
|
||
}
|
||
}
|
||
|
||
map {
|
||
pattern = shared/shared-boxes/anyone/\$from
|
||
table = anyone_shares
|
||
value_field = dummy
|
||
|
||
fields {
|
||
from_user = \$from
|
||
}
|
||
}
|
||
EOF
|
||
if [[ "$?" -gt 0 ]]; then
|
||
_failed=true
|
||
fi
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext failed"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
## -
|
||
## - End: Using SQL dictionary
|
||
## ------------------------------------------------------------------------
|
||
|
||
|
||
## -----------------
|
||
## --- Configure managesieve support for dovecot
|
||
|
||
# edit /usr/local/dovecot/etc/dovecot/conf.d/20-managesieve.conf
|
||
#
|
||
_failed=false
|
||
_conf_file="/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf"
|
||
if [[ $dovecot_major_version -gt 2 ]] \
|
||
|| ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then
|
||
|
||
echononl " Configure managesieve '$(basename "${_conf_file}")'.."
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service managesieve-login {
|
||
|
||
inet_listener sieve {
|
||
#listen = 127.0.0.1 $ipv4 $ipv6
|
||
listen = 127.0.0.1
|
||
port = 4190
|
||
}
|
||
|
||
#inet_listener sieve_deprecated {
|
||
# port = 2000
|
||
#}
|
||
|
||
# Number of connections to handle before starting a new process. Typically
|
||
# the only useful values are "unlimited" or 1. 1 is more secure, but
|
||
# "unlimited" is faster.
|
||
#restart_request_count = 1
|
||
|
||
# Number of processes to always keep waiting for more connections.
|
||
#process_min_avail = 0
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "service managesieve-login" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
service managesieve {
|
||
# Max. number of ManageSieve processes (connections)
|
||
#process_limit = 1024
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "service managesieve" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<EOF
|
||
protocol sieve {
|
||
|
||
# Maximum ManageSieve command line length in bytes. ManageSieve usually does
|
||
# not involve overly long command lines, so this setting will not normally
|
||
# need adjustment
|
||
#managesieve_max_line_length = 65536
|
||
|
||
# Maximum number of ManageSieve connections allowed for a user from each
|
||
# IP address.
|
||
# NOTE: The username is compared case-sensitively.
|
||
#mail_max_userip_connections = 10
|
||
|
||
# List of plugins to load (none known to be useful so far).
|
||
# Do NOT try to load IMAP plugins here.
|
||
#mail_plugins {
|
||
#}
|
||
|
||
# MANAGESIEVE logout format string:
|
||
# %i - total number of bytes read from client
|
||
# %o - total number of bytes sent to client
|
||
#managesieve_logout_format = bytes=%i/%o
|
||
|
||
# To fool ManageSieve clients that are focused on CMU's timesieved you can
|
||
# specify the IMPLEMENTATION capability that the dovecot reports to clients.
|
||
# For example: 'Cyrus timsieved v2.2.13'
|
||
#managesieve_implementation_string = Dovecot Pigeonhole
|
||
|
||
# Explicitly specify the SIEVE and NOTIFY capability reported by the server
|
||
# before login. If left unassigned these will be reported dynamically
|
||
# according to what the Sieve interpreter supports by default (after login
|
||
# this may differ depending on the user).
|
||
#managesieve_sieve_capability =
|
||
#managesieve_notify_capability =
|
||
|
||
# The maximum number of compile errors that are returned to the client
|
||
# upon script upload or script verification.
|
||
#managesieve_max_compile_errors = 5
|
||
}
|
||
EOF
|
||
|
||
replace_or_append_code_block "protocol sieve" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
|
||
read -r -d '' NEW_BLOCK <<'EOF'
|
||
sieve_script personal {
|
||
path = ~/sieve
|
||
active_path = ~/.dovecot.sieve
|
||
}
|
||
EOF
|
||
if grep -qE "^\s*sieve_script\s+personal\s+{" "${_conf_file}"; then
|
||
|
||
replace_code_block "sieve_script personal" "${NEW_BLOCK}" "${_conf_file}" || _failed=true
|
||
|
||
else
|
||
|
||
cat <<EOF >> "${_conf_file}" || _failed=true
|
||
|
||
# Used by both the Sieve plugin and the ManageSieve protocol
|
||
${NEW_BLOCK}
|
||
EOF
|
||
fi
|
||
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting Adjusting file ${_conf_file} failed"
|
||
error "$(cat "${log_file}")"
|
||
|
||
echo ""
|
||
echononl "continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Interupted by user"
|
||
fi
|
||
|
||
else
|
||
|
||
## - edit /usr/local/dovecot/etc/dovecot/conf.d/20-managesieve.conf
|
||
## -
|
||
## - service managesieve-login {
|
||
## - inet_listener sieve {
|
||
## - #address = 127.0.0.1 $ipv4 $ipv6
|
||
## - address = 127.0.0.1
|
||
## - port = 4190
|
||
## - }
|
||
## - ..
|
||
## - }
|
||
## -
|
||
|
||
echononl " Configure managesieve '20-managesieve.conf'.."
|
||
perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(service managesieve-login\ +{.*)#\1service managesieve-login {#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true
|
||
if [[ -n "$ipv6" ]]; then
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(inet_listener\ +sieve\ +{.*)#\1inet_listener sieve {\n\1 \#address = 127.0.0.1 $ipv4 $ipv6\n\1 address = 127.0.0.1\n\1 port = 4190\n\1}\n\1\#\# \2#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true
|
||
else
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(inet_listener\ +sieve\ +{.*)#\1inet_listener sieve {\n\1 \#address = 127.0.0.1 $ipv4\n\1 address = 127.0.0.1\n\1 port = 4190\n\1}\n\1\#\# \2#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true
|
||
fi
|
||
perl -i -n -p -e "s#^([ ]*\#?\ ?vsz_limit.*)#\1\n}#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*)\#?\ ?(service managesieve\ +{.*)#\1service managesieve {#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true
|
||
|
||
# since divecot 2.2.4: process_count changed to process_limit.
|
||
#
|
||
#perl -i -n -p -e "s#^([ ]*\#?\ ?process_count.*)#\1\n}#g" \
|
||
# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true
|
||
perl -i -n -p -e "s#^([ ]*\#?\ ?process_limit.*)#\1\n}#g" \
|
||
/usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf || _failed=true
|
||
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-managesieve.conf failed"
|
||
fi
|
||
|
||
fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-managesieve.conf
|
||
|
||
|
||
blank_line
|
||
|
||
_mode=644
|
||
_owner="root"
|
||
_group="staff"
|
||
echononl " Set owner/group permissions all configuration files to 'root:staff'."
|
||
find "/usr/local/dovecot-${_version}/etc/dovecot" -type f -exec chown "${_owner}:${_group}" {} +
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Setting the owner and group for the configuration files failed!"
|
||
fi
|
||
|
||
echononl " Set permissions for all configuration files to '644'."
|
||
find "/usr/local/dovecot-${_version}/etc/dovecot" -type f -exec chmod "${_mode}" {} +
|
||
if ! $_failed ; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Setting permissions on configuration files failed!"
|
||
fi
|
||
|
||
blank_line
|
||
|
||
|
||
## - Add a cronjob to check if certifice/key for dovecot service is-up-to-date
|
||
## -
|
||
echononl " Create cronjob for checking if certifice/key for dovecot service is-up-to-date"
|
||
|
||
if [[ -f "$_backup_crontab_file" ]] ; then
|
||
|
||
if ! grep -e "/root/bin/monitoring/check_cert_for_dovecot.sh" "$_backup_crontab_file" > /dev/null ; then
|
||
echo "" >> $_backup_crontab_file
|
||
echo "# - Check if cert/key for dovecot service is up-to-date" >> $_backup_crontab_file
|
||
echo "# -" >> $_backup_crontab_file
|
||
echo "46 05 * * * /root/bin/monitoring/check_cert_for_dovecot.sh" >> $_backup_crontab_file
|
||
crontab $_backup_crontab_file
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
else
|
||
|
||
_crontab_tmp_file=/tmp/crontab_root.$$
|
||
crontab -l > $_crontab_tmp_file 2> /dev/null
|
||
|
||
if [[ ! -s $_crontab_tmp_file ]]; then
|
||
echo "PATH=/usr/local/dovecot/bin:$PATH" > $_crontab_tmp_file
|
||
fi
|
||
|
||
if ! grep -e "/root/bin/monitoring/check_cert_for_dovecot.sh" $_crontab_tmp_file > /dev/null ; then
|
||
echo "" >> $_crontab_tmp_file
|
||
echo "# - Check if cert/key for dovecot service is up-to-date" >> $_crontab_tmp_file
|
||
echo "# -" >> $_crontab_tmp_file
|
||
echo "46 05 * * * /root/bin/monitoring/check_cert_for_dovecot.sh" >> $_crontab_tmp_file
|
||
crontab $_crontab_tmp_file
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
rm -f $_crontab_tmp_file
|
||
|
||
fi
|
||
|
||
echononl " Run script 'check_cert_for_dovecot.sh' if possible.."
|
||
if [[ -x "/root/bin/monitoring/check_cert_for_dovecot.sh" ]] ; then
|
||
/root/bin/monitoring/check_cert_for_dovecot.sh > $log_file 2>&1
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "$(cat "$log_file")"
|
||
|
||
echononl " continue anyway [yes/no]: "
|
||
read OK
|
||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||
echononl "Wrong entry! - repeat [yes/no]: "
|
||
read OK
|
||
done
|
||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
|
||
blank_line
|
||
echononl " Create symlink '/usr/local/dovecot' --> 'dovecot-${_version}'.."
|
||
rm -f /usr/local/dovecot
|
||
ln -s dovecot-${_version} /usr/local/dovecot
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Creating Symlink /usr/local/dovecot --> dovecot-${_version} /usr/local/dovecot failed"
|
||
fi
|
||
|
||
#_restart=""
|
||
#echo
|
||
#echo -e -n "Start/Restart services (dovecot/postfix)? [y/n]: "
|
||
#read _restart
|
||
#if [ "y" = "$_restart" -o "Y" = "$_restart" -o "Yes" = "$_restart" -o "yes" = "$_restart" ];then
|
||
# echononl " Start dovecot service.."
|
||
# if $systemd_support ; then
|
||
# systemctl start dovecot
|
||
# else
|
||
# /etc/init.d/dovecot start > /dev/null 2>&1
|
||
# fi
|
||
# if [ "$?" = 0 ]; then
|
||
# echo -e "$rc_done"
|
||
# else
|
||
# echo -e "$rc_failed"
|
||
# error "Starting dovecot service failed"
|
||
# fi
|
||
# echononl " Restart postfix.."
|
||
# if $SYSTEMD_EXISTS ; then
|
||
# systemctl restart postfix
|
||
# else
|
||
# /etc/init.d/postfix restart > /dev/null 2>&1
|
||
# fi
|
||
# if [ "$?" = 0 ]; then
|
||
# echo -e "$rc_done"
|
||
# else
|
||
# echo -e "$rc_failed"
|
||
# fatal "Restarting postfix failed"
|
||
# fi
|
||
#fi
|
||
|
||
echononl " Start dovecot service.."
|
||
if $systemd_support ; then
|
||
systemctl start dovecot
|
||
else
|
||
/etc/init.d/dovecot start > /dev/null 2>&1
|
||
fi
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Starting dovecot service failed"
|
||
fi
|
||
echononl " Restart postfix.."
|
||
if $SYSTEMD_EXISTS ; then
|
||
systemctl restart postfix
|
||
else
|
||
/etc/init.d/postfix restart > /dev/null 2>&1
|
||
fi
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
fatal "Restarting postfix failed"
|
||
fi
|
||
|
||
blank_line
|
||
echononl " Set '_update=true' in file '$(basename "$conf_file")'.."
|
||
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"
|
||
if [ "$?" = 0 ]; then
|
||
echo -e "$rc_done"
|
||
else
|
||
echo -e "$rc_failed"
|
||
error "Adjusting '"$conf_file"' (set _update=true) failed!"
|
||
fi
|
||
else
|
||
echo -e "$rc_skipped"
|
||
fi
|
||
|
||
echo -e "
|
||
|
||
\033[33m\033[1mNotice:\033[m
|
||
The Dovecot Service is configured to support more than 128 simultanously connections.
|
||
|
||
So, you have to \033[1mincrease /proc/sys/fs/inotify/max_user_instances\033[m (default is 128):
|
||
|
||
# echo \"fs.inotify.max_user_instances = 2048\" >> /etc/sysctl.conf
|
||
# sysctl -p
|
||
|
||
If you are running dovecot on a Virtual Guest System, you have to do that on the
|
||
Host (Root) System.
|
||
|
||
"
|
||
|
||
clean_up 0
|