You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ch...@apache.org on 2001/03/22 11:33:01 UTC

cvs commit: jakarta-james/src/org/apache/james/smtpserver SMTPHandlerNew.java

charlesb    01/03/22 02:33:01

  Added:       src/org/apache/james/pop3server POP3HandlerNew.java
               src/org/apache/james/smtpserver SMTPHandlerNew.java
  Log:
  Added new handlers proposed by Harmeet Bedi, untested
  
  Revision  Changes    Path
  1.1                  jakarta-james/src/org/apache/james/pop3server/POP3HandlerNew.java
  
  Index: POP3HandlerNew.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.pop3server;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.io.PrintWriter;
  import java.net.Socket;
  import java.util.Enumeration;
  import java.util.Iterator;
  import java.util.List;
  import java.util.StringTokenizer;
  import java.util.Vector;
  import javax.mail.MessagingException;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.ComponentManager;
  import org.apache.avalon.ComponentManagerException;
  import org.apache.avalon.Composer;
  import org.apache.avalon.Context;
  import org.apache.avalon.Contextualizable;
  import org.apache.avalon.Initializable;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.avalon.util.ListUtils;
  import org.apache.cornerstone.services.connection.ConnectionHandler;
  import org.apache.cornerstone.services.scheduler.PeriodicTimeTrigger;
  import org.apache.cornerstone.services.scheduler.Target;
  import org.apache.cornerstone.services.scheduler.TimeScheduler;
  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.InternetPrintWriter;
  import org.apache.mailet.Mail;
  
  /**
   * @author Federico Barbieri <sc...@systemy.it>
   * @version 0.9
   */
  public class POP3Handler 
      extends AbstractLoggable
      implements ConnectionHandler, Contextualizable, Composer, Configurable, Target {
  
      private String softwaretype        = "JAMES POP3 Server " + Constants.SOFTWARE_VERSION;
  
      private ComponentManager compMgr;
      private MailServer mailServer;
      private MailRepository userInbox;
      private UsersRepository users;
      private TimeScheduler scheduler;
      private int timeout;
  
      private Socket socket;
      private BufferedReader in;
      private PrintWriter out;
      private OutputStream outs;
      private String remoteHost;
      private String remoteIP;
      private String servername;
      private int state;
      private String user;
      private Vector userMailbox = new Vector();
      private Vector backupUserMailbox;
      private static final Mail DELETED = new MailImpl();
  
      private static int AUTHENTICATION_READY = 0;
      private static int AUTHENTICATION_USERSET = 1;
      private static int TRANSACTION = 2;
  
      private final static String OK_RESPONSE = "+OK";
      private final static String ERR_RESPONSE = "-ERR";
  
      public void  contextualize( final Context context ) {
          servername = (String)context.get( Constants.HELO_NAME );
      }
  
      public void configure( final Configuration configuration ) 
          throws ConfigurationException {
          timeout = configuration.getChild( "connectiontimeout" ).getValueAsInt( 120000 );
      }
  
      public void compose( final ComponentManager componentManager ) 
          throws ComponentManagerException {
          mailServer = (MailServer)componentManager.
              lookup( "org.apache.james.services.MailServer" );
          UsersStore usersStore = (UsersStore)componentManager.
              lookup( "org.apache.james.services.UsersStore" );
  	users = usersStore.getRepository("LocalUsers");
          scheduler = (TimeScheduler)componentManager.
              lookup( "org.apache.cornerstone.services.scheduler.TimeScheduler" );
      }
  
      /**
       * Handle a connection.
       * This handler is responsible for processing connections as they occur.
       *
       * @param connection the connection
       * @exception IOException if an error reading from socket occurs
       * @exception ProtocolException if an error handling connection occurs
       */
      public void handleConnection( Socket connection ) 
          throws IOException {
  
          try {
              this.socket = connection;
              in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
              outs = socket.getOutputStream();
              out = new InternetPrintWriter(outs, true);
              remoteHost = socket.getInetAddress ().getHostName ();
              remoteIP = socket.getInetAddress ().getHostAddress ();
          } catch (Exception e) {
              getLogger().error( "Cannot open connection from " + remoteHost + 
                                 " (" + remoteIP + "): " + e.getMessage(), e );
          }
  
          getLogger().info( "Connection from " + remoteHost + " (" + remoteIP + ")" );
  
          try {
              final PeriodicTimeTrigger trigger = new PeriodicTimeTrigger( timeout, -1 );
              scheduler.addTrigger( this.toString(), trigger, this );
              state = AUTHENTICATION_READY;
              user = "unknown";
              out.println( OK_RESPONSE + " " + this.servername + 
                           " POP3 server (" + this.softwaretype + ") ready " );
              while (parseCommand(in.readLine())) {
                  scheduler.resetTrigger(this.toString());
              }
              socket.close();
              scheduler.removeTrigger(this.toString());
              getLogger().info("Connection closed");
  
          } catch (Exception e) {
              out.println(ERR_RESPONSE + " Error closing connection.");
              out.flush();
              getLogger().error( "Exception during connection from " + remoteHost + 
                                 " (" + remoteIP + ") : " + e.getMessage(), e );
              try {
                  socket.close();
              } catch (IOException ioe) {
              }
          }
      }
  
      public void targetTriggered( final String triggerName ) {
          getLogger().error("Connection timeout on socket");
          try {
              out.println("Connection timeout. Closing connection");
              socket.close();
          } catch (IOException e) {
          }
      }
  
      private void stat() {
          userMailbox = new Vector();
          userMailbox.addElement(DELETED);
          for (Iterator it = userInbox.list(); it.hasNext(); ) {
              String key = (String) it.next();
              MailImpl mc = userInbox.retrieve(key);
              userMailbox.addElement(mc);
          }
          backupUserMailbox = (Vector) userMailbox.clone();
      }
  
      private boolean parseCommand(String commandRaw) {
          if (commandRaw == null) return false;
          getLogger().info("Command received: " + commandRaw);
          String command = commandRaw.trim();
          StringTokenizer commandLine = new StringTokenizer(command, " ");
          int arguments = commandLine.countTokens();
          if (arguments == 0) {
              return true;
          } else if(arguments > 0) {
              command = commandLine.nextToken();
          }
          String argument = (String) null;
          if(arguments > 1) {
              argument = commandLine.nextToken();
          }
          String argument1 = (String) null;
          if(arguments > 2) {
              argument1 = commandLine.nextToken();
          }
  
          if (command.equalsIgnoreCase("USER"))
              doUSER(command,argument,argument1);
          else if (command.equalsIgnoreCase("PASS"))
              doPASS(command,argument,argument1);
          else if (command.equalsIgnoreCase("STAT"))
              doSTAT(command,argument,argument1);
          else if (command.equalsIgnoreCase("LIST"))
              doLIST(command,argument,argument1);
          else if (command.equalsIgnoreCase("UIDL"))
              doUIDL(command,argument,argument1);
          else if (command.equalsIgnoreCase("RSET"))
              doRSET(command,argument,argument1);
          else if (command.equalsIgnoreCase("DELE"))
              doDELE(command,argument,argument1);
          else if (command.equalsIgnoreCase("NOOP"))
              doNOOP(command,argument,argument1);
          else if (command.equalsIgnoreCase("RETR"))
              doRETR(command,argument,argument1);
          else if (command.equalsIgnoreCase("TOP"))
              doTOP(command,argument,argument1);
          else if (command.equalsIgnoreCase("QUIT"))
              doQUIT(command,argument,argument1);
          else
              doUnknownCmd(command,argument,argument1);
          return (command.equalsIgnoreCase("QUIT") == false);
      }
  
      private void doUSER(String command,String argument,String argument1) {
          if (state == AUTHENTICATION_READY && argument != null) {
              user = argument;
              state = AUTHENTICATION_USERSET;
              out.println(OK_RESPONSE);
          } else {
              out.println(ERR_RESPONSE);
          }
      }
  
      private void doPASS(String command,String argument,String argument1) {
          if (state == AUTHENTICATION_USERSET && argument != null) {
              String passArg = argument;
              if (users.test(user, passArg)) {
                  state = TRANSACTION;
                  out.println(OK_RESPONSE + " Welcome " + user);
                  userInbox = mailServer.getUserInbox(user);
                  stat();
              } else {
                  state = AUTHENTICATION_READY;
                  out.println(ERR_RESPONSE + " Authentication failed.");
              }
          } else {
              out.println(ERR_RESPONSE);
          }
      }
  
      private void doSTAT(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              long size = 0;
              int count = 0;
              try {
                  for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); ) {
                      MailImpl mc = (MailImpl) e.nextElement();
                      if (mc != DELETED) {
                          size += mc.getSize();
                          count++;
                      }
                  }
                  out.println(OK_RESPONSE + " " + count + " " + size);
              } catch (MessagingException me) {
                  out.println(ERR_RESPONSE);
              }
          } else {
              out.println(ERR_RESPONSE);
          }
      }
      private void doLIST(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              if (argument == null) {
                  long size = 0;
                  int count = 0;
                  try {
                      for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); ) {
                          MailImpl mc = (MailImpl) e.nextElement();
                          if (mc != DELETED) {
                              size += mc.getSize();
                              count++;
                          }
                      }
                      out.println(OK_RESPONSE + " " + count + " " + size);
                      count = 0;
                      for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); count++) {
                          MailImpl mc = (MailImpl) e.nextElement();
                          if (mc != DELETED) {
                              out.println(count + " " + mc.getSize());
                          }
                      }
                      out.println(".");
                  } catch (MessagingException me) {
                      out.println(ERR_RESPONSE);
                  }
              } else {
                  int num = 0;
                  try {
                      num = Integer.parseInt(argument);
                      MailImpl mc = (MailImpl) userMailbox.elementAt(num);
                      if (mc != DELETED) {
                          out.println(OK_RESPONSE + " " + num + " " + mc.getSize());
                      } else {
                          out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
                      }
                  } catch (ArrayIndexOutOfBoundsException npe) {
                      out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
                  } catch (NumberFormatException nfe) {
                      out.println(ERR_RESPONSE + " " + argument + " is not a valid number");
                  } catch (MessagingException me) {
                      out.println(ERR_RESPONSE);
                  }
              }
          } else {
              out.println(ERR_RESPONSE);
          }
      }
  
      private void doUIDL(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              if (argument == null) {
                  out.println(OK_RESPONSE + " unique-id listing follows");
                  int count = 0;
                  for (Enumeration e = userMailbox.elements(); e.hasMoreElements(); count++) {
                      MailImpl mc = (MailImpl) e.nextElement();
                      if (mc != DELETED) {
                          out.println(count + " " + mc.getName());
                      }
                  }
                  out.println(".");
              } else {
                  int num = 0;
                  try {
                      num = Integer.parseInt(argument);
                      MailImpl mc = (MailImpl) userMailbox.elementAt(num);
                      if (mc != DELETED) {
                          out.println(OK_RESPONSE + " " + num + " " + mc.getName());
                      } else {
                          out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
                      }
                  } catch (ArrayIndexOutOfBoundsException npe) {
                      out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
                  } catch (NumberFormatException nfe) {
                      out.println(ERR_RESPONSE + " " + argument + " is not a valid number");
                  }
              }
          } else {
              out.println(ERR_RESPONSE);
          }
      }
      private void doRSET(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              stat();
              out.println(OK_RESPONSE);
          } else {
              out.println(ERR_RESPONSE);
          }
      }
  
      private void doDELE(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              int num = 0;
              try {
                  num = Integer.parseInt(argument);
              } catch (Exception e) {
                  out.println(ERR_RESPONSE + " Usage: DELE [mail number]");
                  return;
              }
              try {
                  MailImpl mc = (MailImpl) userMailbox.elementAt(num);
                  if (mc == DELETED) {
                      out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
                  } else {
                      userMailbox.setElementAt(DELETED, num);
                      out.println(OK_RESPONSE + " Message removed");
                  }
              } catch (ArrayIndexOutOfBoundsException iob) {
                  out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
              }
          } else {
              out.println(ERR_RESPONSE);
          }
      }
      private void doNOOP(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              out.println(OK_RESPONSE);
          } else {
              out.println(ERR_RESPONSE);
          }
      }
      private void doRETR(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              int num = 0;
              try {
                  num = Integer.parseInt(argument.trim());
              } catch (Exception e) {
                  out.println(ERR_RESPONSE + " Usage: RETR [mail number]");
                  return;
              }
              //?May be written as 
              //return parseCommand("TOP " + num + " " + Integer.MAX_VALUE);?
              try {
                  MailImpl mc = (MailImpl) userMailbox.elementAt(num);
                  if (mc != DELETED) {
                      out.println(OK_RESPONSE + " Message follows");
                      mc.writeMessageTo(outs);
                      out.println();
                      out.println(".");
                  } else {
                      out.println(ERR_RESPONSE + " Message (" + num + ") deleted.");
                  }
              } catch (IOException ioe) {
                  out.println(ERR_RESPONSE + " Error while retrieving message.");
              } catch (MessagingException me) {
                  out.println(ERR_RESPONSE + " Error while retrieving message.");
              } catch (ArrayIndexOutOfBoundsException iob) {
                  out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
              }
              // -------------------------------------------?
          } else {
              out.println(ERR_RESPONSE);
          }
      }
      private void doTOP(String command,String argument,String argument1) {
          if (state == TRANSACTION) {
              int num = 0;
              int lines = 0;
              try {
                  num = Integer.parseInt(argument);
                  lines = Integer.parseInt(argument1);
              } catch (NumberFormatException nfe) {
                  out.println(ERR_RESPONSE + " Usage: TOP [mail number] [Line number]");
                  return;
              }
              try {
                  MailImpl mc = (MailImpl) userMailbox.elementAt(num);
                  if (mc != DELETED) {
                      out.println(OK_RESPONSE + " Message follows");
                      for (Enumeration e = mc.getMessage().getAllHeaderLines(); e.hasMoreElements(); ) {
                          out.println(e.nextElement());
                      }
                      out.println("");
                      mc.writeContentTo(outs, lines);
                      out.println(".");
                  } else {
                      out.println(ERR_RESPONSE + " Message (" + num + ") already deleted.");
                  }
              } catch (IOException ioe) {
                  out.println(ERR_RESPONSE + " Error while retrieving message.");
              } catch (MessagingException me) {
                  out.println(ERR_RESPONSE + " Error while retrieving message.");
              } catch (ArrayIndexOutOfBoundsException iob) {
                  out.println(ERR_RESPONSE + " Message (" + num + ") does not exist.");
              }
          } else {
              out.println(ERR_RESPONSE);
          }
      }
      private void doQUIT(String command,String argument,String argument1) {
          if (state == AUTHENTICATION_READY ||  state == AUTHENTICATION_USERSET) {
              return;
          }
          List toBeRemoved =  ListUtils.subtract(backupUserMailbox, userMailbox);
          try {
              for (Iterator it = toBeRemoved.iterator(); it.hasNext(); ) {
                  MailImpl mc = (MailImpl) it.next();
                  userInbox.remove(mc.getName());
              }
              out.println(OK_RESPONSE + " Apache James POP3 Server signing off.");
          } catch (Exception ex) {
              out.println(ERR_RESPONSE + " Some deleted messages were not removed");
              getLogger().error("Some deleted messages were not removed: " + ex.getMessage());
          }
      }
      private void doUnknownCmd(String command,String argument,String argument1) {
          out.println(ERR_RESPONSE);
      }
  }
  
  
  
  
  1.1                  jakarta-james/src/org/apache/james/smtpserver/SMTPHandlerNew.java
  
  Index: SMTPHandlerNew.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.james.smtpserver;
  
  import java.io.*;
  import java.net.*;
  import java.util.*;
  import javax.mail.*;
  import javax.mail.internet.*;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.ComponentManager;
  import org.apache.avalon.ComponentManagerException;
  import org.apache.avalon.Composer;
  import org.apache.avalon.Context;
  import org.apache.avalon.Contextualizable;
  import org.apache.avalon.Initializable;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.cornerstone.services.connection.ConnectionHandler;
  import org.apache.cornerstone.services.scheduler.PeriodicTimeTrigger;
  import org.apache.cornerstone.services.scheduler.Target;
  import org.apache.cornerstone.services.scheduler.TimeScheduler;
  import org.apache.james.*;
  import org.apache.james.core.*;
  import org.apache.james.services.MailServer;
  import org.apache.james.util.*;
  import org.apache.mailet.*;
  
  /**
   * This handles an individual incoming message.  It handles regular SMTP
   * commands, and when it receives a message, adds it to the spool.
   * @author Serge Knystautas <se...@lokitech.com>
   * @author Federico Barbieri <sc...@systemy.it>
   * @version 0.9
   */
  public class SMTPHandler 
      extends AbstractLoggable
      implements ConnectionHandler, Contextualizable, Composer, Configurable, Target  {
  
      public final static String SERVER_NAME = "SERVER_NAME";
      public final static String SERVER_TYPE = "SERVER_TYPE";
      public final static String REMOTE_NAME = "REMOTE_NAME";
      public final static String REMOTE_IP = "REMOTE_IP";
      public final static String NAME_GIVEN = "NAME_GIVEN";
      public final static String CURRENT_HELO_MODE = "CURRENT_HELO_MODE";
      public final static String SENDER = "SENDER_ADDRESS";
      public final static String RCPT_VECTOR = "RCPT_VECTOR";
      public final static String SMTP_ID = "SMTP_ID";
      public final static char[] SMTPTerminator = {'\r','\n','.','\r','\n'};
  
      private Socket socket;
      private DataInputStream in;
      private PrintWriter out;
  
      private String remoteHost;
      private String remoteHostGiven;
      private String remoteIP;
      private String messageID;
      private String smtpID;
  
      private Configuration conf;
      private TimeScheduler scheduler;
      private MailServer mailServer;
  
      private String servername;
      private String softwaretype = "JAMES SMTP Server " + Constants.SOFTWARE_VERSION;
      private static long count;
      private Hashtable state     = new Hashtable();
      private Random random       = new Random();
      private int timeout;
  
      public void configure(Configuration conf) throws ConfigurationException {
          this.conf = conf;
          timeout = conf.getChild( "connectiontimeout" ).getValueAsInt( 120000 );
      }
  
      public void  contextualize( final Context context ) {
          servername = (String)context.get( Constants.HELO_NAME );
      }
  
      public void compose( final ComponentManager componentManager ) 
          throws ComponentManagerException {
          mailServer = (MailServer)componentManager.lookup("org.apache.james.services.MailServer");
          scheduler = (TimeScheduler)componentManager.
              lookup("org.apache.cornerstone.services.scheduler.TimeScheduler");
      }
  
      /**
       * Handle a connection.
       * This handler is responsible for processing connections as they occur.
       *
       * @param connection the connection
       * @exception IOException if an error reading from socket occurs
       * @exception ProtocolException if an error handling connection occurs
       */
      public void handleConnection( Socket connection ) 
          throws IOException {
          try {
              this.socket = connection;
              final InputStream bufferedInput = 
                  new BufferedInputStream( socket.getInputStream(), 1024 );
              in = new DataInputStream( bufferedInput );
              out = new InternetPrintWriter(socket.getOutputStream(), true);
  
              remoteHost = socket.getInetAddress ().getHostName ();
              remoteIP = socket.getInetAddress ().getHostAddress ();
              smtpID = Math.abs(random.nextInt() % 1024) + "";
              state.clear();
              state.put(SERVER_NAME, this.servername );
              state.put(SERVER_TYPE, this.softwaretype );
              state.put(REMOTE_NAME, remoteHost);
              state.put(REMOTE_IP, remoteIP);
              state.put(SMTP_ID, smtpID);
          } catch (Exception e) {
              getLogger().error("Cannot open connection from " + remoteHost + " (" + remoteIP + "): " + e.getMessage(), e );
              throw new RuntimeException("Cannot open connection from " + remoteHost + " (" + remoteIP + "): " + e.getMessage());
          }
  
          getLogger().info("Connection from " + remoteHost + " (" + remoteIP + ")");
  
          try {
              // Initially greet the connector
              // Format is:  Sat,  24 Jan 1998 13:16:09 -0500
  
              final PeriodicTimeTrigger trigger = new PeriodicTimeTrigger( timeout, -1 );
              scheduler.addTrigger( this.toString(), trigger, this );
              out.println("220 " + this.servername + " SMTP Server (" + softwaretype + ") ready " + RFC822DateFormat.toString(new Date()));
  
              while  (parseCommand(in.readLine())) {
                  scheduler.resetTrigger(this.toString());
              }
              socket.close();
              scheduler.removeTrigger(this.toString());
          } catch (SocketException se) {
              getLogger().debug("Socket to " + remoteHost + " closed remotely.", se );
          } catch ( InterruptedIOException iioe ) {
              getLogger().debug( "Socket to " + remoteHost + " timeout.", iioe );
          } catch ( IOException ioe ) {
              getLogger().debug( "Exception handling socket to " + remoteHost + ":"
                                 + ioe.getMessage(), ioe );
          } catch (Exception e) {
              getLogger().debug( "Exception opening socket: " + e.getMessage(), e );
          } finally {
              try {
                  socket.close();
              } catch (IOException e) {
                  getLogger().error("Exception closing socket: " + e.getMessage());
              }
          }
      }
  
      public void targetTriggered( final String triggerName ) {
          getLogger().error("Connection timeout on socket");
          try {
              out.println("Connection timeout. Closing connection");
              socket.close();
          } catch (IOException e) {
          }
      }
  
      private void resetState() {
          state.clear();
          state.put(SERVER_NAME, this.servername );
          state.put(SERVER_TYPE, this.softwaretype );
          state.put(REMOTE_NAME, remoteHost);
          state.put(REMOTE_IP, remoteIP);
          state.put(SMTP_ID, smtpID);
      }
  
      private boolean parseCommand(String command)
          throws Exception {
  
          if (command == null) return false;
          getLogger().info("Command received: " + command);
          StringTokenizer commandLine = new StringTokenizer(command.trim(), " :");
          int arguments = commandLine.countTokens();
          if (arguments == 0) {
              return true;
          } else if(arguments > 0) {
              command = commandLine.nextToken();
          }
          String argument = (String) null;
          if(arguments > 1) {
              argument = commandLine.nextToken();
          }
          String argument1 = (String) null;
          if(arguments > 2) {
              argument1 = commandLine.nextToken();
          }
  
          if (command.equalsIgnoreCase("HELO"))
              doHELO(command,argument,argument1);
          else if (command.equalsIgnoreCase("EHLO"))
              doEHLO(command,argument,argument1);
          else if (command.equalsIgnoreCase("MAIL"))
              doMAIL(command,argument,argument1);
          else if (command.equalsIgnoreCase("RCPT"))
              doRCPT(command,argument,argument1);
          else if (command.equalsIgnoreCase("NOOP"))
              doNOOP(command,argument,argument1);
          else if (command.equalsIgnoreCase("RSET"))
              doRSET(command,argument,argument1);
          else if (command.equalsIgnoreCase("DATA"))
              doDATA(command,argument,argument1);
          else if (command.equalsIgnoreCase("QUIT"))
              doQUIT(command,argument,argument1);
          else
              doUnknownCmd(command,argument,argument1);
          return (command.equalsIgnoreCase("QUIT") == false);
      }
  
      private void doHELO(String command,String argument,String argument1) {
          if (state.containsKey(CURRENT_HELO_MODE)) {
              out.println("250 " + state.get(SERVER_NAME) + " Duplicate HELO/EHLO");
          } else if (argument == null) {
              out.println("501 domain address required: " + command);
          } else {
              state.put(CURRENT_HELO_MODE, command);
              state.put(NAME_GIVEN, argument);
              out.println("250 " + state.get(SERVER_NAME) + " Hello " + argument + 
                          " (" + state.get(REMOTE_NAME) + 
                          " [" + state.get(REMOTE_IP) + "])");
          }
      }
      private void doEHLO(String command,String argument,String argument1) {
          doHELO(command,argument,argument1);
      }
      private void doMAIL(String command,String argument,String argument1) {
          if (state.containsKey(SENDER)) {
              out.println("503 Sender already specified");
          } else if (argument == null || !argument.equalsIgnoreCase("FROM") 
                     || argument1 == null) {
              out.println("501 Usage: MAIL FROM:<sender>");
          } else {
              String sender = argument1.trim();
              if (!sender.startsWith("<") || !sender.endsWith(">")) {
                  out.println("501 Syntax error in parameters or arguments");
                  getLogger().error("Error parsing sender address: " + sender
                                    + ": did not start and end with < >");
                  return;
              }
              MailAddress senderAddress = null;
              //Remove < and >
              sender = sender.substring(1, sender.length() - 1);
              try {
                  senderAddress = new MailAddress(sender);
              } catch (Exception pe) {
                  out.println("501 Syntax error in parameters or arguments");
                  getLogger().error("Error parsing sender address: " + sender
                                    + ": " + pe.getMessage());
                  return;
              }
              state.put(SENDER, senderAddress);
              out.println("250 Sender <" + sender + "> OK");
          }
      }
  
      private void doRCPT(String command,String argument,String argument1) {
          if (!state.containsKey(SENDER)) {
              out.println("503 Need MAIL before RCPT");
          } else if (argument == null || !argument.equalsIgnoreCase("TO") || argument1 == null) {
              out.println("501 Usage: RCPT TO:<recipient>");
          } else {
              Collection rcptColl = (Collection) state.get(RCPT_VECTOR);
              if (rcptColl == null) {
                  rcptColl = new Vector();
              }
              String recipient = argument1.trim();
              if (!recipient.startsWith("<") || !recipient.endsWith(">")) {
                  out.println("Syntax error in parameters or arguments");
                  getLogger().error("Error parsing recipient address: "
                                    + recipient
                                    + ": did not start and end with < >");
                  return;
              }
              MailAddress recipientAddress = null;
              //Remove < and >
              recipient = recipient.substring(1, recipient.length() - 1);
              try {
                  recipientAddress = new MailAddress(recipient);
              } catch (Exception pe) {
                  out.println("501 Syntax error in parameters or arguments");
                  getLogger().error("Error parsing recipient address: "
                                    + recipient + ": " + pe.getMessage());
                  return;
              }
              rcptColl.add(recipientAddress);
              state.put(RCPT_VECTOR, rcptColl);
              out.println("250 Recipient <" + recipient + "> OK");
          }
      }
      private void doNOOP(String command,String argument,String argument1) {
          out.println("250 OK");
      }
      private void doRSET(String command,String argument,String argument1) {
          resetState();
          out.println("250 OK");
      }
  
      private void doDATA(String command,String argument,String argument1) {
          if (!state.containsKey(SENDER)) {
              out.println("503 No sender specified");
          } else if (!state.containsKey(RCPT_VECTOR)) {
              out.println("503 No recipients specified");
          } else {
              out.println("354 Ok Send data ending with <CRLF>.<CRLF>");
              try {
                  // parse headers
                  InputStream msgIn = new CharTerminatedInputStream(in, SMTPTerminator);
                  MailHeaders headers = new MailHeaders(msgIn);
                  // if headers do not contains minimum REQUIRED headers fields add them
                  if (!headers.isSet("Date")) {
                      headers.setHeader("Date", RFC822DateFormat.toString (new Date ()));
                  }
                  /*
                    We no longer add To as this in practice is not set (from what I've seen)
                    if (!headers.isSet("To")) {
                    headers.setHeader("To", );
                    }
                  */
                  if (!headers.isSet("From")) {
                      headers.setHeader("From", state.get(SENDER).toString());
                  }
                  
                  String received = "from " + state.get(REMOTE_NAME) + " ([" + state.get(REMOTE_IP)
                      + "])\r\n          by " + this.servername + " ("
                      + softwaretype + ") with SMTP ID " + state.get(SMTP_ID);
                  if (((Collection)state.get(RCPT_VECTOR)).size () == 1) {
                      //Only indicate a recipient if they're the only recipient
                      //(prevents email address harvesting and large headers in bulk email)
                      received += "\r\n          for <"
                          + ((Vector)state.get(RCPT_VECTOR)).elementAt(0).toString() + ">";
                  }
                  received += ";\r\n          " + RFC822DateFormat.toString (new Date ());
                  headers.addHeader ("Received", received);
                  
                  // headers.setReceivedStamp("Unknown", (String) serverNames.elementAt(0));
                  ByteArrayInputStream headersIn = new ByteArrayInputStream(headers.toByteArray());
                  MailImpl mail = new MailImpl(mailServer.getId(), (MailAddress)state.get(SENDER),
                                               (Vector)state.get(RCPT_VECTOR), 
                                               new SequenceInputStream(headersIn, msgIn));
                  mail.setRemoteHost((String)state.get(REMOTE_NAME));
                  mail.setRemoteAddr((String)state.get(REMOTE_IP));
                  mailServer.sendMail(mail);
              } catch (MessagingException me) {
                  out.println("451 Error processing message: " + me.getMessage());
                  getLogger().error("Error processing message: "
                                    + me.getMessage());
                  return;
              }
              getLogger().info("Mail sent to Mail Server");
              resetState();
              out.println("250 Message received");
          }
      }
      private void doQUIT(String command,String argument,String argument1) {
          out.println("221 " + state.get(SERVER_NAME) + " Service closing transmission channel");
      }
  
      private void doUnknownCmd(String command,String argument,String argument1) {
          out.println("500 " + state.get(SERVER_NAME) + " Syntax error, command unrecognized: " + 
                      command);
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org