changeset 0:010452cfaf53

mod_offline_email: Initial commit
author Matthew Wild <mwild1@gmail.com>
date Sat, 22 Aug 2009 01:14:51 +0100
parents
children 21e089282b8f
files mod_offline_email/mod_offline_email.lua
diffstat 1 files changed, 123 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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