001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    package org.apache.james.protocols.smtp.core.esmtp;
021    
022    import java.util.ArrayList;
023    import java.util.Collection;
024    import java.util.List;
025    
026    import org.apache.james.protocols.api.handler.WiringException;
027    import org.apache.james.protocols.smtp.SMTPResponse;
028    import org.apache.james.protocols.smtp.SMTPRetCode;
029    import org.apache.james.protocols.smtp.SMTPSession;
030    import org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler;
031    import org.apache.james.protocols.smtp.dsn.DSNStatus;
032    import org.apache.james.protocols.smtp.hook.HeloHook;
033    import org.apache.james.protocols.smtp.hook.HookResult;
034    
035    /**
036     * Handles EHLO command
037     */
038    public class EhloCmdHandler extends AbstractHookableCmdHandler<HeloHook> implements EhloExtension{
039    
040        /**
041         * The name of the command handled by the command handler
042         */
043        private final static String COMMAND_NAME = "EHLO";
044    
045        private List<EhloExtension> ehloExtensions;
046    
047        /**
048         * Handler method called upon receipt of a EHLO command. Responds with a
049         * greeting and informs the client whether client authentication is
050         * required.
051         * 
052         * @param session
053         *            SMTP session object
054         * @param argument
055         *            the argument passed in with the command by the SMTP client
056         */
057        private SMTPResponse doEHLO(SMTPSession session, String argument) {
058            SMTPResponse resp = new SMTPResponse(SMTPRetCode.MAIL_OK, new StringBuilder(session.getHelloName()).append(" Hello ").append(argument)
059                    .append(" (").append(session.getRemoteHost()).append(" [")
060                    .append(session.getRemoteIPAddress()).append("])"));
061            
062            session.getConnectionState().put(SMTPSession.CURRENT_HELO_MODE,
063                    COMMAND_NAME);
064    
065            processExtensions(session, resp);
066    
067    
068     
069            return resp;
070    
071        }
072    
073        /**
074         * @see org.apache.james.protocols.api.handler.CommandHandler#getImplCommands()
075         */
076        public Collection<String> getImplCommands() {
077            Collection<String> implCommands = new ArrayList<String>();
078            implCommands.add(COMMAND_NAME);
079    
080            return implCommands;
081        }
082    
083        /**
084         * @see org.apache.james.protocols.api.handler.ExtensibleHandler#getMarkerInterfaces()
085         */
086        public List<Class<?>> getMarkerInterfaces() {
087            List<Class<?>> classes = super.getMarkerInterfaces();
088            classes.add(EhloExtension.class);
089            return classes;
090        }
091    
092        /**
093         * @see org.apache.james.protocols.api.handler.ExtensibleHandler#wireExtensions(java.lang.Class,
094         *      java.util.List)
095         */
096        public void wireExtensions(Class interfaceName, List extension) {
097            super.wireExtensions(interfaceName, extension);
098            if (EhloExtension.class.equals(interfaceName)) {
099                this.ehloExtensions = extension;
100            }
101        }
102    
103        /**
104         * Process the ehloExtensions
105         * 
106         * @param session SMTPSession 
107         * @param resp SMTPResponse
108         */
109        private void processExtensions(SMTPSession session, SMTPResponse resp) {
110            if (ehloExtensions != null) {
111                int count = ehloExtensions.size();
112                for (int i = 0; i < count; i++) {
113                    List<String> lines = ((EhloExtension) ehloExtensions.get(i))
114                            .getImplementedEsmtpFeatures(session);
115                    if (lines != null) {
116                        for (int j = 0; j < lines.size(); j++) {
117                            resp.appendLine(lines.get(j));
118                        }
119                    }
120                }
121            }
122        }
123    
124        /**
125         * @see org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler#doCoreCmd(org.apache.james.protocols.smtp.SMTPSession,
126         *      java.lang.String, java.lang.String)
127         */
128        protected SMTPResponse doCoreCmd(SMTPSession session, String command,
129                String parameters) {
130            return doEHLO(session, parameters);
131        }
132    
133        /**
134         * @see org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler#doFilterChecks(org.apache.james.protocols.smtp.SMTPSession,
135         *      java.lang.String, java.lang.String)
136         */
137        protected SMTPResponse doFilterChecks(SMTPSession session, String command,
138                String parameters) {
139            session.resetState();
140    
141            if (parameters == null) {
142                return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,
143                        DSNStatus.getStatus(DSNStatus.PERMANENT,
144                                DSNStatus.DELIVERY_INVALID_ARG)
145                                + " Domain address required: " + COMMAND_NAME);
146            } else {
147                // store provided name
148                session.getState().put(SMTPSession.CURRENT_HELO_NAME, parameters);
149                return null;
150            }
151        }
152    
153        /**
154         * @see org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler#getHookInterface()
155         */
156        protected Class<HeloHook> getHookInterface() {
157            return HeloHook.class;
158        }
159    
160        /**
161         * {@inheritDoc}
162         */
163        protected HookResult callHook(HeloHook rawHook, SMTPSession session, String parameters) {
164            return rawHook.doHelo(session, parameters);
165        }
166    
167    
168    
169        /**
170         * @see org.apache.james.protocols.smtp.core.esmtp.EhloExtension#getImplementedEsmtpFeatures(org.apache.james.protocols.smtp.SMTPSession)
171         */
172        public List<String> getImplementedEsmtpFeatures(SMTPSession session) {
173            List<String> extensions = new ArrayList<String>();
174            extensions.add("PIPELINING");
175            extensions.add("ENHANCEDSTATUSCODES");
176            // see http://issues.apache.org/jira/browse/JAMES-419
177            extensions.add("8BITMIME");
178            return extensions;
179        }
180    
181    }