# Postfix SMTP Relay for RunCloud-Managed Servers

When a RunCloud-managed server (like wphost02) accumulates stuck email in Postfix's queue because port 25 outgoing is blocked, the fix is to relay through a working SMTP server. This is common with netcup infrastructure where only port 2525 works.

## Symptoms

- `mailq` shows 50+ stuck messages with "Connection timed out" to port 25 destinations
- Postfix logs show: `connect to <mx>[...]:25: Connection timed out`
- WP Mail SMTP on WordPress may work (if configured for port 2525), but the system's PHP `mail()` function goes through Postfix which tries port 25

## Diagnosis

```bash
mailq                          # Count stuck messages
grep "status=deferred" /var/log/mail.log | tail -5   # See delivery failures
```

## Fix: Relay through MXroute port 2525

Configure Postfix as a satellite relay through `mail.germainebrown.com:2525` with SASL auth:

```bash
postconf -e "relayhost = mail.germainebrown.com:2525"
postconf -e "smtp_sasl_auth_enable = yes"
postconf -e "smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd"
postconf -e "smtp_sasl_security_options = noanonymous"
postconf -e "smtp_tls_security_level = encrypt"
postconf -e "smtp_tls_wrappermode = no"
```

Create the SASL password file:

```bash
echo "mail.germainebrown.com:2525 shonuff@germainebrown.com:Catches.bullets1985" > /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
```

DNS: The sender domain must resolve. The system hostname (`wphost02`) will be the default sender domain, which MXroute rejects. Fix by setting a valid `myorigin` and generic address mapping:

```bash
postconf -e "smtp_generic_maps = hash:/etc/postfix/generic"
postconf -e "myorigin = /etc/mailname"
echo "apextrackexperience.com" > /etc/mailname
echo "@wphost02 contact@apextrackexperience.com" > /etc/postfix/generic
echo "root@wphost02 contact@apextrackexperience.com" >> /etc/postfix/generic
postmap /etc/postfix/generic
```

Restart and flush:

```bash
systemctl restart postfix
postqueue -f
```

## Verify

```bash
mailq                          # Should show: "Mail queue is empty"
grep "relay=mail.germainebrown.com" /var/log/mail.log | tail -5  # Check deliveries
```

## Note on stuck emails

Emails queued BEFORE the relay was configured will likely hit their 5-day expiry and bounce locally. The fix ensures **new** emails deliver correctly. Old ones may need to be re-sent by the application (WPForms, etc.).

## Diagnostic: Stuck Postfix after RunCloud reboot

When wphost02 reboots, Postfix may start stuck in an earlier state. Check `systemctl status postfix` for unexpected stop times or stale PIDs. A `systemctl restart postfix` followed by `postqueue -f` is usually sufficient to clear any accumulated queue.

## Credentials used

- Relay host: `mail.germainebrown.com:2525`
- Auth user: `shonuff@germainebrown.com`
- Auth pass: `Catches.bullets1985` (stored in send-shonuff.py and sasl_passwd)
- Sender override: `@wphost02` → `contact@apextrackexperience.com`
