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.fastfail;
021    
022    import java.net.UnknownHostException;
023    
024    
025    import org.apache.james.protocols.smtp.DNSService;
026    import org.apache.james.protocols.smtp.SMTPRetCode;
027    import org.apache.james.protocols.smtp.SMTPSession;
028    import org.apache.james.protocols.smtp.dsn.DSNStatus;
029    import org.apache.james.protocols.smtp.hook.HeloHook;
030    import org.apache.james.protocols.smtp.hook.HookResult;
031    import org.apache.james.protocols.smtp.hook.HookReturnCode;
032    import org.apache.james.protocols.smtp.hook.RcptHook;
033    import org.apache.mailet.MailAddress;
034    
035    
036    /**
037     * This CommandHandler can be used to reject not resolvable EHLO/HELO
038     */
039    public class ResolvableEhloHeloHandler implements RcptHook, HeloHook {
040    
041        public final static String BAD_EHLO_HELO = "BAD_EHLO_HELO";
042    
043        protected DNSService dnsService = null;
044    
045        /**
046         * Gets the DNS service.
047         * @return the dnsService
048         */
049        public final DNSService getDNSService() {
050            return dnsService;
051        }
052    
053        /**
054         * Sets the DNS service.
055         * @param dnsService the dnsService to set
056         */
057        public final void setDNSService(DNSService dnsService) {
058            this.dnsService = dnsService;
059        }
060    
061    
062        /**
063         * Check if EHLO/HELO is resolvable
064         * 
065         * @param session
066         *            The SMTPSession
067         * @param argument
068         *            The argument
069         */
070        protected void checkEhloHelo(SMTPSession session, String argument) {
071            
072            if (isBadHelo(session, argument)) {
073                session.getState().put(BAD_EHLO_HELO, "true");
074            }
075        }
076        
077        /**
078         * @param session the SMTPSession
079         * @param argument the argument
080         * @return true if the helo is bad.
081         */
082        protected boolean isBadHelo(SMTPSession session, String argument) {
083            // try to resolv the provided helo. If it can not resolved do not
084            // accept it.
085            try {
086                    dnsService.getByName(argument);
087            } catch (UnknownHostException e) {
088                return true;
089            }
090            return false;
091            
092        }
093    
094        protected boolean check(SMTPSession session,MailAddress rcpt) {
095            // not reject it
096            if (session.getState().get(BAD_EHLO_HELO) == null) {
097                return false;
098            }
099    
100            return true;
101        }
102    
103        /**
104         * @see org.apache.james.protocols.smtp.hook.RcptHook#doRcpt(org.apache.james.protocols.smtp.SMTPSession, org.apache.mailet.MailAddress, org.apache.mailet.MailAddress)
105         */
106        public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
107            if (check(session,rcpt)) {
108                return new HookResult(HookReturnCode.DENY,SMTPRetCode.SYNTAX_ERROR_ARGUMENTS,DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_INVALID_ARG)
109                        + " Provided EHLO/HELO " + session.getState().get(SMTPSession.CURRENT_HELO_NAME) + " can not resolved.");
110            } else {
111                return new HookResult(HookReturnCode.DECLINED);
112            }
113        }
114    
115        /**
116         * @see org.apache.james.protocols.smtp.hook.HeloHook#doHelo(org.apache.james.protocols.smtp.SMTPSession, java.lang.String)
117         */
118        public HookResult doHelo(SMTPSession session, String helo) {
119            checkEhloHelo(session, helo);
120            return new HookResult(HookReturnCode.DECLINED);
121        }
122    
123    }