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    
021    
022    
023    package org.apache.james.protocols.smtp.core.fastfail;
024    
025    import org.apache.james.protocols.smtp.SMTPRetCode;
026    import org.apache.james.protocols.smtp.SMTPSession;
027    import org.apache.james.protocols.smtp.dsn.DSNStatus;
028    import org.apache.james.protocols.smtp.hook.HookResult;
029    import org.apache.james.protocols.smtp.hook.HookReturnCode;
030    import org.apache.james.protocols.smtp.hook.RcptHook;
031    import org.apache.mailet.MailAddress;
032    
033    
034    /**
035     * Handler which want todo an recipient check should extend this
036     *
037     */
038    public abstract class AbstractValidRcptHandler implements RcptHook {
039    
040        
041        /**
042         * @see org.apache.james.protocols.smtp.hook.RcptHook#doRcpt(org.apache.james.protocols.smtp.SMTPSession, org.apache.mailet.MailAddress, org.apache.mailet.MailAddress)
043         */
044        public HookResult doRcpt(SMTPSession session, MailAddress sender, MailAddress rcpt) {
045            boolean reject = false;
046            
047            if (session.isRelayingAllowed()) {
048                // check if the domain is local, if so we still want to check if the recipient is valid or not as we want to fail fast in such cases
049                if (isLocalDomain(session, rcpt.getDomain())) {
050                    if (isValidRecipient(session, rcpt) == false) {
051                        reject = true;
052                    }
053                }
054            } else {
055                if (isLocalDomain(session, rcpt.getDomain()) == false) {
056                    session.getLogger().debug("Unknown domain " + rcpt.getDomain() + " so reject it");
057    
058                } else {
059                    if (isValidRecipient(session, rcpt) == false) {
060                        reject= true;
061                    }
062                }
063            }
064           
065            if (reject) {
066              //user not exist
067                session.getLogger().info("Rejected message. Unknown user: " + rcpt.toString());
068                return new HookResult(HookReturnCode.DENY,SMTPRetCode.MAILBOX_PERM_UNAVAILABLE, DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_MAILBOX) + " Unknown user: " + rcpt.toString());
069            } else {
070                return new HookResult(HookReturnCode.DECLINED);
071            }
072        }
073        
074      
075        /**
076         * Return true if email for the given recipient should get accepted
077         * 
078         * @param recipient
079         * @return isValid
080         */
081        protected abstract boolean isValidRecipient(SMTPSession session, MailAddress recipient);
082        
083        /**
084         * Return true if the domain is local
085         * 
086         * @param session
087         * @param domain
088         * @return local
089         */
090        protected abstract boolean isLocalDomain(SMTPSession session, String domain);
091    }