Skip to content

Actions

An action asks the server to do something immediately: reload its settings, pick up a renewed certificate, pause the outbound queue, or test how a message would be authenticated or classified. Actions suit operations whose result the administrator wants at once, as opposed to the background jobs described in Tasks.

Each request creates an Action object of one of the variants listed below. The object is found in the WebUI under Management › Actions. The server runs the action, returns any results in the response and keeps nothing. Actions are create-only, so the result is available only in the response to the x:Action/set call that created the action, and cannot be read later.

With the CLI, an action is created with stalwart-cli create Action/<Variant>. The following command reloads the settings:

Terminal window
stalwart-cli create Action/ReloadSettings

Through the management API, an action is an x:Action/set call with one create entry, whose @type names the variant and whose other fields are the input of the action. The following request runs the DMARC troubleshooting checks for a message from 192.0.2.25:

Terminal window
curl -X POST https://mail.example.com/jmap/ \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"using": ["urn:ietf:params:jmap:core", "urn:stalwart:jmap"],
"methodCalls": [
["x:Action/set", {
"create": {
"a1": {
"@type": "TroubleshootDmarc",
"remoteIp": "192.0.2.25",
"ehloDomain": "mx.example.net",
"mailFrom": "[email protected]",
"spfEhloDomain": "mx.example.net",
"spfMailFromDomain": "example.net"
}
}
}, "0"]
]
}'

The response lists the action under created. The server fills in the result fields, which in this case hold the SPF, reverse DNS, DKIM, ARC and DMARC results:

{
"methodResponses": [
["x:Action/set", {
"created": {
"a1": {
"id": "<id>",
"spfEhloResult": {"@type": "Pass"},
"spfMailFromResult": {"@type": "Pass"},
"dmarcPass": true,
"elapsed": 412
}
}
}, "0"]
]
}

The response above is abbreviated. The Action reference lists every result field of every variant.

Each variant performs one operation, summarised in the table below. In a cluster, the variants that reload or clear state need a coordinator to reach the other nodes. Without one, they apply only to the node that received the request.

VariantEffect
ReloadSettingsReads the server settings from the data store again and applies them without a restart (Reload settings).
ReloadTlsCertificatesReloads the Certificate objects, reading again the values stored in files, so that new or renewed certificates are used without a restart.
ReloadLookupStoresReloads the lookup stores used by access lists, block lists and similar data sets.
ReloadBlockedIpsReloads the list of blocked IP addresses.
UpdateAppsDownloads and unpacks every enabled application, including the WebUI.
TroubleshootDmarcRuns the SPF, reverse DNS, DKIM, DKIM2, ARC and DMARC checks that the server applies to an incoming message, and returns their results.
ClassifySpamRuns a message through the spam filter and returns its score, tags and result.
InvalidateCachesClears every in-memory cache, including the cached permissions of accounts.
InvalidateNegativeCachesClears only the cached negative results, such as failed DNS lookups.
PauseMtaQueueStops delivery attempts from the outbound queue; messages continue to be queued.
ResumeMtaQueueResumes delivery from the outbound queue.

Some settings are compiled into the running server, such as MTA rules, directories and authentication settings. A change to them takes effect only after ReloadSettings, which reads the settings from the data store again and applies them without a restart. The reload runs on every node when a coordinator is configured, and on the node that receives the request otherwise.

Listener definitions are an exception. The reload validates them, but they take effect only after a restart (Applying changes).

A reload that finds an error changes nothing and returns the errors, so the running configuration stays as it was. A successful reload returns the warnings it produced, such as license problems, in the result’s warnings field.

TroubleshootDmarc answers the question of why a sender’s mail passes or fails authentication. It replays, for a described message, the checks that the server would apply on receipt.

The caller describes the connection and the envelope of the message:

  • remoteIp, ehloDomain and mailFrom, and optionally rcptTo
  • The domains used for the SPF checks, spfEhloDomain and spfMailFromDomain
  • Optionally the raw message

The message itself matters because the DKIM, ARC and DMARC checks work on its content: without it, they have no message to work on. The server returns the result of each check, the overall dkimPass, dkim2Pass and dmarcPass flags, the applicable dmarcPolicy and the elapsed time in milliseconds. The same checks are available in the WebUI’s troubleshooting tools (Troubleshooting).

ClassifySpam shows how the spam filter would judge a message, without delivering it. The verdict depends on how the message arrived as well as on its content, so the caller supplies both: the raw message, and the context in which it would have been received. That context consists of remoteIp, ehloDomain, mailFrom with optional mailFromParameters, the rcptTo recipients, isTls and, for an authenticated submission, authenticatedAs.

The server returns the score, the tags that contributed to it and the result: spam, ham, reject or discard. When the AI spam classifier is enabled (Enterprise), the response also contains three fields about it: aiGate, which states whether the classifier was consulted or why it was skipped, the aiFacts sent to it, and its aiVerdict.

Creating an action requires two permissions: sysActionCreate, and the permission of its variant, action<Variant>, for example actionReloadSettings or actionClassifySpam. The default System Administrator role holds all of them.

The per-variant permissions allow finer delegation. A custom role can allow individual actions by granting sysActionCreate and the permissions of the chosen variants only, so an operator could be allowed to classify messages without being able to pause the queue. Because actions are not stored, there are no permissions to read, list or delete them.