Upload files to "deployments/services/email/Proxmox Mail Gateway"
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 4s

This commit is contained in:
2026-07-22 17:33:33 -06:00
parent 9ada534310
commit ba60557c6f
@@ -0,0 +1,315 @@
---
tags:
- Mailcow
- Proxmox Mail Gateway
- SMTP
- Email
---
## Purpose
This workflow describes how to configure Mailcow to trust Proxmox Mail Gateway (PMG) as an upstream SMTP relay after PMG has been placed in front of Mailcow for inbound filtering. It prevents Mailcow from applying sender-domain validation and duplicate spam filtering to messages that PMG has already accepted, including messages released from the PMG quarantine.
In the current Bunny Lab design, this trust applies to the inbound delivery path from `192.168.3.15` to `192.168.3.61`. Mailcow continues to send outbound mail directly to the Internet and does not relay outbound mail through PMG.
!!! info "Assumptions"
- Mailcow is already deployed at `192.168.3.61`.
- PMG is already deployed at `192.168.3.15`.
- Public inbound SMTP port `25` is forwarded to PMG.
- PMG relays accepted inbound mail to Mailcow on `192.168.3.61:25`.
- Mailcow remains responsible for mailbox hosting, authenticated submission, DKIM signing, and outbound delivery.
- You have `root` access to the Mailcow host.
!!! warning "Trust Only the PMG Host"
Add only `192.168.3.15/32` to Mailcow's trusted networks. Do not trust the entire `192.168.3.0/24` subnet unless every system on that subnet is authorized to relay mail through Mailcow without authentication.
## Architecture
```text
Internet
|
v
pfSense WAN :25
|
v
PMG 192.168.3.15:25
|
v
Mailcow 192.168.3.61:25
|
v
User Mailbox
```
PMG is the primary inbound spam and virus filtering authority. Mailcow should accept the SMTP session from PMG as a trusted relay and avoid repeating edge filtering or rejecting PMG-generated envelope senders.
## Symptoms
Use this workflow when PMG receives and processes mail correctly, but Mailcow rejects or defers the final delivery.
Common symptoms include:
- A released PMG quarantine message remains in the PMG deferred queue
- Clicking **Flush** in PMG does not deliver the message
- PMG repeatedly attempts delivery to `192.168.3.61:25`
- Mailcow rejects a PMG-generated envelope sender such as `postmaster@lab-mail-gw-01.bunny-lab.io`
- PMG reports an SMTP response similar to:
```text
450 4.1.8 Sender address rejected: Domain not found
```
The visible message sender may be valid even when Mailcow rejects the PMG-generated envelope sender used during quarantine release.
## Confirm the PMG Source Address
Mailcow must trust the source address it actually sees on the SMTP connection. Confirm that address before changing the configuration.
On the Mailcow host, run:
```sh
cd /opt/mailcow-dockerized
docker compose logs --since 5m postfix-mailcow
```
Flush or resend a test message from PMG, then locate the connection line.
Expected connection source:
```text
connect from lab-mail-gw-01[192.168.3.15]
```
If Mailcow sees a different address because of NAT, a load balancer, or another SMTP proxy, use that observed address instead of `192.168.3.15`.
## Configure Mailcow Forwarding Hosts
Configure PMG as a trusted forwarding host in the Mailcow WebUI.
- Navigate to "**System > Configuration > Options > Forwarding Hosts**"
- Add `192.168.3.15`
- Set the forwarding-host spam filter option to **Inactive**
- Save the configuration
!!! note "Forwarding Host Behavior"
The forwarding-host entry tells Mailcow that PMG is the immediate upstream SMTP relay. Keeping the forwarding-host spam filter inactive avoids applying a second aggressive spam-filtering layer to mail that PMG has already inspected.
## Configure Postfix Trusted Networks
The forwarding-host entry does not replace Postfix `mynetworks`. Add PMG to `mynetworks` so Postfix treats SMTP sessions from PMG as trusted and evaluates `permit_mynetworks` before sender-domain restrictions.
### Inspect the Active Configuration
On the Mailcow host, run:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf mynetworks
```
The validated Bunny Lab configuration is:
```text
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
Preserve every existing loopback and Mailcow Docker network. The PMG address must be appended as a single-host CIDR.
### Update the Persistent Postfix Override
Edit the Mailcow Postfix override file:
```sh
nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf
```
Set the complete `mynetworks` value:
```ini title="/opt/mailcow-dockerized/data/conf/postfix/extra.cf"
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
!!! warning "Preserve Existing Networks"
Defining `mynetworks` replaces the automatically derived value. Do not remove `127.0.0.0/8`, `172.22.1.0/24`, or `[::1]/128` from the validated Bunny Lab configuration.
### Restart Mailcow Postfix
Apply the persistent override:
```sh
cd /opt/mailcow-dockerized
docker compose restart postfix-mailcow
```
## Validate the Trusted Relay Configuration
Confirm the active Postfix configuration after the restart:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf mynetworks
```
Expected result:
```text
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
Confirm the active SMTP restriction order includes `permit_mynetworks`:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf \
smtpd_sender_restrictions \
smtpd_recipient_restrictions \
smtpd_relay_restrictions
```
The exact restriction lists may change between Mailcow releases. Confirm that `permit_mynetworks` remains present and that the effective configuration recognizes `192.168.3.15/32` as trusted.
## Retry Deferred PMG Mail
After Mailcow trusts PMG, retry the deferred message from the PMG WebUI.
- Navigate to "**Administration > Queue Administration > Deferred Mail**"
- Select the deferred message
- Click **Flush**
Alternatively, run the following on PMG:
```sh
postqueue -f
```
To retry one specific queue item:
```sh
postsuper -r <QUEUE_ID>
postqueue -f
```
## Validate Mail Delivery
Monitor Mailcow while PMG retries the message:
```sh
cd /opt/mailcow-dockerized
docker compose logs -f postfix-mailcow
```
Mailcow should accept the SMTP transaction and return a successful queue response similar to:
```text
250 2.0.0 Ok: queued as <MAILCOW_QUEUE_ID>
```
On PMG, confirm the deferred queue no longer contains the message:
```sh
postqueue -p
```
Confirm the message is present in the destination Mailcow mailbox.
!!! success "Trusted PMG Delivery Confirmed"
The workflow is complete when Mailcow accepts mail from `192.168.3.15`, the PMG deferred queue clears, and the destination mailbox receives the message.
## Security Boundaries
Adding `192.168.3.15/32` to `mynetworks` permits PMG to relay mail through Mailcow without SMTP authentication. This is appropriate only while PMG remains a controlled gateway host.
Maintain the following boundaries:
- Restrict the trusted entry to `192.168.3.15/32`
- Prevent other hosts from impersonating the PMG source address
- Keep Mailcow port `25` restricted to expected SMTP sources where practical
- Confirm PMG is not configured as an unrestricted open relay
- Continue routing authenticated client submission directly to Mailcow on ports `465` and `587`
- Continue routing public inbound SMTP port `25` to PMG rather than directly to Mailcow
## Troubleshooting
### Mailcow Still Returns `450 4.1.8`
Confirm Mailcow is using the updated configuration:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf mynetworks
```
If `192.168.3.15/32` is missing, verify `/opt/mailcow-dockerized/data/conf/postfix/extra.cf` and restart `postfix-mailcow`.
### Mailcow Sees a Different Source Address
Inspect the Mailcow Postfix logs:
```sh
cd /opt/mailcow-dockerized
docker compose logs --since 5m postfix-mailcow
```
Use the IP address shown in the `connect from ...[IP_ADDRESS]` line. Do not assume Mailcow sees the PMG management address when NAT or an SMTP proxy exists between the systems.
### PMG Flushes the Message but the Mailbox Does Not Receive It
Determine whether Mailcow accepted the message.
If Mailcow returned `250 2.0.0`, the PMG-to-Mailcow relay succeeded. Continue troubleshooting inside Mailcow by reviewing Postfix, Rspamd, and Dovecot logs.
```sh
cd /opt/mailcow-dockerized
docker compose logs --since 10m postfix-mailcow rspamd-mailcow dovecot-mailcow
```
If Mailcow returned a `4xx` or `5xx` response, use the complete SMTP response as the controlling error and resolve that policy or recipient failure before retrying again.
### Mailcow Applies Spam Filtering Again
Confirm the PMG entry under "**System > Configuration > Options > Forwarding Hosts**" has its spam filter set to **Inactive**.
PMG should remain the primary inbound filtering authority in this deployment.
### Mail Clients or Outbound Delivery Stop Working
This workflow does not change client access or outbound delivery.
Confirm the existing service ownership remains:
```text
Inbound SMTP: Internet -> PMG -> Mailcow
Outbound SMTP: Mailcow -> Internet
SMTP Submission: Clients -> Mailcow
IMAP and POP3: Clients -> Mailcow
Webmail and Admin: Internet -> Traefik -> Mailcow
```
Do not redirect ports `465`, `587`, `993`, `995`, `110`, `143`, or `4190` to PMG.
## Rollback
Remove the PMG forwarding-host entry from the Mailcow WebUI only when PMG is no longer the upstream SMTP gateway.
Then edit:
```sh
nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf
```
Restore the previous `mynetworks` value:
```ini title="/opt/mailcow-dockerized/data/conf/postfix/extra.cf"
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128
```
Restart Postfix:
```sh
cd /opt/mailcow-dockerized
docker compose restart postfix-mailcow
```
!!! warning "Coordinate the SMTP Path Before Rollback"
Do not remove PMG trust while public inbound SMTP still routes through PMG. Mailcow may begin rejecting legitimate messages relayed from PMG.
## Confirmed Final State
The validated Bunny Lab configuration is:
```text
PMG Address: 192.168.3.15
Mailcow Address: 192.168.3.61
Mailcow Forwarder: 192.168.3.15
Forwarder Spam Check: Inactive
Postfix mynetworks: 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
The resulting mail flow is:
```text
Inbound SMTP:
Internet -> pfSense WAN :25 -> PMG 192.168.3.15:25 -> Mailcow 192.168.3.61:25
Outbound SMTP:
Mailcow -> Internet
```