Author: bago
Date: Thu Apr  6 15:12:28 2006
New Revision: 392092

URL: http://svn.apache.org/viewcvs?rev=392092&view=rev
Log:
Limit MaxRcpt per Email (JAMES-468)

Modified:
    james/server/trunk/src/conf/james-config.xml
    james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java
    james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java
    
james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java

Modified: james/server/trunk/src/conf/james-config.xml
URL: 
http://svn.apache.org/viewcvs/james/server/trunk/src/conf/james-config.xml?rev=392092&r1=392091&r2=392092&view=diff
==============================================================================
--- james/server/trunk/src/conf/james-config.xml (original)
+++ james/server/trunk/src/conf/james-config.xml Thu Apr  6 15:12:28 2006
@@ -724,7 +724,12 @@
                 <checkValidSenderDomain> false </checkValidSenderDomain>
                 -->
             </handler>
-            <handler command="RCPT" 
class="org.apache.james.smtpserver.RcptCmdHandler"></handler>
+            <handler command="RCPT" 
class="org.apache.james.smtpserver.RcptCmdHandler">
+                <!-- If is set to a bigger value as 0 you can limit the 
maximal recipients per email.
+                     Default is set to 0.
+                <maxRcpt> 0 </maxRcpt>
+                -->
+            </handler>
             <handler command="DATA" 
class="org.apache.james.smtpserver.DataCmdHandler"></handler>
             <handler command="RSET" 
class="org.apache.james.smtpserver.RsetCmdHandler"></handler>
             <handler command="HELP" 
class="org.apache.james.smtpserver.HelpCmdHandler"></handler>

Modified: 
james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java
URL: 
http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java?rev=392092&r1=392091&r2=392092&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java 
(original)
+++ james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java 
Thu Apr  6 15:12:28 2006
@@ -1,245 +1,288 @@
-/***********************************************************************
- * Copyright (c) 1999-2006 The Apache Software Foundation.             *
- * All rights reserved.                                                *
- * ------------------------------------------------------------------- *
- * Licensed 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;
-
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.james.util.mail.dsn.DSNStatus;
-import org.apache.mailet.MailAddress;
-import java.util.Collection;
-import java.util.ArrayList;
-import java.util.StringTokenizer;
-import java.util.Locale;
-
-/**
-  * Handles RCPT command
-  */
-public class RcptCmdHandler
-    extends AbstractLogEnabled
-    implements CommandHandler {
-
-    /**
-     * The keys used to store sender and recepients in the SMTPSession state
-     */
-    private final static String SENDER = "SENDER_ADDRESS";     // Sender's 
email address
-    private final static String RCPT_LIST = "RCPT_LIST";   // The message 
recipients
-
-    /*
-     * handles RCPT command
-     *
-     * @see org.apache.james.smtpserver.CommandHandler#onCommand(SMTPSession)
-    **/
-    public void onCommand(SMTPSession session) {
-        doRCPT(session, session.getCommandArgument());
-    }
-
-
-    /**
-     * 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
-     */
-    private void doRCPT(SMTPSession session, String argument) {
-        String responseString = null;
-        StringBuffer responseBuffer = session.getResponseBuffer();
-
-        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(SENDER)) {
-            responseString = "503 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Need MAIL 
before RCPT";
-            session.writeResponse(responseString);
-        } else if (argument == null || 
!argument.toUpperCase(Locale.US).equals("TO")
-                   || recipient == null) {
-            responseString = "501 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Usage: 
RCPT TO:<recipient>";
-            session.writeResponse(responseString);
-        } else {
-            Collection rcptColl = (Collection) 
session.getState().get(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 (!recipient.startsWith("<") || !recipient.endsWith(">")) {
-                responseString = "501 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Syntax 
error in parameters or arguments";
-                session.writeResponse(responseString);
-                if (getLogger().isErrorEnabled()) {
-                    StringBuffer errorBuffer =
-                        new StringBuffer(192)
-                                .append("Error parsing recipient address: ")
-                                .append("Address did not start and end with < 
>")
-                                .append(getContext(session,null,recipient));
-                    getLogger().error(errorBuffer.toString());
-                }
-                return;
-            }
-            MailAddress recipientAddress = null;
-            //Remove < and >
-            recipient = recipient.substring(1, recipient.length() - 1);
-            if (recipient.indexOf("@") < 0) {
-                recipient = recipient + "@localhost";
-            }
-            try {
-                recipientAddress = new MailAddress(recipient);
-            } catch (Exception pe) {
-                /*
-                 * from RFC2822;
-                 * 553 Requested action not taken: mailbox name not allowed
-                 *     (e.g., mailbox syntax incorrect)
-                 */
-                responseString = "553 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX)+" Syntax 
error in recipient address";
-                session.writeResponse(responseString);
-
-                if (getLogger().isErrorEnabled()) {
-                    StringBuffer errorBuffer =
-                        new StringBuffer(192)
-                                .append("Error parsing recipient address: ")
-                                
.append(getContext(session,recipientAddress,recipient))
-                                .append(pe.getMessage());
-                    getLogger().error(errorBuffer.toString());
-                }
-                return;
-            }
-
-
-            if (session.isBlockListed() &&                                     
           // was found in the RBL
-                (!session.isRelayingAllowed() || (session.isAuthRequired() && 
session.getUser() == null)) &&  // Not an authorized IP or SMTP AUTH is enabled 
and not authenticated
-                !(recipientAddress.getUser().equalsIgnoreCase("postmaster") || 
recipientAddress.getUser().equalsIgnoreCase("abuse"))) {
-                // trying to send e-mail to other than postmaster or abuse
-                responseString = "530 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Rejected: 
unauthenticated e-mail from " + session.getRemoteIPAddress() + " is restricted. 
 Contact the postmaster for details.";
-                session.writeResponse(responseString);
-                return;
-            }
-
-            if (session.isAuthRequired() && !session.isRelayingAllowed()) {
-                // Make sure the mail is being sent locally if not
-                // authenticated else reject.
-                if (session.getUser() == null) {
-                    String toDomain = recipientAddress.getHost();
-                    if 
(!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
-                        responseString = "530 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" 
Authentication Required";
-                        session.writeResponse(responseString);
-                        StringBuffer sb = new StringBuffer(128);
-                        sb.append("Rejected message - authentication is 
required for mail request");
-                        
sb.append(getContext(session,recipientAddress,recipient));
-                        getLogger().error(sb.toString());
-                        return;
-                    }
-                } else {
-                    // Identity verification checking
-                    if (session.getConfigurationData().isVerifyIdentity()) {
-                        String authUser = 
(session.getUser()).toLowerCase(Locale.US);
-                        MailAddress senderAddress = (MailAddress) 
session.getState().get(SENDER);
-
-                        if ((senderAddress == null) || 
(!authUser.equals(senderAddress.getUser())) ||
-                            
(!session.getConfigurationData().getMailServer().isLocalServer(senderAddress.getHost())))
 {
-                            responseString = "503 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Incorrect 
Authentication for Specified Email Address";
-                            session.writeResponse(responseString);
-                            if (getLogger().isErrorEnabled()) {
-                                StringBuffer errorBuffer =
-                                    new StringBuffer(128)
-                                        .append("User ")
-                                        .append(authUser)
-                                        .append(" authenticated, however tried 
sending email as ")
-                                        .append(senderAddress)
-                                        
.append(getContext(session,recipientAddress,recipient));
-                                getLogger().error(errorBuffer.toString());
-                            }
-                            return;
-                        }
-                    }
-                }
-            } else if (!session.isRelayingAllowed()) {
-                String toDomain = recipientAddress.getHost();
-                if 
(!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
-                    responseString = "550 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Requested 
action not taken: relaying denied";
-                    session.writeResponse(responseString);
-                    StringBuffer errorBuffer = new StringBuffer(128)
-                        .append("Rejected message - ")
-                        .append(session.getRemoteIPAddress())
-                        .append(" not authorized to relay to ")
-                        .append(toDomain)
-                        
.append(getContext(session,recipientAddress,recipient));
-                    getLogger().error(errorBuffer.toString());
-                    return;
-                }
-            }
-            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 (getLogger().isDebugEnabled()) {
-                      StringBuffer debugBuffer =
-                          new StringBuffer(128)
-                              .append("RCPT command had 
unrecognized/unexpected option ")
-                              .append(rcptOptionName)
-                              .append(" with value ")
-                              .append(rcptOptionValue)
-                              
.append(getContext(session,recipientAddress,recipient));
-                      getLogger().debug(debugBuffer.toString());
-                  }
-              }
-              optionTokenizer = null;
-            }
-            rcptColl.add(recipientAddress);
-            session.getState().put(RCPT_LIST, rcptColl);
-            responseBuffer.append("250 
"+DSNStatus.getStatus(DSNStatus.SUCCESS,DSNStatus.ADDRESS_VALID)+" Recipient <")
-                          .append(recipient)
-                          .append("> OK");
-            responseString = session.clearResponseBuffer();
-            session.writeResponse(responseString);
-        }
-    }
-
-
-    private String getContext(SMTPSession session, MailAddress 
recipientAddress, String recipient){
-        StringBuffer sb = new StringBuffer(128);
-        if(null!=recipientAddress) {
-            sb.append(" [to:" + 
(recipientAddress).toInternetAddress().getAddress() + "]");
-        } else if(null!=recipient) {
-            sb.append(" [to:" + recipient + "]");
-        }
-        if (null!=session.getState().get(SENDER)) {
-            sb.append(" [from:" + 
((MailAddress)session.getState().get(SENDER)).toInternetAddress().getAddress() 
+ "]");
-        }
-        return sb.toString();
-    } 
-}
+/***********************************************************************
+ * Copyright (c) 1999-2006 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed 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;
+
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.james.util.mail.dsn.DSNStatus;
+import org.apache.mailet.MailAddress;
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.util.Locale;
+
+/**
+  * Handles RCPT command
+  */
+public class RcptCmdHandler
+    extends AbstractLogEnabled
+    implements CommandHandler,Configurable {
+
+    /**
+     * The keys used to store sender and recepients in the SMTPSession state
+     */
+    private final static String SENDER = "SENDER_ADDRESS";     // Sender's 
email address
+    private final static String RCPT_LIST = "RCPT_LIST";   // The message 
recipients
+    private final static String RCPTCOUNT = "RCPT_COUNT";
+    private int maxRcpt = 0;
+    
+    /**
+     * @see 
org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
+     */
+    public void configure(Configuration handlerConfiguration) throws 
ConfigurationException {
+        Configuration configuration = 
handlerConfiguration.getChild("maxRcpt",false);
+        if(configuration != null) {
+           maxRcpt = configuration.getValueAsInteger();
+        }
+    }
+    
+    /*
+     * handles RCPT command
+     *
+     * @see org.apache.james.smtpserver.CommandHandler#onCommand(SMTPSession)
+    **/
+    public void onCommand(SMTPSession session) {
+        doRCPT(session, session.getCommandArgument());
+    }
+
+
+    /**
+     * 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
+     */
+    private void doRCPT(SMTPSession session, String argument) {
+        String responseString = null;
+        StringBuffer responseBuffer = session.getResponseBuffer();
+        boolean maxRcptReached = false;
+        
+        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(SENDER)) {
+            responseString = "503 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_OTHER)+" Need MAIL 
before RCPT";
+            session.writeResponse(responseString);
+        } else if (argument == null || 
!argument.toUpperCase(Locale.US).equals("TO")
+                   || recipient == null) {
+            responseString = "501 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Usage: 
RCPT TO:<recipient>";
+            session.writeResponse(responseString);
+        } else {
+            Collection rcptColl = (Collection) 
session.getState().get(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 (!recipient.startsWith("<") || !recipient.endsWith(">")) {
+                responseString = "501 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_SYNTAX)+" Syntax 
error in parameters or arguments";
+                session.writeResponse(responseString);
+                if (getLogger().isErrorEnabled()) {
+                    StringBuffer errorBuffer =
+                        new StringBuffer(192)
+                                .append("Error parsing recipient address: ")
+                                .append("Address did not start and end with < 
>")
+                                .append(getContext(session,null,recipient));
+                    getLogger().error(errorBuffer.toString());
+                }
+                return;
+            }
+            MailAddress recipientAddress = null;
+            //Remove < and >
+            recipient = recipient.substring(1, recipient.length() - 1);
+            if (recipient.indexOf("@") < 0) {
+                recipient = recipient + "@localhost";
+            }
+            
+            try {
+                recipientAddress = new MailAddress(recipient);
+            } catch (Exception pe) {
+                /*
+                 * from RFC2822;
+                 * 553 Requested action not taken: mailbox name not allowed
+                 *     (e.g., mailbox syntax incorrect)
+                 */
+                responseString = "553 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.ADDRESS_SYNTAX)+" Syntax 
error in recipient address";
+                session.writeResponse(responseString);
+
+                if (getLogger().isErrorEnabled()) {
+                    StringBuffer errorBuffer =
+                        new StringBuffer(192)
+                                .append("Error parsing recipient address: ")
+                                
.append(getContext(session,recipientAddress,recipient))
+                                .append(pe.getMessage());
+                    getLogger().error(errorBuffer.toString());
+                }
+                return;
+            }
+
+            if (session.isBlockListed() &&                                     
           // was found in the RBL
+                (!session.isRelayingAllowed() || (session.isAuthRequired() && 
session.getUser() == null)) &&  // Not an authorized IP or SMTP AUTH is enabled 
and not authenticated
+                !(recipientAddress.getUser().equalsIgnoreCase("postmaster") || 
recipientAddress.getUser().equalsIgnoreCase("abuse"))) {
+                // trying to send e-mail to other than postmaster or abuse
+                responseString = "530 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Rejected: 
unauthenticated e-mail from " + session.getRemoteIPAddress() + " is restricted. 
 Contact the postmaster for details.";
+                session.writeResponse(responseString);
+                return;
+            }
+
+            if (session.isAuthRequired() && !session.isRelayingAllowed()) {
+                // Make sure the mail is being sent locally if not
+                // authenticated else reject.
+                if (session.getUser() == null) {
+                    String toDomain = recipientAddress.getHost();
+                    if 
(!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
+                        responseString = "530 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" 
Authentication Required";
+                        session.writeResponse(responseString);
+                        StringBuffer sb = new StringBuffer(128);
+                        sb.append("Rejected message - authentication is 
required for mail request");
+                        
sb.append(getContext(session,recipientAddress,recipient));
+                        getLogger().error(sb.toString());
+                        return;
+                    }
+                } else {
+                    // Identity verification checking
+                    if (session.getConfigurationData().isVerifyIdentity()) {
+                        String authUser = 
(session.getUser()).toLowerCase(Locale.US);
+                        MailAddress senderAddress = (MailAddress) 
session.getState().get(SENDER);
+
+                        if ((senderAddress == null) || 
(!authUser.equals(senderAddress.getUser())) ||
+                            
(!session.getConfigurationData().getMailServer().isLocalServer(senderAddress.getHost())))
 {
+                            responseString = "503 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Incorrect 
Authentication for Specified Email Address";
+                            session.writeResponse(responseString);
+                            if (getLogger().isErrorEnabled()) {
+                                StringBuffer errorBuffer =
+                                    new StringBuffer(128)
+                                        .append("User ")
+                                        .append(authUser)
+                                        .append(" authenticated, however tried 
sending email as ")
+                                        .append(senderAddress)
+                                        
.append(getContext(session,recipientAddress,recipient));
+                                getLogger().error(errorBuffer.toString());
+                            }
+                            return;
+                        }
+                    }
+                }
+            } else if (!session.isRelayingAllowed()) {
+                String toDomain = recipientAddress.getHost();
+                if 
(!session.getConfigurationData().getMailServer().isLocalServer(toDomain)) {
+                    responseString = "550 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Requested 
action not taken: relaying denied";
+                    session.writeResponse(responseString);
+                    StringBuffer errorBuffer = new StringBuffer(128)
+                        .append("Rejected message - ")
+                        .append(session.getRemoteIPAddress())
+                        .append(" not authorized to relay to ")
+                        .append(toDomain)
+                        
.append(getContext(session,recipientAddress,recipient));
+                    getLogger().error(errorBuffer.toString());
+                    return;
+                }
+            }
+            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 (getLogger().isDebugEnabled()) {
+                      StringBuffer debugBuffer =
+                          new StringBuffer(128)
+                              .append("RCPT command had 
unrecognized/unexpected option ")
+                              .append(rcptOptionName)
+                              .append(" with value ")
+                              .append(rcptOptionValue)
+                              
.append(getContext(session,recipientAddress,recipient));
+                      getLogger().debug(debugBuffer.toString());
+                  }
+              }
+              optionTokenizer = null;
+            }
+            
+            // check if we should check for max recipients
+            if (maxRcpt > 0) {
+                int rcptCount = 0;
+            
+                // check if the key exists
+                if (session.getState().get(RCPTCOUNT) != null) {
+                    Integer rcptCountInteger = 
Integer.valueOf(session.getState().get(RCPTCOUNT).toString());
+                    rcptCount = rcptCountInteger.intValue();
+                }
+                
+                rcptCount++;
+        
+                // check if the max recipients has reached
+                if (rcptCount > maxRcpt) {
+                    maxRcptReached = true;
+                    responseString = "550 
"+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Requested 
action not taken: max recipients reached";
+                    session.writeResponse(responseString);
+                    getLogger().error(responseString);
+                }
+                
+                // put the recipient cound in session hashtable
+                session.getState().put(RCPTCOUNT,Integer.toString(rcptCount));
+            }
+            
+            if (maxRcptReached == false) {
+                rcptColl.add(recipientAddress);
+                session.getState().put(RCPT_LIST, rcptColl);
+                responseBuffer.append("250 
"+DSNStatus.getStatus(DSNStatus.SUCCESS,DSNStatus.ADDRESS_VALID)+" Recipient <")
+                              .append(recipient)
+                              .append("> OK");
+                responseString = session.clearResponseBuffer();
+                session.writeResponse(responseString);
+            }
+        }
+    }
+
+
+    private String getContext(SMTPSession session, MailAddress 
recipientAddress, String recipient){
+        StringBuffer sb = new StringBuffer(128);
+        if(null!=recipientAddress) {
+            sb.append(" [to:" + 
(recipientAddress).toInternetAddress().getAddress() + "]");
+        } else if(null!=recipient) {
+            sb.append(" [to:" + recipient + "]");
+        }
+        if (null!=session.getState().get(SENDER)) {
+            sb.append(" [from:" + 
((MailAddress)session.getState().get(SENDER)).toInternetAddress().getAddress() 
+ "]");
+        }
+        return sb.toString();
+    } 
+}

Modified: 
james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java
URL: 
http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java?rev=392092&r1=392091&r2=392092&view=diff
==============================================================================
--- james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java 
(original)
+++ james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java 
Thu Apr  6 15:12:28 2006
@@ -356,6 +356,69 @@
         smtpProtocol1.quit();
     }
     
+    public void testMaxRcpt() throws Exception, SMTPException {
+        m_testConfiguration.setMaxRcpt(1);
+        finishSetUp(m_testConfiguration);
+
+
+        SMTPProtocol smtpProtocol1 = new SMTPProtocol("127.0.0.1", 
m_smtpListenerPort);
+        smtpProtocol1.openPort();
+
+        assertEquals("first connection taken", 1, smtpProtocol1.getState());
+
+        // no message there, yet
+        assertNull("no mail received by mail server", 
m_mailServer.getLastMail());
+
+        smtpProtocol1.helo(InetAddress.getLocalHost());
+
+        String sender1 = "[EMAIL PROTECTED]";
+        String rcpt1 = "[EMAIL PROTECTED]";
+        String rcpt2 = "[EMAIL PROTECTED]";
+    
+        smtpProtocol1.mail(new Address(sender1));
+        smtpProtocol1.rcpt(new Address(rcpt1));
+
+        try {
+            smtpProtocol1.rcpt(new Address(rcpt2));
+            fail("rcpt should not accepted");
+        } catch (SMTPException e) {
+            assertEquals("expected 550 error", 550, e.getCode());
+        }
+        
+        
smtpProtocol1.data(MimeTreeRenderer.getInstance().renderMimePart(createMail()));
+        
+        // After the data is send the rcpt count is set back to 0.. So a new 
mail with rcpt should be accepted
+        
+        smtpProtocol1.mail(new Address(sender1));
+ 
+        smtpProtocol1.rcpt(new Address(rcpt1));
+        
+        
smtpProtocol1.data(MimeTreeRenderer.getInstance().renderMimePart(createMail()));
+        
+        smtpProtocol1.quit();
+        
+    }
+
+    public void testMaxRcptDefault() throws Exception, SMTPException {
+        finishSetUp(m_testConfiguration);
+
+        SMTPProtocol smtpProtocol1 = new SMTPProtocol("127.0.0.1", 
m_smtpListenerPort);
+        smtpProtocol1.openPort();
+        
+        smtpProtocol1.helo(InetAddress.getLocalHost());
+        
+        String sender1 = "[EMAIL PROTECTED]";
+        String rcpt1 = "[EMAIL PROTECTED]";
+        
+        smtpProtocol1.mail(new Address(sender1));
+        
+        smtpProtocol1.rcpt(new Address(rcpt1));
+        
+        
smtpProtocol1.data(MimeTreeRenderer.getInstance().renderMimePart(createMail()));
+        
+        smtpProtocol1.quit();
+    }
+  
     public void testEhloResolv() throws Exception, SMTPException {
         m_testConfiguration.setEhloResolv();
         finishSetUp(m_testConfiguration);

Modified: 
james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java
URL: 
http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java?rev=392092&r1=392091&r2=392092&view=diff
==============================================================================
--- 
james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java
 (original)
+++ 
james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java
 Thu Apr  6 15:12:28 2006
@@ -34,6 +34,7 @@
     private boolean m_heloResolv = false;
     private boolean m_ehloResolv = false;
     private boolean m_senderDomainResolv = false;
+    private int m_maxRcpt = 0;
     
     public SMTPTestConfiguration(int smtpListenerPort) {
         super("smptserver");
@@ -88,6 +89,10 @@
     public void setSenderDomainResolv() {
         m_senderDomainResolv = true; 
     }
+    
+    public void setMaxRcpt(int maxRcpt) {
+        m_maxRcpt = maxRcpt; 
+    }
 
     public void init() throws ConfigurationException {
 
@@ -117,6 +122,8 @@
                     ((DefaultConfiguration) 
heloConfig[i]).addChild(Util.getValuedConfiguration("checkValidEhlo",m_ehloResolv+""));
                 } else if ("MAIL".equals(cmd)) {
                     ((DefaultConfiguration) 
heloConfig[i]).addChild(Util.getValuedConfiguration("checkValidSenderDomain",m_senderDomainResolv+""));
+                } else if ("RCPT".equals(cmd)) {
+                    ((DefaultConfiguration) 
heloConfig[i]).addChild(Util.getValuedConfiguration("maxRcpt",m_maxRcpt+""));
                 }
                 
             }



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to