Contents
Why ports matter
Port selection looks like trivial detail until it is not. The decision affects firewall rules, application configuration, TLS approach, authentication flow, and ultimately whether PowerMTA can do its job at all. The 2026 SMTP port landscape has stabilized after years of confusion: port 25 for relay, 587 for authenticated submission, 465 for implicit TLS submission (officially recognized by RFC 8314), 2525 as fallback when 587 is blocked. PowerMTA configures its inbound listeners through the smtp-listener directive and each listener can serve a different role.
This guide exists because operators frequently configure PowerMTA listeners by copying examples from old tutorials without understanding why each port is there or what each option does. The result is deployments where port 25 is exposed unnecessarily, TLS is not properly enforced where it should be, source authorization is missing leading to open relay risk, or some combination of these problems creates security exposure or operational fragility.
The structure: the role each port plays in modern email infrastructure, the smtp-listener directive syntax, bind-to-IP patterns versus 0.0.0.0 patterns and when each is appropriate, the source directive for distinguishing trusted from untrusted submitters, the listener-specific options (process-x-virtual-mta, process-x-job, max-message-size, etc.), TLS configuration with certificates, AUTH integration for authenticated submission, firewall configuration that complements the PowerMTA listener config, and the common troubleshooting scenarios when ports do not work as expected.
The role of each SMTP port in 2026
The four ports operators encounter in PowerMTA deployments:
| Port | Role | Status | Use in PowerMTA |
|---|---|---|---|
| 25 | Server-to-server relay | Standard, RFC 5321 | Receive from internal applications |
| 587 | Authenticated submission (STARTTLS) | Standard, RFC 6409 | Receive from authenticated remote clients |
| 465 | Implicit TLS submission | Standard since RFC 8314 | Alternative to 587 with TLS from connection start |
| 2525 | Submission fallback | Unofficial but widely used | When 587 blocked by network |
The 2026 dust has settled. Port 25 for outbound delivery from PowerMTA to receiving MTAs is universal (receiving MTAs almost always listen on 25). Port 25 for inbound submission is appropriate only when network controls (firewall, source directive whitelist) restrict who can connect, because port 25 lacks the authentication-required convention of submission ports. Port 587 with STARTTLS plus AUTH is the standard submission port for authenticated remote clients. Port 465 with implicit TLS is increasingly popular now that RFC 8314 officially blessed it; some operators prefer it because the TLS-from-first-byte approach eliminates the theoretical STRIPTLS downgrade attack. Port 2525 is the fallback when corporate firewalls or cloud providers block 587 (AWS EC2 historically blocked port 587 for new accounts in some regions, prompting many ESPs to support 2525 as alternative).
For typical PowerMTA deployments: listen on port 25 for application handoff on the same network or with source directive whitelist (most common), additionally listen on port 587 with AUTH plus STARTTLS when remote application connections must be supported, optionally also on 465 with implicit TLS for clients preferring that mode, and add 2525 as fallback if specific clients have firewall blocks on 587.
The smtp-listener directive
The smtp-listener directive declares an inbound listener with the bind address, port, and any listener-specific options. The basic syntax:
smtp-listener IP:PORT
Examples:
# Listen on port 25 on all interfaces
smtp-listener 0.0.0.0:25
# Listen on port 25 only on specific internal IP
smtp-listener 10.0.1.22:25
# Listen on port 587 on all interfaces
smtp-listener 0.0.0.0:587
# Listen on port 465 for implicit TLS
smtp-listener 0.0.0.0:465
A listener can be a single line or a block when options are needed:
<smtp-listener 0.0.0.0:587>
process-x-virtual-mta yes
process-x-job yes
starttls-enabled yes
starttls-cert /etc/pmta/certs/server.crt
starttls-key /etc/pmta/certs/server.key
auth-only yes
max-message-size 50M
</smtp-listener>
Multiple smtp-listener directives are valid and PowerMTA accepts connections on all configured listeners simultaneously. A typical production config has 2-3 listeners: one for internal relay (port 25 bound to internal IP), one for authenticated submission (port 587 bound to external IP), optionally one for implicit TLS (port 465 bound to external IP).
Bind-to-IP vs 0.0.0.0 patterns
The bind address controls which network interfaces the listener accepts connections on.
Bind to specific IP. Listener accepts only on the named IP. Other IPs on the same host do not receive traffic. This is the right pattern for separating internal from external traffic on multi-homed hosts. Example: bind port 25 to 10.0.1.22 (internal network only) prevents external internet from reaching the unauthenticated port 25.
# Internal-only port 25
smtp-listener 10.0.1.22:25
# External submission on 587
smtp-listener 203.0.113.42:587
Bind to 0.0.0.0. Listener accepts on all interfaces. Use when the host has a single IP, when you want the same listener serving multiple interfaces (rare), or when other network-level controls (firewall) handle interface separation.
# Listen on all interfaces, firewall handles network separation
smtp-listener 0.0.0.0:25
Bind to 127.0.0.1. Listener accepts only loopback connections. Use when the application submitting messages runs on the same host and there is no need to expose the listener externally. The strictest binding pattern.
# Only same-host applications can submit
smtp-listener 127.0.0.1:25
The choice matters because exposing port 25 externally without proper source authorization creates an open relay risk. The safe defaults: bind port 25 to 127.0.0.1 or internal IP only, bind port 587 with AUTH and TLS to 0.0.0.0 or external IP when remote submission is needed, never expose port 25 on 0.0.0.0 unless source directive whitelist is also configured.
The source directive for authorization
The source directive controls what PowerMTA does with messages from specific source IPs. It is the primary authorization mechanism distinguishing trusted internal submitters from untrusted external connections.
A basic source block:
<source 127.0.0.1>
always-allow-relaying yes
process-x-virtual-mta yes
process-x-job yes
</source>
This block authorizes localhost connections to relay anywhere without authentication and to use X-headers for routing. Connections from any other IP fall through to the default processing path which typically requires authentication.
Common production patterns:
# Localhost - same-server applications
<source 127.0.0.1>
always-allow-relaying yes
process-x-virtual-mta yes
process-x-job yes
</source>
# Internal application servers
<source 10.0.1.0/24>
always-allow-relaying yes
process-x-virtual-mta yes
process-x-job yes
</source>
# Specific MailWizz instance on different host
<source 10.0.2.15>
always-allow-relaying yes
process-x-virtual-mta yes
process-x-job yes
</source>
# Authenticated remote submitters
<source 0.0.0.0/0>
always-allow-relaying no
require-auth true
</source>
Source blocks compose by best-match. A more specific block (single IP) takes precedence over a broader block (CIDR network). The 0.0.0.0/0 catch-all should be most restrictive because anything not matching a more specific block lands there.
The most dangerous misconfiguration is exposing port 25 on a public interface without source directive whitelist and without require-auth on the default path. This makes PowerMTA an open relay that spammers will find within hours of deployment and use to send abuse traffic with your IPs' reputation. The signs: outbound IP reputation degrades rapidly, accounting log shows messages destined for unfamiliar recipient domains, blacklists flag your IPs within days. Prevention: always pair external port 25 listeners with explicit source directive whitelists, or simply do not expose port 25 externally and use 587 with AUTH for remote submission.
Listener-specific options
Each smtp-listener can carry options that adjust how PowerMTA processes connections on that listener.
| Option | Purpose | Typical value |
|---|---|---|
process-x-virtual-mta | Honor X-Virtual-MTA header for routing | yes (when applications inject the header) |
process-x-job | Record X-Job header in accounting | yes (when correlation with downstream is wanted) |
max-message-size | Reject messages above this size | 50M typical for marketing email |
max-recipients-per-message | Maximum RCPT TO per envelope | 1 (one recipient per envelope is standard for MailWizz) |
auth-only | Require AUTH for any submission | yes (for port 587) |
starttls-enabled | Offer STARTTLS during EHLO | yes (for port 587) |
starttls-required | Reject if client does not STARTTLS | yes (for ports requiring TLS) |
tls-enabled | Implicit TLS from connection start | yes (for port 465) |
banner-text | SMTP greeting banner | Custom hostname |
log-smtp-msg-errors | Log message-level SMTP errors | yes (during debugging) |
log-temp-failures | Log 4xx responses | yes (during throttle investigation) |
The substantive operational choices: process-x-virtual-mta and process-x-job should both be yes when applications inject these headers (most MailWizz + PowerMTA deployments do); max-message-size should match what applications actually send (50M is conservative for typical marketing email); auth-only and starttls-required should be yes for any externally exposed listener; banner-text should match the EHLO domain that receiving MTAs will see your PowerMTA presenting on outbound.
TLS configuration
TLS configuration in PowerMTA requires certificate setup plus appropriate listener directives.
Step 1: obtain certificate. Let's Encrypt is the standard free option for public hostnames:
certbot certonly --standalone -d mta.example.com
# Certificates land in /etc/letsencrypt/live/mta.example.com/
For internal-only deployments, use an internal CA-issued certificate.
Step 2: place certificate where PowerMTA can read it.
cp /etc/letsencrypt/live/mta.example.com/fullchain.pem /etc/pmta/certs/server.crt
cp /etc/letsencrypt/live/mta.example.com/privkey.pem /etc/pmta/certs/server.key
chmod 0400 /etc/pmta/certs/server.key
chown pmta:pmta /etc/pmta/certs/server.crt /etc/pmta/certs/server.key
Step 3: configure STARTTLS listener (port 587).
<smtp-listener 0.0.0.0:587>
starttls-enabled yes
starttls-required yes
starttls-cert /etc/pmta/certs/server.crt
starttls-key /etc/pmta/certs/server.key
tls-protocols TLSv1.2 TLSv1.3
auth-only yes
</smtp-listener>
Step 4: configure implicit TLS listener (port 465).
<smtp-listener 0.0.0.0:465>
tls-enabled yes
tls-cert /etc/pmta/certs/server.crt
tls-key /etc/pmta/certs/server.key
tls-protocols TLSv1.2 TLSv1.3
auth-only yes
</smtp-listener>
Step 5: configure auto-renewal with PowerMTA reload. Let's Encrypt certificates renew every 90 days. PowerMTA caches certificates in memory until reload. Add a post-renewal hook:
# /etc/letsencrypt/renewal-hooks/post/pmta-reload.sh
#!/bin/bash
cp /etc/letsencrypt/live/mta.example.com/fullchain.pem /etc/pmta/certs/server.crt
cp /etc/letsencrypt/live/mta.example.com/privkey.pem /etc/pmta/certs/server.key
chmod 0400 /etc/pmta/certs/server.key
chown pmta:pmta /etc/pmta/certs/*
systemctl reload pmta
Make the script executable: chmod +x /etc/letsencrypt/renewal-hooks/post/pmta-reload.sh. Now certificate renewal automatically copies new files and reloads PowerMTA to pick them up.
AUTH integration patterns
SMTP AUTH on port 587 or 465 requires PowerMTA to validate credentials. PowerMTA supports several authentication backends.
Built-in user list. Define users directly in PowerMTA config. Simple but does not scale beyond a few users:
<auth-group app-users>
smtp-user mailwizz-app
password STRONG_SECRET_HERE
</auth-group>
External authentication script. PowerMTA calls a script for each authentication attempt. Script returns success/failure based on whatever logic operator implements (database lookup, LDAP query, API call):
<auth-script /opt/pmta/bin/auth-handler.sh>
timeout 5s
</auth-script>
The script reads username and password from environment variables, returns exit 0 for success, non-zero for failure. This is the standard pattern for production deployments with many users or dynamic user management.
LDAP-style integration. PowerMTA can integrate with external authentication services through script wrappers. Not native LDAP support but operators implement LDAP-backed authentication scripts.
For typical PowerMTA + MailWizz deployments where MailWizz is the only authenticated submitter, a single user in the built-in auth-group is sufficient. For multi-tenant ESPs where each customer authenticates separately, an external authentication script backed by the customer database is the standard.
Firewall configuration
Firewall rules need to complement the PowerMTA listener configuration. The standard pattern for a production PowerMTA host:
# UFW configuration for PowerMTA
ufw default deny incoming
ufw default allow outgoing
# SSH (administration)
ufw allow 22/tcp
# Port 25 inbound only from internal network
ufw allow from 10.0.0.0/8 to any port 25
ufw deny 25
# Port 587 (authenticated submission)
ufw allow 587/tcp
# Port 465 (implicit TLS submission)
ufw allow 465/tcp
# Optional port 2525 fallback
ufw allow 2525/tcp
# PowerMTA HTTP monitoring (if used)
ufw allow from 10.0.0.0/8 to any port 8080
ufw enable
The substantive points: port 25 inbound restricted to internal networks (matches PowerMTA listener bound to internal IP); ports 587 and 465 open globally (authentication and TLS handle security at the application layer); PowerMTA HTTP monitoring port restricted to internal networks; SSH allowed only to administrative IPs in stricter deployments.
For outbound delivery, port 25 must be allowed outbound (default in most environments but blocked by some cloud providers for new accounts). Verify with telnet smtp.gmail.com 25 from the PowerMTA host. If blocked, contact the cloud provider to lift the restriction or use a different cloud provider.
Common troubleshooting
Frequent port-related issues and their resolutions:
PowerMTA fails to start with "address already in use". Another process is already listening on the port. Check with ss -tlnp | grep :25 to identify the conflicting process. Common culprits: Postfix or sendmail not properly disabled before PowerMTA installation. Fix: stop and disable the conflicting service, then start PowerMTA.
MailWizz cannot connect to PowerMTA on port 25. Listener may be bound to wrong IP. Check actual binding with ss -tlnp | grep pmta. If bound to 127.0.0.1 but MailWizz connects from a different host, change binding to internal IP or 0.0.0.0 with source directive whitelist.
External clients cannot reach port 587. Firewall blocking, listener not bound to external IP, or PowerMTA not actually listening. Verify each layer: telnet PUBLIC_IP 587 from external host. If timeout, firewall is blocking. If "connection refused", PowerMTA is not listening on that interface. If immediate disconnect, PowerMTA may be misconfigured to reject the source.
STARTTLS not offered on port 587. Certificate paths wrong or starttls-enabled not set. Check PowerMTA log for certificate load errors. Verify certificate file permissions allow PowerMTA user to read.
AUTH fails with valid credentials. Either credentials configured incorrectly in auth-group, or auth-script returning failure. Test with swaks --to test@example.com --server PMTA_HOST:587 --auth --auth-user USER --auth-password PASS and observe response. Check PowerMTA log for authentication details.
Outbound deliveries hang or fail with "could not connect". Port 25 outbound blocked by cloud provider. Common with AWS EC2 new accounts and similar providers. Verify with telnet smtp.gmail.com 25 from PowerMTA host. If blocked, contact provider for an unlock or use a different provider for outbound.
X-Virtual-MTA header ignored. Listener missing process-x-virtual-mta yes or source missing process-x-virtual-mta yes. Both directives must be set on the matching listener and source. Check current configuration with grep -A5 smtp-listener /etc/pmta/config and grep -A5 source /etc/pmta/config.
A deployment we audited had been running for 6 weeks with port 25 bound to 0.0.0.0, no source directive whitelist, and no auth-only on the default path. The operator inherited the config from a contractor and assumed it was correct. We discovered the issue during a deliverability investigation when outbound IPs showed degraded reputation despite low legitimate volume. Accounting log analysis revealed messages destined for hundreds of thousands of recipients across spam-likely domains, none of which were the operator's actual sending. Spammers had found the open relay (this happens within hours of public IP exposure typically) and were using it to send abuse traffic. The fix took 10 minutes: bind port 25 to internal IP only, add explicit source whitelist for legitimate submitters, restart PowerMTA. The reputation recovery took 6 weeks during which all outbound IPs needed re-warming because the abuse traffic had poisoned reputation thoroughly. The lesson: always verify port 25 is not exposed externally without explicit source authorization, especially when inheriting configs from previous operators or following old tutorials.
The smtp-listener directive is one of the most-touched parts of PowerMTA configuration and getting it right at deployment time prevents substantial categories of operational problems later. The port roles in 2026 are clearer than they were even three years ago, the source directive provides clean authorization patterns, TLS configuration is well-understood, and the firewall complement is straightforward. Operators who configure listeners methodically with awareness of each option produce secure, reliable PowerMTA deployments; operators who copy examples without understanding produce the open-relay-and-other-problems patterns this guide is designed to prevent.