Skip to content

kumo.configure_bounce_classifier {PARAMS}

Configures the bounce classifier. The purpose of the classifier is to attempt to digest complex and wide-ranging responses into a smaller set of categories to help inform the sender how best to respond and react to a delivery failure.

This function should be called only from inside your init event handler.

PARAMS is an object-style table that accepts the following keys:

  • files - required array-style table listing the paths to the set of classification files that define the classification rules.
  • back_pressure - optional integer. default is 131072. Specifies the maximum number of in-flight classifications before submission blocks. (Since: Version 2024.09.02-c5476b89)
  • pool_size - optional integer. default is 1/4 of the available parallelism. Specifies the number of threads to be used to process bounce classification. Classification is CPU intensive and the cost of any given classification scales with the size of the classification rules you have defined. You will likely need to have more than a single thread available for the most optimal throughput. The pool_size option allows you to specify that number of threads. (Since: Version 2024.09.02-c5476b89)
  • cache_size - optional integer. default is 1024. Specifies the size of the bounce classification cache used to hold successful classification results. (Since: Version 2024.09.02-c5476b89)
  • uncategorized_cache_size - optional integer. default is 1024. Specifies the size of the bounce classification cache used to hold unclassified results. These are in a separate cache from the positive classifications to prevent uncategorized results from churning the successful classifications out of the cache. (Since: Version 2024.09.02-c5476b89)

The following classifications are pre-defined:

Label Meaning
InvalidRecipient The recipient is invalid
DNSFailure The message bounced due to a DNS failure.
SpamBlock The message was blocked by the receiver as coming from a known spam source.
SpamContent The message was blocked by the receiver as spam
ProhibitedAttachment The message was blocked by the receiver because it contained an attachment
RelayDenied The message was blocked by the receiver because relaying is not allowed.
AutoReply The message is an auto-reply/vacation mail.
TransientFailure Message transmission has been temporarily delayed.
Subscribe The message is a subscribe request.
Unsubscribe The message is an unsubscribe request.
ChallengeResponse The message is a challenge-response probe.
BadConfiguration messages rejected due to configuration issues with remote host
BadConnection messages bounced due to bad connection issues with remote host
BadDomain messages bounced due to invalid or non-existing domains
ContentRelated messages refused or blocked due to content related reasons
InactiveMailbox messages rejected due to expired
InvalidSender messages bounced due to invalid DNS or MX entry for sending domain
MessageExpired messages bounced due to not being delivered before the bounce-after
NoAnswerFromHost messages bounces due to receiving no response from remote host after connecting
PolicyRelated messages refused or blocked due to general policy reasons
ProtocolErrors messages rejected due to SMTP protocol syntax or sequence errors
QuotaIssues messages rejected or blocked due to mailbox quota issues
RelayingIssues messages refused or blocked due to remote mail server relaying issues
RoutingErrors messages bounced due to mail routing issues for recipient domain
SpamRelated messages refused or blocked due to spam related reasons
VirusRelated messages refused or blocked due to virus related reasons
AuthenticationFailed authentication policy was not met
Uncategorized messages rejected due to other reasons

Since: Version 2023.12.28-63cde9c7

The functionality described in this outlined box requires version 2023.12.28-63cde9c7 of KumoMTA, or a more recent version.


It is now possible to define your own classification labels. You can do so simply by using whatever label you like. It is more efficient (uses less memory) to use one of the predefined codes.

The classifier must be configured with a set of rules files that provide mappings from a set of regular expressions to the available classification codes.

kumo.configure_bounce_classifier will compile the merged set of files and rules into an efficient regex set that can quickly match the rule to the classification code.

Once the classifier has been configured via this function, the logging functions will automatically call into it to populate the bounce_classification field.

kumo.on('init', function()
  kumo.configure_local_logs {
    log_dir = '/var/log/kumomta',
  }
  kumo.configure_bounce_classifier {
    files = {
      '/opt/kumomta/share/bounce_classifier/iana.toml',
    },
  }
end)

The iana.toml file is provided with rules that map from IANA defined status codes to an appropriate bounce class.

You may create and maintain your own classifications and add them to the list of files.

Here's an excerpt of the iana.toml:

# This file contains rules that match SMTP ENHANCEDSTATUSCODES
# codes as defined in the IANA registry:
# https://www.iana.org/assignments/smtp-enhanced-status-codes/smtp-enhanced-status-codes.xhtml
# to bounce classifications.
[rules]
InvalidRecipient = [
  "^(451|550) [45]\\.1\\.[1234] ",
  "^45[02] [45]\\.2\\.4 ", # Mailing list expansion
  "^5\\d{2} [45]\\.7\\.17 ", # RRVS: Mailbox owner has changed
]
BadDomain = [
  "^(451|550) [45]\\.1\\.10 ", # NULL MX
  "^5\\d{2} [45]\\.7\\.18 ", # RRVS: domain owner has changed
]
InactiveMailbox = [
  "^(451|550) [45]\\.1\\.[6] ",
  "^[45]\\d{2} [45]\\.2\\.1 ",
  "^525 [45]\\.7\\.13 ", # User account disabled
]
InvalidSender = [
  "^(451|550) [45]\\.1\\.[78] ",
  "^\\d{3} [45]\\.7\\.27 ", # Send address has NULL MX
]
QuotaIssues = [
  "^552 [45]\\.2\\.2 ",
  "^552 [45]\\.2\\.3 ",
  "^452 [45]\\.3\\.1 ", # Mail System Full
  "^55[24] [45]\\.3\\.4 ", # Message too large for system
]
{
  // This file contains rules that match SMTP ENHANCEDSTATUSCODES
  // codes as defined in the IANA registry:
  // https://www.iana.org/assignments/smtp-enhanced-status-codes/smtp-enhanced-status-codes.xhtml
  // to bounce classifications.
  "rules": {
    "InvalidRecipient": [
      "^(451|550) [45]\\.1\\.[1234] ",
      "^45[02] [45]\\.2\\.4 ",
      "^5\\d{2} [45]\\.7\\.17 "
    ],
    "BadDomain": [
      "^(451|550) [45]\\.1\\.10 ",
      "^5\\d{2} [45]\\.7\\.18 "
    ],
    "InactiveMailbox": [
      "^(451|550) [45]\\.1\\.[6] ",
      "^[45]\\d{2} [45]\\.2\\.1 ",
      "^525 [45]\\.7\\.13 "
    ],
    "InvalidSender": [
      "^(451|550) [45]\\.1\\.[78] ",
      "^\\d{3} [45]\\.7\\.27 "
    ],
    "QuotaIssues": [
      "^552 [45]\\.2\\.2 ",
      "^552 [45]\\.2\\.3 ",
      "^452 [45]\\.3\\.1 ",
      "^55[24] [45]\\.3\\.4 "
    ]
  }
}