📄 pop3driver.java
字号:
SmtpClient.getSmtpClient(this.glob, this.pluginConfig).sendEmail(emailData); } catch (XmlBlasterException e) { log.severe("Lost email: " + e.getMessage() + ": " + emailData.toXml(true)); } */ } /** * Notify a listener about a new email. The registration remains The listener * is searched as a "sessionId-requestId" and as a general "sessionId" * * @param emailData * @param calledFromHoldbackMap is true if we try a redelivery * @return The listener notified or null if none was found */ private String notify(EmailData emailData, boolean calledFromHoldbackMap) { if (emailData == null) return null; // TODO: Does not cleanup listeners!! // so we deliver them to the registrar and they should decide //if (emailData.isExpired()) // return DISCARD; String key = emailData.getSessionId() + emailData.getRequestId(); I_ResponseListener listenerSession = null; I_ResponseListener listenerRequest = null; I_ResponseListener listenerClusterNodeId = null; synchronized (this.listeners) { listenerRequest = (I_ResponseListener) this.listeners.get(key); if (listenerRequest == null) { listenerSession = (I_ResponseListener) this.listeners .get(emailData.getSessionId()); if (listenerSession == null) { listenerClusterNodeId = (I_ResponseListener) this.listeners .get(this.glob.getId()); } } } // A request/reply handler is interested in specific messages only if (listenerRequest != null) { if (log.isLoggable(Level.FINER)) log.finer("Request specific listener found for key=" + key + ", email is " + emailData.toString()); listenerRequest.incomingMessage(emailData.getRequestId(), emailData); return key; } // A session is interested in all messages if (listenerSession != null) { if (log.isLoggable(Level.FINER)) log.finer("SessRequest specific listener found for key=" + emailData.getSessionId() + ", email is " + emailData.toString()); listenerSession.incomingMessage(emailData.getRequestId(), emailData); return emailData.getSessionId(); } // A cluster node is interested in all messages (EmailDriver.java) if (listenerClusterNodeId != null) { if (log.isLoggable(Level.FINER)) log.finer("Node specific listener found for key=" + this.glob.getId() + ", email is " + emailData.toString()); listenerClusterNodeId.incomingMessage(emailData.getRequestId(), emailData); return emailData.getSessionId(); } if (calledFromHoldbackMap) { if (log.isLoggable(Level.FINER)) log.finer("No registrar for holdback mail found, we try again later: " + emailData.toString()); return null; // try again later } if (emailData.isExpired()) return DISCARD; if (this.holdbackExpireTimeout > 0) { Timestamp timestamp = new Timestamp(); this.holdbackMap.put(new Long(timestamp.getTimestamp()), emailData); log.warning("None of our registered listeners '" + getListeners() + "' matches for key=" + key + ", email '" + emailData.extractMessageId(EmailData.METHODNAME_TAG) + "' is holdback in RAM, we try later again"); } else { log.warning("None of our registered listeners '" + getListeners() + "' matches for key=" + key + ", this email is discarded: " + emailData.toString()); handleLostEmail(emailData); } return null; } /** * The command line key prefix * * @return The configured type in xmlBlasterPlugins.xml, defaults to * "plugin/pop3" */ public String getEnvPrefix() { return "plugin/" + getType().toLowerCase(); // return (addressServer != null) ? addressServer.getEnvPrefix() : // "plugin/"+getType().toLowerCase(); } /** Enforced by I_Plugin */ public String getVersion() { return (this.pluginConfig == null) ? "1.0" : this.pluginConfig.getVersion(); } /** * Set session properties and create a session. * <p> * Example settings: * </p> * * <pre> * Properties props = System.getProperties(); * props.put("mail.pop3.url", "pop3://joe:secret@localhost/INBOX"); * props.put("mail.debug", "false"); * </pre> * * <p> * Usage is "pop3://user:password@host:port/INBOX". Only 'INBOX' is supported * for pop3. If a property is not found <tt>System.getProperty()</tt> is * consulted. * </p> * * @see <a * href="http://java.sun.com/products/javamail/javadocs/com/sun/mail/smtp/package-summary.html">SMTP * API</a> * @see <a * href="http://java.sun.com/products/javamail/javadocs/com/sun/mail/pop3/package-summary.html">POP3 * API</a> */ public synchronized void setSessionProperties(Properties properties, Global glob, I_PluginConfig pluginConfig) throws XmlBlasterException { this.props = properties; if (this.props == null) this.props = new Properties(); if (this.props.getProperty("mail.debug") == null) this.props.put("mail.debug", glob.get("mail.debug", System .getProperty("mail.debug", "false"), null, pluginConfig)); // "pop3://user:password@host:port/INBOX" this.pop3Url = glob.get("mail.pop3.url", System.getProperty("mail.pop3.url", "pop3://" + System.getProperty("user.name") + ":" + System.getProperty("user.name") + "@127.0.0.1:110/INBOX " //"pop3://xmlBlaster:xmlBlaster@localhost:110/INBOX ", ), null, pluginConfig); try { this.xbUri = new XbUri(this.pop3Url); if (this.xbUri.getPassword() != null) { this.props.setProperty("mail.smtp.auth", "true"); //Indicate that authentication is required at pop3 server this.authentication = new PasswordAuthentication(this.xbUri.getUser(), this.xbUri.getPassword()); } } catch (URISyntaxException e) { throw new XmlBlasterException(glob, ErrorCode.RESOURCE_CONFIGURATION_ADDRESS, "Pop3Driver", "Your URI '" + this.pop3Url + "' is illegal", e); } // Pass "this" for SMTP authentication with Authenticator this.session = Session.getInstance(this.props, this); // Produces a success logging output Store store = null; try { store = getStore(); } catch (XmlBlasterException e) { log.warning(e.getMessage() + " We poll every " + this.pollingInterval + " milliseconds again."); } finally { try { if (store != null) store.close(); } catch (MessagingException e) { e.printStackTrace(); } } } private Long[] getHoldbackTimestamps() { synchronized (this.holdbackMap) { return (Long[]) this.holdbackMap.keySet().toArray( new Long[this.holdbackMap.size()]); } } /** * Try to deliver hold back messages to local registrars. * This happens if on startup we access POP3 messages but nobody has * registered yet * <br /> * Switch this feature on by setting holdbackExpireTimeout to a value > 0. * After the given milli seconds the message is discarded. * <br /> * For example a client may on startup receive update() mails before he * has initialized the CallbackEmailDriver. Those messages are kept in RAM * if the client stops immediately the mails are lost but redelivered by the server * after the responseTimeout. */ private void tryToDeliverHoldbackMails() { if (this.holdbackExpireTimeout > 0 && getNumberOfHoldbackEmails() > 0) { Long[] keys = getHoldbackTimestamps(); Timestamp now = new Timestamp(); for (int i = 0; i < keys.length; i++) { long tt = new Timestamp(keys[i].longValue()).getMillis(); EmailData emailData = (EmailData)this.holdbackMap.get(keys[i]); if ((tt + this.holdbackExpireTimeout) < now.getMillis()) { log.warning("Can't deliver holdback email, we discard it now: " + emailData.toString()); this.holdbackMap.remove(keys[i]); handleLostEmail(emailData); } else { String listenerKey = notify(emailData, true); if (listenerKey != null) { if (!DISCARD.equals(listenerKey)) { if (log.isLoggable(Level.FINE)) log.fine("Holdback email is now delivered: " + emailData.toString()); this.holdbackMap.remove(keys[i]); } } } } } } /** * Polling for response messages. */ public void timeout(Object userData) { //if (log.isLoggable(Level.FINER)) // log.finer("Timeout: Reading POP3 messages from " + getPop3Url()); // TODO: Remove here again, but for now we leave it to have an expiry check // we need to add a specific holdbackExpireTimeout Timer tryToDeliverHoldbackMails(); try { EmailData[] msgs = readInbox(Pop3Driver.CLEAR_MESSAGES); this.firstException = true; boolean responseArrived = false; for (int i = 0; i < msgs.length; i++) { EmailData emailData = msgs[i]; if (log.isLoggable(Level.FINER)) log.finer("Got from POP3 email" + emailData.toXml(true)); String notifiedListener = notify(emailData, false); if (notifiedListener == null) { if (log.isLoggable(Level.FINE)) log.fine("None of the registered listeners (" + getListeners() + ") wants this email: " + emailData.toXml(true)); } } if (!responseArrived) { //if (log.isLoggable(Level.FINER)) // log.finer("No mails via POP3 found"); } } catch (XmlBlasterException e) { if (this.firstException && !e.isErrorCode(ErrorCode.RESOURCE_CONFIGURATION_CONNECT)) log.severe("[" + this.pop3Url + "] POP3 polling failed: " + e.getMessage()); else { // RESOURCE_CONFIGURATION_CONNECT is logged already if (log.isLoggable(Level.FINE)) log.fine("[" + this.pop3Url + "] POP3 polling failed: " + e.getMessage()); } this.firstException = false; } catch (Throwable e) { log.severe("[" + this.pop3Url + "] POP3 polling failed: " + e.toString()); } try { this.timeoutHandle = this.timeout.addOrRefreshTimeoutListener(this, this.pollingInterval, userData, this.timeoutHandle); } catch (XmlBlasterException e) { log.severe("Waiting on mail response failed: " + e.getMessage()); } } /** * Access the mailing session. */ public Session getSession() { if (this.session == null) { // after a previous shutdown() synchronized (this) { if (this.session == null) { // In such a case we should better throw an exception (the session should be initialized?!) Thread.dumpStack(); if (this.xbUri != null && this.xbUri.getPassword() != null) { this.props.setProperty("mail.smtp.auth", "true"); //Indicate that authentication is required at pop3 server this.authentication = new PasswordAuthentication(this.xbUri.getUser(), this.xbUri.getPassword()); } this.session = Session.getInstance(this.props, this); } } } return this.session; } public Message getMessage() { return new MimeMessage(getSession()); } /** * Returns for example "demo@localhost" which is extracted from * pop3Url="pop3://demo:secret@localhost:110/INBOX" * * @return */ public String getMyEmailAddress() { URLName urln = new URLName(this.pop3Url); return urln.getUsername() + "@" + urln.getHost(); } /** * Returns for example "pop3://demo@localhost:110/INBOX" which is extracted * from pop3Url="pop3://demo:secret@localhost:110/INBOX" * * @return */ public String getUrlWithoutPassword() { URLName urln = new URLName(this.pop3Url); return urln.getProtocol() + "://" + urln.getUsername() + "@" + urln.getHost() + ((urln.getPort() > 0) ? (":" + urln.getPort()) : "") + "/" + urln.getFile(); } /** * Connect to POP3 store. * NOTE: You need to call store.close() after usage to cleanup resources. * @return never null * @throws XmlBlasterException */ private Store getStore() throws XmlBlasterException { Store store = null; //Fails if username contains '@', should be ok for %40? //URLName urln = new URLName(this.pop3Url); // This constructor automatically transforms a '@' in a username to '%40' URLName urln = new URLName(this.xbUri.getScheme(), this.xbUri.getHost(), this.xbUri.getPort(), this.xbUri.getPath(), this.xbUri.getUser(), this.xbUri.getPassword()); try { store = getSession().getStore(urln); } catch (NoSuchProviderException e) { throw new XmlBlasterException(this.glob, ErrorCode.RESOURCE_CONFIGURATION, Pop3Driver.class.getName(), "No POP3 provider for url '" + getUrlWithoutPassword()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -