Making OS functions more accessible to KumoMTA

MailOps engineer writing KumoMTA config.
  • May 22, 2026

The last several months have been hectic to say the least. Four stable releases, over a hundred new functions, and two exciting community events to process.  It's understandable that we missed writing about some of the very cool additions to KumoMTA.  It's time to catch up, and I am going to start with kumo.fs, our safe, direct filesystem access functions.

One of the very helpful things a Mail Transfer Agent (MTA) can do is access local files for configuration settings, saved templates, folder-dropped content, and for writing custom logs and reports. Unfortunately, this file access can often cause a blocking action that slows down email processing, particularly if the mail process needs to wait for file open and close operations to complete.  In October last year, we tackled that problem head-on and created a purpose-built interface that allows KumoMTA to access local files without interfering with the mail stream.

Why is this a big deal? KumoMTA has always allowed access to file system operations and other Operating System functions via the Lua code interface.  Many of our customers use functions like this:

local myfile = io.open ("myconfigfile.dat" , "r")
local configdata = myfile:read("*a")
myfile:close()

The problem is that if there is something wrong with the file,  or the drive is slow, or any number of other file access issues happen, the mail process can be affected. In the October 2025 stable release, we introduced the kumo.fs functions to answer that issue, and now you can do something like this:

local myfile = kumo.fs.open('myconfigfile.dat', 'r')
local configdata = myfile:read()
myfile:close

While this looks almost identical, this purpose-built function specifically does NOT block KumoMTA processing activity.  It is completely asynchronous, which allows for highly flexible local file system integration without fear of blocking mail flow.

The "open" function is just one of several in the suite of file system functions.  Possibly one of the most useful is the "glob"  function, which allows you to read an entire array of files based on their filename pattern.  Using this empowers a mailops team to employ a folder-based approach to config management.  For instance, you could drop all of your customer-specific IP Pool (sources.toml)  files into a folder, then read the entire folder as a "glob".

sources:setup (kumo.fs.glob( '/opt/kumomta/etc/policy/sources/*.toml','.',900))

We didn't stop with file access, though. Another very common operating system-level function is testing and calculating time. But getting the current time or calculating a duration with the Lua functions can be less efficient than we would like for high-volume email operations.  The need for speed led to the addition of a whole suite of Time functions in the December stable release.

With standard Lua, you might have previously used something like: 

local time_now = os.time()

You can now use the built-in function that looks very similar, but is surprisingly more efficient.

local time_now = kumo.time.now()

More importantly for our MailOps readers, we added email-specific time functions like the ability to parse a standard RFC-3339 date from a message header in a single line:

local t = kumo.time.parse_rfc3339 '2000-01-02T03:04:05+00:00'

This is just a small sample of the OS integration functions added to make operations easier and mail processing more efficient. If you have a chance to try these out, we'd love to hear your feedback.

- - - - - - - - - 

KumoMTA is the first open-source MTA designed from the ground up for the world's largest commercial senders. We are fueled by Professional Services and Sponsorship revenue.

Join the Discord | Review the Docs | Read the Blog | Grab the Code | SWAG Shop