Policy to rewrite the domain sender address

Hello.

We are currently testing KumoMTA and encountering difficulties with a specific point.

Our main domain is being impacted by automated application emails, so we have created a subdomain for them. However, due to the difficulty of changing the source address directly within the applications, we are trying to implement a sender rewrite rule in the MTA. The goal is to have messages originating from addresses such as app1@domain, app2@domain, etc., rewritten as app1@sub.domain, app2@sub.domain, and so on.

I am specifically trying to understand if smtp_client_mail_from is the right hook for this, or if I should be using pre_helper_modify_message to rewrite both the Envelope and the From: header to ensure DMARC alignment.

My current configuration:

rewrite.lua

local rewrite = {}

local sender_map = {
["app1@domain"] = "app1@sub.domain",
}

function rewrite.apply(sender)
  local lower = string.lower(sender)
  if sender_map[lower] then
    kumo.log_info(string.format("[REWRITE] %s -> %s", sender, sender_map[lower]))
    return sender_map[lower]
  end
  return sender
end
return rewrite

init.lua

kumo.on('smtp_client_mail_from', function(msg, mail_from)
  local original_sender = mail_from:get_address()
  local rewritten = rewrite.apply(original_sender)
  if rewritten ~= original_sender then
    mail_from:set_address(rewritten)
    kumo.log_info(string.format('[EGRESS-REWRITE] %s -> %s id=%s', original_sender, rewritten, msg:get_id()))
  end
end)

However, the rewrite is not happening. I suspect I might be mishandling the mail_from object or using the wrong event for this purpose.

**Version:** kumod 2026.04.09-ea3b2a9b

Any help would be greatly appreciated. Thanks in advance!

smtp_client_mail_from ?

I think only have smtp_server_mail_from in kumomta . smtp_server_mail_from - KumoMTA Docs

Maybe you can use this code.

  local rewrite = require 'rewrite'

  local function rewrite_sender(msg)
    local sender = msg:sender()
    local original = sender.email
    if not original then
      return
    end

    local rewritten = rewrite.apply(original)
    if rewritten == original then
      return
    end

    msg:set_sender(rewritten)

    local mime = msg:parse_mime()
    local from = mime.headers:from()

    if from then
      for _, mailbox in ipairs(from) do
        if mailbox.address and mailbox.address.local_part and mailbox.address.domain then
          local current = string.lower(mailbox.address.local_part .. '@' .. mailbox.address.domain)
          if current == string.lower(original) then
            local local_part, domain = rewritten:match('^(.+)@([^@]+)$')
            mailbox.address.local_part = local_part
            mailbox.address.domain = domain
          end
        end
      end

      mime.headers:set_from(from)
      msg:set_data(tostring(mime))
    end

    kumo.log_info(string.format('[REWRITE] %s -> %s id=%s', original, rewritten, msg:id()))
  end

  kumo.on('smtp_server_data', function(msg, conn_meta)
    rewrite_sender(msg)
  end)

  -- Also use this for HTTP injection if applicable:
  kumo.on('http_message_generated', function(msg, auth_info)
    rewrite_sender(msg)
  end)

Key point: run this before DKIM signing. If you rewrite From: after signing, you will break the signature. For DMARC, rewriting only the envelope sender may be enough only when SPF alignment is acceptable; if you want the visible/domain identity to move to sub.domain, rewrite both envelope sender and From: then DKIM-sign with the subdomain.

I am guessing you used an AI to help you with this because smtp_client_mail_from does not exist.

smtp_server_mail_fromdoes and might be what you want to use.

Neither does pre_helper_modify_message

If you want to rewrite the envelope, you may want to rebuild the message and craft the sender().email var.