--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_offline_email/mod_offline_email.lua Sat Aug 22 01:14:51 2009 +0100
@@ -0,0 +1,123 @@
+
+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