Wrong submissions SRV DNS record created when using automatic dns

Issue Description

When using the automatic DNS management provided by stalwart, it creates a record like this:
_submissions._tcp 300 IN SRV 0 1 465 mail.mydomain.com.

The problem is that there is no listener for 465 and I am actually instead using port 587 for submission. But no record gets created for port 587.

The same happens with manual dns management when querying the expected DNS file using the CLI (wrong record included and none for 587 / submission).

Expected Behavior

Stalwart should not create a dns record for 465, since that port isn’t in use and instead should publish one for _submission._tcp as that is the one in use

Actual Behavior

Currently, it creates a the record for _submissions._tcp (port 465)

Reproduction Steps

  1. Set up listeners: IMAP listener (submission) on port 587 with implicit tls off and no listener no 465
  2. add automatic DNS and look at the created records or query the expected DNS file using the cli (stalwart-cli get domain [domain] --fields dnsZoneFile

Stalwart Version

v0.16.x

Installation Method

Binary (Linux)

Database Backend

PostgreSQL

Blob Storage

S3-compatible

Search Engine

Internal

Directory Backend

Internal

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

Let me look into how Stalwart generates DNS records for mail submission services.

This is a confirmed bug in the server source code. Here is what is happening and why.

In crates/common/src/network/dns/records.rs, the SRV record generation logic for SMTP is hardcoded as:

ServiceProtocol::Smtp => [("submission", 587), ("submissions", 465)],

The loop then uses is_tls == 1 (i.e., the second entry in the array) as the condition for publishing the TLS/implicit-TLS variant (_submissions._tcp, port 465), and publishes the plaintext/STARTTLS variant (_submission._tcp, port 587) only when service.cleartext is true.

The bug: The logic is inverted. When you have a listener with STARTTLS (cleartext/opportunistic TLS) on port 587, service.cleartext is the flag being checked – but the code emits the _submissions._tcp (port 465) record unconditionally for is_tls == 1, regardless of whether you actually have an implicit-TLS listener on 465. It never checks your actual listener ports. So if you only have port 587 active without a corresponding port-465 listener, you still get the 465 record, and the 587 record only appears if service.cleartext is set.

This is a genuine bug in the DNS record generation code – the SRV records published do not reflect the actual listener configuration. The correct behavior would be to only publish SRV records for ports that have active listeners, and to map those ports to the correct service names (_submission._tcp for 587 with STARTTLS, _submissions._tcp for 465 with implicit TLS).

A human maintainer will need to address this in the source. In the meantime, you can work around it by using manual DNS management and explicitly setting only the _submission._tcp SRV record for port 587, ignoring the generated zone file output.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

You can configure what is published from Network → Services, this is independent to the ports you have enabled or not.
Also note that is is not possible to just publish the clear text port of a given service. This is done in order to be aligned with PACC which only works with implicit TLS ports.

So to advertise port 587, I enable “Allow Cleartext” under Network → Services → SMTP submission?
I wanted to only advertise 587 because I read that it was the de-facto standard. But if it is not possible to only advertise that, should I then re-enable submissions via port 465 / add the required listener for submissions via port 465 again?

Yes, port 465 is the future-proof port you should use.