Question about handling inbound emails

Can Kumo handle (e.g. accept and call the log hooks, etc) inbound email? For example. is it possible to use Kumo for sending transactional emails from a ticketing system, where users can reply to the ticket notifications (or just send an email to support@domain.com where domain.com MX is pointing to the KumoMTA server), and have Kumo accept those emails and process the log hooks for them?

Hey there @original-baboon, thanks for posting. Please read the “Troubleshooting” and “How to Ask for Help” buttons below. If you would like a 1:1 support session from the KumoMTA team, details are at the “Book a Support Session” button below.

Of course, at the end of the day the only real difference between a sending and receiving server is in the relay config, allowing from all hosts to a given destination instead of from limited hosts to all destinations.

And webhooks can fire logs or can fire select messages.

So you’d setup the incoming domains in the listener_domains helper, setting them relay_to = true and then some variation of Routing Messages via HTTP Request - KumoMTA Docs to either forward the message whole, or chop out the interesting bits and send those to the API.

Thanks @yearning-hyena. I have relay_to = true on a domain (let’s say kumo.example.com), but after sending emails to info@kumo.example.com I see nothing in the logs (using tailer /var/log/kumomta/). Am I supposed to see them logged somewhere?

Does the log_hooks:new_json helper function log these inbound messages as well? And will the smtp_server_message_received event get fired when an inbound message is received? Right now it doesn’t seem like they are getting called.

listener_domains.toml

['*']
log_oob = false
log_arf = false
relay_to = false

['kumo.example.com']
log_oob = true
log_arf = false
relay_to = true
root@send:/opt/kumomta/etc/policy# dig +short -t mx kumo.example.com 
10 mx.myesp.com.
root@send:/opt/kumomta/etc/policy# dig +short mx.myesp.com
1.2.3.4
# this is the IP of the kumo server

Am I missing something?

What I find helps with understanding this is to realize that every message, “inbound” or “outbound” is just a message to the MTA. The MTA gets a message in, sends a message out. The difference in outcome is down to just the config. So yes, every “inbound” message also passes through smtp_server_message_received because all messages that arrive via SMTP are the same in the eyes of the MTA, at least before the config is applies.

The lack of the message in the logs is probably because the relevant part of the logs is still active and hasn’t shown in tailer yet, try a restart and see if it appears.

Thanks, I think I found the issue, I’d written the code for smtp_server_message_received under the assumption that is only called for outbound messages and it’s throwing an error on inbound emails. I’ll fix that and try again :slightly_smiling_face:

OK - I’m now receiving the inbound messages, queuing them in a separate queue to be delivered to a HTTP API. Everything is getting called and it’s going through.

I feel your next message will start with “but” :wink:

It is :sweat_smile: but I want to make sure it’s not my fault before I send it :grinning_face_with_smiling_eyes:

although it’s a futile error, I know… It’s always my fault when it comes to KumoMTA :grinning_face_with_smiling_eyes: It’s just that robust

Hey we’re not infallible.

And even when it’s someone’s mistake it’s a chance for me to review where the docs could be more explicit.

OK, here it is. I’m receiving this bounce message where “sender” is empty in the log event and I can’t figure out why:

{
    "type": "Reception",
    "id": "e6ee565bd29111eeb69a960002cafe7c",
    "sender": "",
    "recipient": "info@kumo.example.com",
    "queue": "direction-inbound:4cdd7bdd-294e-4762-892f-83d40abf5a87@kumo.example.com",
    "site": "",
    "size": 55761,
    "response": {
        "code": 250,
        "enhanced_code": null,
        "content": "",
        "command": ""
    },
    "peer_address": {
        "name": "traffic02.clientspanel.com",
        "addr": "162.55.128.206"
    },
    "timestamp": 1708723458,
    "created": 1708723458,
    "num_attempts": 0,
    "bounce_classification": "Uncategorized",
    "egress_pool": "",
    "egress_source": "",
    "feedback_report": "",
    "meta": {
        "domain_id": "92b694de-8142-4641-9a48-35e506f25955",
        "customer_id": "4cdd7bdd-294e-4762-892f-83d40abf5a87"
    },
    "headers": {
        "Subject": "Mail delivery failed: returning message to sender",
        "From": "Mail Delivery System \u003cMailer-Daemon@traffic02.clientspanel.com\u003e"
    },
    "delivery_protocol": "",
    "reception_protocol": "ESMTP",
    "nodeid": "2f6489ba-9d9d-47d5-83bb-8492ac3fdd93"
}

Other inbound messages have the right sender set, but the sender in log events for bounce emails from traffic02.clientspanel.com is empty.

Ok, so here’s the thing: that’s a DSN, an Out of Band Bounce. Most systems will use a Null envelope sender when sending DSNs to avoid the other MTA having a problem and sending back their own DSN, creating a loop that could fill the disks of both servers.

By using a null envelope sender, there’s no risk of your MTA sending their MTA a bounce email.

That makes sense. But then shouldn’t this email have the type OOB or Bounce instead of Reception?

IIRC First it’s received, then it’s evaluated to be an OOB. You may want to check the log for another entry for the ID.

The only other one is the from my custom-lua queue where I’m sending the message data somewhere else to be logged. Maybe having it go to that queue prevents the default OOB one from being called?