Is there any option to inject some tracking code to message body

So something like …

local my_tracking_link = '<img src="http://10.0.0.1/img_chania.jpg" alt="Flowers in Chania">'
msg_data = msg_data:gsub("</body>, my_tracking_link .. "</body>")

https://docs.kumomta.com/reference/message/get_data/

^^ Note that I have not tested that exact code snippet, but it is similar to what I have done in my other testing.

Then you reassemble and re-inject with HTTP similar to this:

  local client = kumo.http.build_client {}
  local sender = {}

  function sender:send(message)
    local msg_body = message:get_data())
    local my_tracking_link = '<img src="http://10.0.0.1/img_chania.jpg" alt="Flowers in Chania">'
    msg_body = msg_body:gsub("</body>, my_tracking_link .. "</body>")

    local msg_payload = '{\
             "envelope_sender": message:sender().email,\
             "content":msg_body,\
             "recipients": [ {  "email": msg.recipient().email } ] }'


      local request = client:post 'http://127.0.0.1:8000/api/inject/v1'

      request:header('Content-Type', 'application/json')
      request:body(msg_payload)

      -- Make the request
      local response = request:send()

      -- and handle the result
      local disposition = string.format(
        '%d %s %s',
        response:status_code(),
        response:status_reason(),
        response:text()
      )
      if response:status_is_success() then
        -- Success!
        return disposition
      end

      -- Failed!
      kumo.reject(400, disposition)
    end
  end
  return sender
end)

And you need to also kumo.reject() the original message so it does not deliver.

so… even though you can, you probably should not unless there is no other way to modify the message before injection.

If this is an important feature to you, funding the work is a great way to get it to the front of the development queue. Let us know if this is worth accelerating to the from of the queue and we can figure out the work and cost involved in doing that.

@faithful-ostrich @yearning-hyena Thanks fo the update

This is not working. No error is logged. Please check the code. Due to length limitations, split and upload the code.

`–[[
########################################################
KumoMTA minimal Send Policy
(Save this as /opt/kumomta/etc/policy/init.lua for systemd automation)
This config policy defines KumoMTA with a minimal
set of modifications from default.
Please read the docs at https://docs.kumomta.com/
For detailed configuration instructions.
########################################################
]]

local kumo = require ‘kumo’
local shaping = require ‘policy-extras.shaping’
local sources = require ‘policy-extras.sources’
sources:setup { ‘/opt/kumomta/etc/policy/sources.toml’ }
local queue_module = require ‘policy-extras.queue’
local queue_helper = queue_module:setup ({ ‘/opt/kumomta/etc/policy/queues.toml’ })

–[[ Start of INIT section ]]

kumo.on(‘init’, function()
kumo.start_esmtp_listener {
listen = ‘0:25’,
hostname = ‘kumo.domain.com’,
relay_hosts = {‘127.0.0.1’,},
}

kumo.start_esmtp_listener {
listen = ‘0.0.0.0:587’,
hostname = ‘kumo.domain.com’,
relay_hosts = { ‘127.0.0.1’ },
tls_certificate = ‘/opt/kumomta/etc/ssl/kumo-cert.pem’,
tls_private_key = ‘/opt/kumomta/etc/ssl/kumo-key.pem’,
}
kumo.start_http_listener {
listen = ‘127.0.0.1:8000’,
hostname = ‘kumomta.domain.com’,
tls_certificate = ‘’,
tls_private_key = ‘/etc/letsencrypt/live/kumomta.domain.com/privkey.pem’,
use_tls = false
}

kumo.define_spool {
name = ‘data’,
path = ‘/var/spool/kumomta/data’,
}

kumo.define_spool {
name = ‘meta’,
path = ‘/var/spool/kumomta/meta’,
}

kumo.configure_local_logs {
log_dir = ‘/var/log/kumomta’,
}

end)
–[[ End of INIT Section ]]`

`–[[ Start of Non-INIT level config ]]

kumo.on(‘smtp_server_message_received’, function(msg)
queue_helper:apply(msg)
msg:append_header(“X-Server-Id”, “Vinam-Kumo”)
msg:append_header(“X-Sender-Id”, msg:sender().email)
msg:append_header(“List-Unsubscribe”, kumo.encode.base64_encode( msg:recipient().email .. ‘/’ .. msg:id() ))
msg:append_header(“List-Unsubscribe-Post”, “List-Unsubscribe=One-Click”)
local signer = kumo.dkim.rsa_sha256_signer {
domain = ‘domain.com’,
selector = ‘kmdk’,
headers = { ‘From’, ‘To’, ‘Subject’ },
key = ‘/opt/kumomta/etc/dkim/domain.com/kumo1.pem’,
}
msg:dkim_sign(signer)

      local double_signer = kumo.dkim.rsa_sha256_signer {
            domain = msg:from_header().domain,
            selector = 'kmdk',
            headers = { 'From', 'To', 'Subject' },
            key = '/opt/kumomta/etc/dkim/' .. string.gsub(msg:from_header().domain,'kumo.','') .. '/kumo1.pem',
       }
       msg:dkim_sign(double_signer)

end)

local AUTH_CONFIG = kumo.json_load ‘/opt/kumomta/etc/auth_file.json’

kumo.on(‘smtp_server_auth_plain’, function(authz, authc, password)
if password == ‘’ then
return false
end
return AUTH_CONFIG[authc] == password
end)

kumo.on(‘get_egress_path_config’,
shaping:setup { ‘/opt/kumomta/etc/shaping.json’ }
)

`

`kumo.on(‘get_queue_config’, function(domain, tenant, campaign, routing_domain)
return kumo.make_queue_config {
protocol = {
custom_lua = {
constructor = ‘make.reinjector’,
},
},
}
end)

kumo.on(‘make.reinjector’, function(domain, tenant, campaign)
local client = kumo.http.build_client {}
local sender = {}
function sender:send(message)
local msg_body = message:get_data()
local my_tracking_link = ‘Flowers in Chania
msg_body = msg_body:gsub(“” .. my_tracking_link .. “”)
local msg_payload = ‘{“envelope_sender”: message:sender().email,“content”:msg_body,“recipients”: [{“email”: msg.recipient().email}]}’

        local request = client:post 'http://127.0.0.1:8000/api/inject/v1'
        request:header('Content-Type', 'application/json')
        request:body(msg_payload)

        local response = request:send()

        local disposition = string.format('%d %s %s',response:status_code(),response:status_reason(),response:text())
        if response:status_is_success() then
            return disposition
        else
                      
            kumo.reject(400, disposition)
        end
            end
              return sender
      end)

– PLEASE read https://docs.kumomta.com/ for extensive documentation on customizing this config.
–[[ End of Non-INIT level config ]]`

@faithful-ostrich Please check and give me proper guidance

I have downloaded all of this config, but I may not be able to look at it until tomorrow. As per our guidelines in this channel, I am working on some complicated configs for priority paid support customers first.

Ok @faithful-ostrich . I am stuck with this issue. Hope you are helping.

:eyes:

There are several missing files, but I am working through testing this config now. and “faking” the missing ones. Feel free to share those too.

** file - /opt/kumomta/etc/policy/sources.toml**

`[source.“ip-1”]
source_address = “127.0.0.1”
ehlo_domain = ‘kumo.domain.com

Pool containing just ip-1, which has weight=1

[pool.“pool-1”]
[pool.“pool-1”.“ip-1”]`

file - cat /opt/kumomta/etc/policy/queues.toml

`scheduling_header = “X-Schedule”
tenant_header = “X-Tenant”
remove_tenant_header = true

campaign_header = “X-Campaign”
remove_campaign_header = true

default_tenant = “default-tenant”

[tenant.‘default-tenant’]
egress_pool = ‘pool-1’

[queue.‘gmail.com’]
max_age = ‘22 hours’
retry_interval = ‘17 mins’`

file - /opt/kumomta/etc/auth_details.json

{ "arun******@gmail.com": { "blocked_emails": { "1arun******.com": "aru******.com", "geethi******.com": "geet******.com" } } }

** file - /opt/kumomta/etc/auth_file.json**

{"arun*****.com":"123456789"}