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 no...@apache.org on 2010/02/01 10:29:58 UTC

svn commit: r905220 [2/4] - in /james/protocols/trunk: ./ smtp/ smtp/src/ smtp/src/main/ smtp/src/main/java/ smtp/src/main/java/org/ smtp/src/main/java/org/apache/ smtp/src/main/java/org/apache/james/ smtp/src/main/java/org/apache/james/dsn/ smtp/src/m...

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/AcceptRecipientIfRelayingIsAllowed.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/AcceptRecipientIfRelayingIsAllowed.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/AcceptRecipientIfRelayingIsAllowed.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/AcceptRecipientIfRelayingIsAllowed.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,44 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.james.smtpserver.protocol.hook.HookResult;
+import org.apache.james.smtpserver.protocol.hook.HookReturnCode;
+import org.apache.james.smtpserver.protocol.hook.RcptHook;
+import org.apache.mailet.MailAddress;
+
+/**
+ * This hook will stop the hook chain if relaying is allowed 
+ */
+public class AcceptRecipientIfRelayingIsAllowed implements RcptHook {
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.hook.RcptHook#doRcpt(org.apache.james.smtpserver.protocol.SMTPSession,
+     *      org.apache.mailet.MailAddress, org.apache.mailet.MailAddress)
+     */
+    public HookResult doRcpt(SMTPSession session, MailAddress sender,
+            MailAddress rcpt) {
+        if (session.isRelayingAllowed()) {
+            return new HookResult(HookReturnCode.OK);
+        }
+        return new HookResult(HookReturnCode.DECLINED);
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,173 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.protocols.api.ExtensibleHandler;
+import org.apache.james.protocols.api.LineHandler;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.WiringException;
+import org.apache.james.smtpserver.protocol.MailEnvelopeImpl;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.mailet.MailAddress;
+
+
+/**
+  * handles DATA command
+ */
+public class DataCmdHandler implements CommandHandler<SMTPSession>, ExtensibleHandler {
+
+    public final class DataConsumerLineHandler implements LineHandler<SMTPSession> {
+
+        /*
+         * (non-Javadoc)
+         * @see org.apache.james.api.protocol.LineHandler#onLine(org.apache.james.api.protocol.ProtocolSession, byte[])
+         */
+        public void onLine(SMTPSession session, byte[] line) {
+            
+            // Discard everything until the end of DATA session
+            if (line.length == 3 && line[0] == 46) {
+                session.popLineHandler();
+            }
+        }
+    }
+
+    public final class DataLineFilterWrapper implements LineHandler<SMTPSession> {
+
+        private DataLineFilter filter;
+        private LineHandler<SMTPSession> next;
+        
+        public DataLineFilterWrapper(DataLineFilter filter, LineHandler<SMTPSession> next) {
+            this.filter = filter;
+            this.next = next;
+        }
+        
+        /*
+         * (non-Javadoc)
+         * @see org.apache.james.api.protocol.LineHandler#onLine(org.apache.james.api.protocol.ProtocolSession, byte[])
+         */
+        public void onLine(SMTPSession session, byte[] line) {
+            filter.onLine(session, line, next);
+        }
+                
+    }
+   
+    public final static String MAILENV = "MAILENV";
+    
+    private LineHandler<SMTPSession> lineHandler;
+    
+    /**
+     * process DATA command
+     *
+     */
+    public Response onCommand(SMTPSession session, Request request) {
+        String parameters = request.getArgument();
+        SMTPResponse response = doDATAFilter(session,parameters);
+        
+        if (response == null) {
+            return doDATA(session, parameters);
+        } else {
+            return response;
+        }
+    }
+
+
+    /**
+     * Handler method called upon receipt of a DATA command.
+     * Reads in message data, creates header, and delivers to
+     * mail server service for delivery.
+     *
+     * @param session SMTP session object
+     * @param argument the argument passed in with the command by the SMTP client
+     */
+    @SuppressWarnings("unchecked")
+    protected SMTPResponse doDATA(SMTPSession session, String argument) {
+        MailEnvelopeImpl env = new MailEnvelopeImpl();
+        env.setRecipients(new ArrayList<MailAddress>((Collection)session.getState().get(SMTPSession.RCPT_LIST)));
+        env.setSender((MailAddress) session.getState().get(SMTPSession.SENDER));
+        session.getState().put(MAILENV, env);
+        session.pushLineHandler(lineHandler);
+        
+        return new SMTPResponse(SMTPRetCode.DATA_READY, "Ok Send data ending with <CRLF>.<CRLF>");
+    }
+    
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add("DATA");
+        
+        return implCommands;
+    }
+
+
+    /**
+     * @see org.apache.james.api.protocol.ExtensibleHandler#getMarkerInterfaces()
+     */
+    @SuppressWarnings("unchecked")
+    public List getMarkerInterfaces() {
+        List classes = new LinkedList();
+        classes.add(DataLineFilter.class);
+        return classes;
+    }
+
+
+    /**
+     * @see org.apache.james.api.protocol.ExtensibleHandler#wireExtensions(java.lang.Class, java.util.List)
+     */
+    @SuppressWarnings("unchecked")
+    public void wireExtensions(Class interfaceName, List extension) throws WiringException {
+        if (DataLineFilter.class.equals(interfaceName)) {
+
+            LineHandler<SMTPSession> lineHandler = new DataConsumerLineHandler();
+            for (int i = extension.size() - 1; i >= 0; i--) {
+                lineHandler = new DataLineFilterWrapper((DataLineFilter) extension.get(i), lineHandler);
+            }
+
+            this.lineHandler = lineHandler;
+        }
+    }
+
+    protected SMTPResponse doDATAFilter(SMTPSession session, String argument) {
+        if ((argument != null) && (argument.length() > 0)) {
+            return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_COMMAND_UNRECOGNIZED, DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Unexpected argument provided with DATA command");
+        }
+        if (!session.getState().containsKey(SMTPSession.SENDER)) {
+            return new SMTPResponse(SMTPRetCode.BAD_SEQUENCE, DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" No sender specified");
+        } else if (!session.getState().containsKey(SMTPSession.RCPT_LIST)) {
+            return new SMTPResponse(SMTPRetCode.BAD_SEQUENCE, DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" No recipients specified");
+        }
+        return null;
+    }
+    
+    protected LineHandler<SMTPSession> getLineHandler() {
+    	return lineHandler;
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineFilter.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineFilter.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineFilter.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineFilter.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,41 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import org.apache.james.protocols.api.LineHandler;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+
+/**
+ * DataLineFilter are used to check the Data stream while the message is
+ * being received.
+ */
+public interface DataLineFilter {
+    
+    /**
+     * Handle line processing
+     * 
+     * @param session
+     * @param line
+     * @param next
+     */
+    void onLine(SMTPSession session, byte[] line, LineHandler<SMTPSession> next);
+}
\ No newline at end of file

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineMessageHookHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineMessageHookHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineMessageHookHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/DataLineMessageHookHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,152 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.ExtensibleHandler;
+import org.apache.james.protocols.api.LineHandler;
+import org.apache.james.protocols.api.WiringException;
+import org.apache.james.smtpserver.protocol.MailEnvelopeImpl;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.james.smtpserver.protocol.hook.HookResult;
+import org.apache.james.smtpserver.protocol.hook.HookResultHook;
+import org.apache.james.smtpserver.protocol.hook.MessageHook;
+import org.apache.mailet.Mail;
+
+public final class DataLineMessageHookHandler implements DataLineFilter, ExtensibleHandler {
+
+    
+    private List messageHandlers;
+    
+    private List rHooks;
+    
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.smtpserver.protocol.core.DataLineFilter#onLine(org.apache.james.smtpserver.protocol.SMTPSession, byte[], org.apache.james.api.protocol.LineHandler)
+     */
+    public void onLine(SMTPSession session, byte[] line, LineHandler<SMTPSession> next) {
+        MailEnvelopeImpl env = (MailEnvelopeImpl) session.getState().get(DataCmdHandler.MAILENV);
+        OutputStream out = env.getMessageOutputStream();
+        try {
+            // 46 is "."
+            // Stream terminated
+            if (line.length == 3 && line[0] == 46) {
+                out.flush();
+                out.close();
+                
+                processExtensions(session, env);
+                session.popLineHandler();
+
+            // DotStuffing.
+            } else if (line[0] == 46 && line[1] == 46) {
+                out.write(line,1,line.length-1);
+            // Standard write
+            } else {
+                // TODO: maybe we should handle the Header/Body recognition here
+                // and if needed let a filter to cache the headers to apply some
+                // transformation before writing them to output.
+                out.write(line);
+            }
+            out.flush();
+        } catch (IOException e) {
+            SMTPResponse response;
+            response = new SMTPResponse(SMTPRetCode.LOCAL_ERROR,DSNStatus.getStatus(DSNStatus.TRANSIENT,
+                            DSNStatus.UNDEFINED_STATUS) + " Error processing message: " + e.getMessage());
+            
+            session.getLogger().error(
+                    "Unknown error occurred while processing DATA.", e);
+            session.writeResponse(response);
+            return;
+        }
+    }
+
+
+    /**
+     * @param session
+     */
+    private void processExtensions(SMTPSession session, MailEnvelopeImpl mail) {
+        if(mail != null && mail instanceof Mail && messageHandlers != null) {
+            try {
+                int count = messageHandlers.size();
+                for(int i =0; i < count; i++) {
+                    Object rawHandler =  messageHandlers.get(i);
+                    session.getLogger().debug("executing message handler " + rawHandler);
+                    HookResult hRes = ((MessageHook)rawHandler).onMessage(session, mail);
+                    
+                    if (rHooks != null) {
+                        for (int i2 = 0; i2 < rHooks.size(); i2++) {
+                            Object rHook = rHooks.get(i2);
+                            session.getLogger().debug("executing hook " + rHook);
+                            hRes = ((HookResultHook) rHook).onHookResult(session, hRes, rawHandler);
+                        }
+                    }
+                    
+                    SMTPResponse response = AbstractHookableCmdHandler.calcDefaultSMTPResponse(hRes);
+                    
+                    //if the response is received, stop processing of command handlers
+                    if(response != null) {
+                        session.writeResponse(response);
+                        break;
+                    }
+                }
+            } finally {
+               
+                //do the clean up
+                session.resetState();
+            }
+        }
+    }
+    
+    /**
+     * @see org.apache.james.api.protocol.ExtensibleHandler#wireExtensions(java.lang.Class, java.util.List)
+     */
+    @SuppressWarnings("unchecked")
+    public void wireExtensions(Class interfaceName, List extension) throws WiringException {
+        if (MessageHook.class.equals(interfaceName)) {
+            this.messageHandlers = extension;
+            if (messageHandlers.size() == 0) {
+                throw new WiringException("No messageHandler configured");
+            }
+        } else if (HookResultHook.class.equals(interfaceName)) {
+            this.rHooks = extension;
+        }
+    }
+
+    /**
+     * @see org.apache.james.api.protocol.ExtensibleHandler#getMarkerInterfaces()
+     */
+    public List<Class<?>> getMarkerInterfaces() {
+        List<Class<?>> classes = new LinkedList<Class<?>>();
+        classes.add(MessageHook.class);
+        classes.add(HookResultHook.class);
+        return classes;
+    }
+
+}
\ No newline at end of file

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ExpnCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ExpnCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ExpnCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ExpnCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,65 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+
+/**
+  * Handles EXPN command
+  */
+public class ExpnCmdHandler implements CommandHandler<SMTPSession> {
+
+    /**
+     * The name of the command handled by the command handler
+     */
+    private final static String COMMAND_NAME = "EXPN";
+    
+    /**
+     * Handler method called upon receipt of a EXPN command.
+     * This method informs the client that the command is
+     * not implemented.
+     *
+     */
+    public Response onCommand(SMTPSession session, Request request) {
+        return new SMTPResponse(SMTPRetCode.UNIMPLEMENTED_COMMAND, DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SYSTEM_NOT_CAPABLE)+" EXPN is not supported");
+    }
+    
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add(COMMAND_NAME);
+        
+        return implCommands;
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HeloCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HeloCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HeloCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HeloCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,104 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.james.smtpserver.protocol.hook.HeloHook;
+import org.apache.james.smtpserver.protocol.hook.HookResult;
+
+/**
+ * Handles HELO command
+ */
+public class HeloCmdHandler extends AbstractHookableCmdHandler<HeloHook> {
+
+    /**
+     * The name of the command handled by the command handler
+     */
+    private final static String COMMAND_NAME = "HELO";
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add(COMMAND_NAME);
+
+        return implCommands;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#doCoreCmd(org.apache.james.smtpserver.protocol.SMTPSession,
+     *      java.lang.String, java.lang.String)
+     */
+    protected SMTPResponse doCoreCmd(SMTPSession session, String command,
+            String parameters) {
+        session.getConnectionState().put(SMTPSession.CURRENT_HELO_MODE,
+                COMMAND_NAME);
+        StringBuilder response = new StringBuilder();
+        response.append(session.getHelloName()).append(
+                " Hello ").append(parameters).append(" (").append(
+                session.getRemoteHost()).append(" [").append(
+                session.getRemoteIPAddress()).append("])");
+        return new SMTPResponse(SMTPRetCode.MAIL_OK, response);
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#doFilterChecks(org.apache.james.smtpserver.protocol.SMTPSession,
+     *      java.lang.String, java.lang.String)
+     */
+    protected SMTPResponse doFilterChecks(SMTPSession session, String command,
+            String parameters) {
+        session.resetState();
+
+        if (parameters == null) {
+            return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,
+                    DSNStatus.getStatus(DSNStatus.PERMANENT,
+                            DSNStatus.DELIVERY_INVALID_ARG)
+                            + " Domain address required: " + COMMAND_NAME);
+        } else {
+            // store provided name
+            session.getState().put(SMTPSession.CURRENT_HELO_NAME, parameters);
+            return null;
+        }
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#getHookInterface()
+     */
+    protected Class<HeloHook> getHookInterface() {
+        return HeloHook.class;
+    }
+
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#callHook(java.lang.Object, org.apache.james.smtpserver.protocol.SMTPSession, java.lang.String)
+     */
+    protected HookResult callHook(HeloHook rawHook, SMTPSession session, String parameters) {
+        return rawHook.doHelo(session, parameters);
+    }
+
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HelpCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HelpCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HelpCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/HelpCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,62 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+
+/**
+  * Handles HELP command
+  */
+public class HelpCmdHandler implements CommandHandler<SMTPSession> {
+    /**
+     * The name of the command handled by the command handler
+     */
+    private final static String COMMAND_NAME = "HELP";
+
+
+    /**
+     * handles HELP command
+     *
+    **/
+    public Response onCommand(SMTPSession session, Request request){
+        return new SMTPResponse(SMTPRetCode.UNIMPLEMENTED_COMMAND, DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SYSTEM_NOT_CAPABLE)+" " + COMMAND_NAME + " is not supported");
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add(COMMAND_NAME);
+        
+        return implCommands;
+    }
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/MailCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/MailCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/MailCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/MailCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,306 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.protocols.api.RetCodeResponse;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.james.smtpserver.protocol.hook.HookResult;
+import org.apache.james.smtpserver.protocol.hook.MailHook;
+import org.apache.james.smtpserver.protocol.hook.MailParametersHook;
+import org.apache.mailet.MailAddress;
+
+/**
+ * Handles MAIL command
+ */
+public class MailCmdHandler extends AbstractHookableCmdHandler<MailHook> {
+
+    /**
+     * A map of parameterHooks
+     */
+    private Map<String, MailParametersHook> paramHooks;
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#onCommand(org.apache.james.smtpserver.protocol.SMTPSession, org.apache.james.api.protocol.Request)
+     */
+	public Response onCommand(SMTPSession session, Request request) {
+	    Response response =  super.onCommand(session, request);
+		// Check if the response was not ok 
+		if (((RetCodeResponse)response).getRetCode().equals(SMTPRetCode.MAIL_OK) == false) {
+			// cleanup the session
+			session.getState().remove(SMTPSession.SENDER);
+		}
+		
+		return response;
+	}
+
+	/**
+     * Handler method called upon receipt of a MAIL command. Sets up handler to
+     * deliver mail as the stated sender.
+     * 
+     * @param session
+     *            SMTP session object
+     * @param argument
+     *            the argument passed in with the command by the SMTP client
+     */
+    private SMTPResponse doMAIL(SMTPSession session, String argument) {
+        StringBuilder responseBuffer = new StringBuilder();
+        MailAddress sender = (MailAddress) session.getState().get(
+                SMTPSession.SENDER);
+        responseBuffer.append(
+                DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.ADDRESS_OTHER))
+                .append(" Sender <");
+        if (sender != null) {
+            responseBuffer.append(sender);
+        }
+        responseBuffer.append("> OK");
+        return new SMTPResponse(SMTPRetCode.MAIL_OK, responseBuffer);
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add("MAIL");
+
+        return implCommands;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#doCoreCmd(org.apache.james.smtpserver.protocol.SMTPSession,
+     *      java.lang.String, java.lang.String)
+     */
+    protected SMTPResponse doCoreCmd(SMTPSession session, String command,
+            String parameters) {
+        return doMAIL(session, parameters);
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#doFilterChecks(org.apache.james.smtpserver.protocol.SMTPSession,
+     *      java.lang.String, java.lang.String)
+     */
+    protected SMTPResponse doFilterChecks(SMTPSession session, String command,
+            String parameters) {
+        return doMAILFilter(session, parameters);
+    }
+
+    /**
+     * @param session
+     *            SMTP session object
+     * @param argument
+     *            the argument passed in with the command by the SMTP client
+     */
+    private SMTPResponse doMAILFilter(SMTPSession session, String argument) {
+        String sender = null;
+
+        if ((argument != null) && (argument.indexOf(":") > 0)) {
+            int colonIndex = argument.indexOf(":");
+            sender = argument.substring(colonIndex + 1);
+            argument = argument.substring(0, colonIndex);
+        }
+        if (session.getState().containsKey(SMTPSession.SENDER)) {
+            return new SMTPResponse(SMTPRetCode.BAD_SEQUENCE, DSNStatus
+                    .getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_OTHER)
+                    + " Sender already specified");
+        } else if (!session.getConnectionState().containsKey(
+                SMTPSession.CURRENT_HELO_MODE)
+                && session.useHeloEhloEnforcement()) {
+            return new SMTPResponse(SMTPRetCode.BAD_SEQUENCE, DSNStatus
+                    .getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_OTHER)
+                    + " Need HELO or EHLO before MAIL");
+        } else if (argument == null
+                || !argument.toUpperCase(Locale.US).equals("FROM")
+                || sender == null) {
+            return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,
+                    DSNStatus.getStatus(DSNStatus.PERMANENT,
+                            DSNStatus.DELIVERY_INVALID_ARG)
+                            + " Usage: MAIL FROM:<sender>");
+        } else {
+            sender = sender.trim();
+            // the next gt after the first lt ... AUTH may add more <>
+            int lastChar = sender.indexOf('>', sender.indexOf('<'));
+            // Check to see if any options are present and, if so, whether they
+            // are correctly formatted
+            // (separated from the closing angle bracket by a ' ').
+            if ((lastChar > 0) && (sender.length() > lastChar + 2)
+                    && (sender.charAt(lastChar + 1) == ' ')) {
+                String mailOptionString = sender.substring(lastChar + 2);
+
+                // Remove the options from the sender
+                sender = sender.substring(0, lastChar + 1);
+
+                StringTokenizer optionTokenizer = new StringTokenizer(
+                        mailOptionString, " ");
+                while (optionTokenizer.hasMoreElements()) {
+                    String mailOption = optionTokenizer.nextToken();
+                    int equalIndex = mailOption.indexOf('=');
+                    String mailOptionName = mailOption;
+                    String mailOptionValue = "";
+                    if (equalIndex > 0) {
+                        mailOptionName = mailOption.substring(0, equalIndex)
+                                .toUpperCase(Locale.US);
+                        mailOptionValue = mailOption.substring(equalIndex + 1);
+                    }
+
+                    // Handle the SIZE extension keyword
+
+                    if (paramHooks.containsKey(mailOptionName)) {
+                        MailParametersHook hook = paramHooks.get(mailOptionName);
+                        SMTPResponse res = calcDefaultSMTPResponse(hook.doMailParameter(session, mailOptionName, mailOptionValue));
+                        if (res != null) {
+                            return res;
+                        }
+                    } else {
+                        // Unexpected option attached to the Mail command
+                        if (session.getLogger().isDebugEnabled()) {
+                            StringBuilder debugBuffer = new StringBuilder(128)
+                                    .append(
+                                            "MAIL command had unrecognized/unexpected option ")
+                                    .append(mailOptionName).append(
+                                            " with value ").append(
+                                            mailOptionValue);
+                            session.getLogger().debug(debugBuffer.toString());
+                        }
+                    }
+                }
+            }
+            if (session.useAddressBracketsEnforcement()
+                    && (!sender.startsWith("<") || !sender.endsWith(">"))) {
+                if (session.getLogger().isErrorEnabled()) {
+                    StringBuilder errorBuffer = new StringBuilder(128).append(
+                            "Error parsing sender address: ").append(sender)
+                            .append(": did not start and end with < >");
+                    session.getLogger().error(errorBuffer.toString());
+                }
+                return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,
+                        DSNStatus.getStatus(DSNStatus.PERMANENT,
+                                DSNStatus.ADDRESS_SYNTAX_SENDER)
+                                + " Syntax error in MAIL command");
+            }
+            MailAddress senderAddress = null;
+
+            if (session.useAddressBracketsEnforcement()
+                    || (sender.startsWith("<") && sender.endsWith(">"))) {
+                // Remove < and >
+                sender = sender.substring(1, sender.length() - 1);
+            }
+
+            if (sender.length() == 0) {
+                // This is the <> case. Let senderAddress == null
+            } else {
+
+                if (sender.indexOf("@") < 0) {
+                    sender = sender
+                            + "@"
+                            + getDefaultDomain();
+                }
+
+                try {
+                    senderAddress = new MailAddress(sender);
+                } catch (Exception pe) {
+                    if (session.getLogger().isErrorEnabled()) {
+                        StringBuilder errorBuffer = new StringBuilder(256)
+                                .append("Error parsing sender address: ")
+                                .append(sender).append(": ").append(
+                                        pe.getMessage());
+                        session.getLogger().error(errorBuffer.toString());
+                    }
+                    return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,
+                            DSNStatus.getStatus(DSNStatus.PERMANENT,
+                                    DSNStatus.ADDRESS_SYNTAX_SENDER)
+                                    + " Syntax error in sender address");
+                }
+            }
+
+            // Store the senderAddress in session map
+            session.getState().put(SMTPSession.SENDER, senderAddress);
+        }
+        return null;
+    }
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#getHookInterface()
+     */
+    protected Class<MailHook> getHookInterface() {
+        return MailHook.class;
+    }
+
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#callHook(java.lang.Object, org.apache.james.smtpserver.protocol.SMTPSession, java.lang.String)
+     */
+    protected HookResult callHook(MailHook rawHook, SMTPSession session, String parameters) {
+        return rawHook.doMail(session,(MailAddress) session.getState().get(SMTPSession.SENDER));
+    }
+
+    
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#getMarkerInterfaces()
+     */
+    public List<Class<?>> getMarkerInterfaces() {
+        List<Class<?>> l = super.getMarkerInterfaces();
+        l.add(MailParametersHook.class);
+        return l;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#wireExtensions(java.lang.Class, java.util.List)
+     */
+    @SuppressWarnings("unchecked")
+    public void wireExtensions(Class interfaceName, List extension) {
+        if (MailParametersHook.class.equals(interfaceName)) {
+            this.paramHooks = new HashMap<String, MailParametersHook>();
+            for (Iterator<MailParametersHook> i = extension.iterator(); i.hasNext(); ) {
+                MailParametersHook hook =  i.next();
+                String[] params = hook.getMailParamNames();
+                for (int k = 0; k < params.length; k++) {
+                    paramHooks.put(params[k], hook);
+                }
+            }
+        } else {
+            super.wireExtensions(interfaceName, extension);
+        }
+    }
+
+    /**
+     * Return the default domain to append if the sender contains none
+     * 
+     * @return defaultDomain
+     */
+    protected String getDefaultDomain() {
+        return "localhost";
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/NoopCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/NoopCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/NoopCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/NoopCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,65 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+
+/**
+  * Handles NOOP command
+  */
+public class NoopCmdHandler implements CommandHandler<SMTPSession> {
+
+    /**
+     * The name of the command handled by the command handler
+     */
+    private final static String COMMAND_NAME = "NOOP";
+
+    /**
+     * Handler method called upon receipt of a NOOP command.
+     * Just sends back an OK and logs the command.
+     *
+     */
+    public Response onCommand(SMTPSession session, Request request) {
+        return new SMTPResponse(SMTPRetCode.MAIL_OK, DSNStatus.getStatus(DSNStatus.SUCCESS,DSNStatus.UNDEFINED_STATUS)+" OK");
+    }
+    
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add(COMMAND_NAME);
+        
+        return implCommands;
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/PostmasterAbuseRcptHook.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/PostmasterAbuseRcptHook.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/PostmasterAbuseRcptHook.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/PostmasterAbuseRcptHook.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,44 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.james.smtpserver.protocol.hook.HookResult;
+import org.apache.james.smtpserver.protocol.hook.HookReturnCode;
+import org.apache.james.smtpserver.protocol.hook.RcptHook;
+import org.apache.mailet.MailAddress;
+
+/**
+ * Handler which whitelist "postmaster" and "abuse" recipients.
+ */
+public class PostmasterAbuseRcptHook implements RcptHook {
+    
+    /**
+     * @see org.apache.james.smtpserver.protocol.hook.RcptHook#doRcpt(org.apache.james.smtpserver.protocol.SMTPSession, org.apache.mailet.MailAddress, org.apache.mailet.MailAddress)
+     */
+    public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
+        if (rcpt.getLocalPart().equalsIgnoreCase("postmaster") || rcpt.getLocalPart().equalsIgnoreCase("abuse")) {
+            session.getLogger().debug("Sender allowed");
+            return new HookResult(HookReturnCode.OK);
+        } else {
+            return new HookResult(HookReturnCode.DECLINED);
+        }
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/QuitCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/QuitCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/QuitCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/QuitCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,114 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.james.smtpserver.protocol.hook.HookResult;
+import org.apache.james.smtpserver.protocol.hook.QuitHook;
+
+/**
+ * Handles QUIT command
+ */
+public class QuitCmdHandler extends AbstractHookableCmdHandler<QuitHook> {
+
+    /**
+     * The name of the command handled by the command handler
+     */
+    private final static String COMMAND_NAME = "QUIT";
+
+    /**
+     * Handler method called upon receipt of a QUIT command. This method informs
+     * the client that the connection is closing.
+     * 
+     * @param session
+     *            SMTP session object
+     * @param argument
+     *            the argument passed in with the command by the SMTP client
+     */
+    private SMTPResponse doQUIT(SMTPSession session, String argument) {
+        SMTPResponse ret;
+        if ((argument == null) || (argument.length() == 0)) {
+            StringBuilder response = new StringBuilder();
+            response.append(
+                    DSNStatus.getStatus(DSNStatus.SUCCESS,
+                            DSNStatus.UNDEFINED_STATUS)).append(" ").append(
+                    session.getHelloName()).append(
+                    " Service closing transmission channel");
+            ret = new SMTPResponse(SMTPRetCode.SYSTEM_QUIT, response);
+        } else {
+            ret = new SMTPResponse(
+                    SMTPRetCode.SYNTAX_ERROR_COMMAND_UNRECOGNIZED, DSNStatus
+                            .getStatus(DSNStatus.PERMANENT,
+                                    DSNStatus.DELIVERY_INVALID_ARG)
+                            + " Unexpected argument provided with QUIT command");
+        }
+        ret.setEndSession(true);
+        return ret;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add(COMMAND_NAME);
+
+        return implCommands;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#doCoreCmd(org.apache.james.smtpserver.protocol.SMTPSession,
+     *      java.lang.String, java.lang.String)
+     */
+    protected SMTPResponse doCoreCmd(SMTPSession session, String command,
+            String parameters) {
+        return doQUIT(session, parameters);
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#doFilterChecks(org.apache.james.smtpserver.protocol.SMTPSession,
+     *      java.lang.String, java.lang.String)
+     */
+    protected SMTPResponse doFilterChecks(SMTPSession session, String command,
+            String parameters) {
+        return null;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#getHookInterface()
+     */
+    protected Class<QuitHook> getHookInterface() {
+        return QuitHook.class;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#callHook(java.lang.Object, org.apache.james.smtpserver.protocol.SMTPSession, java.lang.String)
+     */
+    protected HookResult callHook(QuitHook rawHook, SMTPSession session, String parameters) {
+        return rawHook.doQuit(session);
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RcptCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RcptCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RcptCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RcptCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,262 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.james.smtpserver.protocol.hook.HookResult;
+import org.apache.james.smtpserver.protocol.hook.RcptHook;
+import org.apache.mailet.MailAddress;
+
+/**
+ * Handles RCPT command
+ */
+public class RcptCmdHandler extends AbstractHookableCmdHandler<RcptHook> implements
+        CommandHandler<SMTPSession> {
+
+    public static final String CURRENT_RECIPIENT = "CURRENT_RECIPIENT"; // Current recipient
+
+   
+    
+    /**
+     * Handler method called upon receipt of a RCPT command. Reads recipient.
+     * Does some connection validation.
+     * 
+     * 
+     * @param session
+     *            SMTP session object
+     * @param argument
+     *            the argument passed in with the command by the SMTP client
+     */
+    @SuppressWarnings("unchecked")
+    protected SMTPResponse doCoreCmd(SMTPSession session, String command,
+            String parameters) {
+        Collection<MailAddress> rcptColl = (Collection<MailAddress>) session.getState().get(
+                SMTPSession.RCPT_LIST);
+        if (rcptColl == null) {
+            rcptColl = new ArrayList<MailAddress>();
+        }
+        MailAddress recipientAddress = (MailAddress) session.getState().get(
+                CURRENT_RECIPIENT);
+        rcptColl.add(recipientAddress);
+        session.getState().put(SMTPSession.RCPT_LIST, rcptColl);
+        StringBuilder response = new StringBuilder();
+        response
+                .append(
+                        DSNStatus.getStatus(DSNStatus.SUCCESS,
+                                DSNStatus.ADDRESS_VALID))
+                .append(" Recipient <").append(recipientAddress).append("> OK");
+        return new SMTPResponse(SMTPRetCode.MAIL_OK, response);
+
+    }
+
+    /**
+     * @param session
+     *            SMTP session object
+     * @param argument
+     *            the argument passed in with the command by the SMTP client
+     */
+    protected SMTPResponse doFilterChecks(SMTPSession session, String command,
+            String argument) {
+        String recipient = null;
+        if ((argument != null) && (argument.indexOf(":") > 0)) {
+            int colonIndex = argument.indexOf(":");
+            recipient = argument.substring(colonIndex + 1);
+            argument = argument.substring(0, colonIndex);
+        }
+        if (!session.getState().containsKey(SMTPSession.SENDER)) {
+            return new SMTPResponse(SMTPRetCode.BAD_SEQUENCE, DSNStatus
+                    .getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_OTHER)
+                    + " Need MAIL before RCPT");
+        } else if (argument == null
+                || !argument.toUpperCase(Locale.US).equals("TO")
+                || recipient == null) {
+            return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,
+                    DSNStatus.getStatus(DSNStatus.PERMANENT,
+                            DSNStatus.DELIVERY_SYNTAX)
+                            + " Usage: RCPT TO:<recipient>");
+        }
+
+        Collection rcptColl = (Collection) session.getState().get(
+                SMTPSession.RCPT_LIST);
+        if (rcptColl == null) {
+            rcptColl = new ArrayList();
+        }
+        recipient = recipient.trim();
+        int lastChar = recipient.lastIndexOf('>');
+        // Check to see if any options are present and, if so, whether they
+        // are correctly formatted
+        // (separated from the closing angle bracket by a ' ').
+        String rcptOptionString = null;
+        if ((lastChar > 0) && (recipient.length() > lastChar + 2)
+                && (recipient.charAt(lastChar + 1) == ' ')) {
+            rcptOptionString = recipient.substring(lastChar + 2);
+
+            // Remove the options from the recipient
+            recipient = recipient.substring(0, lastChar + 1);
+        }
+        if (session.useAddressBracketsEnforcement()
+                && (!recipient.startsWith("<") || !recipient.endsWith(">"))) {
+            if (session.getLogger().isErrorEnabled()) {
+                StringBuilder errorBuffer = new StringBuilder(192).append(
+                        "Error parsing recipient address: ").append(
+                        "Address did not start and end with < >").append(
+                        getContext(session, null, recipient));
+                session.getLogger().error(errorBuffer.toString());
+            }
+            return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,
+                    DSNStatus.getStatus(DSNStatus.PERMANENT,
+                            DSNStatus.DELIVERY_SYNTAX)
+                            + " Syntax error in parameters or arguments");
+        }
+        MailAddress recipientAddress = null;
+        // Remove < and >
+        if (session.useAddressBracketsEnforcement()
+                || (recipient.startsWith("<") && recipient.endsWith(">"))) {
+            recipient = recipient.substring(1, recipient.length() - 1);
+        }
+
+        if (recipient.indexOf("@") < 0) {
+            // set the default domain
+            recipient = recipient
+                    + "@"
+                    + getDefaultDomain();
+        }
+
+        try {
+            recipientAddress = new MailAddress(recipient);
+        } catch (Exception pe) {
+            if (session.getLogger().isErrorEnabled()) {
+                StringBuilder errorBuffer = new StringBuilder(192).append(
+                        "Error parsing recipient address: ").append(
+                        getContext(session, recipientAddress, recipient))
+                        .append(pe.getMessage());
+                session.getLogger().error(errorBuffer.toString());
+            }
+            /*
+             * from RFC2822; 553 Requested action not taken: mailbox name
+             * not allowed (e.g., mailbox syntax incorrect)
+             */
+            return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_MAILBOX,
+                    DSNStatus.getStatus(DSNStatus.PERMANENT,
+                            DSNStatus.ADDRESS_SYNTAX)
+                            + " Syntax error in recipient address");
+        }
+
+        if (rcptOptionString != null) {
+
+            StringTokenizer optionTokenizer = new StringTokenizer(
+                    rcptOptionString, " ");
+            while (optionTokenizer.hasMoreElements()) {
+                String rcptOption = optionTokenizer.nextToken();
+                int equalIndex = rcptOption.indexOf('=');
+                String rcptOptionName = rcptOption;
+                String rcptOptionValue = "";
+                if (equalIndex > 0) {
+                    rcptOptionName = rcptOption.substring(0, equalIndex)
+                            .toUpperCase(Locale.US);
+                    rcptOptionValue = rcptOption.substring(equalIndex + 1);
+                }
+                // Unexpected option attached to the RCPT command
+                if (session.getLogger().isDebugEnabled()) {
+                    StringBuilder debugBuffer = new StringBuilder(128)
+                            .append(
+                                    "RCPT command had unrecognized/unexpected option ")
+                            .append(rcptOptionName).append(" with value ")
+                            .append(rcptOptionValue).append(
+                                    getContext(session, recipientAddress,
+                                            recipient));
+                    session.getLogger().debug(debugBuffer.toString());
+                }
+
+                return new SMTPResponse(
+                        SMTPRetCode.PARAMETER_NOT_IMPLEMENTED,
+                        "Unrecognized or unsupported option: "
+                                + rcptOptionName);
+            }
+            optionTokenizer = null;
+        }
+
+        session.getState().put(CURRENT_RECIPIENT,recipientAddress);
+
+        return null;
+    }
+
+    private String getContext(SMTPSession session,
+            MailAddress recipientAddress, String recipient) {
+        StringBuilder sb = new StringBuilder(128);
+        if (null != recipientAddress) {
+            sb
+                    .append(" [to:"
+                            + (recipientAddress).toInternetAddress()
+                                    .getAddress() + "]");
+        } else if (null != recipient) {
+            sb.append(" [to:" + recipient + "]");
+        }
+        if (null != session.getState().get(SMTPSession.SENDER)) {
+            sb
+                    .append(" [from:"
+                            + ((MailAddress) session.getState().get(
+                                    SMTPSession.SENDER)).toInternetAddress()
+                                    .getAddress() + "]");
+        }
+        return sb.toString();
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add("RCPT");
+
+        return implCommands;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#getHookInterface()
+     */
+    protected Class<RcptHook> getHookInterface() {
+        return RcptHook.class;
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.core.AbstractHookableCmdHandler#callHook(java.lang.Object,
+     *      org.apache.james.smtpserver.protocol.SMTPSession, java.lang.String)
+     */
+    protected HookResult callHook(RcptHook rawHook, SMTPSession session,
+            String parameters) {
+        return rawHook.doRcpt(session,
+                (MailAddress) session.getState().get(SMTPSession.SENDER),
+                (MailAddress) session.getState().get(CURRENT_RECIPIENT));
+    }
+
+    protected String getDefaultDomain() {
+    	return "localhost";
+    }
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ReceivedDataLineFilter.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ReceivedDataLineFilter.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ReceivedDataLineFilter.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/ReceivedDataLineFilter.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,140 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.james.protocols.api.LineHandler;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+import org.apache.mailet.base.RFC2822Headers;
+import org.apache.mailet.base.RFC822DateFormat;
+
+public class ReceivedDataLineFilter implements DataLineFilter {
+
+    private final static String SOFTWARE_TYPE = "JAMES SMTP Server ";
+
+    // Replace this with something usefull
+    // + Constants.SOFTWARE_VERSION;
+
+    /**
+     * Static RFC822DateFormat used to generate date headers
+     */
+    private final static RFC822DateFormat rfc822DateFormat = new RFC822DateFormat();
+    private final static String HEADERS_WRITTEN = "HEADERS_WRITTEN";
+
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.smtpserver.protocol.core.DataLineFilter#onLine(org.apache.james.smtpserver.protocol.SMTPSession, byte[], org.apache.james.api.protocol.LineHandler)
+     */
+    public void onLine(SMTPSession session,  byte[] line, LineHandler<SMTPSession> next) {
+        if (session.getState().containsKey(HEADERS_WRITTEN) == false) {
+            addNewReceivedMailHeaders(session, next);
+            session.getState().put(HEADERS_WRITTEN, true);
+        }
+        next.onLine(session, line);
+    }
+
+    private void addNewReceivedMailHeaders(SMTPSession session, LineHandler<SMTPSession> next) {
+        StringBuilder headerLineBuffer = new StringBuilder();
+
+        String heloMode = (String) session.getConnectionState().get(
+                SMTPSession.CURRENT_HELO_MODE);
+        String heloName = (String) session.getConnectionState().get(
+                SMTPSession.CURRENT_HELO_NAME);
+
+        // Put our Received header first
+        headerLineBuffer.append(RFC2822Headers.RECEIVED + ": from ").append(
+                session.getRemoteHost());
+
+        if (heloName != null) {
+            headerLineBuffer.append(" (").append(heloMode).append(" ").append(
+                    heloName).append(") ");
+        }
+
+        headerLineBuffer.append(" ([").append(session.getRemoteIPAddress())
+                .append("])").append("\r\n");
+        try {
+            next.onLine(session, headerLineBuffer.toString().getBytes("US-ASCII"));
+        } catch (UnsupportedEncodingException e1) {
+            // should never happen
+            e1.printStackTrace();
+        }
+        headerLineBuffer.delete(0, headerLineBuffer.length());
+
+        headerLineBuffer.append("          by ").append(session.getHelloName())
+                .append(" (").append(SOFTWARE_TYPE).append(") with ");
+
+        // Check if EHLO was used
+        if ("EHLO".equals(heloMode)) {
+            // Not successful auth
+            if (session.getUser() == null) {
+                headerLineBuffer.append("ESMTP");
+            } else {
+                // See RFC3848
+                // The new keyword "ESMTPA" indicates the use of ESMTP when the
+                // SMTP
+                // AUTH [3] extension is also used and authentication is
+                // successfully
+                // achieved.
+                headerLineBuffer.append("ESMTPA");
+            }
+        } else {
+            headerLineBuffer.append("SMTP");
+        }
+
+        headerLineBuffer.append(" ID ").append(session.getSessionID());
+        try {
+
+            if (((Collection) session.getState().get(SMTPSession.RCPT_LIST)).size() == 1) {
+                // Only indicate a recipient if they're the only recipient
+                // (prevents email address harvesting and large headers in
+                // bulk email)
+                headerLineBuffer.append("\r\n");
+                next.onLine(session, headerLineBuffer.toString().getBytes("US-ASCII"));
+                headerLineBuffer.delete(0, headerLineBuffer.length());
+
+                headerLineBuffer.delete(0, headerLineBuffer.length());
+                headerLineBuffer.append("          for <").append(((List) session.getState().get(SMTPSession.RCPT_LIST)).get(0).toString()).append(">;").append("\r\n");
+
+                next.onLine(session, headerLineBuffer.toString().getBytes("US-ASCII"));
+                headerLineBuffer.delete(0, headerLineBuffer.length());
+
+                headerLineBuffer.delete(0, headerLineBuffer.length());
+            } else {
+                // Put the ; on the end of the 'by' line
+                headerLineBuffer.append(";");
+                headerLineBuffer.append("\r\n");
+
+                next.onLine(session, headerLineBuffer.toString().getBytes("US-ASCII"));
+
+                headerLineBuffer.delete(0, headerLineBuffer.length());
+            }
+            headerLineBuffer = null;
+            next.onLine(session, ("          " + rfc822DateFormat.format(new Date()) + "\r\n").getBytes("US-ASCII"));
+        } catch (UnsupportedEncodingException e) {
+            // Should never happen
+            e.printStackTrace();
+            
+        }
+    }
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RsetCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RsetCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RsetCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/RsetCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,80 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+
+/**
+  * Handles RSET command
+  */
+public class RsetCmdHandler implements CommandHandler<SMTPSession> {
+    /**
+     * The name of the command handled by the command handler
+     */
+    private final static String COMMAND_NAME = "RSET";
+
+    /**
+     * handles RSET command
+     *
+    **/
+    public Response onCommand(SMTPSession session, Request request) {
+        return doRSET(session, request.getArgument());
+    }
+
+
+    /**
+     * Handler method called upon receipt of a RSET command.
+     * Resets message-specific, but not authenticated user, state.
+     *
+     * @param session SMTP session object
+     * @param argument the argument passed in with the command by the SMTP client
+     * @return 
+     */
+    private SMTPResponse doRSET(SMTPSession session, String argument) {
+        if ((argument == null) || (argument.length() == 0)) {
+            session.resetState();
+            return new SMTPResponse(SMTPRetCode.MAIL_OK, DSNStatus.getStatus(DSNStatus.SUCCESS,DSNStatus.UNDEFINED_STATUS)+" OK");
+        } else {
+            return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_COMMAND_UNRECOGNIZED, DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Unexpected argument provided with RSET command");
+        }
+    }
+
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add(COMMAND_NAME);
+        
+        return implCommands;
+    }
+    
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/SMTPCommandDispatcherLineHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/SMTPCommandDispatcherLineHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/SMTPCommandDispatcherLineHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/SMTPCommandDispatcherLineHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,65 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.james.protocols.api.AbstractCommandDispatcher;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+
+
+/**
+ * Dispatch CommandHandler for SMTP Requests
+ * 
+ *
+ */
+public class SMTPCommandDispatcherLineHandler extends AbstractCommandDispatcher<SMTPSession> {
+
+
+    private final CommandHandler<SMTPSession> unknownHandler = new UnknownCmdHandler();
+
+    private final static String[] mandatoryCommands = { "MAIL" , "RCPT", "DATA"};
+    
+
+
+    /**
+     * @see org.apache.james.api.protocol.AbstractCommandDispatcher#getUnknownCommandHandlerIdentifier()
+     */
+    protected String getUnknownCommandHandlerIdentifier() {
+        return UnknownCmdHandler.UNKNOWN_COMMAND;
+    }
+
+    /**
+     * @see org.apache.james.api.protocol.AbstractCommandDispatcher#getMandatoryCommands()
+     */
+    protected List<String> getMandatoryCommands() {
+        return Arrays.asList(mandatoryCommands);
+    }
+
+    /**
+     * @see org.apache.james.api.protocol.AbstractCommandDispatcher#getUnknownCommandHandler()
+     */
+    protected CommandHandler<SMTPSession> getUnknownCommandHandler() {
+        return unknownHandler;
+    }
+
+}

Added: james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/UnknownCmdHandler.java
URL: http://svn.apache.org/viewvc/james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/UnknownCmdHandler.java?rev=905220&view=auto
==============================================================================
--- james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/UnknownCmdHandler.java (added)
+++ james/protocols/trunk/smtp/src/main/java/org/apache/james/smtpserver/protocol/core/UnknownCmdHandler.java Mon Feb  1 09:29:55 2010
@@ -0,0 +1,68 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.smtpserver.protocol.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.james.dsn.DSNStatus;
+import org.apache.james.protocols.api.CommandHandler;
+import org.apache.james.protocols.api.Request;
+import org.apache.james.protocols.api.Response;
+import org.apache.james.smtpserver.protocol.SMTPResponse;
+import org.apache.james.smtpserver.protocol.SMTPRetCode;
+import org.apache.james.smtpserver.protocol.SMTPSession;
+
+/**
+  * Default command handler for handling unknown commands
+  */
+public class UnknownCmdHandler implements CommandHandler<SMTPSession>{
+
+    /**
+     * The name of the command handled by the command handler
+     */
+    public static final String UNKNOWN_COMMAND = "UNKNOWN";
+    
+    /**
+     * Handler method called upon receipt of an unrecognized command.
+     * Returns an error response and logs the command.
+     *
+    **/
+    public Response onCommand(SMTPSession session, Request request) {
+        StringBuilder result = new StringBuilder();
+        result.append(DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_INVALID_CMD))
+                      .append(" Command ")
+                      .append(request.getCommand())
+                      .append(" unrecognized.");
+        return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_COMMAND_UNRECOGNIZED, result);
+    }
+    
+    /**
+     * @see org.apache.james.smtpserver.protocol.CommandHandler#getImplCommands()
+     */
+    public Collection<String> getImplCommands() {
+        Collection<String> implCommands = new ArrayList<String>();
+        implCommands.add(UNKNOWN_COMMAND);
+        
+        return implCommands;
+    }
+}



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