Skip to content

Connection

When Stalwart delivers a message to another server, the way it opens the connection shapes how that server judges the mail. Receiving servers judge a sender largely by its IP address, and by whether the address, its PTR record and the name the sender gives in EHLO agree. On a server with several addresses, the choice of address and name therefore directly affects deliverability. The connection also needs limits on how long to wait for a slow remote server.

A connection strategy holds these choices. It decides from which local IP address Stalwart connects, which name it gives in its EHLO command, and how long it waits at each step of the SMTP dialogue. Each strategy is an MtaConnectionStrategy object (found in the WebUI under Settings › MTA › Outbound › Connection Strategies). The connection expression of the outbound strategy selects one for each delivery. A new installation has one strategy, named default.

localIps lists the local addresses from which deliveries are sent. Each entry has a localIp and, optionally, an ehloHostname to use with that address.

The list may mix IPv4 and IPv6 addresses. For each connection, Stalwart considers only the addresses of the same family as the remote server’s address, and picks one of them at random. When the list has no address of that family, the connection uses the address that the operating system chooses.

Each local address needs consistent DNS. The PTR record of the address should resolve to the EHLO name used with it, and that name should resolve back to the address. This check is called forward-confirmed reverse DNS, and many receiving servers reject or penalise mail from addresses that fail it. The following strategy sends from two IPv4 addresses, each with its own name, and from one IPv6 address:

{
"name": "default",
"ehloHostname": "mx.example.org",
"localIps": {
"0": {"localIp": "192.0.2.10", "ehloHostname": "mx1.example.org"},
"1": {"localIp": "192.0.2.11", "ehloHostname": "mx2.example.org"},
"2": {"localIp": "2001:db8::10"}
}
}

The moment at which the address is chosen decides which expressions can see it. The address is chosen before the outbound throttles are evaluated for the connection, so the throttles see it as local_ip, and a throttle keyed on localIp limits each address separately. The tls expression, on the other hand, is evaluated once for each remote host before any address is chosen, so local_ip is not available to it.

The name in the EHLO command comes from the first of the following that is set:

  1. The ehloHostname of the chosen local address
  2. The ehloHostname of the strategy
  3. The server’s host name

Because the strategy can carry a name of its own, a strategy for a separate kind of traffic can present its own identity. Bulk notifications sent from their own address, for example, can present a name of their own.

A remote server that stops answering would hold a delivery open indefinitely, so each step of the delivery has a timeout. Each timeout limits how long Stalwart waits for the remote server at one step, in milliseconds. When a timeout expires, the attempt fails with a temporary error, and the recipient is retried according to its schedule.

FieldDefaultStep
connectTimeout5 minutesOpening the TCP connection.
greetingTimeout5 minutesWaiting for the server’s greeting.
ehloTimeout5 minutesReply to EHLO.
mailFromTimeout5 minutesReply to MAIL FROM.
rcptToTimeout5 minutesReply to RCPT TO.
dataTimeout10 minutesReply after the message data.

The defaults for the greeting, MAIL FROM, RCPT TO and the data are the timeouts that RFC 5321 recommends. The RFC sets no timeout for opening the connection or for the reply to EHLO.

Changing the timeouts is a trade-off. Shorter timeouts release delivery threads sooner when remote servers are slow or unreachable. They also risk abandoning deliveries to servers that are slow but working, such as servers that delay their greeting deliberately. The following object body shortens the connection and greeting timeouts to two minutes:

{
"connectTimeout": 120000,
"greetingTimeout": 120000
}

Tuning mail throughput describes how timeouts and delivery threads interact.