Logic Machine Forum
LM as SMTP-Server - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: LM as SMTP-Server (/showthread.php?tid=6027)



LM as SMTP-Server - xxyzz - 19.06.2025

Hi, I am fiddeling with a concept for sending alerts on LM

I have a server that can send me E-Mails if something's wrong. I'd like to use LM alerts as a single point to check for alarms.
Can I setup an SMTP-Server on LM to recive mails and display the messages in the alert manager?

I have thought about using NodeRED as SMTP-Server and forward messages via MQTT but if i could lose that layer of abstraction it would probably benefit me in the long run.

As always, thanks for taking you time!

Cheers


RE: LM as SMTP-Server - admin - 21.06.2025

Run as a resident script with 0 sleep time. Received messages and headers will be visible in LM Logs tab.
Code:
local server = require('socket').tcp()

server:bind('*', 25)
server:settimeout(60)
server:listen()

local function handleclient(client)
  local init = {}
  local headers = {}
  local message = {}
  local state = 'helo'

  client:settimeout(3)
  client:send('220 localhost\r\n')

  local function sendok()
    client:send('250 ok\r\n')
  end

  while true do
    local line = client:receive()
    -- log(line)
    if not line then
      break
    end

    if state == 'helo' then
      local head = line:match('^(%w+)%s+')

      if head == 'HELO' or head == 'EHLO' then
        sendok()
        state = 'init'
      else
        break
      end
    elseif state == 'init' then
      if line == 'DATA' then
        state = 'headers'
        client:send('354 continue\r\n')
      else
        if line ~= '' then
          init[ #init + 1 ] = line
        end

        sendok()
      end
    elseif state == 'headers' then
      if line == '' then
        state = 'message'
      else
        local header, value = line:match('^([^:]+):%s+(.+)$')

        if header and value then
          headers[ header:lower() ] = value
        end
      end
    elseif state == 'message' then
      if line == '.' then
        state = 'quit'
        sendok()
      elseif line ~= '' then
        message[ #message + 1 ] = line
      end
    elseif state == 'quit' then
      if line == 'QUIT' then
        state = 'done'
        client:send('221 bye\r\n')
      end

      break
    end
  end

  if state == 'done' then
    log(init)
    log(headers)
    log(message)
  end

  client:close()
end

while true do
  local client = server:accept()
  if client then
    handleclient(client)
  end
end