📄 pop3driver.java
字号:
/*------------------------------------------------------------------------------ Name: Pop3Driver.java Project: xmlBlaster.org Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file Comment: javac EmailData.java Pop3Driver.java ------------------------------------------------------------------------------*/package org.xmlBlaster.util.protocol.email;import javax.mail.NoSuchProviderException;import javax.mail.PasswordAuthentication;import javax.mail.Session;import javax.mail.Message;import javax.mail.Store;import javax.mail.Folder;import javax.mail.Flags;import javax.mail.Address;import javax.mail.Authenticator;import javax.mail.MessagingException;import javax.mail.URLName;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeBodyPart;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeMultipart;import javax.mail.internet.MimePart;import java.util.Collections;import java.util.HashMap;import java.util.Map;import java.util.Properties;import java.io.IOException;import java.net.URISyntaxException;import java.util.logging.Level;import java.util.logging.Logger;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.I_ResponseListener;import org.xmlBlaster.util.I_Timeout;import org.xmlBlaster.util.Timeout;import org.xmlBlaster.util.Timestamp;import org.xmlBlaster.util.XbUri;import org.xmlBlaster.util.XmlBlasterException;import org.xmlBlaster.util.context.ContextNode;import org.xmlBlaster.util.def.Constants;import org.xmlBlaster.util.def.ErrorCode;import org.xmlBlaster.util.plugin.I_Plugin;import org.xmlBlaster.util.plugin.I_PluginConfig;import org.xmlBlaster.util.plugin.PluginInfo;/** * This class is capable to poll for emails using the POP3 protocol. * * Configuration is done in <code>xmlBlasterPlugins.xml</code>: * * <pre> * <plugin id='pop3' className='org.xmlBlaster.util.protocol.email.Pop3Driver'> * <action do='LOAD' onStartupRunlevel='7' sequence='2' * onFail='resource.configuration.pluginFailed'/> * <action do='STOP' onShutdownRunlevel='7' sequence='5'/> * <attribute id='mail.pop3.url'>pop3://xmlBlaster:xmlBlaster@localhost:110/INBOX</attribute> * <attribute id='pop3PollingInterval'>500</attribute> * </plugin> * </pre> * * <p> * Switch on logging with * * <pre> * -logging/org.xmlBlaster.util.protocol.email.Pop3Driver FINE * </pre> * * and add to xmlBlasterJdk14Logging.properties: * * <pre> * handlers = org.xmlBlaster.util.log.XmlBlasterJdk14LoggingHandler.level = FINEST * </pre> * <p /> * Standalone test: * <pre> * 1. Start a command line poller for user 'xmlBlaster': * * java -Dmail.pop3.url=pop3://xmlBlaster:xmlBlaster@localhost/INBOX org.xmlBlaster.util.protocol.email.Pop3Driver -receivePolling * * 2. Send from command line an email: * * java -Dmail.smtp.url=smtp://xmlBlaster:xmlBlaster@localhost org.xmlBlaster.util.protocol.email.SmtpClient -from xmlBlaster@localhost -to xmlBlaster@localhost * </pre> * <p> * TODO: Implement reusing inbox.getMessage() for better performance * currently we reconnect for each query ( * the benefit is that we don't block the POP3 server * with a permanent connection). * </p> * @see <a * href="http://www-106.ibm.com/developerworks/java/library/j-james1.html">James * MTA</a> * @see <a href="http://java.sun.com/products/javamail/javadocs/index.html">Java * Mail API</a> * @see <a href="http://java.sun.com/developer/onlineTraining/JavaMail/contents.html">Javamail tutorial</a> * @see <a * href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/protocol.email.html">The * protocol.email requirement</a> * @author <a href="mailto:xmlBlaster@marcelruff.info">Marcel Ruff</a> */public class Pop3Driver extends Authenticatorimplements I_Plugin, I_Timeout, Pop3DriverMBean { private static Logger log = Logger.getLogger(Pop3Driver.class.getName()); private Global glob; private ContextNode contextNode; private Session session; private String pop3Url; private I_PluginConfig pluginConfig; private Timeout timeout; private Timestamp timeoutHandle; private long pollingInterval; private Properties props; private final Map listeners = new HashMap(); private boolean firstException = true; // Avoid too many logging output lines private boolean isConnected; private PasswordAuthentication authentication; protected XbUri xbUri; /** My JMX registration */ private Object mbeanHandle; // Not tested and currently switched off private Map holdbackMap = Collections.synchronizedMap(new HashMap()); private long holdbackExpireTimeout; public static final boolean CLEAR_MESSAGES = true; public static final boolean LEAVE_MESSAGES = false; public static final String POP3_FOLDER = "inbox"; public static String threadName = "POP3Driver-pollingTimer"; public static final String OBJECTENTRY_KEY = Pop3Driver.class.getName(); public static final String DISCARD = "--discard--"; /** * The Pop3Driver is a singleton in the Global scope. * Access this singleton for the given global, and if it * doesn't exist create one instance. * @param glob * @param pluginConfig * @return never null * @throws XmlBlasterException */ public static Pop3Driver getPop3Driver(Global glob, I_PluginConfig pluginConfig) throws XmlBlasterException { Global serverNode = (org.xmlBlaster.util.Global)glob.getObjectEntry(Constants.OBJECT_ENTRY_ServerScope); if (serverNode == null) serverNode = glob; Pop3Driver pop3Driver = (Pop3Driver)serverNode.getObjectEntry(OBJECTENTRY_KEY); if (pop3Driver != null) return pop3Driver; synchronized(glob.objectMapMonitor) { pop3Driver = (Pop3Driver)serverNode.getObjectEntry(OBJECTENTRY_KEY); if (pop3Driver == null) { pop3Driver = new Pop3Driver(); // Uhhh - a downcast: pop3Driver.init(glob, pluginConfig); // adds itself as ObjectEntry } return pop3Driver; } } /** * Used by Authenticator to access user name and password */ public PasswordAuthentication getPasswordAuthentication() { if (this.authentication == null) return null; if (log.isLoggable(Level.FINE)) log.fine("Entering getPasswordAuthentication: " + this.authentication.toString()); return this.authentication; } /** * This method is called by the PluginManager (enforced by I_Plugin). The * Pop3Driver singleton is registered in the Global object store. * * @see org.xmlBlaster.util.plugin.I_Plugin#init(org.xmlBlaster.util.Global,org.xmlBlaster.util.plugin.PluginInfo) */ public void init(Global glob, PluginInfo pluginInfo) throws XmlBlasterException { init(glob, (I_PluginConfig)pluginInfo); } public void init(Global glob, I_PluginConfig pluginConfig) throws XmlBlasterException { this.glob = glob; this.pluginConfig = pluginConfig; // For JMX instanceName may not contain "," this.contextNode = new ContextNode(ContextNode.SERVICE_MARKER_TAG, "Pop3Driver[" + getType() + "]", this.glob .getScopeContextNode()); this.mbeanHandle = this.glob.registerMBean(this.contextNode, this); this.pollingInterval = glob.get("pop3PollingInterval", 2000L, null, this.pluginConfig); boolean activate = glob.get("activate", true, null, this.pluginConfig); // Default is 20 sec, use 0 to switch off this.holdbackExpireTimeout = glob.get("holdbackExpireTimeout", 20000, null, this.pluginConfig); setSessionProperties(null, glob, this.pluginConfig); // Make this singleton available for others // key="org.xmlBlaster.util.protocol.email.Pop3Driver" Global serverNode = (org.xmlBlaster.util.Global)this.glob.getObjectEntry(Constants.OBJECT_ENTRY_ServerScope); if (serverNode == null) serverNode = this.glob; serverNode.addObjectEntry(OBJECTENTRY_KEY, this); this.timeout = new Timeout(threadName); if (activate) { try { activate(); } catch (Exception e) { throw (XmlBlasterException) e; } } } /** * You need to call setSessionProperties() thereafter. */ public Pop3Driver() { } /** * Access the xmlBlaster internal name of the protocol driver. * * @return The configured [type] in xmlBlaster.properties, defaults to "pop3" */ public String getProtocolId() { return (this.pluginConfig == null) ? "pop3" : this.pluginConfig.getType(); } /** * Enforced by I_Plugin * * @return The configured type in xmlBlaster.properties, defaults to "pop3" */ public String getType() { return getProtocolId(); } /** * If you are interested in an email register it here. * * @param key * <secretSessionId>:<requestId> * @param listener */ public void registerForEmail(String secretSessionId, String requestId, I_ResponseListener listener) { if (secretSessionId == null) secretSessionId = ""; if (requestId == null) requestId = ""; if (secretSessionId.length() == 0 && requestId.length() == 0) throw new IllegalArgumentException( "registerForEmail with null arguments"); String key = secretSessionId + requestId; synchronized (this.listeners) { this.listeners.put(key, listener); } if (log.isLoggable(Level.FINE)) log.fine("Added listener with key=" + key); // Try to deliver hold back messages tryToDeliverHoldbackMails(); } public Object deregisterForEmail(String secretSessionId, String requestId) { if (secretSessionId == null && requestId == null) throw new IllegalArgumentException( "deregisterForEmail with null arguments"); if (secretSessionId == null) secretSessionId = ""; if (requestId == null) requestId = ""; String key = secretSessionId + requestId; synchronized (this.listeners) { return this.listeners.remove(key); } } /** * Deregister all existing registrations for the given listener. * @param listener The listener to cleanup * @return Number of registrations cleared */ public int deregisterForEmail(I_ResponseListener listener) { if (listener == null) throw new IllegalArgumentException( "deregisterForEmail with null listener argument"); int count=0; Map.Entry[] arr = getListenerInterfaces(); for (int i = 0; i < arr.length; i++) { if (listener == arr[i].getValue()) { synchronized (this.listeners) { Object o = this.listeners.remove(arr[i].getKey()); if (o != null) count++; } } } return count; } public Map.Entry[] getListenerInterfaces() { synchronized (this.listeners) { return (Map.Entry[]) this.listeners.entrySet().toArray( new Map.Entry[this.listeners.size()]); } } public String[] getListenerKeys() { synchronized (this.listeners) { return (String[]) this.listeners.keySet().toArray( new String[this.listeners.size()]); } } public String getListeners() { String[] arr = getListenerKeys(); StringBuffer buf = new StringBuffer(); for (int i = 0; i < arr.length; i++) { buf.append(arr[i]); if (i < arr.length - 1) buf.append(", "); } return buf.toString(); } private void handleLostEmail(EmailData emailData) { // TODO: What to do with lost emails? /* try { emailData.convertToException(ErrorCode.COMMUNICATION);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -