📄 pop3handler.java
字号:
/*********************************************************************** * Copyright (c) 2000-2004 The Apache Software Foundation. * * All rights reserved. * * ------------------------------------------------------------------- * * Licensed under the Apache License, Version 2.0 (the "License"); you * * may not use this file except in compliance with the License. You * * may obtain a copy of the License at: * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * * implied. See the License for the specific language governing * * permissions and limitations under the License. * ***********************************************************************/package org.apache.james.pop3server;import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;import org.apache.avalon.excalibur.collections.ListUtils;import org.apache.avalon.excalibur.pool.Poolable;import org.apache.avalon.framework.activity.Disposable;import org.apache.avalon.framework.logger.AbstractLogEnabled;import org.apache.james.Constants;import org.apache.james.core.MailImpl;import org.apache.james.services.MailRepository;import org.apache.james.services.MailServer;import org.apache.james.services.UsersRepository;import org.apache.james.services.UsersStore;import org.apache.james.util.CRLFTerminatedReader;import org.apache.james.util.ExtraDotOutputStream;import org.apache.james.util.InternetPrintWriter;import org.apache.james.util.watchdog.BytesWrittenResetOutputStream;import org.apache.james.util.watchdog.Watchdog;import org.apache.james.util.watchdog.WatchdogTarget;import org.apache.mailet.Mail;import javax.mail.MessagingException;import java.io.*;import java.net.Socket;import java.util.*;/** * The handler class for POP3 connections. * */public class POP3Handler extends AbstractLogEnabled implements ConnectionHandler, Poolable { // POP3 Server identification string used in POP3 headers private static final String softwaretype = "JAMES POP3 Server " + Constants.SOFTWARE_VERSION; // POP3 response prefixes private final static String OK_RESPONSE = "+OK"; // OK response. Requested content // will follow private final static String ERR_RESPONSE = "-ERR"; // Error response. Requested content // will not be provided. This prefix // is followed by a more detailed // error message // Authentication states for the POP3 interaction private final static int AUTHENTICATION_READY = 0; // Waiting for user id private final static int AUTHENTICATION_USERSET = 1; // User id provided, waiting for // password private final static int TRANSACTION = 2; // A valid user id/password combination // has been provided. In this state // the client can access the mailbox // of the specified user private static final Mail DELETED = new MailImpl(); // A placeholder for emails deleted // during the course of the POP3 // transaction. This Mail instance // is used to enable fast checks as // to whether an email has been // deleted from the inbox. /** * The per-service configuration data that applies to all handlers */ private POP3HandlerConfigurationData theConfigData; /** * The mail server's copy of the user's inbox */ private MailRepository userInbox; /** * The thread executing this handler */ private Thread handlerThread; /** * The TCP/IP socket over which the POP3 interaction * is occurring */ private Socket socket; /** * The reader associated with incoming characters. */ private BufferedReader in; /** * The writer to which outgoing messages are written. */ private PrintWriter out; /** * The socket's output stream */ private OutputStream outs; /** * The current transaction state of the handler */ private int state; /** * The user id associated with the POP3 dialogue */ private String user; /** * A dynamic list representing the set of * emails in the user's inbox at any given time * during the POP3 transaction. */ private ArrayList userMailbox = new ArrayList(); private ArrayList backupUserMailbox; // A snapshot list representing the set of // emails in the user's inbox at the beginning // of the transaction /** * The watchdog being used by this handler to deal with idle timeouts. */ private Watchdog theWatchdog; /** * The watchdog target that idles out this handler. */ private WatchdogTarget theWatchdogTarget = new POP3WatchdogTarget(); /** * Set the configuration data for the handler. * * @param theData the configuration data */ void setConfigurationData(POP3HandlerConfigurationData theData) { theConfigData = theData; } /** * Set the Watchdog for use by this handler. * * @param theWatchdog the watchdog */ void setWatchdog(Watchdog theWatchdog) { this.theWatchdog = theWatchdog; } /** * Gets the Watchdog Target that should be used by Watchdogs managing * this connection. * * @return the WatchdogTarget */ WatchdogTarget getWatchdogTarget() { return theWatchdogTarget; } /** * Idle out this connection */ void idleClose() { if (getLogger() != null) { getLogger().error("POP3 Connection has idled out."); } try { if (socket != null) { socket.close(); } } catch (Exception e) { // ignored } finally { socket = null; } synchronized (this) { // Interrupt the thread to recover from internal hangs if (handlerThread != null) { handlerThread.interrupt(); handlerThread = null; } } } /** * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandler#handleConnection(Socket) */ public void handleConnection( Socket connection ) throws IOException { String remoteHost = ""; String remoteIP = ""; try { this.socket = connection; synchronized (this) { handlerThread = Thread.currentThread(); } // in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ASCII"), 512); in = new CRLFTerminatedReader(new BufferedInputStream(socket.getInputStream(), 512), "ASCII"); remoteIP = socket.getInetAddress().getHostAddress (); remoteHost = socket.getInetAddress().getHostName (); } catch (Exception e) { if (getLogger().isErrorEnabled()) { StringBuffer exceptionBuffer = new StringBuffer(256) .append("Cannot open connection from ") .append(remoteHost) .append(" (") .append(remoteIP) .append("): ") .append(e.getMessage()); getLogger().error( exceptionBuffer.toString(), e ); } } if (getLogger().isInfoEnabled()) { StringBuffer logBuffer = new StringBuffer(128) .append("Connection from ") .append(remoteHost) .append(" (") .append(remoteIP) .append(") "); getLogger().info(logBuffer.toString()); } try { outs = new BufferedOutputStream(socket.getOutputStream(), 1024); out = new InternetPrintWriter(outs, true); state = AUTHENTICATION_READY; user = "unknown"; StringBuffer responseBuffer = new StringBuffer(256) .append(OK_RESPONSE) .append(" ") .append(theConfigData.getHelloName()) .append(" POP3 server (") .append(POP3Handler.softwaretype) .append(") ready "); out.println(responseBuffer.toString()); theWatchdog.start(); while (parseCommand(readCommandLine())) { theWatchdog.reset(); } theWatchdog.stop(); if (getLogger().isInfoEnabled()) { StringBuffer logBuffer = new StringBuffer(128) .append("Connection for ") .append(user) .append(" from ") .append(remoteHost) .append(" (") .append(remoteIP) .append(") closed."); getLogger().info(logBuffer.toString()); } } catch (Exception e) { out.println(ERR_RESPONSE + " Error closing connection."); out.flush(); StringBuffer exceptionBuffer = new StringBuffer(128) .append("Exception during connection from ") .append(remoteHost) .append(" (") .append(remoteIP) .append(") : ") .append(e.getMessage()); getLogger().error(exceptionBuffer.toString(), e ); } finally { resetHandler(); } } /** * Resets the handler data to a basic state. */ private void resetHandler() { if (theWatchdog != null) { if (theWatchdog instanceof Disposable) { ((Disposable)theWatchdog).dispose(); } theWatchdog = null; } // Close and clear streams, sockets try { if (socket != null) { socket.close(); socket = null; } } catch (IOException ioe) { // Ignoring exception on close } finally { socket = null; } try { if (in != null) { in.close(); } } catch (Exception e) { // Ignored } finally { in = null; } try { if (out != null) { out.close(); } } catch (Exception e) { // Ignored } finally { out = null; } try { if (outs != null) { outs.close(); } } catch (Exception e) { // Ignored } finally { outs = null; } synchronized (this) { handlerThread = null; } // Clear user data user = null; userInbox = null; if (userMailbox != null) { userMailbox.clear(); userMailbox = null; } if (backupUserMailbox != null) { backupUserMailbox.clear(); backupUserMailbox = null; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -