Skip to main content

SMTP Gateways

An SMTP gateway is a named SMTP relay registered with EmailEngine. A submission that names a gateway is delivered through that relay instead of the account's own SMTP server or provider API. The message still belongs to the account: it waits in the account's outbox, its webhooks name the account, and a copy is uploaded to the account's Sent Mail folder.

Gateways exist for mail that should not go out through the mailbox's own server: bulk or transactional mail routed through a relay built for volume, so that it does not count against the mailbox's sending limits, and mail from an account that has no SMTP configuration of its own. An account with neither an SMTP nor an OAuth2 configuration can still send when the submission names a gateway.

The Gateway Record​

A gateway is identified by a gateway ID and holds one set of SMTP connection settings.

FieldTypeRequired on createDescription
gatewaystring, up to 256 charactersYes over the APIThe ID the gateway is referred to by. The admin form can leave it empty, in which case EmailEngine generates a 16-character lowercase ID; the API refuses an empty value
namestring, up to 256 charactersYesDisplay name
hosthostnameYesSMTP server to connect to
portinteger, 1 to 65536YesSMTP port
userstring, up to 1024 charactersNoLogin name. Leave unset or null for a relay that takes no authentication
passstring, up to 1024 charactersNoPassword. Encrypted at rest with the secret and never returned
secureboolean, default falseNotrue opens a TLS connection from the start, the usual choice for port 465. false opens a plaintext connection and upgrades it with STARTTLS when the server offers it, the usual choice for ports 587 and 25

Three read-only fields record how the gateway has been used:

FieldDescription
deliveriesNumber of messages the gateway has accepted
lastUseTime of the last delivery attempt, successful or not
lastErrorThe last failed attempt, or null after a successful delivery. Carries created, status (error), response and responseCode from the server, the nodemailer code and command, a description, and the networkRouting (local address, proxy, EHLO name) of the attempt. Recorded for the failures EmailEngine can describe: connection, DNS, timeout, TLS, protocol, envelope, message and authentication errors

Managing Gateways over the API​

OperationPermissionDescription
GET /v1/gatewaysread on gatewayLists gateways, paged with page (zero-based) and pageSize (default 20, maximum 1000). Each entry carries gateway, name, deliveries, lastUse and lastError; the connection settings are not listed
GET /v1/gateway/{gateway}read on gatewayReturns the full record. pass reads back as ****** when a password is stored
POST /v1/gatewaywrite on provisioningRegisters a gateway. The response carries gateway and state: new, or existing when the ID was already registered, in which case the connection settings are overwritten and the usage fields kept
PUT /v1/gateway/edit/{gateway}write on provisioningUpdates the fields in the payload and keeps the rest. user: null and pass: null remove the stored credentials
DELETE /v1/gateway/{gateway}destructive on gatewayRemoves the gateway. Messages already queued for it fail when their delivery runs, see below

Creating and editing a gateway are in the provisioning permission group rather than gateway, because a changed host receives the stored password on the next delivery. A token narrowed with a permissions record has to name provisioning to register or edit a gateway, and gateway to read or delete one. Before EmailEngine 2.80.1 registering and editing were in the never-grantable admin group, so only an instance-wide token could do either.

The same five operations are available to AI agents as the list_gateways, get_gateway, create_gateway, update_gateway and delete_gateway MCP tools of the mcp-manage scope.

Register a gateway:

curl -XPOST "https://emailengine.example.com/v1/gateway" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"gateway": "transactional-relay",
"name": "Transactional relay",
"host": "smtp.relay.example.com",
"port": 587,
"secure": false,
"user": "relay-user",
"pass": "relay-password"
}'
{
"gateway": "transactional-relay",
"state": "new"
}

Read it back:

curl "https://emailengine.example.com/v1/gateway/transactional-relay" \
-H "Authorization: Bearer <token>"
{
"gateway": "transactional-relay",
"name": "Transactional relay",
"host": "smtp.relay.example.com",
"port": 587,
"user": "relay-user",
"pass": "******",
"secure": false
}

The usage fields appear once the gateway has been used: GET /v1/gateway/{gateway} leaves them out until then, while the listing reports deliveries: 0, lastUse: null and lastError: null for a gateway that has not delivered anything.

Rotate the password without touching the other fields:

curl -XPUT "https://emailengine.example.com/v1/gateway/edit/transactional-relay" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"pass": "new-relay-password"}'

Do not write a masked pass back: ****** is not the stored password, and the update stores it as given.

Managing Gateways in the Admin Interface​

Gateways are listed under Gateways in the Email section of the side menu, with their ID, status, the number of emails sent and the last activity. Add gateway opens a form with Gateway ID (optional, generated when left empty), Display Name, Server Address, Port, Username, Password and Use direct TLS, which is the secure field. Test connection opens an SMTP connection with the settings in the form and logs in before anything is saved, and reports the failure in plain words (an unknown hostname, a refused login, a TLS error, a timeout). The gateway page shows the stored settings with the password masked, the delivery count and the last error, with Edit gateway and the delete action in the actions menu.

Routing a Message through a Gateway​

A submission names a gateway in one of three ways:

curl -XPOST "https://emailengine.example.com/v1/account/example/submit" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"to": [{ "address": "recipient@example.com" }],
"subject": "Order confirmation",
"text": "Your order has shipped.",
"gateway": "transactional-relay"
}'

The gateway is looked up when the message is queued. A submission naming a gateway that does not exist is refused with 404 and the message Gateway "transactional-relay" was not found. The queued entry shows the gateway in its gateway field in the outbox API.

What Changes for a Gateway Delivery​

  • Connection. The host, port, TLS mode and credentials come from the gateway record. The account's SMTP settings, its OAuth2 token and its authentication server are not used. A Gmail API or MS Graph account delivers over SMTP through the gateway instead of its provider API.
  • Network settings still come from the account and the instance. The local address is selected as for any SMTP delivery, including a localAddress given on the submission. The proxy is the submission's proxy, then the account's, then the global proxy setting. The account's smtpEhloName sets the EHLO name, and the ignoreMailCertErrors setting applies to the gateway's certificate too.
  • Sent Mail copy. A gateway delivery is uploaded to the Sent Mail folder by default for every account type, Gmail and Microsoft 365 included, because the provider never sees a message sent through a relay. copy: false suppresses it, and no copy is stored for an account with IMAP disabled, with no IMAP or OAuth2 configuration, or with no folder flagged \Sent. See Skip Sent Folder.
  • Statistics. A successful delivery increments the gateway's deliveries, sets lastUse and clears lastError. A failed attempt sets lastUse and records the failure in lastError, in addition to the account's own smtpStatus.
  • Webhooks. messageSent, messageDeliveryError and messageFailed are sent for the account, and their networkRouting describes the connection to the gateway.

Retries, the deliveryAttempts limit and the distinction between permanent and transient failures are the same as for any SMTP delivery; see Outbox Queue.

A Gateway that No Longer Exists​

A message queued for a gateway is never sent through the account's own server instead. If the gateway is deleted between queuing and delivery, the delivery fails before any connection is made, with the permanent error code GatewayNotFound. No messageDeliveryError is sent for it, because no attempt reached a server; the job ends at once and messageFailed reports it. Submit the message again, with another gateway or without one, to send it.

See Also​