#!/bin/sh

# stanv@ :

# This backend uses `augtool'

# stanv@: Чтобы заполучить ключ DrWeb для тестирования:
# Регистрируемся на http://beta.drweb.com/
# Скачать универсальный ключ /win/10.0/keys/drweb32.key
# Данный ключ подходит для всех продуктов DrWeb.
# Ключ обновляется каждых три месяца.

# set `verbose' to get debug output for `alterator -l -d'

# Debug Postfix:
# add -v into master.cf
# smtp      inet  n       -       -       -       -       smtpd -v

# Debug Dovecot:
# edit /etc/dovecot/conf.d/10-logging.conf

# http://wiki2.dovecot.org/HowTo/PostfixAndDovecotSASL
# https://wiki.debian.org/PostfixAndSASL
# http://www.postfix.org/postconf.5.html
#
# 1.
# как я понимаю, всегда используется защита соединения: STARTTLS
# Это видно по коммиту:
# commit 4ee3ef3c96d0bba0f3fc32b8bafda0ff1f0d3d72
#     - remove option smtpd_tls_auth_only, default yes

# при STARTTLS требовать зашифрованный пароль для SASL авторизации - не нужно,
# т.е. STARTTLS + зашифрованный пароль для SASL авторизации не работает.
# postconf_write smtpd_tls_auth_only yes ???

# http://www.postfix.org/postconf.5.html#smtpd_tls_auth_only
# 'smtpd_tls_auth_only' -- When TLS encryption is optional in the Postfix SMTP
# server, do not announce or accept SASL authentication over unencrypted connections.
# Т.е. == заставляет SASL аутентификацию только через TLS.
# stanv@: глубокий смысл в том что: TLS у нас не форсируется. Но если хочешь SASL
# авторизацию, тогда включай TLS

# smtpd_sasl_security_options --- в учет в нашем случае (STARTTLS - force) НЕ идет
# smtpd_sasl_tls_security_options --- при STARTTLS смотрится этот
#
# 2.
# у нас всегда включен STARTTLS, и он форсируется
# правда мне не понятно кто его включает впервые, наверно хук, какой-то
#
# Если тест на вирус включен, в доставленном письме должен быть заголовок:
# X-Virus-Scanned: ClamAV using ClamSMTP

# 3.
# The end of each list is equivalent to a PERMIT result.

alterator_api_version=1
po_domain="alterator-postfix-dovecot"

# libshell
verbose=
. shell-error

v() {
    verbose "__DEBUG__" $@
}

readonly CLAM_S_CONF="/etc/clamsmtpd.conf"
readonly DRWEB_CONFIG="/etc/drweb/maild_postfix.conf"
readonly DRWEB_MONITOR_CONFIG="/etc/drweb/monitor.conf"
readonly DRWEB_DAEMON="/opt/drweb/drwebd"
readonly DRWEB_USER="drweb"
readonly DRWEB_GROUP="drweb"
readonly DRWEB_SERVICE="drweb-monitor"
readonly POSTFIX_MASTER="/etc/postfix/master.cf"
readonly POSTFIX_MAIN="/etc/postfix/main.cf"

readonly SASL_SOCKET_PATH="/var/spool/postfix/private/auth"
readonly SASL_SOCKET_USER="postfix"
readonly SASL_SOCKET_GROUP="postfix"
readonly SASL_SOCKET_MODE="0660"

# clamsmtpd: scan service port
readonly CLAM_PORT_IN="10026"
# drweb: scan service port
readonly DRWEB_PORT_IN="8025"
# postfix: injecting mail back into Postfix from antivirus software
readonly POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK="8026"

# Augeas Dovecot path
readonly AUG_DOVECOT_BASE="/files/etc/dovecot/conf.d"

. alterator-sh-functions
. shell-ini-config
. alterator-service-functions
. alterator-postfix-dovecot-functions
. shell-config

# augtool for this backend
# load only necessary modules
# See available modules at: /usr/share/augeas/lenses/dist
# and # augtool match '/augeas/load/*'
# Prints results to STDOUT
aug() {
    v "invoke augtool with: $@"
    augtool -A -i << _EOF_
set /augeas/load/Postfix_Main/lens postfix_main.lns
set /augeas/load/Postfix_Main/incl /etc/postfix/main.cf

set /augeas/load/Postfix_Master/lens postfix_master.lns
set /augeas/load/Postfix_Master/incl /etc/postfix/master.cf

set /augeas/load/Dovecot/lens dovecot.lns
set /augeas/load/Dovecot/incl[1] /etc/dovecot/conf.d/*.conf
set /augeas/load/Dovecot/incl[2] /etc/dovecot/dovecot.conf

load

$@

save
quit
_EOF_
    return $?
}

# Augeas: remove path
aug_rm() {
    local file="$1"
    local entry="$2"

    if [ -z "$file" -o -z "$entry" ]; then
        v "aug_rm() wrong invocation"
        return
    fi

    local path="/files/$file/$entry"

    v "aug_rm() path = $path"

    aug "rm" "$path"
}

# Augeas: test existence
aug_present() {
    local file="$1"
    local entry="$2"

    if [ -z "$file" -o -z "$entry" ]; then
        v "aug_present() wrong invocation"
        return
    fi

    local path="/files/$file/$entry"

    v "aug_present() path = $path"

    local result="$(aug "get" "$path")"

    v "aug_present() key value = $result"

    if [ -z "${result##*\(o\)}" ]; then
        v "aug_present() key $path isn't present"
        return 1
    fi

    v "aug_present() key $path is present"
    return 0
}

# Dovecot turn On SASL authorization
dovecot_provide_sasl_set_on() {
    v "dovecot_provide_sasl_set_on() -- enter"
    aug "set" "$AUG_DOVECOT_BASE/*/service[. = 'auth']/unix_listener[. = '/var/spool/postfix/private/auth']" "$SASL_SOCKET_PATH"
    aug "set" "$AUG_DOVECOT_BASE/*/service[. = 'auth']/unix_listener[. = '/var/spool/postfix/private/auth']/group" "$SASL_SOCKET_GROUP"
    aug "set" "$AUG_DOVECOT_BASE/*/service[. = 'auth']/unix_listener[. = '/var/spool/postfix/private/auth']/user" "$SASL_SOCKET_USER"
    aug "set" "$AUG_DOVECOT_BASE/*/service[. = 'auth']/unix_listener[. = '/var/spool/postfix/private/auth']/mode" "$SASL_SOCKET_MODE"
}

# Dovecot turn Off SASL authorization
dovecot_provide_sasl_set_off() {
    v "dovecot_provide_sasl_set_off() -- enter"
    aug "rm" "$AUG_DOVECOT_BASE/*/service[. = 'auth']/unix_listener[. = '/var/spool/postfix/private/auth']"
}

# Dovecot test SASL authorization
dovecot_provide_sasl_status() {
    v "dovecot_provide_sasl_status() -- enter"
    local status="$(aug "get" "$AUG_DOVECOT_BASE/*/service[. = 'auth']/unix_listener[. = '/var/spool/postfix/private/auth']")"
    if [ -z "${status##*\(o\)}" ]; then
        v "Dovecot SASL is disabled"
        return 1
    fi

    v "Dovecot SASL is activated"
    return
}

# Clamsmtpd is available?
is_clamsmtpd_avail() {
    v "is_clamsmtpd_avail() -- enter"
    if ! [ -e "$CLAM_S_CONF" ]; then
        v "check clamsmtpd avail: no"
        return 1
    fi

    v "check clamsmtpd avail: yes"
    return 0
}

# DrWeb is available?
is_drweb_avail() {
    v "is_drweb_avail() -- enter"
    if ! [ -e "$DRWEB_DAEMON" ]; then
        v "check $DRWEB_DAEMON is avail: no"
        return 1
    fi

    v "check DrWeb is avail: yes"
    return 0
}

print_info() {
    echo ' '
    echo "# $@"
    $@ 2>&1
    echo ' '
}

# Write any debug information to frontend
write_debug_info() {
        local info=

        info="${info}$(print_info "service dovecot status")"
        info="${info}$(print_info "service clamd status")"
        info="${info}$(print_info "service postfix status")"
        info="${info}$(print_info "service clamsmtpd status")"
        info="${info}$(print_info "lsof -c "master" -a -iTCP -sTCP:LISTEN")"
        info="${info}$(print_info "lsof -c "dovecot" -a -iTCP -sTCP:LISTEN")"
        info="${info}$(print_info "lsof -c "clamsmtpd" -a -iTCP -sTCP:LISTEN")"
        write_string_param information "$info"
}

# Postfix: SASL off
postfix_use_sasl_off() {
    v "postfix_use_sasl_off() -- enter"
    postconf_write "smtpd_sasl_auth_enable" "no"
}

# Postfix: SASL on
# Follow rule: Restrictions are applied in the order as specified; the first restriction that matches wins.
# Look at: http://www.postfix.org/postconf.5.html#smtpd_recipient_restrictions
# The end of each list is equivalent to a PERMIT result.
postfix_use_sasl_on() {
    v "postfix_use_sasl_on() -- enter"
    postconf_write "smtpd_sasl_type" "dovecot"
    postconf_write "smtpd_sasl_path" "private/auth"
    postconf_write "smtpd_sasl_auth_enable" "yes"
    postconf_write "smtpd_sasl_tls_security_options" "noanonymous"
    postconf_write "smtpd_tls_auth_only" "yes"

    # Add 'permit_sasl_authenticated' to 'smtpd_recipient_restrictions'
    if ! postconf_has "smtpd_recipient_restrictions" "permit_sasl_authenticated"; then
        v "Add 'permit_sasl_authenticated' to 'smtpd_recipient_restrictions'"
        local v1="$(postconf_read "smtpd_recipient_restrictions")"
        v1="$(echo "$v1" | sed "s/permit_mynetworks${end_delim_re}/permit_mynetworks, permit_sasl_authenticated\1/")"
        v "new 'smtpd_recipient_restrictions': $v1"
        postconf_write "smtpd_recipient_restrictions" "$v1"
    fi
}

postfix_use_sasl_status() {
    v "postfix_use_sasl_status() -- enter"

    if postconf_has "smtpd_sasl_auth_enable" "yes" &&
        postconf_has "smtpd_recipient_restrictions" "permit_sasl_authenticated"; then
        # Yes
        return 0
    fi

    # No
    return 1
}

# Print to front-end SASL status
determine_sasl_setup() {
    v "determine_sasl_setup() -- enter"

    if ! dovecot_provide_sasl_status; then
        v "Dovecot disables socket for postfix SASL authorization"
        write_bool_param "use_sasl" "no"
        return
    fi

    v "dovecot provides socket for postfix SASL authorization"

    if ! postfix_use_sasl_status; then
        v "Postfix isn't configured for SASL"
        write_bool_param "use_sasl" "no"
        return
    fi

    v "Postfix is configured for SASL"
    write_bool_param "use_sasl" "yes"
}

sasl_setup() {
    v "sasl_setup() -- enter"

    if test_bool "$in_use_sasl"; then
        v "use SASL flag is on"
        if ! dovecot_provide_sasl_status; then
            dovecot_provide_sasl_set_on
        fi

        if ! postfix_use_sasl_status; then
            postfix_use_sasl_on
        fi
    else
        v "use SASL flag is off"
        if dovecot_provide_sasl_status; then
            v "Dovecot provides SASL, turn it off"
            dovecot_provide_sasl_set_off
        fi

        if postfix_use_sasl_status; then
            v "Postfix uses SASL, turn it off"
            postfix_use_sasl_off
        fi

    fi
}


dump_clamav_conf()
{
    v "dump_clamav_conf() - enter"

    # Is ClamAV software available?
    if ! is_clamsmtpd_avail; then
        write_bool_param "is_installed_clamsmtpd" "no"
        v "can't use clamav, clamsmtpd is absent"
        write_string_param "label_clamav" "$(_ 'Clamav software is absent')"
        return
    fi

    local clam_port_in="$(clamsmtpd_port_in)"
    local clam_port_out="$(clamsmtpd_port_out)"
    v "clamsmtpd listen at port : $clam_port_in"
    v "clamsmtpd sends checked mail to port: $clam_port_out"

    # Does ClamAV have good config?
    if [ "$clam_port_in" != "$CLAM_PORT_IN" ]; then
        write_bool_param "is_installed_clamsmtpd" "no"
        v "can't use clamav, clamsmtpd has bad configuration"
        write_string_param "label_clamav" "$(_ 'Clamav software has wrong configuration')"
        return
    fi

    write_bool_param "is_installed_clamsmtpd" "yes"

    local scaner=$(postconf_read "content_filter")
    v "Postfix scaner is: $scaner"

    # Format is: content_filter = scan:127.0.0.1:10026
    echo "$scaner" |
    while IFS=':' read master_name host port; do
        case "$port" in
            $clam_port_in)
                write_bool_param "use_antivirus" "yes"
                if [ "$clam_port_out" == "$DRWEB_PORT_IN" ]; then
                    v "Postfix configured for using ClamAV, than DrWeb"
                    write_string_param "selected_antivirus" "clamav-drweb"
                elif [ "$clam_port_out" == "$POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK" ]; then
                    v "Postfix configured for using ClamAV only "
                    write_string_param "selected_antivirus" "clamav"
                else
                    v "Bad ClamAV configuration"
                fi
                ;;
        esac
    done
}


dump_drweb_conf()
{
    v "dump_drweb_conf() - enter"

    # Is DrWeb software available?
    if ! is_drweb_avail; then
        write_bool_param "is_installed_drwebd" "no"
        v "can't use drweb, software is absent"
        write_string_param "label_drweb" "$(_ 'DrWeb software is absent')"
        return
    fi

    local drweb_port_in="$(drweb_port_in)"
    local drweb_port_out="$(drweb_port_out)"

    v "DrWeb in port: $drweb_port_in"
    v "DrWeb out port: $drweb_port_out"

    # Does DrWeb have good config?
    if [ "$drweb_port_in" != "$DRWEB_PORT_IN" ]; then
        write_bool_param "is_installed_drwebd" "no"
        v "can't use DrWeb, DrWeb has bad configuration"
        write_string_param "label_drweb" "$(_ 'DrWeb software has wrong configuration')"
        return
    fi

    write_bool_param "is_installed_drwebd" "yes"

    local scaner=$(postconf_read "content_filter")
    v "Postfix scaner is: $scaner"

    # Format is: content_filter = scan:127.0.0.1:10026
    echo "$scaner" |
    while IFS=':' read master_name host port; do
        case "$port" in
            $drweb_port_in)
                write_bool_param "use_antivirus" "yes"
                if [ "$drweb_port_out" == "$CLAM_PORT_IN" ]; then
                    v "Postfix configured for using DrWeb, than ClamAV"
                    write_string_param "selected_antivirus" "drweb-clamav"
                elif [ "$drweb_port_out" == "$POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK" ]; then
                    v "Postfix configured for using DrWeb only "
                    write_string_param "selected_antivirus" "drweb"
                else
                    v "Bad DrWeb configuration"
                fi
                ;;
        esac
    done
}

shell_set()
{
    local name="$1"
    shift

    quote_sed_regexp_variable value "$1"
    shift

    local file="$1"
    shift

    local msg="${1:-invalid value}"

    if [ -n "$name" -a -n "$value" ];then
        sed -e "/^$name:/s/.*/$name: $value/g" -i "$file"
    else
        write_error "$msg"
        return 1
    fi

    return 0
}


determine_antivirus()
{
    v "determine_antivirus() -- enter"

    local scaner=$(postconf_read "content_filter")

    v "Postfix is configured for scaner: $scaner"

    if [ -z "$scaner" ]; then
        write_bool_param "use_antivirus" "no"
        v "don't use antivirus"
    fi

    dump_clamav_conf
    dump_drweb_conf
    write_debug_info
}

# Configure Postfix to not use antivirus
write_antivirus_off()
{
    v "write_antivirus_off() -- enter"

    v "Clean content_filter in $POSTFIX_MAIN"
    postconf_write "content_filter" ""

    v "Clean inject port in $POSTFIX_MASTER"
    aug_rm "$POSTFIX_MASTER" "127.0.0.1:${POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK}"

    v "Clean inject port $POSTFIX_MASTER"
    aug_rm "$POSTFIX_MASTER" "scan"
}


# Get clamsmtpd listen port
clamsmtpd_port_in() {
    v "clamsmtpd_port_in() -- enter"
    local port="$(grep ^Listen "$CLAM_S_CONF" | cut -f 3 -d ':')"
    echo "$port"
}


# Get clamsmtpd out/forward port
clamsmtpd_port_out() {
    v "clamsmtpd_port_out() -- enter"
    local port="$(grep ^OutAddress "$CLAM_S_CONF" | cut -f 3 -d ':')"
    echo "$port"
}


# Get clamsmtpd listen port
drweb_port_in() {
    v "drweb_port_in() -- enter"
    # Should be something like: inet:8025@127.0.0.1
    local drwebd_in="$(ini_config_get "$DRWEB_CONFIG" "Receiver" "Address")"
    local port="$(echo "$drwebd_in" | sed -n -e 's/inet:\([[:digit:]]\+\)@.*/\1/p')"
    echo "$port"
}


# Get clamsmtpd out/forward port
drweb_port_out() {
    v "drweb_port_out() -- enter"
    # Should be something like: inet:8026@127.0.0.1
    local drwebd_out="$(ini_config_get "$DRWEB_CONFIG" "Sender" "Address")"
    local port="$(echo "$drwebd_out" | sed -n -e 's/inet:\([[:digit:]]\+\)@.*/\1/p')"
    echo "$port"
}


# Postfix config
postfix_do_scan()
{
    v "postfix_do_scan() -- enter"

    if aug_present "$POSTFIX_MASTER" "scan"; then
        v "antivirus scan is configured"
        return
    fi

    v "Postfix antivirus scan is not configured, configure it at $POSTFIX_MASTER" >&2

    local scan_service="
    set /files/$POSTFIX_MASTER/scan/type unix
    set /files/$POSTFIX_MASTER/scan/private -
    set /files/$POSTFIX_MASTER/scan/unprivileged -
    set /files/$POSTFIX_MASTER/scan/chroot n
    set /files/$POSTFIX_MASTER/scan/wakeup -
    set /files/$POSTFIX_MASTER/scan/limit 16
    set /files/$POSTFIX_MASTER/scan/command \"smtp -o smtp_send_xforward_command=yes\""

    aug "$scan_service"

    local inject="127.0.0.1:${POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK}"
    local inject_service="
    set /files/$POSTFIX_MASTER/$inject/type inet
    set /files/$POSTFIX_MASTER/$inject/private n
    set /files/$POSTFIX_MASTER/$inject/unprivileged -
    set /files/$POSTFIX_MASTER/$inject/chroot n
    set /files/$POSTFIX_MASTER/$inject/wakeup -
    set /files/$POSTFIX_MASTER/$inject/limit 16
    set /files/$POSTFIX_MASTER/$inject/command \"smtpd \
        -o mynetworks=127.0.0.0/8 \
        -o content_filter= \
        -o receive_override_options=no_unknown_recipient_checks,no_header_body_checks \
        -o smtpd_helo_restrictions= \
        -o smtpd_client_restrictions= \
        -o smtpd_sender_restrictions= \
        -o smtpd_recipient_restrictions=permit_mynetworks,reject \
        -o mynetworks_style=host \
        -o smtpd_authorized_xforward_hosts=127.0.0.0/8\""

    aug "$inject_service"
}


setup_drweb() {

    local port_out="$1"

    if ! is_drweb_avail; then
        v "Do not setup DrWeb, software is absent"
        return
    fi

    # Out port
    ini_config_set "$DRWEB_CONFIG" "Sender" "Address" "inet:$port_out@127.0.0.1"

    # In port. Stays always the same.
    ini_config_set "$DRWEB_CONFIG" "Receiver" "Address" "inet:$DRWEB_PORT_IN@127.0.0.1"
    
    # Start 'maild' plugin as a monitor service
    ini_config_set "$DRWEB_MONITOR_CONFIG" "Monitor" "RunAppList" "AGENT, MAILD"

    # function `ini_config_get' at /bin/shell-ini-config resets rights, it does mv
    # restore rights
    chown "${DRWEB_USER}:${DRWEB_GROUP}" "$DRWEB_CONFIG" "$DRWEB_MONITOR_CONFIG"
    chmod "0644" "$DRWEB_CONFIG" "$DRWEB_MONITOR_CONFIG"

    # Restart services
    v "Do restart for drwebdd"
    service "$DRWEB_SERVICE" "restart"
}


setup_clamav() {

    local port_out="$1"

    if ! is_clamsmtpd_avail; then
        v "Do not setup clamav, clamsmtpd is absent"
        return
    fi

    # Do not use quarantine
    shell_set "Quarantine" "off" "$CLAM_S_CONF"

    # Out port
    shell_set "OutAddress" "127.0.0.1:$port_out" "$CLAM_S_CONF"

    # In port. Stays always the same.
    shell_set "Listen" "127.0.0.1:$CLAM_PORT_IN" "$CLAM_S_CONF"

    # Restart services
    v "Do retart for clamsmtpd"
    service clamsmtpd restart
}


write_antivirus_on()
{
    v "write_antivirus_on() -- enter"

    local antivirus_port_in=

    case "$in_selected_antivirus" in
        clamav)
            setup_clamav "$POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK"
            antivirus_port_in="$CLAM_PORT_IN"
            ;;
        clamav-drweb)
            setup_clamav "$DRWEB_PORT_IN"
            setup_drweb "$POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK"
            antivirus_port_in="$CLAM_PORT_IN"
            ;;
        drweb)
            setup_drweb "$POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK"
            antivirus_port_in="$DRWEB_PORT_IN"
            ;;
        drweb-clamav)
            setup_drweb "$CLAM_PORT_IN"
            setup_clamav "$POSTFIX_LISTEN_PORT_FROM_ANTIVIRUS_BACK"
            antivirus_port_in="$DRWEB_PORT_IN"
            ;;
    esac

    # Configure Postfix
    postconf_write "content_filter" "scan:127.0.0.1:${antivirus_port_in}"

    # postconf.5: Disable canonical address mapping, virtual alias map
    # expansion, address masquerading, and automatic BCC (blind carbon-copy)
    # recipients. This is typically specified BEFORE an external content
    # filter.
    postconf_write "receive_override_options" "no_address_mappings"

    postfix_do_scan

    shell_set "Quarantine" "off" "$CLAM_S_CONF"
}

write_limit_param()
{
    local v="$(postconf_read "message_size_limit")"
    write_string_param "$1" "$(($v / 1048576))"
}

read_limit_param()
{
    if [ -z "$2" ]; then
        v "read_limit_param() wrong invocation"
        return
    fi

    postconf_write "$1" "$(($2 * 1048576))"
}

control_postfix()
{
    local status=
    if [ -n "$1" ]; then
        v "set Postfix 'control' switch: $1"
        /usr/sbin/control postfix "$1"
     else
        status="$(/usr/sbin/control postfix)"
        v "current Postfix 'control' switch: $status"
        echo "$status"
    fi
}

daemon_status()
{
    test -n "$1" || return 1

    if service_control "$1" is-enabled && service_control "$1" is-active; then
        return 0
    fi

    return 1
}

daemon_on()
{
    test -n "$1" || return
    daemon_status "$1" && return 0

    service_control "$1" on
    service_control "$1" start || :
}

daemon_off()
{
    test -n "$1" || return
    service_control "$1" condstop
    service_control "$1" off
}

daemon_condreload()
{
    test -n "$1" || return
    service_control "$1" condreload
}

domain_is_master()
{
    [ "$(shell_config_get /etc/sysconfig/system SERVER_ROLE)" = "master" ] &&
        return 0 || return 1
}

on_message() {
    set | grep '^in_' >&2
    echo >&2
    case "$in_action" in
        type)
            write_type_item relayhost		hostname
            write_type_item message_size_limit	postfix-limit
            write_type_item domainlist		hostname-list
            #			write_type_item filtered_recipients	hostname-list
            ;;
        list)
            case "$in__objects" in
                modes)
                    write_enum_item relay "`_ "Relay"`"
                    write_enum_item mx "`_ "MX"`"
                    ;;
            esac
            ;;
        read)
            if [ "$(control_postfix)" != "local" ]; then
                write_bool_param postfix_daemon yes
            else
                write_bool_param postfix_daemon no
            fi

            # Operational mode
            if [ -n "$(postconf_read "relayhost")" ]; then
                write_string_param mode 'relay'
            else
                write_string_param mode 'mx'
            fi

            # Upstream SMTP host
            write_string_param relayhost "$(postconf_read "relayhost")"

            # Domain list - accept mail for these domains
            write_string_param domainlist "$(cat "$MYDESTINATION" | tr '\n' ' ')"

            # Root mail alias
            write_string_param rootmail "$(rootmail_read)"
            write_limit_param message_size_limit

            # Filter spam
            if [ "$(control_postfix)" = "filter" ]; then
                ! daemon_status spamd
                write_bool_param spamfilter "$?"
            else
                write_bool_param spamfilter no
            fi

            # Filter senders
            if postconf_has smtpd_client_restrictions reject_rbl_client ; then
                write_bool_param filter_senders yes
            else
                write_bool_param filter_senders no
            fi

            # Filter recipients
            if grep -qs '\bREJECT\b' "$(list_name recipient)"; then
                write_bool_param filter_recipients yes
                write_string_param filtered_recipients "$(reject_list recipient | tr '\n' ' ')"
            else
                write_bool_param filter_recipients no
            fi

            # Antivirus
            determine_antivirus

            # Dovecot
            if ! dovecot_read protocols | grep -qs '\bimap pop3 lmtp\b'; then
                v "Dovecot is not configured"
                write_bool_param "pop3_imap" "no"
            else
                # Dovecot status
                ! daemon_status dovecot >/dev/null 1>&2
                local res=$?

                # If Dovecot avaible, check SASL
                if shell_var_is_yes "$res"; then
                    v "Dovecot is active"
                    write_bool_param pop3_imap "yes"
                    v "Look up SASL setings"
                    determine_sasl_setup
                else
                    v "Dovecot is disabled"
                    write_bool_param pop3_imap "yes"
                fi
            fi



            write_string_param "mynetworks" "$(cat "$MYNETWORKS" | tr '\n' ' ')"

            [ "$(shell_config_get /etc/sysconfig/system SERVER_ROLE)" = "master" ] &&
                write_bool_param domain_master true ||
                write_bool_param domain_master false
            ;;
  write)
      case "$in_mode" in
          mx)
              postconf_write "relayhost" ""
              echo -n > "$MYDESTINATION"
              for i in $in_domainlist; do
                  echo "$i" >> "$MYDESTINATION"
              done
              ;;
          relay)
              postconf_write "relayhost" "$in_relayhost"
              ;;
      esac

      rootmail_write "$in_rootmail"
      read_limit_param message_size_limit "$in_message_size_limit"

      if test_bool "$in_filter_senders"; then
          # functions from /usr/bin/alterator-postfix-dovecot-functions
          postconf_restrict_on
      else
          postconf_restrict_off
      fi

      if test_bool "$in_use_antivirus"; then
          write_antivirus_on
          daemon_condreload "postfix"
      else
          write_antivirus_off
          daemon_condreload "postfix"
      fi

      if test_bool "$in_filter_recipients"; then
          for i in $in_filtered_recipients; do
              # reject_* functions are in /usr/bin/alterator-postfix-dovecot-functions
              reject_has "$(list_name recipient)" "$i" ||
                  reject_add "$(list_name recipient)" "$i"
          done
      else
          reject_clean "$(list_name recipient)"
      fi

      echo -n > "$MYNETWORKS"
      for i in $in_mynetworks; do
          echo "$i" >> "$MYNETWORKS"
      done

      if test_bool "$in_pop3_imap"; then
          dovecot_write protocols "imap pop3 lmtp"
          #				dovecot_auth_write auth_mechanisms "plain login"
          daemon_condreload dovecot
          daemon_on dovecot
      else
          dovecot_write protocols "none"
          daemon_condreload dovecot
      fi

      if test_bool "$in_postfix_daemon"; then
          if test_bool "$in_spamfilter"; then
              daemon_on spamd
              if [ "$(control_postfix)" = "filter" ]; then
                  daemon_condreload postfix
              else
                  control_postfix filter
              fi
          else
              daemon_off spamd
              if [ "$(control_postfix)" != "server" ]; then
                  control_postfix server
                  # enabled: Enable Postfix SMTP:587 service, see smtpd(8)
                  # should be enabled - but broken: stanv@
                  /usr/sbin/control postfix-submission disabled
              fi
          fi

          v "Setup SASL setings"
          sasl_setup

      else
          if [ "$(control_postfix)" != "local" ]; then
              # disabled: Disable Postfix SMTP:587 service, see smtpd(8)
              /usr/sbin/control postfix-submission disabled
              control_postfix local
              daemon_off spamd
          fi
      fi
      ;;
  esac
}

message_loop
# vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=sh
