SMTPD-TABLES(7)
π SMTPD-TABLES(7) π
okay bestie, welcome to the smtpd-tables(7) page β itβs the table API for the smtpd daemon, from the Miscellaneous Information Manual, and weβre gonna make it make sense. no cap. π
πΈ NAME πΈ
smtpd-tables β table API for the smtpd daemon
β¨ DESCRIPTION β¨
The smtpd(8) daemon gives you a Simple Mail Transfer Protocol (SMTPD) implementation, which lets ordinary machines become Mail eXchangers (MX). Some features MXes commonly use β like querying databases for user credentials β are outside SMTPβs scope and too complex to fit inside smtpd(8).
Because an MX may need those features, smtpd(8) provides an API to implement table(5) backends with a simple text-based protocol. itβs giving βsmall protocol, big possibilitiesβ β¨
π οΈ DESIGN π οΈ
smtpd-tables are programs that run as unique standalone processes β they do not share smtpd(8)βs address space. Theyβre executed by smtpd(8) at startup and expected to run in an infinite loop, reading events and queries from standard input and writing responses to standard output. They are not allowed to terminate. periodt. π
Because smtpd-tables are standalone programs that talk to smtpd(8), they may run as different users than smtpd(8) and may be written in any language. smtpd-tables must not use blocking I/O, and they must support answering asynchronously to smtpd(8). no blocking, no drama π«Ά
π¦ PROTOCOL π¦
The protocol is literally human-readable lines exchanged between smtpd-tables and smtpd(8). cute, right?
π€ The Handshake π€
The protocol begins with a handshake.
First, smtpd(8) provides smtpd-tables with general configuration information in the form of key-value lines, terminated by config|ready. For example:
config|smtpd-version|7.9.0
config|protocol|0.1
config|tablename|devs
config|ready
Then, smtpd-tables register the supported services, terminating with register|ready. For example:
register|alias
register|credentials
register|ready
Finally, smtpd(8) can start querying the table. For example:
table|0.1|1713795082.354255|devs|lookup|alias|b72508d|op
π§ The Pipe Rule π§
The | character is used to separate the fields and may only appear verbatim in the last field of the payload, in which case it should be considered a regular character and not a separator. No other field may contain a |.
bestie, this is important: only the last field can have a literal pipe, and then itβs just a regular character, not a separator. every other field stays pipe-free. π«‘
π¦ Common Request Fields π¦
Each request has a common set of fields, followed by some other fields that are operation-specific. The common format consists of a protocol prefix table, the protocol version, the timestamp and the table name. For example:
table|0.1|1713795091.202157|devs
The protocol is inherently asynchronous, so multiple requests may be sent without waiting for the table to reply. All the replies have a common prefix, followed by the operation-specific response. The common format consists of a prefix with the operation name followed by -result, and the unique ID of the request. For example:
lookup-result|b72508d
π Operations π
The list of operations, operation-specific parameters and responses is exactly this:
update idβ Ask the table to reload its configuration. The result is eitherokon success orerrorand a message upon a failure to do so.check service id queryβ Check whether query is present in the table. The result isfoundif found,not-foundif not, orerrorand a message upon an error.lookup service id queryβ Look up a value in the table for given the query. The result isfoundand the value if found,not-foundif not found, orerrorand a message upon an error.fetch service idβ Fetch the next item from the table, eventually wrapping around. It is only supported for thesourceandrelayhostservices. The result isfoundand the value if found,not-foundif the table is empty, orerrorand a message upon an error.
π Service Result Formats π
Each service has a specific format for the result. The exact syntax for the values and eventually the keys are described in table(5). The services and their result format are as follows:
aliasβ One or more aliases separated by a comma.authβ Only usable forcheck. Lookup key is username and cleartext password separated by:.domainβ A domain name.credentialsβ The user name, followed by:and the encrypted password as persmtpctl(8) encryptsubcommand.netaddrβ IPv4 and IPv6 address or netmask.userinfoβ The user id, followed by:then the group id, then:and finally the home directory.sourceβ IPv4 and IPv6 address.mailaddrβ An username, a domain or a full email address.addrnameβ Used to map IP addresses to hostnames.
π₯ EXAMPLES π₯
Assuming the table is called devs, hereβs an example of a failed update transaction:
table|0.1|1713795097.394049|devs|update|478ff0d2
update-result|478ff0d2|error|failed to connect to the database
A check request for the netaddr service for the 192.168.0.7 IPv4 address which is not in the table:
table|0.1|1713795103.314423|devs|check|netaddr|e5862859|192.168.0.7
check-result|e5862859|not-found
A successful lookup request for the userinfo service for the user op:
table|0.1|1713795110.354921|devs|lookup|userinfo|f993c74|op
lookup-result|f993c74|found|1000:1000:/home/op
A series of fetch requests for the source service that wraps around:
table|0.1|1713795116.227321|devs|fetch|source|189bd3ee
lookup-result|189bd3ee|found|192.168.1.7
table|0.1|1713795120.162438|devs|fetch|source|9e4c56d4
lookup-result|9e4c56d4|found|10.0.0.8
table|0.1|1713795122.930928|devs|fetch|source|f2c8b906
lookup-result|f2c8b906|found|192.168.1.7
π SEE ALSO π
π°οΈ HISTORY π°οΈ
smtpd-tables first appeared in OpenBSD 7.6. iconic behavior honestly β
xoxo, this page is from Debian, for SMTPD-TABLES(7), dated April 16, 2026 π
π¦ where this page comes from
- arch rolling: opensmtpd 7.9.0p0-1 Β· custom
- opensuse-leap 16.0: OpenSMTPD 7.9.0p0-bp160.1.1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- opensuse-leap 16.0: OpenSMTPD 7.9.0p0-bp160.1.1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- opensuse-leap 16.0: OpenSMTPD 7.9.0p0-bp160.1.1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- opensuse-leap 16.0: OpenSMTPD 7.9.0p0-bp160.1.1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4-Clause AND ISC
- Copyright (c) 2008 Janne Johansson <jj@openbsd.org>
- Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
- Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
- Copyright (c) 2024 Omar Polo <op@openbsd.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms