masqmail-0.2

changeset 117:5ec5e6637049

added server-side SMTP SIZE support (patch by Paolo) ``SIZE 0'' (= unlimited) is currently not supported client-side support was already implemented
author meillo@marmaro.de
date Thu, 01 Jul 2010 13:08:53 +0200
parents ddc8041fdee1
children 7f1f364c2a29
files man/masqmail.conf.5 src/accept.c src/conf.c src/masqmail.c src/masqmail.h src/smtp_in.c
diffstat 6 files changed, 77 insertions(+), 8 deletions(-) [+]
line diff
     1.1 --- a/man/masqmail.conf.5	Wed Jun 30 15:45:34 2010 +0200
     1.2 +++ b/man/masqmail.conf.5	Thu Jul 01 13:08:53 2010 +0200
     1.3 @@ -1,4 +1,4 @@
     1.4 -.TH masqmail.conf 5 2010-06-30 masqmail-0.2.25 "File Formats"
     1.5 +.TH masqmail.conf 5 2010-07-01 masqmail-0.2.25 "File Formats"
     1.6  
     1.7  .SH NAME
     1.8  masqmail.conf \- masqmail configuration file
     1.9 @@ -482,6 +482,18 @@
    1.10  For example you can feed your mails into a program like hypermail
    1.11  for archiving purpose by placing an appropriate pipe command in masqmail.alias
    1.12  
    1.13 +.TP
    1.14 +\fBmax_msg_size\fR = \fIbytes\fR
    1.15 +
    1.16 +This option sets the maximum size in bytes masqmail will accept for delivery.
    1.17 +This value is advertised to the SMTP client by the `SIZE' message during SMTP
    1.18 +session setup.
    1.19 +Clients pretending to send, or actually send,
    1.20 +more than \fIbytes\fR will get a 552 error message.
    1.21 +
    1.22 +Default is 104857600 (= 100MB).
    1.23 +(This should be sufficient for most cases.)
    1.24 +
    1.25  
    1.26  .SH AUTHOR
    1.27  
     2.1 --- a/src/accept.c	Wed Jun 30 15:45:34 2010 +0200
     2.2 +++ b/src/accept.c	Thu Jul 01 13:08:53 2010 +0200
     2.3 @@ -155,6 +155,13 @@
     2.4  				line_cnt++;
     2.5  			}
     2.6  		}
     2.7 +		if (data_size > conf.max_msg_size) {
     2.8 +			DEBUG(4) debugf("accept_message_stream(): "
     2.9 +					"received %d bytes (conf.max_msg_size=%d)\n",
    2.10 +			                data_size, conf.max_msg_size);
    2.11 +			return AERR_SIZE;
    2.12 +		}
    2.13 +
    2.14  	}
    2.15  
    2.16  	if (msg->data_list != NULL)
     3.1 --- a/src/conf.c	Wed Jun 30 15:45:34 2010 +0200
     3.2 +++ b/src/conf.c	Thu Jul 01 13:08:53 2010 +0200
     3.3 @@ -431,6 +431,7 @@
     3.4  	conf.do_relay = TRUE;
     3.5  	conf.alias_local_cmp = strcmp;
     3.6  	conf.max_defer_time = 86400 * 4;  /* 4 days */
     3.7 +	conf.max_msg_size = 100*1024*1024; /* in bytes (100MB are probably enough) */
     3.8  
     3.9  	if ((in = fopen(filename, "r")) == NULL) {
    3.10  		fprintf(stderr, "could not open config file %s: %s\n", filename, strerror(errno));
    3.11 @@ -581,7 +582,11 @@
    3.12  				conf.max_defer_time = ival;
    3.13  		} else if (strcmp(lval, "log_user") == 0)
    3.14  			conf.log_user = g_strdup(rval);
    3.15 -
    3.16 +		else if(strcmp(lval, "max_msg_size") == 0) {
    3.17 +			conf.max_msg_size = atol(rval);
    3.18 +			DEBUG(6) fprintf(stderr,"rval=%s, conf.max_msg_size=%ld\n",
    3.19 +			                 rval, conf.max_msg_size);
    3.20 +		}
    3.21  		else
    3.22  			fprintf(stderr, "var '%s' not (yet) known, ignored\n", lval);
    3.23  	}
     4.1 --- a/src/masqmail.c	Wed Jun 30 15:45:34 2010 +0200
     4.2 +++ b/src/masqmail.c	Thu Jul 01 13:08:53 2010 +0200
     4.3 @@ -317,6 +317,9 @@
     4.4  		case AERR_NORCPT:
     4.5  			fprintf(stderr, "no recipients.\n");
     4.6  			exit(EXIT_FAILURE);
     4.7 +		case AERR_SIZE:
     4.8 +			fprintf(stderr, "max message size exceeded.\n");
     4.9 +			exit(EXIT_FAILURE);
    4.10  		default:
    4.11  			/* should never happen: */
    4.12  			fprintf(stderr, "Unknown error (%d)\r\n", err);
     5.1 --- a/src/masqmail.h	Wed Jun 30 15:45:34 2010 +0200
     5.2 +++ b/src/masqmail.h	Thu Jul 01 13:08:53 2010 +0200
     5.3 @@ -174,6 +174,10 @@
     5.4  
     5.5  	guint remote_port;
     5.6  
     5.7 +	/* ANSI C defines unsigned long to be at least 32bit
     5.8 +	   i.e. ca. 4GB max; that should be enough. */
     5.9 +	gulong max_msg_size;
    5.10 +
    5.11  	gboolean do_save_envelope_to;
    5.12  
    5.13  	gboolean defer_all;
    5.14 @@ -332,6 +336,7 @@
    5.15  	AERR_SYNTAX,
    5.16  	AERR_NOSPOOL,
    5.17  	AERR_NORCPT,
    5.18 +	AERR_SIZE,  /* max msg size exeeded (SMTP SIZE) */
    5.19  	AERR_UNKNOWN
    5.20  } accept_error;
    5.21  
     6.1 --- a/src/smtp_in.c	Wed Jun 30 15:45:34 2010 +0200
     6.2 +++ b/src/smtp_in.c	Thu Jul 01 13:08:53 2010 +0200
     6.3 @@ -55,8 +55,29 @@
     6.4  	return SMTP_ERROR;
     6.5  }
     6.6  
     6.7 +static gboolean
     6.8 +get_size(gchar *line, unsigned long *msize) {
     6.9 +	gchar *s = NULL;
    6.10 +
    6.11 +	/* hope we need not to handle cases like SiZe= ...*/
    6.12 +	s = strstr(line, "SIZE=");
    6.13 +	if (!s) {
    6.14 +		/* try it in lowercase too */
    6.15 +		if (!(s = strstr(line, "size="))) {
    6.16 +			return FALSE;
    6.17 +		}
    6.18 +	}
    6.19 +	s += 5;
    6.20 +	*msize = atol(s);
    6.21 +	DEBUG(5) debugf("get_size(): line=%s, msize=%ld\n", line, *msize);
    6.22 +
    6.23 +	return TRUE;
    6.24 +}
    6.25 +
    6.26 +
    6.27  /* this is a quick hack: we expect the address to be syntactically correct
    6.28 -   and containing the mailbox only:
    6.29 +   and containing the mailbox only, though we first check for size in
    6.30 +   smtp_in().
    6.31  */
    6.32  static gboolean
    6.33  get_address(gchar * line, gchar * addr)
    6.34 @@ -135,6 +156,7 @@
    6.35  	message *msg = NULL;
    6.36  	smtp_connection *psc;
    6.37  	int len;
    6.38 +	unsigned long size, msize;
    6.39  
    6.40  	DEBUG(5) debugf("smtp_in entered, remote_host = %s\n", remote_host);
    6.41  
    6.42 @@ -168,7 +190,7 @@
    6.43  
    6.44  			if (psc->prot == PROT_ESMTP) {
    6.45  				smtp_printf(out, "250-%s Nice to meet you with ESMTP\r\n", conf.host_name);
    6.46 -				/* not yet: fprintf(out, "250-SIZE\r\n"); */
    6.47 +				smtp_printf(out, "250-SIZE %d\r\n", conf.max_msg_size);
    6.48  				smtp_printf(out, "250-PIPELINING\r\n" "250 HELP\r\n");
    6.49  			} else {
    6.50  				smtp_printf(out, "250 %s pretty old mailer, huh?\r\n", conf.host_name);
    6.51 @@ -176,6 +198,15 @@
    6.52  			break;
    6.53  
    6.54  		case SMTP_MAIL_FROM:
    6.55 +			if (get_size(buffer, &msize)) {
    6.56 +				DEBUG(5) debugf("smtp_in(): get_size: msize=%ld, conf.mms=%d\n",
    6.57 +				                msize, conf.max_msg_size);
    6.58 +				if (msize > conf.max_msg_size) {
    6.59 +					smtp_printf(out, "552 Message size exceeds fixed limit.\r\n");
    6.60 +					break;
    6.61 +				}
    6.62 +			}
    6.63 +
    6.64  			{
    6.65  				gchar buf[MAX_ADDRESS];
    6.66  				address *addr;
    6.67 @@ -278,12 +309,18 @@
    6.68  
    6.69  			err = accept_message(in, msg, conf.do_save_envelope_to ? ACC_SAVE_ENVELOPE_TO : 0);
    6.70  			if (err != AERR_OK) {
    6.71 -				if (err == AERR_TIMEOUT || err == AERR_EOF) {
    6.72 +				switch (err) {
    6.73 +				case AERR_TIMEOUT:
    6.74 +				case AERR_EOF:
    6.75 +					return;
    6.76 +				case AERR_SIZE:
    6.77 +					smtp_printf(out, "552 Error: message too large.\r\n");
    6.78 +					return;
    6.79 +				default:
    6.80 +					/* should never happen: */
    6.81 +					smtp_printf(out, "451 Unknown error\r\n");
    6.82  					return;
    6.83  				}
    6.84 -				/* should never happen: */
    6.85 -				smtp_printf(out, "451 Unknown error\r\n");
    6.86 -				return;
    6.87  			}
    6.88  
    6.89