Skip to main content

SMTP

Synopsis​

Creates an SMTP server that receives email messages. Supports authentication, TLS encryption through either STARTTLS or implicit TLS, automatic message handling, and JSON conversion.

For details, see Appendix.

Schema​

- id: <numeric>
name: <string>
description: <string>
type: smtp
tags: <string[]>
pipelines: <pipeline[]>
status: <boolean>
properties:
address: <string>
username: <string>
password: <string>
allow_insecure_auth: <boolean>
port: <numeric>
timeout: <numeric>
tls:
status: <boolean>
mode: <string>
require_tls: <boolean>
cert_name: <string>
key_name: <string>
passphrase: <string>
min_tls_version: <string>
max_tls_version: <string>
client_ca_name: <string>
client_auth_required: <boolean>
insecure_skip_verify: <boolean>

Configuration​

The following fields are used to define the device:

Device​

FieldRequiredDefaultDescription
idYUnique identifier
nameYDevice name
descriptionN-Optional description
typeYMust be smtp
tagsN-Optional tags
pipelinesN-Optional pre-processor pipelines
statusNtrueEnable/disable the device

Connection​

FieldRequiredDefaultDescription
addressN"0.0.0.0"Listen address
portYListen port
usernameN-Authentication username
passwordN-Authentication password
allow_insecure_authNfalseAdvertise AUTH on connections that are not encrypted
timeoutN15Connection timeout in seconds
note

AUTH PLAIN is the only mechanism offered, and it is advertised only when a username is configured. It carries credentials as base64 rather than encrypted, so it is withheld from unencrypted connections unless allow_insecure_auth is true.

TLS​

FieldRequiredDefaultDescription
tls.statusNfalseEnable TLS encryption
tls.cert_nameY*cert.pemTLS certificate
tls.key_nameY*key.pemTLS private key
tls.passphraseN-Passphrase for an encrypted private key
tls.min_tls_versionNtls1.2Minimum accepted TLS version (tls1.0, tls1.1, tls1.2, tls1.3)
tls.max_tls_versionN-Maximum accepted TLS version. When unset, the highest mutually supported version is negotiated.
tls.client_ca_nameN-CA bundle used to verify client certificates (mTLS)
tls.client_auth_requiredN**falseRequire connecting clients to present a valid certificate. When false, a client certificate is verified only if one is presented.
tls.insecure_skip_verifyNfalseHas no effect on a listener. It applies only where the Director connects to a server, never to the connections it accepts: a client certificate is checked only through tls.client_ca_name and tls.client_auth_required. Changing it restarts the listener and nothing else.

* = Required when tls.status is true.

** = Requires tls.client_ca_name. If tls.client_auth_required is true or tls.client_ca_name is set and the named CA cannot be loaded, the configuration is rejected and the device fails to start.

note

tls.min_version is a deprecated alias for tls.min_tls_version, honored only when tls.min_tls_version is unset. Use tls.min_tls_version in new configurations.

note

TLS material fields (cert_name, key_name, ca_name, client_ca_name) accept any of the following:

  • File name — resolved relative to the service root directory. Nested paths such as certs/prod/server.pem are supported.
  • Absolute path — honored only if it resolves inside the service root. Any path that escapes the root is refused.
  • Inline PEM content — used verbatim when the value contains -----BEGIN.
  • Environment variable — ${ENV_VAR}.
  • Vault reference — $secret{id=...} or $secret{store=...,ref=...}.

SMTP can carry TLS two ways, so it reads two keys no other device has:

FieldRequiredDefaultDescription
tls.modeNstarttlsHow TLS is carried. starttls connects in the clear and upgrades in place (RFC 3207, ports 25 and 587); implicit encrypts from the first byte (SMTPS, port 465)
tls.require_tlsNtrueRefuse MAIL, RCPT and DATA with 530 5.7.0 Must issue a STARTTLS command first until the connection is encrypted
warning

The mode is not inferred from the port, so a sender on a non-standard port needs tls.mode set explicitly. An unrecognized value is rejected rather than falling back — the listener refuses to start rather than guess the transport — and that check runs even when tls.status is false.

note

STARTTLS is advertised, not compelled, which is what tls.require_tls enforces: with it disabled, a sender can decline the upgrade and submit in cleartext on a port configured for TLS. It has no effect under tls.mode: implicit, where the connection is never cleartext, and is inert when tls.status is false.

Performance​

FieldRequiredDefaultDescription
max_buffer_sizeN128MBIngest buffer admission cap. Also sizes this listener's ingest buffers: 3/8 of this value at start, growing to at most 3x
note

This device does not apply reuse or workers. It serves its port from one listener, whatever they are set to, and both keys are still accepted rather than refused. When workers is set to anything other than 1, a Verbose log line says The listener serves SMTP on one socket, so it runs 1 worker instead of the N configured., with N the configured count. Throughput is not capped by this: SMTP sessions are served concurrently, one per connection, and their writes fan out across the ingest buffer's shards.

In Director versions before v2.4.0, a device whose workers resolved above 1 never stayed listening. That included every device left at the default on a Director with 8 or more CPUs, and any device configured with workers: 2 or more. Each extra worker failed to bind the port already taken by the first, which stopped the device; the Director restarted it every minute, and clients saw connection refused. Such a device now listens on one listener, with no change to its configuration. A device created in the web interface sends workers: 1 with reuse off, so it runs one listener on those versions as well.

note

max_buffer_size is the ingest-buffer admission cap, and is distinct from any buffer_size field above, which sizes the network read buffer. Left unset it is 128MB, whose buffers take 48 MiB of heap per listener worker at start and grow to at most 384 MiB as bursts need the room — and with reuse: true a device runs one worker per listener. Size strings are binary, and 32MB and 32MiB are exact synonyms.

See Listener Memory Sizing for the arithmetic, the sizing table, and what happens when the cap is exhausted.

Details​

Emails​

The server captures and processes email headers, sender information, recipient information, message content, attachments, and remote client information.

JSON Conversion​

All email messages are automatically converted to JSON format with the following fields:

FieldDescription
FromSender address
ToRecipient addresses
SubjectEmail subject
BodyMessage body
HostnameHostname the server greeted with
LocalAddrAddress the server accepted the connection on
RemoteAddrClient address

Only the subject is retained from the message headers; the remaining headers are not carried through.

Certificate Rotation​

When tls.cert_name and tls.key_name resolve to files under the service root, the listener reloads them once the file modification time advances, so a certificate replaced in place is picked up without a restart. If a reload fails, the last certificate loaded successfully stays in service rather than the listener dropping TLS mid-rotation.

Material supplied inline, or through an environment variable or a vault reference, is read once when the device starts and does not rotate.

Examples​

The following are commonly used configuration types.

Basic​

Minimal SMTP server listening on port 25:

Creating a simple SMTP server...

devices:
- id: 1
name: basic_smtp
type: smtp
properties:
address: "0.0.0.0"
port: 25

Secure​

SMTP server upgrading through STARTTLS, with credential authentication:

Configuring STARTTLS and authentication...

devices:
- id: 2
name: secure_smtp
type: smtp
properties:
address: "0.0.0.0"
port: 587
username: "mailuser"
password: "secret"
timeout: 30
tls:
status: true
mode: starttls
require_tls: true
cert_name: "smtp.crt"
key_name: "smtp.key"
note

The listener binds in the clear, advertises STARTTLS in its EHLO response, and upgrades the connection in place. With require_tls enabled, a sender that does not upgrade cannot submit mail. Ports 25 and 587 are conventional for this mode.

Implicit TLS​

SMTP server encrypted from the first byte on the conventional SMTPS port:

Configuring implicit TLS on port 465...

devices:
- id: 3
name: smtps_smtp
type: smtp
properties:
address: "0.0.0.0"
port: 465
username: "mailuser"
password: "secret"
timeout: 30
tls:
status: true
mode: implicit
cert_name: "smtp.crt"
key_name: "smtp.key"
note

STARTTLS is never advertised in this mode because the connection is already encrypted, and require_tls is not read.

Mutual TLS​

SMTP server requiring client certificates, with an encrypted private key and vault-sourced material:

Verifying client certificates against a CA bundle...

devices:
- id: 4
name: mtls_smtp
type: smtp
properties:
address: "0.0.0.0"
port: 587
timeout: 30
tls:
status: true
mode: starttls
require_tls: true
cert_name: "$secret{id=41}"
key_name: "$secret{id=42}"
passphrase: "$secret{id=43}"
min_tls_version: tls1.2
max_tls_version: tls1.3
client_ca_name: "clients-ca.pem"
client_auth_required: true
note

passphrase decrypts a PKCS#8 or legacy PEM-encrypted private key. Resolution failures — a missing vault entry, a wrong passphrase, an unreadable path — are reported when the configuration is validated rather than surfacing later as a handshake error.

Pipelines​

Applying preprocessing pipelines to incoming emails:

Applying custom processing to emails...

devices:
- id: 6
name: pipeline_smtp
type: smtp
pipelines:
- email_parser
- spam_filter
properties:
address: "0.0.0.0"
port: 25
timeout: 30
note

Pipelines are processed sequentially and can modify or drop messages before ingestion.