# HG changeset patch # User meillo@marmaro.de # Date 1277982533 -7200 # Node ID 5ec5e6637049eb85c90facd15012b2c29695ca5f # Parent ddc8041fdee18f21835cb04a8a098ee93f52c0d5 added server-side SMTP SIZE support (patch by Paolo) ``SIZE 0'' (= unlimited) is currently not supported client-side support was already implemented diff -r ddc8041fdee1 -r 5ec5e6637049 man/masqmail.conf.5 --- a/man/masqmail.conf.5 Wed Jun 30 15:45:34 2010 +0200 +++ b/man/masqmail.conf.5 Thu Jul 01 13:08:53 2010 +0200 @@ -1,4 +1,4 @@ -.TH masqmail.conf 5 2010-06-30 masqmail-0.2.25 "File Formats" +.TH masqmail.conf 5 2010-07-01 masqmail-0.2.25 "File Formats" .SH NAME masqmail.conf \- masqmail configuration file @@ -482,6 +482,18 @@ For example you can feed your mails into a program like hypermail for archiving purpose by placing an appropriate pipe command in masqmail.alias +.TP +\fBmax_msg_size\fR = \fIbytes\fR + +This option sets the maximum size in bytes masqmail will accept for delivery. +This value is advertised to the SMTP client by the `SIZE' message during SMTP +session setup. +Clients pretending to send, or actually send, +more than \fIbytes\fR will get a 552 error message. + +Default is 104857600 (= 100MB). +(This should be sufficient for most cases.) + .SH AUTHOR diff -r ddc8041fdee1 -r 5ec5e6637049 src/accept.c --- a/src/accept.c Wed Jun 30 15:45:34 2010 +0200 +++ b/src/accept.c Thu Jul 01 13:08:53 2010 +0200 @@ -155,6 +155,13 @@ line_cnt++; } } + if (data_size > conf.max_msg_size) { + DEBUG(4) debugf("accept_message_stream(): " + "received %d bytes (conf.max_msg_size=%d)\n", + data_size, conf.max_msg_size); + return AERR_SIZE; + } + } if (msg->data_list != NULL) diff -r ddc8041fdee1 -r 5ec5e6637049 src/conf.c --- a/src/conf.c Wed Jun 30 15:45:34 2010 +0200 +++ b/src/conf.c Thu Jul 01 13:08:53 2010 +0200 @@ -431,6 +431,7 @@ conf.do_relay = TRUE; conf.alias_local_cmp = strcmp; conf.max_defer_time = 86400 * 4; /* 4 days */ + conf.max_msg_size = 100*1024*1024; /* in bytes (100MB are probably enough) */ if ((in = fopen(filename, "r")) == NULL) { fprintf(stderr, "could not open config file %s: %s\n", filename, strerror(errno)); @@ -581,7 +582,11 @@ conf.max_defer_time = ival; } else if (strcmp(lval, "log_user") == 0) conf.log_user = g_strdup(rval); - + else if(strcmp(lval, "max_msg_size") == 0) { + conf.max_msg_size = atol(rval); + DEBUG(6) fprintf(stderr,"rval=%s, conf.max_msg_size=%ld\n", + rval, conf.max_msg_size); + } else fprintf(stderr, "var '%s' not (yet) known, ignored\n", lval); } diff -r ddc8041fdee1 -r 5ec5e6637049 src/masqmail.c --- a/src/masqmail.c Wed Jun 30 15:45:34 2010 +0200 +++ b/src/masqmail.c Thu Jul 01 13:08:53 2010 +0200 @@ -317,6 +317,9 @@ case AERR_NORCPT: fprintf(stderr, "no recipients.\n"); exit(EXIT_FAILURE); + case AERR_SIZE: + fprintf(stderr, "max message size exceeded.\n"); + exit(EXIT_FAILURE); default: /* should never happen: */ fprintf(stderr, "Unknown error (%d)\r\n", err); diff -r ddc8041fdee1 -r 5ec5e6637049 src/masqmail.h --- a/src/masqmail.h Wed Jun 30 15:45:34 2010 +0200 +++ b/src/masqmail.h Thu Jul 01 13:08:53 2010 +0200 @@ -174,6 +174,10 @@ guint remote_port; + /* ANSI C defines unsigned long to be at least 32bit + i.e. ca. 4GB max; that should be enough. */ + gulong max_msg_size; + gboolean do_save_envelope_to; gboolean defer_all; @@ -332,6 +336,7 @@ AERR_SYNTAX, AERR_NOSPOOL, AERR_NORCPT, + AERR_SIZE, /* max msg size exeeded (SMTP SIZE) */ AERR_UNKNOWN } accept_error; diff -r ddc8041fdee1 -r 5ec5e6637049 src/smtp_in.c --- a/src/smtp_in.c Wed Jun 30 15:45:34 2010 +0200 +++ b/src/smtp_in.c Thu Jul 01 13:08:53 2010 +0200 @@ -55,8 +55,29 @@ return SMTP_ERROR; } +static gboolean +get_size(gchar *line, unsigned long *msize) { + gchar *s = NULL; + + /* hope we need not to handle cases like SiZe= ...*/ + s = strstr(line, "SIZE="); + if (!s) { + /* try it in lowercase too */ + if (!(s = strstr(line, "size="))) { + return FALSE; + } + } + s += 5; + *msize = atol(s); + DEBUG(5) debugf("get_size(): line=%s, msize=%ld\n", line, *msize); + + return TRUE; +} + + /* this is a quick hack: we expect the address to be syntactically correct - and containing the mailbox only: + and containing the mailbox only, though we first check for size in + smtp_in(). */ static gboolean get_address(gchar * line, gchar * addr) @@ -135,6 +156,7 @@ message *msg = NULL; smtp_connection *psc; int len; + unsigned long size, msize; DEBUG(5) debugf("smtp_in entered, remote_host = %s\n", remote_host); @@ -168,7 +190,7 @@ if (psc->prot == PROT_ESMTP) { smtp_printf(out, "250-%s Nice to meet you with ESMTP\r\n", conf.host_name); - /* not yet: fprintf(out, "250-SIZE\r\n"); */ + smtp_printf(out, "250-SIZE %d\r\n", conf.max_msg_size); smtp_printf(out, "250-PIPELINING\r\n" "250 HELP\r\n"); } else { smtp_printf(out, "250 %s pretty old mailer, huh?\r\n", conf.host_name); @@ -176,6 +198,15 @@ break; case SMTP_MAIL_FROM: + if (get_size(buffer, &msize)) { + DEBUG(5) debugf("smtp_in(): get_size: msize=%ld, conf.mms=%d\n", + msize, conf.max_msg_size); + if (msize > conf.max_msg_size) { + smtp_printf(out, "552 Message size exceeds fixed limit.\r\n"); + break; + } + } + { gchar buf[MAX_ADDRESS]; address *addr; @@ -278,12 +309,18 @@ err = accept_message(in, msg, conf.do_save_envelope_to ? ACC_SAVE_ENVELOPE_TO : 0); if (err != AERR_OK) { - if (err == AERR_TIMEOUT || err == AERR_EOF) { + switch (err) { + case AERR_TIMEOUT: + case AERR_EOF: + return; + case AERR_SIZE: + smtp_printf(out, "552 Error: message too large.\r\n"); + return; + default: + /* should never happen: */ + smtp_printf(out, "451 Unknown error\r\n"); return; } - /* should never happen: */ - smtp_printf(out, "451 Unknown error\r\n"); - return; }