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