Backported from 2.3: Bugfix: the SMTP server now separates the message size check from the queue space check, so that the size check can be done before an SMTPD proxy filter. Files: smtpd/smtpd.c, smtpd/smtpd_check.c. diff -ur postfix-2.2.3/src/smtpd/smtpd.c postfix-2.2.3-size/src/smtpd/smtpd.c --- postfix-2.2.3/src/smtpd/smtpd.c 2005-03-09 21:07:43.000000000 +0100 +++ postfix-2.2.3-size/src/smtpd/smtpd.c 2005-09-07 01:57:23.933600904 +0200 @@ -1555,6 +1555,10 @@ return (-1); } } + if ((err = smtpd_check_size(state, state->msg_size)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } if (verp_delims && argv[2].strval[0] == 0) { smtpd_chat_reply(state, "503 Error: %s requires non-null sender", VERP_CMD); @@ -1573,7 +1577,7 @@ * Check the queue file space, if applicable. */ if (!USE_SMTPD_PROXY(state)) { - if ((err = smtpd_check_size(state, state->msg_size)) != 0) { + if ((err = smtpd_check_queue(state)) != 0) { smtpd_chat_reply(state, "%s", err); return (-1); } diff -ur postfix-2.2.3/src/smtpd/smtpd_check.c postfix-2.2.3-size/src/smtpd/smtpd_check.c --- postfix-2.2.3/src/smtpd/smtpd_check.c 2005-03-05 02:13:10.000000000 +0100 +++ postfix-2.2.3-size/src/smtpd/smtpd_check.c 2005-09-07 02:04:32.193697648 +0200 @@ -39,6 +39,13 @@ /* /* char *smtpd_check_eod(state) /* SMTPD_STATE *state; +/* +/* char *smtpd_check_size(state, size) +/* SMTPD_STATE *state; +/* off_t size; +/* +/* char *smtpd_check_queue(state) +/* SMTPD_STATE *state; /* DESCRIPTION /* This module implements additional checks on SMTP client requests. /* A client request is validated in the context of the session state. @@ -101,11 +108,13 @@ /* .PP /* smtpd_check_size() checks if a message with the given size can /* be received (zero means that the message size is unknown). The -/* message is rejected when: -/* .IP \(bu -/* The message size exceeds the non-zero bound specified with the +/* message is rejected when +/* the message size exceeds the non-zero bound specified with the /* \fImessage_size_limit\fR configuration parameter. This is a /* permanent error. +/* +/* smtpd_check_queue() checks the available queue file system +/* space. The message is rejected when: /* .IP \(bu /* The available queue file system space is less than the amount /* specified with the \fImin_queue_free\fR configuration parameter. @@ -4115,8 +4124,6 @@ char *smtpd_check_size(SMTPD_STATE *state, off_t size) { - char *myname = "smtpd_check_size"; - struct fsspace fsbuf; int status; /* @@ -4127,16 +4134,38 @@ return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); /* - * Avoid overflow/underflow when comparing message size against available - * space. + * Check against file size limit. */ -#define BLOCKS(x) ((x) / fsbuf.block_size) if (var_message_limit > 0 && size > var_message_limit) { (void) smtpd_check_reject(state, MAIL_ERROR_POLICY, "552 Message size exceeds fixed limit"); return (STR(error_text)); } + return (0); +} + +/* smtpd_check_queue - check queue space */ + +char *smtpd_check_queue(SMTPD_STATE *state) +{ + char *myname = "smtpd_check_queue"; + struct fsspace fsbuf; + int status; + + /* + * Return here in case of serious trouble. + */ + SMTPD_CHECK_RESET(); + if ((status = setjmp(smtpd_check_buf)) != 0) + return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); + + /* + * Avoid overflow/underflow when comparing message size against available + * space. + */ +#define BLOCKS(x) ((x) / fsbuf.block_size) + fsspace(".", &fsbuf); if (msg_verbose) msg_info("%s: blocks %lu avail %lu min_free %lu msg_size_limit %lu", diff -ur postfix-2.2.3/src/smtpd/smtpd_check.h postfix-2.2.3-size/src/smtpd/smtpd_check.h --- postfix-2.2.3/src/smtpd/smtpd_check.h 2004-11-19 14:23:23.000000000 +0100 +++ postfix-2.2.3-size/src/smtpd/smtpd_check.h 2005-09-07 02:02:10.668212792 +0200 @@ -19,6 +19,7 @@ extern char *smtpd_check_helo(SMTPD_STATE *, char *); extern char *smtpd_check_mail(SMTPD_STATE *, char *); extern char *smtpd_check_size(SMTPD_STATE *, off_t); +extern char *smtpd_check_queue(SMTPD_STATE *); extern char *smtpd_check_rcpt(SMTPD_STATE *, char *); extern char *smtpd_check_etrn(SMTPD_STATE *, char *); extern char *smtpd_check_data(SMTPD_STATE *);