#!/bin/bash # Path B hybrid: relay internal mail for a cPanel-only user via transport map. # Prerequisite: user removed from AD Mail-Users, mailbox inactive in Mailcow Admin. # Usage: setup-transport-cpanel-user.sh user@geonet.co.id set -euo pipefail EMAIL="${1:-}" NEXTHOP="${TRANSPORT_NEXTHOP:-[sc138.idcloudhosting.cloud]:587}" RELAYHOST_ID="${TRANSPORT_RELAYHOST_ID:-1}" STACK='/opt/stacks/mailcow' MYSQL_C='mailcowdockerized-mysql-mailcow-1' POSTFIX_C='mailcowdockerized-postfix-mailcow-1' PHP_C='mailcowdockerized-php-fpm-mailcow-1' if [ -z "$EMAIL" ]; then echo "Usage: $0 user@geonet.co.id" exit 1 fi mysql_q() { docker exec "$MYSQL_C" bash -lc "mysql mailcow -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -N -e \"$1\"" } mysql_exec() { docker exec "$MYSQL_C" bash -lc "mysql mailcow -uroot -p\"\$MYSQL_ROOT_PASSWORD\" -e \"$1\"" } echo "== LDAP sync ==" docker exec "$PHP_C" php /crons/ldap-sync.php || true echo "== Mailbox check (expect active=0) ==" MB=$(mysql_q "SELECT username, active, authsource FROM mailbox WHERE username='${EMAIL}';") echo "$MB" if echo "$MB" | grep -qP '\t1\t'; then echo "WARN: mailbox still active — deactivate in Mailcow Admin first (Path B)" fi echo "== Transport map ==" CNT=$(mysql_q "SELECT COUNT(*) FROM transports WHERE destination='${EMAIL}';") if [ "${CNT}" = "0" ]; then mysql_exec " INSERT INTO transports (destination, nexthop, username, password, is_mx_based, active) SELECT '${EMAIL}', '${NEXTHOP}', r.username, r.password, 0, 1 FROM relayhosts r WHERE r.id=${RELAYHOST_ID} AND r.active=1 LIMIT 1; " echo "Inserted transport for ${EMAIL} -> ${NEXTHOP}" else mysql_exec " UPDATE transports t JOIN relayhosts r ON r.id=${RELAYHOST_ID} AND r.active=1 SET t.nexthop='${NEXTHOP}', t.username=r.username, t.password=r.password, t.active=1 WHERE t.destination='${EMAIL}'; " echo "Updated existing transport for ${EMAIL}" fi mysql_exec "SELECT id, destination, nexthop, username, is_mx_based, active FROM transports WHERE destination='${EMAIL}';" echo "== Alias (SOGo RCPT acceptance) ==" ALIAS=$(mysql_q "SELECT COUNT(*) FROM alias WHERE address='${EMAIL}';") if [ "${ALIAS}" != "0" ]; then mysql_exec "UPDATE alias SET active=1 WHERE address='${EMAIL}';" mysql_exec "SELECT address, goto, active FROM alias WHERE address='${EMAIL}';" else echo "No alias row for ${EMAIL} (OK if sending only via postfix, not SOGo)" fi echo "== Postfix lookup ==" docker exec "$POSTFIX_C" postmap -q "${EMAIL}" mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf || true echo "== Reload postfix ==" docker exec "$POSTFIX_C" postfix reload echo "" echo "DONE. Test: send from support@ to ${EMAIL}, verify inbox on cPanel." echo "Admin UI: Configuration -> Routing -> Transport maps"