Your question
Hi,
I’m running into an issue with Stalwart where a previously working configuration suddenly stopped working.
The submissions listener (port 465) is now logging repeated Proxy Protocol errors:
2026-06-30T09:35:58Z WARN Proxy protocol error (network.proxy-error)
listenerId = "submissions"
localIp = ::
localPort = 465
tls = true
reason = "invalid proxy header"
2026-06-30T09:36:01Z WARN Proxy protocol error (network.proxy-error)
listenerId = "submissions"
localIp = ::
localPort = 465
tls = true
reason = "invalid proxy header"
2026-06-30T09:36:01Z WARN Proxy protocol error (network.proxy-error)
listenerId = "submissions"
localIp = ::
localPort = 465
tls = true
reason = "invalid proxy header"
The confusing part is that this listener is configured to trust Proxy Protocol connections from my Kubernetes Pod CIDR and Service CIDR:
❯ stalwart-cli query NetworkListener
Id Name Protocol Bind addresses Implicit TLS
iwefv2ikahqb http HTTP [::]:80 No
iwefv2icahab https HTTP [::]:443 Yes
iwefv2h7agqb sieve ManageSieve [::]:4190 No
iwefv2hsagab pop3s POP3 [::]:995 Yes
iwefv2hkafqb imaps IMAP4 [::]:993 Yes
iwefv2hcafab submissions SMTP [::]:465 Yes
iwefv2g7aeqb smtp SMTP [::]:25 No
❯ stalwart-cli get NetworkListener iwefv2hcafab
Listener settings
Listener Id: submissions
Protocol: SMTP
Bind addresses: [::]:465
Max Connections: 8192
TLS options
Enable TLS: Yes
Implicit TLS: Yes
Disabled Protocols: <none>
Disabled Ciphersuites: <none>
Handshake Timeout: 1 m
Ignore client order: Yes
Proxy networks
Override proxy networks: 10.42.0.0/16, 10.43.0.0/16
Socket options
Backlog: 1024
TTL: <none>
Type of Service: <none>
Send buffer: <none>
Receive buffer: <none>
No delay: Yes
Reuse Address: Yes
Reuse port: Yes
The X-Forwarded-For header is only enabled for HTTP.
❯ stalwart-cli get Http
Response
Headers: <none>
Redirect root: /account
Proxy
Obtain remote IP from Forwarded header: Yes
Security
Allowed endpoints:
Expression
Conditions:
<empty>
Default Value: 200
Enable HTTP Strict Transport Security: No
Permissive CORS policy: No
Rate Limit
Authenticated:
Rate
Count: 1000
Period: 1 m
Anonymous:
Rate
Count: 100
Period: 1 m
Even when I create a pod in the same Kubernetes cluster and connect directly to the service, I cannot establish a TLS connection on port 465:
kubectl run alpine --image=alpine:latest --restart=Never -it --rm -- sh
/ # apk add openssl
(1/1) Installing openssl (3.5.7-r0)
Executing busybox-1.37.0-r31.trigger
OK: 13.8 MiB in 26 packages
/ # openssl s_client -connect stalwart.stalwart.svc.cluster.local:465
Connecting to 10.43.12.94
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
Negotiated TLS1.3 group: <NULL>
---
SSL handshake has read 0 bytes and written 1568 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Protocol: TLSv1.3
This TLS version forbids renegotiation.
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
364: eth0@if365: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether aa:fd:ed:3e:fa:33 brd ff:ff:ff:ff:ff:ff
inet 10.42.4.87/32 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::a8fd:edff:fe3e:fa33/64 scope link
valid_lft forever preferred_lft forever
~ # nc -v stalwart.stalwart.svc.cluster.local 465
stalwart.stalwart.svc.cluster.local (10.43.12.94:465) open
~ # nc -v stalwart.stalwart.svc.cluster.local 25
stalwart.stalwart.svc.cluster.local (10.43.12.94:25) open
220 mail.example.com Stalwart ESMTP at your service
~ #
The client pod has the IP address 10.42.4.87, which falls within my configured trusted proxy network (10.42.0.0/16).
It appears the connection is closed before the TLS handshake begins, as if the listener is expecting a Proxy Protocol header even when it shouldn’t, or is incorrectly determining that the client should be using Proxy Protocol.
This configuration had been working previously and I don’t changed anything related to the listener configuration before this started happening.
Is the current behavior expected? Any guidance would be appreciated.