mod_offline_email/mod_offline_email.lua
changeset 0 010452cfaf53
child 1285 f1a0a0754b87
equal deleted inserted replaced
-1:000000000000 0:010452cfaf53
       
     1 
       
     2 local full_sessions = full_sessions;
       
     3 local bare_sessions = bare_sessions;
       
     4 
       
     5 local st = require "util.stanza";
       
     6 local jid_bare = require "util.jid".bare;
       
     7 local jid_split = require "util.jid".split;
       
     8 local user_exists = require "core.usermanager".user_exists;
       
     9 local urlencode = require "net.http".urlencode;
       
    10 local add_task = require "util.timer".add_task;
       
    11 local os_time = os.time;
       
    12 local t_concat = table.concat;
       
    13 local smtp = require "socket.smtp";
       
    14 
       
    15 local smtp_server = module:get_option("smtp_server");
       
    16 local smtp_user = module:get_option("smtp_username");
       
    17 local smtp_pass = module:get_option("smtp_password");
       
    18 
       
    19 local smtp_address = module:get_option("smtp_from") or ((smtp_user or "xmpp").."@"..(smtp_server or module.host));
       
    20 
       
    21 local queue_offline_emails = module:get_option("queue_offline_emails");
       
    22 if queue_offline_emails == true then queue_offline_emails = 300; end
       
    23 
       
    24 local send_message_as_email;
       
    25 local message_body_from_stanza;
       
    26 
       
    27 function process_to_bare(bare, origin, stanza)
       
    28 	local user = bare_sessions[bare];
       
    29 	
       
    30 	local t = stanza.attr.type;
       
    31 	if t == nil or t == "chat" or t == "normal" then -- chat or normal message
       
    32 		if not (user and user.top_resources) then -- No resources online?
       
    33 			if user_exists(jid_split(bare)) then
       
    34 				local text = message_body_from_stanza(stanza);
       
    35 				if text then
       
    36 					send_message_as_email(bare, jid_bare(stanza.attr.from), text);
       
    37 				else
       
    38 					module:log("error", "Unable to extract message body from offline message to put into an email");
       
    39 				end
       
    40 			end
       
    41 		end
       
    42 	end
       
    43 	return; -- Leave for further processing
       
    44 end
       
    45 
       
    46 
       
    47 module:hook("message/full", function(data)
       
    48 	-- message to full JID recieved
       
    49 	local origin, stanza = data.origin, data.stanza;
       
    50 	
       
    51 	local session = full_sessions[stanza.attr.to];
       
    52 	if not session then -- resource not online
       
    53 		return process_to_bare(jid_bare(stanza.attr.to), origin, stanza);
       
    54 	end
       
    55 end, 20);
       
    56 
       
    57 module:hook("message/bare", function(data)
       
    58 	-- message to bare JID recieved
       
    59 	local origin, stanza = data.origin, data.stanza;
       
    60 
       
    61 	return process_to_bare(stanza.attr.to or (origin.username..'@'..origin.host), origin, stanza);
       
    62 end, 20);
       
    63 
       
    64 function send_message_as_email(address, from_address, message_text, subject)
       
    65 		module:log("info", "Forwarding offline message to %s via email", address);
       
    66 		local rcpt = "<"..address..">";
       
    67 		local from_user, from_domain = jid_split(from_address);
       
    68 		local from = "<"..urlencode(from_user).."@"..from_domain..">";
       
    69 		
       
    70 		local mesgt = {
       
    71 			headers = {
       
    72 				to = address;
       
    73 				subject = subject or ("Offline message from "..jid_bare(from_address));
       
    74 			};
       
    75 			body = message_text;
       
    76 		};
       
    77 		
       
    78 	local ok, err = smtp.send{ from = from, rcpt = rcpt, source = smtp.message(mesgt), 
       
    79 		server = smtp_server, user = smtp_user, password = smtp_pass };
       
    80 	if not ok then
       
    81 		module:log("error", "Failed to deliver to %s: %s", tostring(address), tostring(err));
       
    82 		return false;
       
    83 	end
       
    84 	return true;
       
    85 end
       
    86 
       
    87 if queue_offline_emails then
       
    88 	local queues = {};
       
    89 	local real_send_message_as_email = send_message_as_email;
       
    90 	function send_message_as_email(address, from_address, message_text)
       
    91 		local pair_key = address.."\0"..from_address;
       
    92 		local queue = queues[pair_key];
       
    93 		if not queue then
       
    94 			queue = { from = from_address, to = address, messages = {} };
       
    95 			queues[pair_key] = queue;
       
    96 	
       
    97 			add_task(queue_offline_emails+5, function () 
       
    98 				module:log("info", "Checking on %s", from_address);
       
    99 				local current_time = os_time();
       
   100 				local diff = current_time - queue.last_message_time;
       
   101 				if diff > queue_offline_emails then
       
   102 					module:log("info", "Enough silence, sending...");
       
   103 					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)
       
   104 				else
       
   105 					module:log("info", "Next check in %d", queue_offline_emails - diff + 5);
       
   106 					return queue_offline_emails - diff + 5;
       
   107 				end
       
   108 			end);
       
   109 		end
       
   110 		
       
   111 		queue.last_message_time = os_time();
       
   112 
       
   113 		local messages = queue.messages;
       
   114 		messages[#messages+1] = message_text;
       
   115 	end
       
   116 end
       
   117 
       
   118 function message_body_from_stanza(stanza)
       
   119 	local message_text = stanza:child_with_name("body");
       
   120 	if message_text then
       
   121 		return message_text:get_text();
       
   122 	end
       
   123 end