mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-28 23:19:33 +00:00
281 lines
7.8 KiB
Lua
281 lines
7.8 KiB
Lua
--
|
|
-- (C) 2017-24 - ntop.org
|
|
--
|
|
|
|
local email = {
|
|
name = "Email",
|
|
endpoint_params = {
|
|
{ param_name = "smtp_server" },
|
|
{ param_name = "email_sender"},
|
|
{ param_name = "smtp_port", optional = true },
|
|
{ param_name = "use_proxy", optional = true },
|
|
{ param_name = "smtp_username", optional = true },
|
|
{ param_name = "smtp_password", optional = true },
|
|
},
|
|
endpoint_template = {
|
|
script_key = "email",
|
|
template_name = "email_endpoint.template"
|
|
},
|
|
recipient_params = {
|
|
{ param_name = "email_recipient" },
|
|
{ param_name = "cc", optional = true },
|
|
},
|
|
recipient_template = {
|
|
script_key = "email",
|
|
template_name = "email_recipient.template"
|
|
},
|
|
}
|
|
|
|
require "lua_utils"
|
|
local json = require("dkjson")
|
|
local alert_utils = require "alert_utils"
|
|
local format_utils = require "format_utils"
|
|
local debug_endpoint = false
|
|
|
|
email.EXPORT_FREQUENCY = 60
|
|
email.prio = 200
|
|
|
|
local MAX_ALERTS_PER_EMAIL = 100
|
|
local MAX_NUM_SEND_ATTEMPTS = 5
|
|
local NUM_ATTEMPTS_KEY = "ntopng.alerts.modules_notifications_queue.email.num_attemps"
|
|
|
|
if ntop.getPref("ntopng.prefs.debug_email") == "1" then
|
|
debug_endpoint = true
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
-- @brief Returns the desided formatted output for recipient params
|
|
function email.format_recipient_params(recipient_params)
|
|
return string.format("%s (%s)", recipient_params.email_recipient, email.name)
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
local function recipient2sendMessageSettings(recipient)
|
|
local settings = {
|
|
smtp_server = recipient.endpoint_conf.smtp_server,
|
|
smtp_port = recipient.endpoint_conf.smtp_port,
|
|
use_proxy = toboolean(recipient.endpoint_conf.use_proxy),
|
|
from_addr = recipient.endpoint_conf.email_sender,
|
|
to_addr = recipient.recipient_params.email_recipient,
|
|
cc_addr = recipient.recipient_params.cc,
|
|
username = recipient.endpoint_conf.smtp_username,
|
|
password = recipient.endpoint_conf.smtp_password,
|
|
}
|
|
|
|
return settings
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
local function buildMessageHeader(now_ts, from, to, cc, subject, body)
|
|
local msg_id = "<" .. now_ts .. "." .. os.clock() .. "@ntopng>"
|
|
|
|
local lines = {
|
|
"From: " .. from,
|
|
"To: " .. to,
|
|
"Subject: " .. subject,
|
|
"Date: " .. format_utils.formatEpochRFC2822(now_ts),
|
|
"Message-ID: " .. msg_id,
|
|
"Content-Type: text/html; charset=UTF-8",
|
|
}
|
|
|
|
if not isEmptyString(cc) then
|
|
lines[#lines + 1] = "Cc: "..cc
|
|
end
|
|
|
|
return table.concat(lines, "\r\n") .. "\r\n\r\n" .. body .. "\r\n"
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
function email.isAvailable()
|
|
return(ntop.sendMail ~= nil)
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
function email.sendEmail(subject, message_body, settings)
|
|
local smtp_server = settings.smtp_server
|
|
local smtp_port = settings.smtp_port
|
|
local use_proxy = settings.use_proxy
|
|
local from = settings.from_addr:gsub(".*<(.*)>", "%1")
|
|
local to = settings.to_addr:gsub(".*<(.*)>", "%1")
|
|
local cc = settings.cc_addr:gsub(".*<(.*)>", "%1")
|
|
local product = ntop.getInfo(false).product
|
|
local info = ntop.getHostInformation()
|
|
|
|
if not isEmptyString(subject) then
|
|
subject = subject .. " - "
|
|
else
|
|
subject = ""
|
|
end
|
|
subject = subject .. product .. " @ " .. info.instance_name .. " (" .. info.ip .. ")"
|
|
|
|
if not string.find(smtp_server, "://") then
|
|
smtp_server = "smtp://" .. smtp_server
|
|
end
|
|
|
|
smtp_port = tonumber(smtp_port)
|
|
if smtp_port and smtp_port > 0 then
|
|
smtp_server = smtp_server .. ":"..smtp_port
|
|
end
|
|
|
|
local parts = string.split(to, "@")
|
|
|
|
if #parts == 2 then
|
|
local sender_domain = parts[2]
|
|
smtp_server = smtp_server .. "/" .. sender_domain
|
|
end
|
|
|
|
local message = buildMessageHeader(os.time(), settings.from_addr, settings.to_addr, settings.cc_addr, subject, message_body)
|
|
|
|
-- Pass nil username and password when auth is not required
|
|
local username = nil
|
|
local password = nil
|
|
if not isEmptyString(settings.username) then username = settings.username end
|
|
if not isEmptyString(settings.password) then password = settings.password end
|
|
|
|
return ntop.sendMail(from, to, cc, message, smtp_server, username, password, use_proxy, debug_endpoint)
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
-- Dequeue alerts from a recipient queue for sending notifications
|
|
function email.dequeueRecipientAlerts(recipient, budget)
|
|
local sent = 0
|
|
local more_available = true
|
|
local budget_used = 0
|
|
|
|
local success = true
|
|
local error_message = nil
|
|
local delivered = 0
|
|
local discarded = 0
|
|
local failures = 0
|
|
|
|
local settings = recipient2sendMessageSettings(recipient)
|
|
|
|
-- Dequeue alerts up to budget x MAX_ALERTS_PER_EMAIL
|
|
-- Note: in this case budget is the number of email to send
|
|
while budget_used <= budget and more_available do
|
|
-- Dequeue MAX_ALERTS_PER_EMAIL notifications
|
|
|
|
local notifications = {}
|
|
|
|
local i = 0
|
|
local total_len = 0
|
|
while i < MAX_ALERTS_PER_EMAIL do
|
|
local notification = ntop.recipient_dequeue(recipient.recipient_id)
|
|
|
|
if notification then
|
|
|
|
if debug_endpoint then
|
|
tprint("Email: dequeued notification")
|
|
tprint(notification)
|
|
end
|
|
|
|
if alert_utils.filter_notification(notification, recipient.recipient_id) then
|
|
local notif = json.decode(notification.alert)
|
|
|
|
if debug_endpoint then
|
|
tprint("Email: notification matched the filter")
|
|
end
|
|
|
|
notifications[#notifications + 1] = notif
|
|
i = i + 1
|
|
|
|
if not notif.score then
|
|
-- Not an alert (e.g. report), send out
|
|
goto send_out
|
|
end
|
|
else
|
|
discarded = discarded + 1
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
::send_out::
|
|
|
|
if not notifications or #notifications == 0 then
|
|
more_available = false
|
|
break
|
|
end
|
|
|
|
-- Prepare email
|
|
|
|
-- Subject
|
|
local subject = format_utils.formatSubject(notifications)
|
|
|
|
-- Body
|
|
local messages = {}
|
|
for _, notif in ipairs(notifications) do
|
|
messages[#messages + 1] = format_utils.formatMessage(notif, {show_entity = true, nohtml=false, nolabelhtml=true})
|
|
end
|
|
local message_body = table.concat(messages, "<br>")
|
|
|
|
if debug_endpoint then tprint(message_body) end
|
|
|
|
-- Send email
|
|
local rv = email.sendEmail(subject, message_body, settings)
|
|
|
|
-- Handle retries on failure
|
|
if not rv.success then
|
|
local num_attemps = (tonumber(ntop.getCache(NUM_ATTEMPTS_KEY)) or 0) + 1
|
|
|
|
if num_attemps >= MAX_NUM_SEND_ATTEMPTS then
|
|
ntop.delCache(NUM_ATTEMPTS_KEY)
|
|
success = false
|
|
error_message = "Unable to send alerts by email"
|
|
failures = failures + #notifications
|
|
goto done
|
|
else
|
|
ntop.setCache(NUM_ATTEMPTS_KEY, tostring(num_attemps))
|
|
goto done
|
|
end
|
|
|
|
else
|
|
delivered = delivered + #notifications
|
|
ntop.delCache(NUM_ATTEMPTS_KEY)
|
|
end
|
|
|
|
-- Remove the processed messages from the queue
|
|
budget_used = budget_used + #notifications
|
|
sent = sent + 1
|
|
end
|
|
|
|
::done::
|
|
return {
|
|
success = success,
|
|
error_message = error_message,
|
|
delivered = delivered,
|
|
discarded = discarded,
|
|
failures = failures,
|
|
more_available = more_available,
|
|
}
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
function email.runTest(recipient)
|
|
local message_info
|
|
|
|
local settings = recipient2sendMessageSettings(recipient)
|
|
|
|
local sent = email.sendEmail("TEST MAIL", "Email notification is working", settings)
|
|
|
|
if sent.success then
|
|
message_info = i18n("prefs.email_sent_successfully")
|
|
else
|
|
message_info = i18n("prefs.email_send_error", {msg = sent.msg, url = "https://www.ntop.org/guides/ntopng/user_interface/shared/alerts/available_endpoints.html#email"})
|
|
end
|
|
|
|
return sent.success, message_info
|
|
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
return email
|