Commit fd3b36c6 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Initial version that is still under development. It connects to the email...

Initial version that is still under development. It connects to the email server and gets new messages but no IMs are being sent (yet).

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@9684 b35dd754-fafc-0310-a699-88a17e54d16e
parent 7878db5a
<?xml version="1.0" encoding="UTF-8"?>
<!--
Plugin configuration for the broadcast plugin.
-->
<plugin>
<class>org.jivesoftware.openfire.plugin.EmailListenerPlugin</class>
<name>Email Listener</name>
<description>Listen for emails and send alerts to specific users.</description>
<author>Jive Software</author>
<version>1.0</version>
<date>12/25/2007</date>
<url>http://www.igniterealtime.org</url>
<minServerVersion>3.4.3</minServerVersion>
<adminconsole>
<tab id="tab-server">
<sidebar id="sidebar-server-settings">
<item id="email-listener" name="Email Listener" url="email-listener.jsp"
description="Click to configure email listener" />
</sidebar>
</tab>
</adminconsole>
</plugin>
\ No newline at end of file
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.plugin;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.openfire.plugin.emailListener.EmailListener;
import java.io.File;
/**
* Plugin that connects to a mail server using IMAP and sends instant messages
* to specified users when new email messages are found.
*
* @author Gaston Dombiak
*/
public class EmailListenerPlugin implements Plugin {
public void initializePlugin(PluginManager manager, File pluginDirectory) {
// Start the email listener process
EmailListener.getInstance().start();
}
public void destroyPlugin() {
// Stop the email listener process
EmailListener.getInstance().stop();
}
}
/**
* $RCSfile$
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.openfire.plugin.emailListener;
import com.sun.mail.imap.IMAPFolder;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import javax.mail.*;
import javax.mail.event.MessageCountAdapter;
import javax.mail.event.MessageCountEvent;
import java.io.IOException;
import java.security.Security;
import java.util.Properties;
/**
* Email listener service that will send an instant message to specified users
* when new email messages are found.
*
* @author Gaston Dombiak
*/
public class EmailListener {
private static final String SSL_FACTORY = "org.jivesoftware.util.SimpleSSLSocketFactory";
private static final EmailListener instance = new EmailListener();
/**
* Message listener that will process new emails found in the IMAP server.
*/
private MessageCountAdapter messageListener;
private Folder folder;
private boolean started = false;
public static EmailListener getInstance() {
return instance;
}
private EmailListener() {
}
/**
* Opens a connection to the IMAP server and listen for new messages.
*/
public void start() {
// Check that the listner service is not running
if (started) {
return;
}
Thread thread = new Thread("Email Listener Thread") {
public void run() {
// Open the email folder and keep it
folder = openFolder();
if (folder != null) {
// Listen for new email messages until #stop is requested
listenMessages();
}
}
};
thread.setDaemon(true);
thread.start();
started = true;
}
/**
* Closes the active connection to the IMAP server.
*/
public void stop() {
closeFolder(folder, messageListener);
started = false;
folder = null;
messageListener = null;
}
/**
* Returns true if a connection to the IMAP server was successful.
*
* @return true if a connection to the IMAP server was successful.
*/
public boolean testConnection() {
Folder folder = openFolder();
boolean success = folder != null && folder.isOpen();
closeFolder(folder, null);
return success;
}
private void listenMessages() {
try {
// Add messageCountListener to listen for new messages
messageListener = new MessageCountAdapter() {
public void messagesAdded(MessageCountEvent ev) {
Message[] msgs = ev.getMessages();
System.out.println("Got " + msgs.length + " new messages");
// Just dump out the new messages
for (int i = 0; i < msgs.length; i++) {
try {
System.out.println("-----");
System.out.println("Message " +
msgs[i].getMessageNumber() + ":");
msgs[i].writeTo(System.out);
} catch (IOException ioex) {
ioex.printStackTrace();
} catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
};
folder.addMessageCountListener(messageListener);
// Check mail once in "freq" MILLIseconds
int freq = getFrequency();
boolean supportsIdle = false;
try {
if (folder instanceof IMAPFolder) {
IMAPFolder f = (IMAPFolder) folder;
f.idle();
supportsIdle = true;
}
} catch (FolderClosedException fex) {
throw fex;
} catch (MessagingException mex) {
supportsIdle = false;
}
while (messageListener != null) {
if (supportsIdle && folder instanceof IMAPFolder) {
IMAPFolder f = (IMAPFolder) folder;
f.idle();
} else {
Thread.sleep(freq); // sleep for freq milliseconds
// This is to force the IMAP server to send us
// EXISTS notifications.
if (folder != null && folder.isOpen()) {
folder.getMessageCount();
}
}
}
} catch (Exception ex) {
Log.error("Error listening new email messages", ex);
}
}
private Folder openFolder(){
try {
Properties props = System.getProperties();
props.setProperty("mail.imap.host", getHost());
props.setProperty("mail.imap.port", String.valueOf(getPort()));
// props.setProperty("mail.imap.user", getUser());
props.setProperty("mail.imap.connectiontimeout", String.valueOf(10 * 1000));
// Allow messages with a mix of valid and invalid recipients to still be sent.
props.setProperty("mail.debug", JiveGlobals.getProperty("plugin.email.listener.debug", "false"));
// Methology from an article on www.javaworld.com (Java Tip 115)
// We will attempt to failback to an insecure connection
// if the secure one cannot be made
if (isSSLEnabled()) {
// Register with security provider.
Security.setProperty("ssl.SocketFactory.provider", SSL_FACTORY);
//props.setProperty("mail.imap.starttls.enable", "true");
props.setProperty("mail.imap.socketFactory.class", SSL_FACTORY);
props.setProperty("mail.imap.socketFactory.fallback", "true");
}
// Get a Session object
Session session = Session.getInstance(props, null);
// Get a Store object
Store store = session.getStore(isSSLEnabled() ? "imaps" : "imap");
// Connect
store.connect(getHost(), getUser(), getPassword());
// Open a Folder
Folder newFolder = store.getFolder(getFolder());
if (newFolder == null || !newFolder.exists()) {
Log.error("Invalid email folder: " + getFolder());
return null;
}
newFolder.open(Folder.READ_WRITE);
return newFolder;
} catch (MessagingException e) {
Log.error("Error while initializing email listener", e);
}
return null;
}
private void closeFolder(Folder folder, MessageCountAdapter messageListener) {
if (folder != null) {
if (messageListener != null) {
folder.removeMessageCountListener(messageListener);
}
try {
folder.close(false);
} catch (MessagingException e) {
Log.error("Error closing folder", e);
}
}
}
/**
* Returns the host where the IMAP server is running or <tt>null</tt> if none was defined.
*
* @return the host where the IMAP server is running or null if none was defined.
*/
public String getHost() {
return JiveGlobals.getProperty("plugin.email.listener.host");
}
/**
* Returns the port where the IMAP server is listening. By default unsecured connections
* use port 143 and secured ones use 993.
*
* @return port where the IMAP server is listening.
*/
public int getPort() {
return JiveGlobals.getIntProperty("plugin.email.listener.port", isSSLEnabled() ? 993 : 143);
}
/**
* Sets the port where the IMAP server is listening. By default unsecured connections
* use port 143 and secured ones use 993.
*
* @param port port where the IMAP server is listening.
*/
public void setPort(int port) {
JiveGlobals.setProperty("plugin.email.listener.port", Integer.toString(port));
}
/**
* Returns the user to use to connect to the IMAP server. A null value means that
* this property needs to be configured to be used.
*
* @return the user to use to connect to the IMAP server.
*/
public String getUser() {
return JiveGlobals.getProperty("plugin.email.listener.user");
}
/**
* Returns the password to use to connect to the IMAP server. A null value means that
* this property needs to be configured to be used.
*
* @return the password to use to connect to the IMAP server.
*/
public String getPassword() {
return JiveGlobals.getProperty("plugin.email.listener.password");
}
/**
* Returns the name of the folder. In some Stores, name can be an absolute path if
* it starts with the hierarchy delimiter. Else it is interpreted relative to the
* 'root' of this namespace.
*
* @return the name of the folder.
*/
public String getFolder() {
return JiveGlobals.getProperty("plugin.email.listener.folder");
}
/**
* Returns the milliseconds to wait to check for new emails. This frequency
* is used if the IMAP server does not support idle.
*
* @return the milliseconds to wait to check for new emails.
*/
public int getFrequency() {
return JiveGlobals.getIntProperty("plugin.email.listener.frequency", 5 * 60 * 1000);
}
/**
* Returns true if SSL is enabled to connect to the server.
*
* @return true if SSL is enabled to connect to the server.
*/
public boolean isSSLEnabled() {
return JiveGlobals.getBooleanProperty("plugin.email.listener.ssl", false);
}
/**
* Sets if SSL is enabled to connect to the server.
*
* @param enabled true if SSL is enabled to connect to the server.
*/
public void setSSLEnabled(boolean enabled) {
JiveGlobals.setProperty("plugin.email.listener.ssl", Boolean.toString(enabled));
}
/**
* Sets the host where the IMAP server is running or <tt>null</tt> if none was defined.
*
* @param host the host where the IMAP server is running or null if none was defined.
*/
public void setHost(String host) {
JiveGlobals.setProperty("plugin.email.listener.host", host);
}
/**
* Sets the user to use to connect to the IMAP server. A null value means that
* this property needs to be configured to be used.
*
* @param user the user to use to connect to the IMAP server.
*/
public void setUser(String user) {
JiveGlobals.setProperty("plugin.email.listener.user", user);
}
/**
* Sets the password to use to connect to the IMAP server. A null value means that
* this property needs to be configured to be used.
*
* @param password the password to use to connect to the IMAP server.
*/
public void setPassword(String password) {
JiveGlobals.setProperty("plugin.email.listener.password", password);
}
/**
* Sets the name of the folder. In some Stores, name can be an absolute path if
* it starts with the hierarchy delimiter. Else it is interpreted relative to the
* 'root' of this namespace.
*
* @param folder the name of the folder.
*/
public void setFolder(String folder) {
JiveGlobals.setProperty("plugin.email.listener.folder", folder);
}
/**
* Sets the milliseconds to wait to check for new emails. This frequency
* is used if the IMAP server does not support idle.
*
* @param frequency the milliseconds to wait to check for new emails.
*/
public void setFrequency(int frequency) {
JiveGlobals.setProperty("plugin.email.listener.frequency", Integer.toString(frequency));
}
}
<%--
- Copyright (C) 2007 Jive Software. All rights reserved.
-
- This software is published under the terms of the GNU Public License (GPL),
- a copy of which is included in this distribution.
--%>
<%@ page import="org.jivesoftware.openfire.plugin.emailListener.EmailListener,
org.jivesoftware.util.ParamUtils"
%>
<%@ page import="org.jivesoftware.util.StringUtils" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>
<%
// get parameters
String host = ParamUtils.getParameter(request,"host");
int port = ParamUtils.getIntParameter(request,"port",0);
String username = ParamUtils.getParameter(request,"server_username");
String password = ParamUtils.getParameter(request,"server_password");
boolean ssl = ParamUtils.getBooleanParameter(request,"ssl");
String folder = ParamUtils.getParameter(request,"folder");
int frequency = ParamUtils.getIntParameter(request,"frequency",0);
boolean save = request.getParameter("save") != null;
boolean test = request.getParameter("test") != null;
boolean success = ParamUtils.getBooleanParameter(request,"success");
boolean testSuccess = false;
// Handle a test request
EmailListener emailListener = EmailListener.getInstance();
if (test) {
testSuccess = emailListener.testConnection();
}
// Save the email settings if requested
Map errors = new HashMap();
if (save) {
if (host == null) {
errors.put("host","");
}
if (username == null) {
errors.put("username","");
}
if (password == null) {
errors.put("password","");
}
if (folder == null) {
errors.put("folder","");
}
if (frequency <= 0) {
errors.put("frequency","");
}
if (port <= 0) {
errors.put("port","");
}
if (errors.isEmpty()) {
// Get hash value of existing password
String existingHashPassword = "";
if (emailListener.getPassword() != null) {
existingHashPassword = StringUtils.hash(emailListener.getPassword());
}
// Check if the new password was changed. If it wasn't changed, then it is the original hashed password
// NOTE: if the new PLAIN password equals the previous HASHED password this fails, but is unlikely.
if (!existingHashPassword.equals(password)) {
// Hash the new password since it was changed
String newHashPassword = "";
if (password != null) {
newHashPassword = StringUtils.hash(password);
}
// Change password if hash values are different
if (!existingHashPassword.equals(newHashPassword)) {
emailListener.setPassword(password);
}
}
emailListener.setHost(host);
emailListener.setPort(port);
emailListener.setSSLEnabled(ssl);
emailListener.setUser(username);
emailListener.setFolder(folder);
emailListener.setFrequency(frequency);
// Restart the email listener service
emailListener.stop();
emailListener.start();
response.sendRedirect("email-listener.jsp?success=true");
}
}
host = emailListener.getHost();
port = emailListener.getPort();
ssl = emailListener.isSSLEnabled();
username = emailListener.getUser();
password = emailListener.getPassword();
folder = emailListener.getFolder();
frequency = emailListener.getFrequency();
%>
<html>
<head>
<title>Email Listener</title>
<meta name="pageID" content="email-listener"/>
</head>
<body>
<p>
Configure the email listener service with the following form. The email listener service
connects to an SMTP server and listens for new messages. Specified users are then alerted by
IM when new messages were detected. Messages are not deleted from the mail server.
</p>
<% if (success) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/success-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Settings updated successfully.</td>
</tr>
</tbody>
</table>
</div>
<% } %>
<% if (test && testSuccess) { %>
<div class="jive-success">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/success-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Test was successful.</td>
</tr>
</tbody>
</table>
</div>
<% } else if (test && !testSuccess) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/error-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Test failed.</td>
</tr>
</tbody>
</table>
</div>
<% } %>
<% if (errors.containsKey("host")) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/error-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Please specify the SMTP server to use.</td>
</tr>
</tbody>
</table>
</div>
<% } else if (errors.containsKey("port")) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/error-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Please specify the port to use to connect to the SMTP server.</td>
</tr>
</tbody>
</table>
</div>
<% } else if (errors.containsKey("username")) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/error-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Please specify the user to use to connect to the SMTP server.</td>
</tr>
</tbody>
</table>
</div>
<% } else if (errors.containsKey("password")) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/error-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Please specify the password to use to connect to the SMTP server.</td>
</tr>
</tbody>
</table>
</div>
<% } else if (errors.containsKey("folder")) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/error-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Please specify the folder to use in the SMTP server.</td>
</tr>
</tbody>
</table>
</div>
<% } else if (errors.containsKey("frequency")) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="/images/error-16x16.gif" width="16" height="16" border="0" alt=""></td>
<td class="jive-icon-label">Please specify the frequency to check for new messages.</td>
</tr>
</tbody>
</table>
</div>
<% } %>
<p>
<!-- BEGIN SMTP settings -->
<form action="email-listener.jsp" name="f" method="post">
<div class="jive-contentBoxHeader">
Email listener settings
</div>
<div class="jive-contentBox">
<table width="80%" cellpadding="3" cellspacing="0" border="0">
<tr>
<td width="30%" nowrap>
Mail Host:
</td>
<td nowrap>
<input type="text" name="host" value="<%= (host != null)?host:"" %>" size="40" maxlength="150">
</td>
</tr>
<tr>
<td nowrap>
Mail Port:
</td>
<td nowrap>
<input type="text" name="port" value="<%= (port > 0) ? String.valueOf(port) : "" %>" size="10" maxlength="15">
</td>
</tr>
<tr>
<td nowrap>
Use SSL (Optional):
</td>
<td nowrap>
<input type="checkbox" name="ssl"<%= (ssl) ? " checked" : "" %>>
</td>
</tr>
<tr>
<td nowrap>
Server Username:
</td>
<td nowrap>
<input type="text" name="server_username" value="<%= (username != null) ? username : "" %>" size="40" maxlength="150">
</td>
</tr>
<tr>
<td nowrap>
Server Password:
</td>
<td nowrap>
<input type="password" name="server_password" value="<%= (password != null) ? StringUtils.hash(password) : "" %>" size="40" maxlength="150">
</td>
</tr>
<tr>
<td nowrap>
Folder:
</td>
<td nowrap>
<input type="text" name="folder" value="<%= (folder != null) ? folder : "" %>" size="40" maxlength="150">
</td>
</tr>
<tr>
<td nowrap>
Check Frequency:
</td>
<td nowrap>
<input type="text" name="frequency" value="<%= (frequency > 0) ? String.valueOf(frequency) : "" %>" size="10" maxlength="15">
</td>
</tr>
</table>
</div>
<input type="submit" name="save" value="Save">
<input type="submit" name="test" value="Test Settings">
</form>
<!-- END SMTP settings -->
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment