Skip to content

Submission configuration ​

Yarilo runs two submission listeners. MX inbound (port 25) is handled by an external MTA (Postfix, Exim, etc.) which delivers to yarilo via LMTP (port 24).

Service keyPortRole
submission587Outbound submission - AUTH required, STARTTLS.
submissions465Outbound submission - AUTH required, implicit TLS.

See Services configuration for listener-level settings (port, ssl_mode, haproxy_protocol, auth_allow_cleartext).


protocol.submission ​

Protocol-level behaviour shared across both submission listeners.

hostname ​

Default
the top-level hostname
Type
string
Helm
protocol.submission.hostname

EHLO/HELO banner and Message-ID domain for submission only. Unset means the installation's name; see General. Setting it here does not rename the LMTP banner, the Received: header or a delivered message's Message-ID.

submission_max_mail_size ​

Default
40M
Type
string
Also accepted as
max_message_size
Helm
protocol.submission.max_message_size

Maximum accepted message size. Takes a size with a unit (40M) or bytes.

max_line_length ​

Default
4096
Type
integer, bytes
Helm
protocol.submission.max_line_length

Maximum SMTP command or DATA line length.

submission_max_recipients ​

Default
0
Type
integer
Also accepted as
max_recipients
Helm
protocol.submission.max_recipients

Maximum recipients per message. 0 is unlimited.

recipient_delimiter ​

Default
+
Type
string
Helm
protocol.submission.recipient_delimiter

Subaddress separator: user+tag@domain → user@domain. Empty disables it.

submission_client_workarounds ​

Default
[]
Type
list
Values
whitespace-before-path mailbox-for-path
Also accepted as
client_workarounds
Helm
protocol.submission.client_workarounds
See also
lmtp_client_workarounds

Compatibility shims for clients that break the protocol. They do the same as the LMTP workarounds of the same name.

submission_add_received_header ​

Default
true
Type
boolean
Helm
protocol.submission.add_received_header

Prepend a Received: trace header to messages before forwarding. Set it to false to keep the sender's address out of the message.

yaml
protocol:
  submission:
    hostname: mail.example.com
    submission_max_mail_size: 40M
    max_line_length: 4096
    submission_max_recipients: 100
    recipient_delimiter: "+"
    submission_add_received_header: true

Submission (port 587 / 465) ​

Accepts mail from MUAs. AUTH is required. yarilo-submission-login offers PLAIN and LOGIN, plus whatever yarilo-auth runs: the SCRAM mechanisms its passdbs can verify (-PLUS only over TLS 1.3) and, with OAuth2 configured, OAUTHBEARER and XOAUTH2 (see OAuth 2.0). A refused login answers 535; a mechanism not offered answers 504. After successful authentication, each transaction is relayed to the configured upstream MTA via protocol.submission.relay as the client sends it; see Relay. If submission_relay_host is empty, MAIL FROM is answered 451 4.3.0.

auth_allow_cleartext: false in the service config blocks AUTH on unencrypted connections; pair it with ssl_mode: starttls (port 587) or ssl_mode: ssl (port 465).

A proxy in front ​

A proxy or relay that passes the client's address with XCLIENT needs xclient_protocol: true on the listener and its own network in general.xclient.trusted_nets, which is empty by default. Only a peer in that list sees 250-XCLIENT in the EHLO reply and has its forwarded address applied; any other client is not told about XCLIENT. See General settings.


Relay (protocol.submission.relay) ​

Configures the upstream MTA for submission. Each transaction gets its own connection, opened at MAIL FROM and closed at the end of DATA, at RSET, or when the client quits or drops. MAIL FROM, every RCPT TO and DATA are passed to the relay as the client sends them, and the relay's reply, code and text, is the client's. A recipient the relay refuses is refused at its RCPT TO, and the message still goes to the others. Any transport error returns 451 4.4.0 to the MUA; a relay that cannot be reached fails MAIL FROM.

A client silent for five minutes between commands is disconnected, and its relay transaction with it; submission_relay_command_timeout bounds each relayed command.

submission_relay_host ​

Default
none
Type
string
Also accepted as
host
Helm
protocol.submission.relay.host

Upstream MTA hostname or IP. Empty disables the relay, and submission answers 451.

submission_relay_port ​

Default
25
Type
integer
Also accepted as
port
Helm
protocol.submission.relay.port

Upstream MTA port.

submission_relay_user ​

Default
none
Type
string
Also accepted as
user
Helm
protocol.submission.relay.user

SASL PLAIN username sent to the upstream; %u (or %{user}) is the session's user. Empty, with no master, sends no AUTH.

submission_relay_master_user ​

Default
none
Type
string
Helm
protocol.submission.relay.master_user

Log in as this master acting for submission_relay_user (the SASL authzid), or for the session's user when that is empty.

submission_relay_password ​

Default
none
Type
string
Also accepted as
password
Helm
protocol.submission.relay.password

SASL PLAIN password, the master's when one is set. Supports ${ENV_VAR}. In the chart, relay.password_secret_ref takes it from a Secret instead.

submission_relay_ssl ​

Default
no
Type
string
Values
no starttls smtps
Also accepted as
ssl
Helm
protocol.submission.relay.ssl

Transport security to the upstream.

submission_relay_ssl_verify ​

Default
true
Type
boolean
Also accepted as
ssl_verify
Helm
protocol.submission.relay.ssl_verify

Verify the upstream's TLS certificate.

submission_relay_ssl_ca ​

Default
none
Type
string
Helm
protocol.submission.relay.ssl_ca

PEM file the upstream certificate is verified against. Empty means the system roots.

submission_relay_trusted ​

Default
false
Type
boolean
Also accepted as
trusted
Helm
protocol.submission.relay.trusted

Send XCLIENT to the upstream with the client's real IP. The upstream must advertise XCLIENT.

submission_relay_connect_timeout ​

Default
30
Type
integer, seconds
Also accepted as
connect_timeout
Helm
protocol.submission.relay.connect_timeout

TCP connect timeout.

submission_relay_command_timeout ​

Default
300
Type
integer, seconds
Also accepted as
command_timeout
Helm
protocol.submission.relay.command_timeout

Per-command timeout.

yaml
protocol:
  submission:
    relay:
      submission_relay_host: smtp.example.com
      submission_relay_port: 587
      submission_relay_user: relay-user
      submission_relay_password: "${RELAY_PASSWORD}"
      submission_relay_ssl: starttls
      submission_relay_ssl_verify: true
      submission_relay_trusted: false
      submission_relay_connect_timeout: 30
      submission_relay_command_timeout: 300

Telling the relay who sends ​

A relay that authenticates through yarilo, such as Postfix with smtpd_sasl_type = dovecot pointed at yarilo-sasl-login, can check the sender against the login (reject_authenticated_sender_login_mismatch). For that it must see the user, not a service account. Log in as a master acting for each user:

yaml
protocol:
  submission:
    relay:
      submission_relay_host: relay.example.internal
      submission_relay_port: 587
      submission_relay_ssl: starttls
      submission_relay_user: "%u"
      submission_relay_master_user: relay-master
      submission_relay_password: "${YARILO_SUBMISSION_RELAY_PASSWORD}"
  • relay-master must be a master user in yarilo-auth (see Master users).
  • The session's user is the one it logged in as, by every mechanism: PLAIN, LOGIN, SCRAM, OAUTHBEARER and XOAUTH2.
  • When the relay needs a user (%u, or a master with no relay user) and the session has none, MAIL FROM is refused before the relay is dialled.

A relay login that fails, or cannot be made for want of a user, answers the client 451 4.7.0 Temporary authentication failure, try again later. The reason is logged with the session id.

In the Helm chart, relay.password_secret_ref (name, key) gives the password from a Secret to every container that relays, as YARILO_SUBMISSION_RELAY_PASSWORD.

JMAP ​

JMAP EmailSubmission sends through this same relay, with the same login as the user and the same limits; see JMAP.

Verifying the relay ​

A relay inside the cluster usually holds a certificate from an internal CA. To verify it against that CA, set submission_relay_ssl_ca to the CA's PEM and keep submission_relay_ssl_verify: true. With internal_tls on, the chart already mounts the internal CA at /etc/yarilo/internal-tls/ca.crt.

WARNING

2.4.3 and earlier delivered a reply a step behind after AUTH through the login, so a client could not send through Submission.

The pre-beta short names - host, port, user, password, ssl, ssl_verify, trusted, connect_timeout, command_timeout - are still accepted.