#!/usr/bin/env bash clear echo -e "\n\t\033[32mStart script for installation of vacation script (from postfixadmin) ..\033[m" ## =================================================================== ## - Install Postfixadmin ## =================================================================== ## ----------------------------------------------------------------- ## ---------------------------------------------------------------- ## --- ## --- For configurations see file conf/install_postfixadmin.conf ## --- ## --- Dont make changes here! ## --- ## ----------------------------------------------------------------- ## ----------------------------------------------------------------- # ------------- # - Settings # ------------- _src_base_dir="$(realpath $(dirname $0))" conf_file="${_src_base_dir}/conf/install_postfixadmin.conf" log_file="$(mktemp)" backup_date="$(date +%Y-%m-%d-%H%M)" declare -A check_entry_main_cf_arr # ------------- # - Functions # ------------- clean_up() { # Perform program exit housekeeping rm -f "$log_file" exit $1 } echononl(){ echo X\\c > /tmp/shprompt$$ if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then echo "$*\\c" 1>&2 else echo -e -n "$*" 1>&2 fi rm /tmp/shprompt$$ } fatal(){ echo "" echo -e "\t[ \033[31m\033[1mFatal\033[m ]: $*" echo "" echo -e "\t\033[31m\033[1mInstalllation wird abgebrochen\033[m\033[m" echo "" clean_up 1 } error(){ echo "" echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*" echo "" } warn (){ echo "" echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*" echo "" } info (){ echo "" echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*" echo "" } # - remove leading/trailling whitespaces # - trim() { local var="$*" var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters echo -n "$var" } echo_ok() { echo -e "\033[75G[ \033[32mok\033[m ]" ## echo -e " [ ok ]" } echo_failed(){ echo -e "\033[75G[ \033[1;31mfailed\033[m ]" ## echo -e " [ failed ]" } echo_skipped() { echo -e "\033[75G[ \033[30m\033[1mskipped\033[m ]" } if [ "$POSTFIX_DB_TYPE" = "postgres" -o "$POSTFIX_DB_TYPE" = "postgresql" -o "$POSTFIX_DB_TYPE" = "pgsql" -o "$POSTFIX_DB_TYPE" = "psql" ];then POSTFIX_DB_TYPE=pgsql fi echo echononl "\tInclude Configuration file.." if [[ ! -f $conf_file ]]; then echo_failed fatal "Missing configuration file '$conf_file'" else source $conf_file echo_ok fi echo -e "\033[32m--\033[m" echo "" echo "Version of the EXISTING Postfixadmin installation" echo "" echo "" PF_ADMIN_VERSION= while [ "X$PF_ADMIN_VERSION" = "X" ] do echononl "Postfixadmin Version: " read PF_ADMIN_VERSION if [ "X$PF_ADMIN_VERSION" = "X" ]; then echo -e "\n\t\033[33m\033[1mA version number is required!\033[m\n" fi done echo "" echo -e "\033[32m--\033[m" echo "" _vacation_script="$(find ${_src_base_dir}/postfixadmin-${PF_ADMIN_VERSION} -type f -name vacation.pl -print 2>/dev/null)" if [[ ! -d "${_src_base_dir}/postfixadmin-${PF_ADMIN_VERSION}" ]]; then fatal "Postfix Admin source directory (${_src_base_dir}/postfixadmin-${PF_ADMIN_VERSION}) not found" fi if [[ -z "$(trim "$_vacation_script")" ]]; then fatal "No vacation script found!" fi # - Default values # - DEFAULT_WEBSITE_BASEDIR="/var/www/${WEBSITE_NAME}" DEFAULT_VACATION_USER="vacation" DEFAULT_VACATION_GROUP="vacation" DEFAULT_POSTFIX_DB_NAME="postfix" DEFAULT_POSTFIX_DB_USER="postfix" DEFAULT_POSTFIX_DB_HOST_MYSQL="unix:/tmp/mysql.sock" [[ -n "$PF_ADMIN_VERSION" ]] || fatal "Version of Postfix Admin to install (PF_ADMIN_VERSION) not present!" [[ -n "$WEBSITE_NAME" ]] || fatal "Website's name (WEBSITE_NAME) not present!" TLD=${WEBSITE_NAME##*.} _tmp_string=${WEBSITE_NAME%.*} MAIN_DOMAIN=${_tmp_string##*.} [[ -n "$AUTOREPLY_HOSTNAME" ]] || AUTOREPLY_HOSTNAME=autoreply.${MAIN_DOMAIN}.$TLD [[ -n "$POSTFIX_DB_HOST_MYSQL" ]] || POSTFIX_DB_HOST_MYSQL="$DEFAULT_POSTFIX_DB_HOST_MYSQL" if [[ "$POSTFIX_DB_HOST_MYSQL" =~ sock$ ]] || [[ "$POSTFIX_DB_HOST_MYSQL" =~ localhost ]]; then VACATION_DB_HOST_MYSQL="127.0.0.1" else VACATION_DB_HOST_MYSQL="$POSTFIX_DB_HOST_MYSQL" fi [[ -n "$POSTFIX_DB_TYPE" ]] || fatal "Database Type of Postfix Database (POSTFIX_DB_TYPE) not present!" [[ -n "$POSTFIX_DB_NAME" ]] || POSTFIX_DB_NAME="$DEFAULT_POSTFIX_DB_NAME" [[ -n "$POSTFIX_DB_USER" ]] || POSTFIX_DB_USER="$DEFAULT_POSTFIX_DB_USER" [[ -n "$POSTFIX_DB_PASS" ]] || fatal "Password of Postfix Database (POSTFIX_DB_PASS) not given!" # - Vacation # - [[ -n "$VACATION_USER" ]] || VACATION_USER=$DEFAULT_VACATION_USER [[ -n "$VACATION_GROUP" ]] || VACATION_GROUP=$DEFAULT_VACATION_GROUP echo "" echo "" echo -e "\033[1;32mSettings for installation of \033[1;37mPostfix Admin / Vacation\033[m" echo "" echo -e "\tPostfix Admin Version................: $PF_ADMIN_VERSION" echo "" echo -e "\tHostname for Vacation Messages.......: $AUTOREPLY_HOSTNAME" echo -e "\tUser of vacation script..............: $VACATION_USER" echo -e "\tGroup of vacation script.............: $VACATION_GROUP" echo "" echo -e "\tName of Postfix Database.............: $POSTFIX_DB_NAME" echo -e "\tUser of Postfix Database.............: $POSTFIX_DB_USER" echo -e "\tPassword of Postfix Database.........: $POSTFIX_DB_PASS" echo "" echo "" echo "" echo -n "Type upper case 'YES' to continue executing with this parameters: " read OK if [[ "$OK" = "YES" ]] ; then echo "" echo "" echo -e "\t\033[1;32mGoing to install Postfix Admin / Vacation \033[1;37m\033[m" else fatal "Abort by user request - Answer as not 'YES'" fi echo -e "\n\n\t\033[37m\033[1mInstall Vacation\033[m\n" echononl "\tInstall database related CPAN Modules" _failed=false > $log_file _needed_cpan_modules=" CPAN DBI Mail::Sender" if [[ "$POSTFIX_DB_TYPE" = "pgsql" ]] ; then _needed_cpan_modules="$_needed_cpan_modules DBD::Pg" else _needed_cpan_modules="$_needed_cpan_modules DBD::mysql" fi for _module in $_needed_cpan_modules ; do cpanm -q --skip-installed $_module >> "$log_file" 2>&1 if [[ "$?" -ne 0 ]] ; then error "$(cat $tmp_err_msg)" fi done if $_failed ; then echo_failed error "$(cat $log_file)" else echo_ok fi echo "" echononl "\tCreate system group '$VACATION_GROUP'" if ! grep -q "$VACATION_GROUP" /etc/group > /dev/null 2>&1 ; then addgroup --system --gid 65501 $VACATION_GROUP > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat $log_file)" else echo_ok fi else echo_skipped fi echononl "\tCreate system user '$VACATION_USER'" if ! grep -q "$VACATION_USER" /etc/passwd > /dev/null 2>&1 ; then adduser --system --home /var/spool/vacation --no-create-home --uid 65501 --gid 65501 --shell /usr/sbin/nologin $VACATION_USER > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat $log_file)" else echo_ok fi else echo_skipped fi echononl "\tCreate directory '/var/spool/vacation'" if [[ ! -d "/var/spool/vacation" ]]; then mkdir /var/spool/vacation > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat $log_file)" else echo_ok fi else echo_skipped fi echononl "\tSet Permissions on directoy '/var/spool/vacation'" chown -R ${VACATION_USER}:$VACATION_GROUP /var/spool/vacation > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat $log_file)" else echo_ok fi echononl "\tBackup existing script 'vacation.pl'" if [[ -f "/var/spool/vacation/vacation.pl" ]] ; then mv /var/spool/vacation/vacation.pl /var/spool/vacation/vacation.pl.${backup_date} > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then echo_failed error "$(cat $log_file)" else echo_ok fi else echo_skipped fi echononl "\tCopy vacation script to '/var/spool/vacation/vacation.pl'" if [[ -n "$(trim "$_vacation_script")" ]] ; then cp -a ${_vacation_script} /var/spool/vacation/ > "$log_file" 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi else error "Vacation script not found!" fi # - Encoding does not work as exspected. # - # - NOTE: # - this IS NOT a fix, but a workaround # - echononl "\tWorkaround, because encoding does not work as exspected." # - Vacation script changed. Since Version 3.2 we need another perl regexp. # - The old one was: # - perl -i -n -p -e "s/(\s*\'ctype\'\s* =>\s*)\'text\/plain.*$/\1\'text\/plain; charset=iso-8859-1\',/" \ # - perl -i -n -p -e "s/(\s*\'Content-Type\'\s* =>\s*)\"text\/plain.*$/\1\"text\/plain; charset=iso-8859-1\",/" \ /var/spool/vacation/vacation.pl > "$log_file" 2>&1 if [[ $? -eq 0 ]];then echo_ok info "This IS NOT a fix, but a workaround." else echo_failed error "$(cat $log_file)" fi echononl "\tSet Permission on vacation script" _failed=false chown ${VACATION_USER}:$VACATION_GROUP /var/spool/vacation/vacation.pl > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi chmod 700 /var/spool/vacation/vacation.pl > "$log_file" 2>&1 if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ;then echo_failed error "$(cat $log_file)" else echo_ok fi # - Script vacation.pl tries to reads setting from # - # - /etc/mail/postfixadmin/vacation.conf # - /etc/postfixadmin/vacation.conf # - # - Instead of changing this script, we put the needed entries # - to file /etc/postfixadmin/vacation.conf: # - echononl "\tCreate directory '/etc/postfixadmin' " if [[ ! -d "/etc/postfixadmin" ]]; then mkdir /etc/postfixadmin > "$log_file" 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi echononl "\tBackup existing file '/etc/postfixadmin/vacation.conf'" if [[ -f "/etc/postfixadmin/vacation.conf" ]]; then mv /etc/postfixadmin/vacation.conf /etc/postfixadmin/vacation.conf.${backup_date} > "$log_file" 2>&1 if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi # - Create configuration file '/etc/postfixadmin/vacation.conf' # - echononl "\tCreate configuration file '/etc/postfixadmin/vacation.conf'" if [[ "$POSTFIX_DB_TYPE" = "pgsql" ]]; then _db_type="Pg" else _db_type="mysql" fi cat < /etc/postfixadmin/vacation.conf 2> "$log_file" \$db_type = '$_db_type'; \$db_username = '${POSTFIX_DB_USER}'; \$db_password = '${POSTFIX_DB_PASS}'; \$db_name = '${POSTFIX_DB_NAME}'; EOF if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then cat <> /etc/postfixadmin/vacation.conf 2> "$log_file" \$db_host = '$VACATION_DB_HOST_MYSQL'; EOF fi cat <> /etc/postfixadmin/vacation.conf 2> "$log_file" \$vacation_domain = '${AUTOREPLY_HOSTNAME}'; \$syslog = 0; \$log_to_file = 1; \$logfile = '/var/log/vacation.log'; \$log_level = 1; \$interval = 60*60*24; \$smtp_ssl = '0'; 1; # required final line - keeps perl happy. EOF if [[ $? -eq 0 ]];then echo_ok else echo_failed error "$(cat $log_file)" fi echononl "\tCreate logfile /var/log/vacation.log" touch /var/log/vacation.log > "$log_file" 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi echononl "\tSet permissions on /var/log/vacation.log" chown ${VACATION_USER}:$VACATION_GROUP /var/log/vacation.log > "$log_file" 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi echononl "\tConfigure logrotation for '/var/log/vacation.log'" cat < /etc/logrotate.d/vacation 2> "$log_file" /var/log/vacation.log { daily start 0 rotate 7 missingok compress delaycompress notifempty create 640 vacation vacation copytruncate } EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi # - Create an entry in /etc/hosts for the (non-existant domain) # - $AUTOREPLY_HOSTNAME # - # - add: # - # - 127.0.0.1 $AUTOREPLY_HOSTNAME # - echononl "\tCreate entry in /etc/hosts for '$AUTOREPLY_HOSTNAME'" if ! grep -q "$AUTOREPLY_HOSTNAME" /etc/hosts > $log_file 2>&1 ; then perl -i -n -p -e"s#(^\s*127.0.0.1\s+localhost.*)#\1\n\n127.0.0.1 ${AUTOREPLY_HOSTNAME}#" /etc/hosts > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi # - Define the transport type in the Postfix master file # - /etc/postfix/master.cf # - # - vacation unix - n n - - pipe # - flags=Rq user=vacation argv=/var/spool/vacation/vacation.pl -f ${sender} -- ${recipient} # - echononl "\tDefine transport for vacation in /etc/postfix/master.cf" if ! grep -q -E "^\s*vacation\s+unix" /etc/postfix/master.cf > $log_file 2>&1 ; then cat <> /etc/postfix/master.cf vacation unix - n n - - pipe flags=Rq user=vacation argv=/var/spool/vacation/vacation.pl -f \${sender} -- \${recipient} EOF if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi # - Setup the transport maps file /etc/postfix/transport # - # - add line: # - # - $AUTOREPLY_HOSTNAME vacation: # - echononl "\tSetup the transport maps for vacation domain in '/etc/postfix/transport'" if ! grep -q -E "^\s*$AUTOREPLY_HOSTNAME\s+vacation:" /etc/postfix/transport > $log_file 2>&1 ; then _failed=false echo "$AUTOREPLY_HOSTNAME vacation:" >> /etc/postfix/transport 2> $log_file if [[ $? -ne 0 ]] ; then _failed=true fi postmap btree:/etc/postfix/transport > $log_file 2>&1 if [[ $? -ne 0 ]] ; then _failed=true fi if [[ $? -ne 0 ]]; then _failed=true fi if $_failed ;then echo_failed error "$(cat $log_file)" else echo_ok fi else echo_skipped fi check_entry_main_cf_arr["transport_maps"]="btree:/etc/postfix/transport" # - Add 'btree:/etc/postfix/transport' ton parameter transport_maps in /etc/postfix/main.cf # - # - take care the entry for transport_maps in /etc/postfix/main.cf # - contains "btree:/etc/postfix/transport" # - echononl "\tAdd 'btree:/etc/postfix/transport' to parameter transport_maps" if ! grep -q "btree:/etc/postfix/transport" /etc/postfix/main.cf > $log_file 2>&1 ; then perl -i -n -p -e "s#(^transport_maps\s+=.*)#\1\n btree:/etc/postfix/transport#" /etc/postfix/main.cf > $log_file 2>&1 if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi else echo_skipped fi echononl "\tReload/Restart postfix" if $systemd_supported ; then systemctl reload postfix > $log_file 2>&1 else /etc/init.d/postfix reload > $log_file 2>&1 fi if [[ $? -eq 0 ]] ; then echo_ok else echo_failed error "$(cat $log_file)" fi echo "" clean_up 0