Matthew,
Thanks for the patches and classes.
I've added them to cvs, except that I've made a new
SizeLimitedSMTPHandler with your patches.
That's because your call to msg.getSize() instantiates a MimeMessage,
whereas Serge recently did a whole load of stuff to delay instantiating
a MimeMessage as long as possible.
I think what we should do is make SMTPServer configurable, so that
admins can choose an instantiate early policy (eg if they want to use
your restricted size stuff) or an instantiate late policy (to minimise
resouce consumpution by never instantiating messages which can be
processed without the MimeMessage )
Thoughts?

Charles


Matthew Pangaro wrote:
> 
> Hello all,
> I made a stab at adding a message size limit to the James Server. I've
> included diffs and new classes in this message. The new functionality
> works at the SMTPHandler level, so it will restrict the size of messages
> for relaying as well as for local delivery. The max message size is
> optionally configured in the conf file in KiloBytes.
> 
> I've done some limited testing running it on Win2K with telnet, Outlook
> Express, and Netscape mail clients connecting, and it seems to work
> well. I've also done a little bit of testing with relaying, and it works
> there, although if the relay is through another james server, you get no
> notification of the failure. Testing with out Netscape Messaging Server,
> however, generated an appropriate bounce message, once the message had
> been relayed.
> 
> Anyway, without further ado, here's the code. I welcome any comments on
> the approach or the code.
> 
> Matt Pangaro
> Loki Technologies
> http://www.lokitech.com
> 
> Index: james.conf.xml
> ===================================================================
> RCS file: /products/cvs/master/james/conf/james.conf.xml,v
> retrieving revision 1.3
> diff -r1.3 james.conf.xml
> 160a161,164
>  >                     <!-- This sets the maximum allowed message size
> for the smtphandler in KBytes.
>  >                         The value defaults to 0, which means no limit.
>  >                     <maxmessagesize> 2000 </maxmessagesize>
>  >                     -->
> 
> Index: SMTPServer.java
> ===================================================================
> RCS file:
> /products/cvs/master/james/src/org/apache/james/smtpserver/SMTPServer.java,v
> retrieving revision 1.16
> diff -r1.16 SMTPServer.java
> 24c24
> <  * @version 1.0.0, 24/04/1999
> ---
>  >  * @version 1.1.0, 06/02/2001
> 25a26
>  >  * @author  Matthew Pangaro <[EMAIL PROTECTED]>
> 34,35c35,36
> <
> <
> ---
>  >     private String handlerStartMesg = "Executing handler";
>  >
> 51c52<  threadPool = ThreadManager.getWorkerPool("whateverNameYouFancy");
> ---
>  >         threadPool = ThreadManager.getWorkerPool("whateverNameYouFancy");
> 61a63,67
>  >         //get the configured max message size so we can log it
>  >         long limit =
> conf.getChild("smtphandler").getChild("maxmessagesize").getValueAsLong(0);
>  >         if (limit > 0) {
>  >             handlerStartMesg += " with message size limit : " + limit
> + " KBytes";
>  >         }
> 76c82
> <             logger.debug("Executing handler.");
> ---
>  >             logger.debug(handlerStartMesg);
> 
> Index: SMTPHandler.java
> ===================================================================
> RCS file:
> /products/cvs/master/james/src/org/apache/james/smtpserver/SMTPHandler.java,v
> retrieving revision 1.28
> diff -r1.28 SMTPHandler.java
> 36c36,37
> <  * @version 0.9
> ---
>  >  * @author Matthew Pangaro <[EMAIL PROTECTED]>
>  >  * @version 0.9.1
> 47a49
>  >     public final static String MESG_FAILED = "MESG_FAILED";
> 74a77
>  >     private long maxmessagesize;
> 78c81,83
> <       timeout = conf.getChild("connectiontimeout").getValueAsLong(120000);
> ---
>  >         timeout =
> conf.getChild("connectiontimeout").getValueAsLong(120000);
>  >         // get the message size limit from the conf file and multiply
> by 1024, to put it in bytes
>  >         maxmessagesize =
> conf.getChild("maxmessagesize").getValueAsLong(0) * 1024;
> 167c172,174
> <         logger.info("Command received: " + command);
> ---
>  >         if (state.get(MESG_FAILED) == null) {
>  >             logger.info("Command received: " + command);
>  >         }
> 208c215,216
> <                 out.println("250 " + state.get(SERVER_NAME) + " Hello
> " + argument + " (" + state.get(REMOTE_NAME) + " [" +
> state.get(REMOTE_IP) + "])");
> ---
>  >                 out.println("250-" + state.get(SERVER_NAME) + " Hello
> " + argument + " (" + state.get(REMOTE_NAME) + " [" +
> state.get(REMOTE_IP) + "])");
>  >                 out.println("250 SIZE " + maxmessagesize);
> 300a309,312
>  >                     // if the message size limit has been set, we'll
> wrap msgIn with a SizeLimitedInputStream
>  >                     if (maxmessagesize > 0) {
>  >                         msgIn = new SizeLimitedInputStream(msgIn,
> maxmessagesize);
>  >                     }
> 332a345,346
>  >                     //call mail.getSize() to force the message to be
> loaded. Need to do this to limit the size
>  >                     mail.getSize();
> 335,337c349,367
> <                     out.println("451 Error processing message: " +
> me.getMessage());
> <                     logger.error("Error processing message: "
> <
>                  + me.getMessage());
> ---
>  >                     //Grab any exception attached to this one.
>  >                     Exception e = me.getNextException();
>  >
>  >                     //If there was an attached exception, and it's a
> MessageSizeException
>  >                     if (e != null && e instanceof MessageSizeException) {
>  >                         logger.error("552 Error processing message: "
>  >                             + e.getMessage());
>  >                         //Add an item to the state to suppress
> logging of extra lines of data
>  >                         //  that are sent after the size limit has
> been hit.
>  >                         state.put(MESG_FAILED, Boolean.TRUE);
>  >
>  >                         //then let the client know that the size
> limit has been hit.
>  >                         out.println("552 Error processing message: "
>  >                             + e.getMessage());
>  >                     } else {
>  >                         out.println("451 Error processing message: "
>  >                             + me.getMessage());
>  >                         logger.error("Error processing message: " +
> me.getMessage());
>  >                     }
> 349c379,381
> <             out.println("500 " + state.get(SERVER_NAME) + " Syntax
> error, command unrecognized: " + command);
> ---
>  >             if (state.get(MESG_FAILED) == null) {
>  >                 out.println("500 " + state.get(SERVER_NAME) + "
> Syntax error, command unrecognized: " + command);
>  >             }
> 
> Index: SizeLimitedInputStream.java
> ===================================================================
> /*****************************************************************************
>   * Copyright (C) The Apache Software Foundation. All rights reserved.
>        *
>   *
> ------------------------------------------------------------------------- *
>   * This software is published under the terms of the Apache Software
> License *
>   * version 1.1, a copy of which has been included  with this
> distribution in *
>   * the LICENSE file.
>        *
> 
> *****************************************************************************/
> package org.apache.james.smtpserver;
> 
> import java.io.*;
> import org.apache.james.smtpserver.*;
> 
> /** This class wraps an underlying input stream, limiting the allowable size
>   * of an incoming MimeMessage. The size limit is configured in the conf
> file,
>   * and when the limit is reached, a MessageSizeException is thrown.
>   * @author Matthew Pangaro <[EMAIL PROTECTED]>
>   */
> public class SizeLimitedInputStream extends InputStream {
> /** Maximum number of bytes to read.
>   */
>      private long maxmessagesize = 0;
> /** Running total of bytes read from wrapped stream.
>   */
>      private long bytesread = 0;
> 
> /** InputStream that will be wrapped.
>   */
>      private InputStream in = null;
> 
> /** Constructor for the stream. Wraps an underlying stream.
>   * @param in InputStream to use as basis for new Stream.
>   * @param maxmessagesize Message size limit, in Kilobytes
>   */
>      public SizeLimitedInputStream(InputStream in, long maxmessagesize) {
>          this.in = in;
>          this.maxmessagesize = maxmessagesize;
>      }
> 
> /** Overrides the read method of InputStream to call the read() method
> of the
>   * wrapped input stream.
>   * @throws IOException Throws a MessageSizeException, which is a
> sub-type of IOException.
>   * @return Returns the int character value of the byte read.
>   */
>      public int read() throws IOException {
>          if (maxmessagesize > 0 && bytesread <= maxmessagesize) {
>              bytesread++;
>              return in.read();
>          } else {
>              throw new MessageSizeException();
>          }
>      }
> }
> 
> Index: MessageSizeException.java
> ===================================================================
> /*****************************************************************************
>   * Copyright (C) The Apache Software Foundation. All rights reserved.
>        *
>   *
> ------------------------------------------------------------------------- *
>   * This software is published under the terms of the Apache Software
> License *
>   * version 1.1, a copy of which has been included  with this
> distribution in *
>   * the LICENSE file.
>        *
> 
> *****************************************************************************/
> package org.apache.james.smtpserver;
> 
> import java.io.*;
> 
> /**
>   * This exceptions is used to indicate when a new MimeMessage has exceeded
>   * the maximum message size for the server, as configured in the conf file.
>   * @author Matthew Pangaro <[EMAIL PROTECTED]>
>   * @version 0.5.1
>   */
> public class MessageSizeException extends IOException {
>      /** Default constructor that sets the message indicating message
> size error.
>       */
>      public MessageSizeException() {
>          super("Message size exceeds fixed maximum message size.");
>      }
> }
> 
> ------------------------------------------------------------
> To subscribe:        [EMAIL PROTECTED]
> To unsubscribe:      [EMAIL PROTECTED]
> Archives:  <http://www.mail-archive.com/james%40list.working-dogs.com/>
> Problems?:           [EMAIL PROTECTED]


------------------------------------------------------------
To subscribe:        [EMAIL PROTECTED]
To unsubscribe:      [EMAIL PROTECTED]
Archives:  <http://www.mail-archive.com/james%40list.working-dogs.com/>
Problems?:           [EMAIL PROTECTED]

Reply via email to