Files
docs/deployments/services/email/Proxmox Mail Gateway/Deploying PMG.md
T
nicole f5a12e7b89
Automatic Documentation Deployment / Sync Docs to https://kb.bunny-lab.io (push) Successful in 10s
Update deployments/services/email/Proxmox Mail Gateway/Deploying PMG.md
2026-07-22 17:46:27 -06:00

1153 lines
25 KiB
Markdown

---
tags:
- Proxmox Mail Gateway
- PMG
- Mailcow
- Email
- SMTP
- Gateway
- Spam Filtering
---
# Proxmox Mail Gateway Inbound Filtering for Mailcow
## Purpose
This document defines the procedure for placing `Proxmox Mail Gateway` in front of an existing `Mailcow` server for inbound SMTP filtering.
PMG will handle inbound SMTP inspection before delivering accepted mail to Mailcow.
This document covers **inbound SMTP filtering only**.
It does not move:
* Outbound SMTP delivery
* DKIM signing
* SMTP submission
* IMAP
* POP3
* ManageSieve
* Mailcow certificates
* Mailcow web access
* Roundcube access
## Assumptions
Mailcow is already deployed and functional.
Mailcow already handles:
* Mailbox hosting
* User authentication
* Webmail
* Mailcow admin interface
* IMAP
* POP3
* SMTP submission
* Outbound delivery
* DKIM signing
* TLS certificates for `mail.bunny-lab.io`
Example environment:
```text
Proxmox Mail Gateway: 192.168.3.15
Mailcow Server: 192.168.3.61
Mail Hostname: mail.bunny-lab.io
Mail Domain: bunny-lab.io
Firewall: pfSense
Reverse Proxy: Traefik
```
!!! warning "Inbound SMTP Only"
Only move public inbound SMTP port `25` to PMG during this stage.
```
Do not move mail client ports, outbound relay behavior, DKIM signing, or Mailcow web access.
```
## Architecture
### Existing Mail Flow
```text
Internet
|
v
pfSense WAN :25
|
v
Mailcow 192.168.3.61:25
```
### Target Mail Flow
```text
Internet
|
v
pfSense WAN :25
|
v
PMG 192.168.3.15:25
|
v
Mailcow 192.168.3.61:25
```
### Final Service Ownership
```text
PMG
- Inbound SMTP on port 25
- Spam filtering
- Virus filtering
- Tracking Center
- Quarantine
- Delivery of accepted inbound mail to Mailcow
Mailcow
- Mailbox hosting
- User authentication
- Webmail
- Mailcow admin interface
- IMAP
- POP3
- SMTP submission
- Outbound mail delivery
- DKIM signing
- TLS certificates for mail.bunny-lab.io
Traefik
- Public HTTP
- Public HTTPS
- Mailcow / Roundcube frontend routing
```
## DNS
Public DNS remains unchanged.
```text
bunny-lab.io MX 10 mail.bunny-lab.io
mail.bunny-lab.io A <Public WAN IP>
```
The public DNS records continue pointing to the WAN IP.
The firewall determines where inbound SMTP is delivered internally.
```text
pfSense WAN :25 -> PMG 192.168.3.15:25
```
!!! note "DNS Does Not Point to PMG Directly"
The public MX and A records do not point to the internal PMG IP.
```
NAT controls the internal SMTP destination.
```
## Firewall and NAT Design
Only public inbound SMTP changes.
Change this:
```text
WAN :25 -> Mailcow 192.168.3.61:25
```
To this:
```text
WAN :25 -> PMG 192.168.3.15:25
```
Leave Mailcow client access ports pointed directly at Mailcow.
```text
WAN :465 -> Mailcow 192.168.3.61:465
WAN :587 -> Mailcow 192.168.3.61:587
WAN :993 -> Mailcow 192.168.3.61:993
WAN :995 -> Mailcow 192.168.3.61:995
WAN :110 -> Mailcow 192.168.3.61:110
WAN :143 -> Mailcow 192.168.3.61:143
WAN :4190 -> Mailcow 192.168.3.61:4190
```
Leave web traffic on the existing reverse proxy path.
```text
WAN :80 -> Traefik :80
WAN :443 -> Traefik :443
```
!!! warning "Do Not Move Mail Client Ports to PMG"
PMG is an SMTP gateway.
```
Do not forward IMAP, POP3, SMTPS, Submission, or ManageSieve ports to PMG.
```
## Initial PMG Access
Access the PMG management interface.
```text
https://192.168.3.15:8006
```
Use the `root` credentials configured during PMG installation.
!!! note "Certificate Warning"
Browser certificate warnings are expected when accessing PMG by IP address unless a trusted certificate has already been configured for the management interface.
## Pre-Cutover Connectivity Checks
Confirm PMG can reach Mailcow on SMTP port `25`.
Run from the PMG shell:
```sh
# Confirm PMG can reach Mailcow SMTP
nc -vz 192.168.3.61 25
```
Expected result:
```text
(UNKNOWN) [192.168.3.61] 25 (smtp) open
```
Reverse DNS warnings are not automatically failures.
```text
inverse host lookup failed: Unknown host
```
If port `25` still reports as open, SMTP connectivity is working.
Confirm Mailcow presents an SMTP banner.
```sh
# Connect from PMG directly to Mailcow SMTP
nc 192.168.3.61 25
```
Expected banner:
```text
220-mail.bunny-lab.io ESMTP Postcow
220 mail.bunny-lab.io ESMTP Postcow
```
Exit the SMTP session.
```text
quit
```
!!! note "Mailcow SMTP Banner"
Mailcow commonly identifies its SMTP service as `Postcow`.
```
That is expected.
```
## PMG Mail Proxy Ports
In PMG, navigate to:
```text
Configuration > Mail Proxy > Ports
```
Confirm:
```text
External SMTP Port: 25
```
No outbound filtering is configured during this stage.
!!! note "Internal SMTP Port"
PMG also has an internal SMTP port used for outbound filtering from an internal mail server.
```
This deployment does not use outbound PMG filtering yet.
```
## PMG Relay Domains
In PMG, navigate to:
```text
Configuration > Mail Proxy > Relay Domains
```
Add the accepted mail domain.
```text
bunny-lab.io
```
This authorizes PMG to accept mail for the domain.
!!! warning "Relay Domains Are Required"
If the domain is missing from Relay Domains, PMG may reject inbound mail because it is not configured as responsible for that domain.
## PMG Default Relay
In PMG, navigate to:
```text
Configuration > Mail Proxy > Relaying
```
Configure Mailcow as the default relay.
```text
Default Relay: 192.168.3.61
Relay Port: 25
Relay Protocol: smtp
Disable MX Lookup: Yes
Smarthost: none
```
Target internal relay path:
```text
PMG 192.168.3.15
|
v
Mailcow 192.168.3.61:25
```
!!! note "Disable MX Lookup"
PMG should deliver accepted inbound mail directly to the internal Mailcow server.
```
It should not perform public MX lookup for the local mail domain.
```
!!! note "No Smarthost"
Leave `Smarthost` unset or set to `none` for inbound-only filtering.
```
Smarthost configuration is used for outbound relay behavior.
```
## Mailcow Forwarding Host
Configure Mailcow to trust PMG as a forwarding host.
In Mailcow, navigate to:
```text
System > Configuration Dropdown > Options > Forwarding Hosts Dropdown
```
Add the PMG IP address.
```text
192.168.3.15
```
Set the forwarding-host spam filter option to:
```text
Inactive
```
!!! note "Forwarding Host Behavior"
After cutover, Mailcow sees PMG as the immediate SMTP source for inbound mail.
```
Trusting PMG allows Mailcow to interpret forwarded mail correctly.
```
!!! note "Spam Filtering Placement"
PMG is the primary inbound spam and virus filtering system.
```
Leave Mailcow forwarding-host spam filtering inactive to avoid double-filtering messages already inspected by PMG.
```
## Outbound Mail
Leave outbound mail unchanged.
```text
Mailcow 192.168.3.61
|
v
Internet
```
Do not configure Mailcow to relay outbound mail through PMG during this stage.
Do not change:
```text
Relayhost
Outbound firewall rules
DKIM signing
SPF record
DMARC record
```
!!! warning "Do Not Move DKIM"
DKIM signing applies to outbound mail.
```
This document only moves inbound SMTP filtering.
```
## Filtering Policy
Initial filtering ownership:
```text
PMG = primary inbound SMTP filtering, tracking, quarantine
Mailcow = mailbox hosting, authentication, webmail, mail client access
```
Avoid configuring both PMG and Mailcow to aggressively quarantine the same inbound mail stream.
!!! note "Keep Filtering Boring"
PMG should own edge filtering first.
```
Mailcow should continue owning mailbox and client access behavior.
```
## SMTP NAT Cutover
After PMG relay domains, PMG default relay, and Mailcow forwarding host settings are configured, update the pfSense NAT rule.
Change:
```text
WAN :25 -> Mailcow 192.168.3.61:25
```
To:
```text
WAN :25 -> PMG 192.168.3.15:25
```
Do not change the remaining Mailcow port forwards.
```text
465 -> 192.168.3.61
587 -> 192.168.3.61
993 -> 192.168.3.61
995 -> 192.168.3.61
143 -> 192.168.3.61
110 -> 192.168.3.61
4190 -> 192.168.3.61
```
Do not change the Traefik web path.
```text
80 -> Traefik
443 -> Traefik
```
!!! warning "Cutover Point"
Changing `WAN :25` is the actual inbound mail cutover.
```
External SMTP servers will begin connecting to PMG instead of Mailcow directly.
```
## Validation
### External SMTP Reachability
From an external system:
```sh
# Confirm public SMTP is reachable
nc -vz mail.bunny-lab.io 25
```
Alternative:
```sh
# Confirm public SMTP banner using telnet
telnet mail.bunny-lab.io 25
```
Expected result:
```text
Port 25 open
SMTP banner returned by gateway
```
!!! note "Internal Testing Limitations"
Internal tests may not represent public mail flow if NAT reflection or split-horizon DNS is involved.
```
Prefer external testing.
```
If external port testing is unavailable, send real mail from an outside provider.
Usable external sources:
```text
Gmail
Outlook.com
iCloud
Proton Mail
Work mailbox hosted outside Mailcow
```
### Inbound Delivery
Send an external message to a Mailcow-hosted mailbox.
Expected path:
```text
External mailbox
|
v
mail.bunny-lab.io
|
v
pfSense WAN :25
|
v
PMG 192.168.3.15
|
v
Mailcow 192.168.3.61
|
v
User mailbox
```
Check PMG:
```text
PMG > Tracking Center
```
Expected PMG status:
```text
Status: accepted/delivered
Relay: 192.168.3.61[192.168.3.61]:25
```
Check Mailcow:
```text
System > Logs
```
or review the relevant Mailcow Postfix and Dovecot logs.
### Mail Client Access
Confirm normal mail client behavior remains unchanged.
Test:
```text
IMAP receive
SMTP submission send
Mobile mail client access
Desktop mail client access
Webmail / Roundcube access
Mailcow UI access
```
Expected service paths:
```text
IMAPS: 993 -> Mailcow
Submission: 587 -> Mailcow
SMTPS: 465 -> Mailcow
Web: 443 -> Traefik -> Mailcow
```
Confirm outbound mail still works by replying from a Mailcow-hosted mailbox to the external sender.
### PMG Queues
Check PMG queues after test delivery.
```text
PMG > Queues
```
Expected state:
```text
Queue empty or near-empty after delivery
```
Queue status confirms PMG is not silently holding or deferring mail because of relay, DNS, or delivery errors.
## Validation Checklist
* [ ] Public MX record points to `mail.bunny-lab.io`
* [ ] `mail.bunny-lab.io` resolves to the correct public WAN IP
* [ ] DNS records are unchanged
* [ ] PMG can reach Mailcow on `192.168.3.61:25`
* [ ] Mailcow SMTP banner is visible from PMG
* [ ] PMG external SMTP port is `25`
* [ ] PMG has `bunny-lab.io` configured as a relay domain
* [ ] PMG default relay points to `192.168.3.61`
* [ ] PMG relay port is `25`
* [ ] PMG relay protocol is `smtp`
* [ ] PMG internal delivery has MX lookup disabled
* [ ] PMG smarthost is unset or `none`
* [ ] Mailcow trusts `192.168.3.15` as a forwarding host
* [ ] Mailcow forwarding-host spam filter is `Inactive`
* [ ] Firewall forwards `WAN :25` to `192.168.3.15:25`
* [ ] Firewall still forwards mail client ports directly to Mailcow
* [ ] Traefik still handles Mailcow / Roundcube web traffic
* [ ] Inbound test mail appears in PMG Tracking Center
* [ ] PMG Tracking Center shows `accepted/delivered`
* [ ] PMG log shows delivery to `192.168.3.61:25`
* [ ] Inbound test mail is delivered to the Mailcow mailbox
* [ ] PMG queue is empty after delivery
* [ ] Mobile email client still works
* [ ] Desktop email client still works
* [ ] Webmail still works
* [ ] Replying outbound from Mailcow still works
* [ ] DKIM behavior is unchanged
* [ ] SPF record is unchanged
* [ ] DMARC record is unchanged
* [ ] Outbound mail routing is unchanged
## Troubleshooting
### Inbound Mail Never Reaches PMG
Verify NAT.
```text
WAN :25 -> 192.168.3.15:25
```
Verify inbound port `25` is not blocked by the ISP.
From an external system:
```sh
# Test public SMTP reachability
nc -vz mail.bunny-lab.io 25
```
If external testing is unavailable, send a real external test message and check:
```text
PMG > Tracking Center
```
### PMG Receives Mail but Does Not Deliver to Mailcow
Verify PMG relay settings.
```text
Default Relay: 192.168.3.61
Relay Port: 25
Relay Protocol: smtp
Disable MX Lookup: Yes
```
Verify Mailcow SMTP is reachable from PMG.
```sh
# Test Mailcow SMTP from PMG
nc -vz 192.168.3.61 25
```
Confirm the Mailcow SMTP banner.
```sh
# Inspect Mailcow SMTP banner from PMG
nc 192.168.3.61 25
```
Expected banner:
```text
220-mail.bunny-lab.io ESMTP Postcow
220 mail.bunny-lab.io ESMTP Postcow
```
### PMG Shows Reverse DNS Warning for Mailcow
A warning like this is not automatically a failure:
```text
inverse host lookup failed: Unknown host
```
If the connection still reports port `25` as open, SMTP connectivity is working.
### Mailcow Rejects Mail from PMG
Verify Mailcow trusts PMG as a forwarding host.
```text
192.168.3.15
```
Verify the recipient domain exists in Mailcow.
```text
bunny-lab.io
```
Verify the recipient mailbox or alias exists in Mailcow.
### Mail Clients Stop Working
Verify only inbound SMTP port `25` was moved to PMG.
These ports should still forward directly to Mailcow:
```text
465
587
993
995
110
143
4190
```
Expected service ownership:
```text
PMG -> inbound SMTP gateway only
Mailcow -> client access and mailbox services
```
### Roundcube or Mailcow Web UI Stops Working
Verify web traffic was not moved to PMG.
Expected path:
```text
WAN :80 -> Traefik :80
WAN :443 -> Traefik :443
```
PMG should not replace Traefik for Mailcow or Roundcube web access.
### Outbound Mail Stops Working
Outbound mail should not change during this deployment.
Verify no changes were made to:
```text
Mailcow relayhost
Outbound firewall behavior
DKIM signing
SPF record
DMARC record
Public DNS records
```
### Spam Filtering Behavior Is Confusing
Use one primary inbound filtering authority.
Recommended initial state:
```text
PMG = primary inbound edge spam filter
Mailcow = mailbox hosting and client access
```
Avoid dual aggressive quarantine policies until basic mail flow is stable.
## Confirmed Final State
After Stage 1, the environment should operate as follows:
```text
Inbound SMTP:
Internet -> pfSense WAN :25 -> PMG 192.168.3.15:25 -> Mailcow 192.168.3.61:25
Outbound SMTP:
Mailcow -> Internet
Mail Client Access:
Clients -> Mailcow
Webmail / Roundcube:
Internet -> Traefik -> Mailcow
```
The only public NAT behavior changed is:
```text
WAN :25
```
Unchanged components:
```text
DNS records
DKIM behavior
SPF record
DMARC record
Outbound mail routing
SMTP submission
IMAP
POP3
ManageSieve
Mailcow certificates
Traefik web routing
Mailcow / Roundcube web access
```
## Deployment Status
This document completes Stage 1 of the PMG deployment.
```text
Stage 1: Inbound filtering only
Stage 2: Optional outbound filtering
```
At the end of Stage 1:
```text
PMG = inbound SMTP filtering only
Mailcow = mailboxes, webmail, authenticated submission, certificates, DKIM, outbound delivery, user-facing mail services
```
## Enabling Direct Unfiltered Communication Between Mailcow and PMG
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 Existing Trusted Networks
Before modifying `mynetworks`, determine the currently active value. Mailcow automatically populates `mynetworks` with its loopback and Docker networks. Defining your own value replaces that automatically generated configuration, so you must preserve the existing entries.
On the Mailcow host, run:
```sh
cd /opt/mailcow-dockerized
docker compose exec postfix-mailcow postconf mynetworks
```
Example output:
```text
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128
```
At this point, append the PMG address as a single-host CIDR. Do not remove any existing networks.
Expected result:
```text
mynetworks = 127.0.0.0/8 172.22.1.0/24 [::1]/128 192.168.3.15/32
```
### Update the Persistent Postfix Override
Edit the Postfix override file:
```sh
nano /opt/mailcow-dockerized/data/conf/postfix/extra.cf
```
If `mynetworks` config line already exists, append the PMG address while preserving the existing values. If the key does not exist, create it using the value discovered in the previous step.
```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 "Do Not Replace Existing Networks"
The `mynetworks` directive replaces Mailcow's automatically generated value. Removing the existing loopback or Docker networks may prevent Postfix from functioning correctly. Always preserve the existing entries and append the PMG address.
### 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
```