diff --git a/install_update_dovecot-2.4.sh b/install_update_dovecot-2.4.sh index 8aad9d3..5dff44a 100755 --- a/install_update_dovecot-2.4.sh +++ b/install_update_dovecot-2.4.sh @@ -274,6 +274,40 @@ replace_or_append_code_block() { 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" @@ -356,7 +390,248 @@ replace_or_append_code_block_if_keyval() { 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 – daher am Ende angehängt." + 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 @@ -838,17 +1113,6 @@ dovecot_minor_patch_level="$(echo $_version | cut -d '.' -f4)" _version_short="${_version%-*}" -#echo "" -#echo "_version: $_version" -#echo "dovecot_main_version $dovecot_main_version" -#echo "dovecot_major_version $dovecot_major_version" -#echo "dovecot_minor_version $dovecot_minor_version" -#echo "dovecot_patch_level $dovecot_patch_level" -#echo "dovecot_minor_patch_level $dovecot_minor_patch_level" -#echo "" -# -#clean_up 0 - # 'expire plugin'was removed in version 2.3.14: This plugin is not needed. # Use mailbox { autoexpunge } Mailbox settings instead. @@ -1050,7 +1314,7 @@ rc_not_yet_implemented="${rc_not_yet_implemented}" EOF -cat <<'EOF' >> ${INSTALL_UPDATE_ENVIRONMENT_FILE} +cat <<'EOF' >> "${INSTALL_UPDATE_ENVIRONMENT_FILE}" # ------------- @@ -1289,6 +1553,40 @@ replace_or_append_code_block() { 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" @@ -1371,7 +1669,248 @@ replace_or_append_code_block_if_keyval() { 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 – daher am Ende angehängt." + 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 @@ -1431,6 +1970,77 @@ delete_code_block() { 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" @@ -1542,12 +2152,13 @@ replace_or_append_variable() { return 0 } + delete_variable() { local var_name="$1" local file="$2" if [[ -z "$var_name" || -z "$file" ]]; then - echo "Verwendung: delete_variable \"variablenname\" \"/pfad/zur/datei\"" + echo "Verwendung: delete_variable_only \"variablenname\" \"/pfad/zur/datei\"" return 1 fi @@ -1571,77 +2182,6 @@ delete_variable() { 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 -} - delete_variable_with_comments() { local var_name="$1" local file="$2" @@ -2370,51 +2910,99 @@ if [[ $dovecot_major_version -gt 2 ]] \ _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 - 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 - - cat <<'EOF' > "${_conf_file}" 2> "${log_file}" + cat <<'EOF' > "${_conf_file}" 2> "${log_file}" ## ## Mail Location ans Namespace Settigs ## EOF - if [[ $? -gt 0 ]] ; then - _failed=true + 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 - touch "${_conf_file}" > ${log_file} + cat <<'EOF' > "${_conf_file}" 2> "${log_file}" +## +## SSL settings +## +EOF if [ "$?" = 0 ]; then echo -e "$rc_done" else echo -e "$rc_failed" - error "Creating empty file '${_conf_file}' failed!" + error "Creating file '${_conf_file}' failed!" fi else echo -e "$rc_skipped" fi - cat <<'EOF' > "${_conf_file}" 2> "${log_file}" + + _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}" ## -## SSL settings +## Mailbox definitions ## EOF - if [[ $? -gt 0 ]] ; then - _failed=true + 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 + + blank_line + fi @@ -2834,19 +3422,8 @@ else fi - 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" - - if $_new ; then if [ "$db_driver" = "pgsql" ]; then @@ -3159,6 +3736,7 @@ fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-master.conf # _failed=false +: > "${log_file}" if [[ $dovecot_major_version -gt 2 ]] \ || ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then @@ -4091,8 +4669,6 @@ ${_param} = ${_val} EOF fi - echo "ssl_min_protocol: done" - # - Replace only the first occurence of the match # - # - Example: @@ -4106,8 +4682,6 @@ EOF 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 - echo "ssl_cipher_list: done" - _param="ssl_min_protocol" _val="TLSv1.2" @@ -4478,49 +5052,48 @@ else ## - ## - mailbox_list_index = yes ## - - echononl " Adjusting file 10-mail.conf" + echononl " Adjusting file '$(basename "${_conf_file}")'.." perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(mail_location\ +=.*)#\1\#\# \2\n\1mail_location = maildir:/var/vmail/%d/%n/Maildir#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_uid.*)#\1\#\# \2\n\1mail_uid = vmail#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_gid.*)#\1\#\# \2\n\1mail_gid = vmail#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_temp_dir.*)#\1\#\# \2\n\1mail_temp_dir = /var/vmail/tmp#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(first_valid_uid.*)#\1\#\# \2\n\1first_valid_uid = 5000#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(last_valid_uid.*)#\1\#\# \2\n\1last_valid_uid = 5000#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(first_valid_gid.*)#\1\#\# \2\n\1first_valid_gid = 5000#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(last_valid_gid.*)#\1\#\# \2\n\1last_valid_gid = 5000#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_socket_path\ +=.*)#\1\#\# \2\n\1auth_socket_path = /run/dovecot/auth-userdb#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true else perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota acl#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + "${_conf_file}" || _failed=true fi perl -i -n -p -e "s#^([ ]*)\#?\ ?(mailbox_list_index\s*=.*)#\1\#\# \2\n\1mailbox_list_index = yes#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true + ${_conf_file} || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting file '10-mail.conf' 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 @@ -4553,7 +5126,7 @@ _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 file '$(basename "${_conf_file}")'.." + echononl " Modify or add namespaces in file '$(basename "${_conf_file}")'.." # modify /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf # @@ -4809,72 +5382,7 @@ EOF else - echononl " Modify file '$(basename "${_conf_file}")'.." - - ## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf - ## - - ## - comment out namespace section "namespace inbox". we will create namespaces later. - ## - in detail, tha means comment out 3 lines: - ## - namespace inbox { - ## - .. - ## - inbox = yes - ## - .. - ## - } - ## - -# _tmp_file="$(mktemp)" -# > $_tmp_file -# while IFS='' read -r _line || [[ -n $_line ]] ; do -# -# if echo "$_line" | grep -i -E "^\s*namespace\s+inbox\s+" > /dev/null 2>&1 ; then -# echo "## $_line" >> $_tmp_file -# _found=true -# continue -# fi -# -# if $_found && echo "$_line" | grep -i -E "^\s*}" > /dev/null 2>&1 ; then -# echo "## $_line" >> $_tmp_file -# _found=false -# continue -# fi -# -# if $_found ; then -# echo "## $_line" >> $_tmp_file -# else -# echo "$_line" >> $_tmp_file -# fi -# done < "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf" -# if [[ "$?" != "0" ]] ; then -# _failed=true -# fi -# mv /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf \ -# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf.TMP -# if [[ "$?" != "0" ]] ; then -# _failed=true -# fi -# mv $_tmp_file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf -# if [[ "$?" != "0" ]] ; then -# _failed=true -# fi -# chmod 644 /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf -# if [[ "$?" != "0" ]] ; then -# _failed=true -# fi -# -# -# #perl -i -n -p -e "s#^([ ]*)(namespace\ +inbox\ +{\ *)#\1\#\#\ \2#g" \ -# # /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true -# #perl -i -n -p -e "s#^([ ]*)(inbox\ +=\ +yes\ *)#\1\#\#\ \2#g" \ -# # /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true -# #perl -i -n -p -e "s#^([ ]*)(}\ *)#\1\#\#\ \2#g" \ -# # /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.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-mail.conf failed" -# fi - + echononl " Modify or add namespaces in file '$(basename "${_conf_file}")'.." ## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf ## - @@ -4920,7 +5428,6 @@ else ## - # namespace handles them (empty prefix should always have this as "yes") ## - #subscriptions = yes ## - } - echononl " Modify file '$(basename "${_conf_file}")'.." if grep -qE "^\s*namespace\s+inbox\s*{" "${_conf_file}"; then @@ -5101,12 +5608,169 @@ 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 - echononl " Adjusting file 15-mailboxes.conf.." - echo -e "$rc_not_yet_implemented" + # 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 file '$(basename "${_conf_file}")'.." + + read -r -d '' NEW_BLOCK <> "${_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 "${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 @@ -5134,47 +5798,47 @@ else ## - } ## - - echononl " Adjusting file 15-mailboxes.conf" + echononl " Adjusting file '$(basename "${_conf_file}")'" perl -i.ORIG -n -p -e "s#^([ ]*)(mailbox\ +Drafts\ +{.*)#\1\2\n\1 auto = subscribe#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1\2\n\1 auto = no#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)(mailbox\ +Junk\ +{.*)#\1\2\n\1 auto = no\n\1 autoexpunge = 30d#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_conf_file} || _failed=true else perl -i -n -p -e "s#^([ ]*)(mailbox\ +Trash\ +{.*)#\1\2\n\1 auto = subscribe\n\1 autoexpunge = 3d#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_conf_file} || _failed=true fi perl -i -n -p -e "s#^([ ]*)(mailbox\ +Sent\ +{.*)#\1\2\n\1 auto = subscribe#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)(mailbox\ +\"Sent Messages\"\ +{.*)#\1\2\n\1 auto = no#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf || _failed=true + ${_conf_file} || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-mailboxes.conf failed" + fatal "Adjusting ${_conf_file} failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/15-mailboxes.conf @@ -5183,11 +5847,127 @@ 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 file '10-auth.conf'.." - echo -e "$rc_not_yet_implemented" + echononl " Adjusting file '$(basename "${_conf_file}")'.." + + # edit /usr/local/dovecot/etc/dovecot/conf.d/10-auth.conf + # + # auth_allow_cleartext = no + # 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_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 <> "${_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 + + replace_variable '!include' "auth-sql.conf.ext" "${_conf_file}" || _failed=true + + 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. +# +# +# +# User database specifies where mails are located and what user/group IDs +# own them. For single-UID configuration use "static" userdb. +# +# + +!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 @@ -5198,23 +5978,23 @@ else ## - !include auth-sql.conf.ext # comment all other includes ## - auth_username_translation = "%@" ## - - echononl " Adjusting file 10-auth.conf" + echononl " Adjusting file '$(basename "${_conf_file}")'.." perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(disable_plaintext_auth\ +=.*)#\1\#\# \2\n\1disable_plaintext_auth = yes#" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_mechanisms\ +=.*)#\1\#\# \2\n\1auth_mechanisms = $auth_mechanisms#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^(\!include\ auth-.*)#\#\1#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^\#(\!include\ auth-sql.*)#\1#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_username_translation\ +=.*)#\1\#\# \2\n\1auth_username_translation = \"%@\"#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf || _failed=true + ${_conf_file} || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-auth.conf failed" + fatal "Adjusting ${_conf_file} failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-auth.conf @@ -5222,11 +6002,247 @@ 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 - echononl " Adjusting file '/auth-sql.conf.ext'.." - echo -e "$rc_not_yet_implemented" + # 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 file '$(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 = '%u' AND active = true user_query = SELECT '/var/vmail/' || maildir AS home, \ + '5000' AS uid, '5000' AS gid \ + FROM mailbox \ + WHERE username = '%u' 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 <> "${_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 username AS user, password \ + FROM mailbox \ + WHERE username = '%u' AND active = true user_query = SELECT '/var/vmail/' || maildir AS home, \ + '5000' AS uid, '5000' AS gid \ + FROM mailbox \ + WHERE username = '%u' 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 <> "${_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 = '%u' AND active = true user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \ + '5000' AS uid, '5000' AS gid \ + FROM mailbox \ + WHERE username = '%u' 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 <> "${_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 username AS user, password \ + FROM mailbox \ + WHERE username = '%u' AND active = true user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \ + '5000' AS uid, '5000' AS gid \ + FROM mailbox \ + WHERE username = '%u' 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 <> "${_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 @@ -5260,14 +6276,95 @@ else 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 if [[ $dovecot_major_version -gt 2 ]] \ || ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then echononl " Create sql configuration file 'sql-connect.conf.ext'.." - echo -e "$rc_not_yet_implemented" + + if [[ "$db_driver" = "pgsql" ]]; then + + cat < /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 < /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 @@ -5288,8 +6385,7 @@ 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 = '%u' AND active = true -user_query = SELECT '/var/vmail/' || maildir AS home, \\ + WHERE username = '%u' AND active = true user_query = SELECT '/var/vmail/' || maildir AS home, \\ '5000' AS uid, '5000' AS gid \\ FROM mailbox \\ WHERE username = '%u' AND active = true @@ -5315,8 +6411,7 @@ 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 = '%u' AND active = true -user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\ + WHERE username = '%u' AND active = true user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\ '5000' AS uid, '5000' AS gid \\ FROM mailbox \\ WHERE username = '%u' AND active = true @@ -5339,10 +6434,11 @@ 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 - echononl " Adjusting file '10-logging.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." echo -e "$rc_not_yet_implemented" else @@ -5370,21 +6466,21 @@ else ## - :msg,contains,"stored mail into mailbox"\ ## - -/var/log/dovecot.lmtp ## - - echononl " Adjusting file '10-logging.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(log_path\ ?=.*)#\1\#\# \2\n\1log_path = syslog#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(syslog_facility\ ?=.*)#\1\#\# \2\n\1syslog_facility = local1#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_verbose\ ?=.*)#\1\#\# \2\n\1auth_verbose = yes#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true + ${_conf_file} || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(auth_verbose_passwords\ ?=.*)#\1\#\# \2\n\1auth_verbose_passwords = plain#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf || _failed=true + ${_conf_file} || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-logging.conf failed" + fatal "Adjusting ${_conf_file} failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-logging.conf @@ -5468,10 +6564,11 @@ 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 - echononl " Adjusting file '15-lda.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." echo -e "$rc_not_yet_implemented" else @@ -5484,23 +6581,23 @@ else ## - lda_mailbox_autocreate = no ## - mail_plugins = $mail_plugins sieve ## - - echononl " Adjusting file '15-lda.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(postmaster_address\ +=.*)#\1\#\# \2\n\1postmaster_address = $postmaster_address#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(hostname\ +=.*)#\1\#\# \2\n\1hostname = $hostname#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(sendmail_path\ +=.*)#\1\#\# \2\n\1sendmail_path = /usr/sbin/sendmail#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(lda_mailbox_autocreate\ +=.*)#\1\#\# \2\n\1lda_mailbox_autocreate = no#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins sieve#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf || _failed=true + "${_conf_file}" || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/15-lda.conf failed" + fatal "Adjusting '${_conf_file}' failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/15-lda.conf @@ -5509,10 +6606,11 @@ 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 - echononl " Adjusting file '20-lmtp.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." echo -e "$rc_not_yet_implemented" else @@ -5522,17 +6620,17 @@ else ## - lmtp_save_to_detail_mailbox = no ## - mail_plugins = $mail_plugins sieve ## - - echononl " Adjusting file '20-lmtp.conf'.." + echononl " Adjusting file '$(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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins sieve#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf || _failed=true + "${_conf_file}" || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-lmtp.conf failed" + fatal "Adjusting '${_conf_file}' failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-lmtp @@ -5541,10 +6639,11 @@ fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-lmtp # 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 - echononl " Adjusting file '20-lmtp.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." echo -e "$rc_not_yet_implemented" else @@ -5557,21 +6656,21 @@ else ## - mail_plugins = $mail_plugins imap_quota ## - imap_client_workarounds = delay-newmail ## - - echononl " Adjusting file 20-imap.conf" + echononl " Adjusting file '$(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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true + "${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins imap_quota#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(imap_client_workarounds\ +=.*)#\1\#\# \2\n\1imap_client_workarounds = delay-newmail#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true + "${_conf_file}" || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf failed" + fatal "Adjusting '${_conf_file}' failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.conf @@ -5580,10 +6679,11 @@ 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 " Adjusting file '20-pop3.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." echo -e "$rc_not_yet_implemented" else @@ -5595,19 +6695,19 @@ else ## - mail_max_userip_connections = 24 ## - pop3_client_workarounds = outlook-no-nuls oe-ns-eoh ## - - echononl " Adjusting file 20-pop3.conf" + echononl " Adjusting file '$(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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_max_userip_connections\ +=.*)#\1\#\# \2\n\1mail_max_userip_connections = 24#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf || _failed=true + "${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf || _failed=true + "${_conf_file}" || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-pop3.conf failed" + fatal "Adjusting '${_conf_file}' failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-pop3.conf @@ -5616,10 +6716,11 @@ 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 file '90-plugin.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." echo -e "$rc_skipped" else @@ -5641,17 +6742,17 @@ else ## - # working as wanted. (v2.2.16+) ## - expire_cache = yes ## - - echononl " Adjusting file 90-plugin.conf" + echononl " Adjusting 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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-plugin.conf || _failed=true + "${_conf_file}" || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-plugin.conf failed" + fatal "Adjusting '${_conf_file}' failed" fi else echo -e "$rc_skipped" @@ -5663,10 +6764,11 @@ 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 file '20-lmtp.conf'.." + echononl " Adjusting file '$(basename "${_conf_file}")'.." echo -e "$rc_not_yet_implemented" else @@ -5680,23 +6782,23 @@ else ## - sieve_global = /usr/local/dovecot/etc/dovecot/sieve/global/ ## - recipient_delimiter = ## - - echononl " Adjusting file 90-sieve.conf" + echononl " Adjusting file '$(basename "${_conf_file}")'.." perl -i.ORIG -n -p -e "s#^([ ]*)\#?\ ?(sieve\ ?=.*)#\1\#\# \2\n\1sieve = ~/.dovecot.sieve#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true + "${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(sieve_dir\ ?=.*)#\1\#\# \2\n\1sieve_dir = ~/sieve#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true + "${_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" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true + "${_conf_file}" || _failed=true perl -i -n -p -e "s#^([ ]*)\#?\ ?(recipient_delimiter\ ?=.*)#\1\#\# \2\n\1recipient_delimiter =#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf || _failed=true + "${_conf_file}" || _failed=true if ! $_failed ; then echo -e "$rc_done" else echo -e "$rc_failed" - fatal "Adjusting /usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" + fatal "Adjusting "${_conf_file}"" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf @@ -5707,6 +6809,7 @@ fi # edit /usr/local/dovecot/etc/dovecot/conf.d/90-sieve.conf # Add Setting for included Pigeonhole Sieve: Vacation Extension # _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 @@ -5754,8 +6857,8 @@ else EOF fi - done < "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" - cp -a "$_tmp_file" "/usr/local/dovecot-${_version}/etc/dovecot/conf.d/90-sieve.conf" > /dev/null 2>&1 + 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 @@ -6578,13 +7681,26 @@ EOF fi fi -fi +fi # if new + +# Renew file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext +# _failed=false -echononl " Renew file sql-dict.conf.ext" -if [ "$db_driver" = "pgsql" ]; then +_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 - cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + echononl " Renew file '$(basename "${_conf_file}")'.." + echo -e "$rc_not_yet_implemented" + +else + + echononl " Renew file '$(basename "${_conf_file}")'.." + if [ "$db_driver" = "pgsql" ]; then + + + cat < "${_conf_file}" ## - if using unix-socket (host=/run/postgresql) ensure that ## - coresponding entries in pg_hba.cof fits ## - for example @@ -6650,24 +7766,24 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname # EXECUTE PROCEDURE merge_quota2(); map { - pattern = priv/quota/storage - table = quota2 - username_field = username - value_field = bytes +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 +pattern = priv/quota/messages +table = quota2 +username_field = username +value_field = messages } EOF - if [[ "$?" -gt 0 ]]; then - _failed=true - fi + if [[ "$?" -gt 0 ]]; then + _failed=true + fi - if $plugin_expire ; then - cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + if $plugin_expire ; then + cat <> "${_conf_file}" # CREATE TABLE expires ( # username varchar(100) not null, @@ -6698,66 +7814,31 @@ EOF # FOR EACH ROW EXECUTE PROCEDURE merge_expires(); map { - pattern = shared/expire/\$user/\$mailbox - table = expires - value_field = expire_stamp +pattern = shared/expire/\$user/\$mailbox +table = expires +value_field = expire_stamp - fields { - username = \$user - mailbox = \$mailbox - } +fields { + username = \$user + mailbox = \$mailbox +} } EOF - if [[ "$?" -gt 0 ]]; then - _failed=true + if [[ "$?" -gt 0 ]]; then + _failed=true + fi + 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 - 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 - - ## - you also have to update the userdb's query in file - ## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to - ## - support extra variable "quota_rule" - ## - - echononl " Renew file sql-connect.conf.ext" -cat < /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 = '%u' 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 = '%u' 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 </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + elif [ "$db_driver" = "mysql" ]; then + cat </usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname # CREATE TABLE quota2 ( @@ -6768,24 +7849,24 @@ connect = host=$dbhost user=$dbuser password=$dbpassword dbname=$dbname # ); map { - pattern = priv/quota/storage - table = quota2 - username_field = username - value_field = bytes +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 +pattern = priv/quota/messages +table = quota2 +username_field = username +value_field = messages } EOF - if [[ "$?" -gt 0 ]]; then - _failed=true - fi + if [[ "$?" -gt 0 ]]; then + _failed=true + fi - if $plugin_expire ; then - cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext + if $plugin_expire ; then + cat <> /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext # CREATE TABLE expires ( # username varchar(100) not null, @@ -6795,43 +7876,309 @@ EOF # ); map { - pattern = shared/expire/\$user/\$mailbox - table = expires - value_field = expire_stamp +pattern = shared/expire/\$user/\$mailbox +table = expires +value_field = expire_stamp - fields { - username = \$user - mailbox = \$mailbox - } +fields { + username = \$user + mailbox = \$mailbox +} } EOF - if [[ "$?" -gt 0 ]]; then - _failed=true + 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 file '$(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 = '%u' 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 = '%u' AND active = true +} +EOF + if grep -qE "^\s*passdb\s+sql\s+{" "${_conf_file}"; then + + replace_code_block "passdb" "${NEW_BLOCK}" "${_conf_file}" || _failed=true + + else + cat <> "${_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 username AS user, password \ + FROM mailbox \ + WHERE username = '%u' 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 = '%u' 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 <> "${_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 = '%u' 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 = '%u' 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 <> "${_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 username AS user, password \ + FROM mailbox \ + WHERE username = '%u' 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 = '%u' 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 <> "${_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" - fatal "Recreating file /usr/local/dovecot-${_version}/etc/dovecot/sql-dict.conf.ext 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 - ## - you also have to update the userdb's query in file - ## - "/usr/local/dovecot/etc/dovecot/sql-connect.conf.ext" to - ## - support extra variable "quota_rule" + +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 file sql-connect.conf.ext" -cat < /usr/local/dovecot-${_version}/etc/dovecot/sql-connect.conf.ext + echononl " Renew file '$(basename "${_conf_file}")'.." + + if [ "$db_driver" = "pgsql" ]; then + + cat < /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 = '%u' 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 = '%u' 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 < /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 = '%u' AND active = true -user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\ +FROM mailbox \\ +WHERE username = '%u' 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 \\ @@ -6841,13 +8188,15 @@ user_query = SELECT CONCAT('/var/vmail/',maildir) AS home, \\ ## - 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" + 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 +fi # Update the userdb's and passdb's SQL query + ## - configure stats service (10-master.conf) @@ -7146,75 +8495,12 @@ fi ## - -## edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf -## -## Add namespaces type shared to 10-mail.conf -## -#if [[ $dovecot_major_version -gt 2 ]] \ -# || ( [[ $dovecot_major_version -eq 2 ]] && [[ $dovecot_minor_version -gt 3 ]] ); then -# -# echononl " Add namespaces type shared to '10-mail.conf'...." -# echo -e "$rc_not_yet_implemented" -# -#else -# -# ## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf -# ## - -# ## - Add namespaces type shared to 10-mail.conf -# ## - Take care to enable ACL plugin also, otherwise all users can access all the shared -# ## - mailboxes, assuming they have permissions on filesystem level to do so. -# ## - we will do that later.. -# ## - namespace { -# ## - type = shared -# ## - separator = / -# ## - prefix = shared/%%u/ -# ## - location = maildir:/var/vmail/%%d/%%n/Maildir:INDEX=~/Maildir/shared/%%u -# ## - subscriptions = no -# ## - list = children -# ## - } -# ## - -# echononl " Add namespaces type shared to 10-mail.conf" -# cat <> /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf -# -#namespace { -# #type = shared -# #separator = / -# type = shared -# separator = / -# -# # Mailboxes are visible under "shared/user@domain/" -# # %%n, %%d and %%u are expanded to the destination user. -# #prefix = shared/%%u/ -# 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 -# -# # List the shared/ namespace only if there are visible shared mailboxes. -# list = children -#} -#EOF -# if [ "$?" = 0 ]; then -# echo -e "$rc_done" -# else -# echo -e "$rc_failed" -# fatal "Adding namespaces to /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf failed" -# fi -# -#fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf - - # 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 @@ -7229,53 +8515,16 @@ else ## - echononl " Add mail_plugin imap_acl to 20-imap.conf" perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = \\\$mail_plugins imap_quota imap_acl#g" \ - /usr/local/dovecot-${_version}/etc/dovecot/conf.d/20-imap.conf || _failed=true + "${_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/20-imap.conf failed" + fatal "Adjusting file '${_conf_file}' failed" fi fi # edit /usr/local/dovecot/etc/dovecot/conf.d/20-imap.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 -# -# echononl " Adjust the mail_plugins parameter in the $(basename "${_conf_file}") file.." -# echo -e "$rc_not_yet_implemented" -# -#else -# -# ## - edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf -# ## - -# ## - mail_plugins = quota expire acl -# ## - -# _failed=false -# echononl " Adjust the mail_plugins parameter in the $(basename "${_conf_file}") file.." -# -# if $plugin_expire ; then -# perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota expire acl#g" \ -# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true -# else -# perl -i -n -p -e "s#^([ ]*)\#?\ ?(mail_plugins\ +=.*)#\1\#\# \2\n\1mail_plugins = quota acl#g" \ -# /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf || _failed=true -# fi -# -# if ! $_failed ; then -# echo -e "$rc_done" -# else -# echo -e "$rc_failed" -# fatal "Adjusting file /usr/local/dovecot-${_version}/etc/dovecot/conf.d/10-mail.conf failed" -# fi -# -#fi # edit /usr/local/dovecot/etc/dovecot/conf.d/10-mail.conf - - ## - !! Notice !! ## - There a two possibilities, configuring acl backend: ## - - flat file