local full_sessions = full_sessions;
local bare_sessions = bare_sessions;
local st = require "util.stanza";
local jid_bare = require "util.jid".bare;
local jid_split = require "util.jid".split;
local user_exists = require "core.usermanager".user_exists;
local urlencode = require "net.http".urlencode;
local add_task = require "util.timer".add_task;
local os_time = os.time;
local t_concat = table.concat;
local smtp = require "socket.smtp";
local smtp_server = module:get_option("smtp_server");
local smtp_user = module:get_option("smtp_username");
local smtp_pass = module:get_option("smtp_password");
local smtp_address = module:get_option("smtp_from") or ((smtp_user or "xmpp").."@"..(smtp_server or module.host));
local queue_offline_emails = module:get_option("queue_offline_emails");
if queue_offline_emails == true then queue_offline_emails = 300; end
local send_message_as_email;
local message_body_from_stanza;
function process_to_bare(bare, origin, stanza)
local user = bare_sessions[bare];
local t = stanza.attr.type;
if t == nil or t == "chat" or t == "normal" then -- chat or normal message
if not (user and user.top_resources) then -- No resources online?
if user_exists(jid_split(bare)) then
local text = message_body_from_stanza(stanza);
if text then
send_message_as_email(bare, jid_bare(stanza.attr.from), text);
else
module:log("error", "Unable to extract message body from offline message to put into an email");
end
end
end
end
return; -- Leave for further processing
end
module:hook("message/full", function(data)
-- message to full JID recieved
local origin, stanza = data.origin, data.stanza;
local session = full_sessions[stanza.attr.to];
if not session then -- resource not online
return process_to_bare(jid_bare(stanza.attr.to), origin, stanza);
end
end, 20);
module:hook("message/bare", function(data)
-- message to bare JID recieved
local origin, stanza = data.origin, data.stanza;
return process_to_bare(stanza.attr.to or (origin.username..'@'..origin.host), origin, stanza);
end, 20);
function send_message_as_email(address, from_address, message_text, subject)
module:log("info", "Forwarding offline message to %s via email", address);
local rcpt = "<"..address..">";
local from_user, from_domain = jid_split(from_address);
local from = "<"..urlencode(from_user).."@"..from_domain..">";
local mesgt = {
headers = {
to = address;
subject = subject or ("Offline message from "..jid_bare(from_address));
};
body = message_text;
};
local ok, err = smtp.send{ from = from, rcpt = rcpt, source = smtp.message(mesgt),
server = smtp_server, user = smtp_user, password = smtp_pass };
if not ok then
module:log("error", "Failed to deliver to %s: %s", tostring(address), tostring(err));
return false;
end
return true;
end
if queue_offline_emails then
local queues = {};
local real_send_message_as_email = send_message_as_email;
function send_message_as_email(address, from_address, message_text)
local pair_key = address.."\0"..from_address;
local queue = queues[pair_key];
if not queue then
queue = { from = from_address, to = address, messages = {} };
queues[pair_key] = queue;
add_task(queue_offline_emails+5, function ()
module:log("info", "Checking on %s", from_address);
local current_time = os_time();
local diff = current_time - queue.last_message_time;
if diff > queue_offline_emails then
module:log("info", "Enough silence, sending...");
real_send_message_as_email(address, from_address, t_concat(queue.messages, "\n"), "You have "..#queue.messages.." offline message"..(#queue.messages == 1 and "" or "s").." from "..from_address)
else
module:log("info", "Next check in %d", queue_offline_emails - diff + 5);
return queue_offline_emails - diff + 5;
end
end);
end
queue.last_message_time = os_time();
local messages = queue.messages;
messages[#messages+1] = message_text;
end
end
function message_body_from_stanza(stanza)
local message_text = stanza:child_with_name("body");
if message_text then
return message_text:get_text();
end
end