+++ /dev/null
---- src/smtpd/smtpd.h.org Wed Feb 9 03:00:14 2005
-+++ src/smtpd/smtpd.h Mon Feb 7 20:06:58 2005
-@@ -111,6 +111,7 @@
- int sender_rcptmap_checked; /* sender validated against maps */
- int recipient_rcptmap_checked; /* recipient validated against maps */
- int warn_if_reject; /* force reject into warning */
-+ int header_if_reject; /* add header instead of rejecting */
- SMTPD_DEFER defer_if_reject; /* force reject into deferral */
- SMTPD_DEFER defer_if_permit; /* force permit into deferral */
- int defer_if_permit_client; /* force permit into warning */
---- src/global/mail_params.h.org Wed Feb 9 03:01:31 2005
-+++ src/global/mail_params.h Wed Feb 9 02:01:01 2005
-@@ -1578,6 +1578,7 @@
- #define CHECK_RECIP_NS_ACL "check_recipient_ns_access"
-
- #define WARN_IF_REJECT "warn_if_reject"
-+#define HEADER_IF_REJECT "header_if_reject"
-
- #define REJECT_RBL "reject_rbl" /* LaMont compatibility */
- #define REJECT_RBL_CLIENT "reject_rbl_client"
---- src/smtpd/smtpd_check.c.org Sat Dec 27 03:54:03 2003
-+++ src/smtpd/smtpd_check.c Wed Feb 9 06:04:25 2005
-@@ -351,29 +351,29 @@
- * permit-style restriction fails. Otherwise, we could reject legitimate
- * mail.
- */
--static void PRINTFLIKE(3, 4) defer_if(SMTPD_DEFER *, int, const char *,...);
-+static void PRINTFLIKE(4, 5) defer_if(SMTPD_STATE *, SMTPD_DEFER *, int, const char *,...);
-
- #define DEFER_IF_REJECT2(state, class, fmt, a1, a2) \
-- defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2))
-+ defer_if((state), &(state)->defer_if_reject, (class), (fmt), (a1), (a2))
- #define DEFER_IF_REJECT3(state, class, fmt, a1, a2, a3) \
-- defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
-+ defer_if((state), &(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
- #define DEFER_IF_REJECT4(state, class, fmt, a1, a2, a3, a4) \
- defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3), (a4))
- #define DEFER_IF_PERMIT2(state, class, fmt, a1, a2) do { \
- if ((state)->warn_if_reject == 0) \
-- defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2)); \
-+ defer_if((state), &(state)->defer_if_permit, (class), (fmt), (a1), (a2)); \
- else \
- (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2)); \
- } while (0)
- #define DEFER_IF_PERMIT3(state, class, fmt, a1, a2, a3) do { \
- if ((state)->warn_if_reject == 0) \
-- defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3)); \
-+ defer_if((state), &(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3)); \
- else \
- (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3)); \
- } while (0)
- #define DEFER_IF_PERMIT4(state, class, fmt, a1, a2, a3, a4) do { \
- if ((state)->warn_if_reject == 0) \
-- defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3), (a4)); \
-+ defer_if((state), &(state)->defer_if_permit, (class), (fmt), (a1), (a2), (a3), (a4)); \
- else \
- (void) smtpd_check_reject((state), (class), (fmt), (a1), (a2), (a3), (a4)); \
- } while (0)
-@@ -712,7 +712,18 @@
- char *format,...)
- {
- va_list ap;
-+
-+ va_start(ap, format);
-+ vstring_vsprintf(error_text, format, ap);
-+ va_end(ap);
-+
-+ return(xsmtpd_check_reject(state, error_class, error_text));
-+}
-+static int xsmtpd_check_reject(SMTPD_STATE *state, int error_class,
-+ VSTRING *error_text)
-+{
- int warn_if_reject;
-+ int header_if_reject;
- const char *whatsup;
-
- /*
-@@ -726,15 +737,18 @@
- warn_if_reject = 0;
- whatsup = "reject";
- }
-+ if (state->header_if_reject && error_class != MAIL_ERROR_SOFTWARE) {
-+ header_if_reject = 1;
-+ whatsup = "header_warning";
-+ } else {
-+ header_if_reject = 0;
-+ }
-
- /*
- * Update the error class mask, and format the response. XXX What about
- * multi-line responses? For now we cheat and send whitespace.
- */
- state->error_mask |= error_class;
-- va_start(ap, format);
-- vstring_vsprintf(error_text, format, ap);
-- va_end(ap);
-
- /*
- * Ensure RFC compliance. We could do this inside smtpd_chat_reply() and
-@@ -796,15 +810,58 @@
- */
- log_whatsup(state, whatsup, STR(error_text));
-
-- return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT);
-+ if (state->header_if_reject) {
-+ VSTRING *hbuf = vstring_alloc(100);
-+ int elen = strlen(STR(error_text));
-+
-+ if (state->prepend == 0)
-+ state->prepend = argv_alloc(1);
-+ printable(STR(error_text), '?');
-+
-+#define PRETTY_HEADER
-+#ifdef PRETTY_HEADER
-+ if (elen > 65) {
-+ int len = 0, n;
-+ char *p;
-+
-+ vstring_sprintf(hbuf, "%s", "X-Reject: ");
-+ while (len < elen-65 && (p = strchr(STR(error_text)+len+64, ' '))) {
-+ *p = '\t';
-+ n = p-(STR(error_text)+len);
-+ vstring_sprintf_append(hbuf, "%.*s\n", n, STR(error_text)+len);
-+ len+=n;
-+ }
-+ vstring_sprintf_append(hbuf, "%s", STR(error_text)+len);
-+ }
-+ else {
-+ vstring_sprintf(hbuf, "X-Reject: %s", STR(error_text));
-+ }
-+#else
-+ vstring_sprintf(hbuf, "X-Reject: %.*s", 999, STR(error_text));
-+#endif
-+ argv_add(state->prepend, STR(hbuf), ARGV_END);
-+ vstring_free(hbuf);
-+ }
-+
-+ return (warn_if_reject || header_if_reject ? 0 : SMTPD_CHECK_REJECT);
- }
-
- /* defer_if - prepare to change our mind */
-
--static void defer_if(SMTPD_DEFER *defer, int error_class, const char *fmt,...)
-+static void defer_if(SMTPD_STATE *state, SMTPD_DEFER *defer, int error_class, const char *fmt,...)
- {
- va_list ap;
-
-+ if (state->header_if_reject) {
-+ va_start(ap, fmt);
-+ vstring_vsprintf(error_text, fmt, ap);
-+ va_end(ap);
-+ if (STR(error_text)[0] == '5') {
-+ xsmtpd_check_reject(state, error_class, error_text);
-+ return;
-+ }
-+ }
-+
- /*
- * Keep the first reason for this type of deferral, to minimize
- * confusion.
-@@ -3147,6 +3204,11 @@
- state->warn_if_reject = state->recursion;
- continue;
- }
-+ if (strcasecmp(name, HEADER_IF_REJECT) == 0) {
-+ if (state->header_if_reject == 0)
-+ state->header_if_reject = state->recursion;
-+ continue;
-+ }
-
- /*
- * Spoof the is_map_command() routine, so that we do not have to make
-@@ -3500,6 +3562,8 @@
-
- if (state->warn_if_reject >= state->recursion)
- state->warn_if_reject = 0;
-+ if (state->header_if_reject >= state->recursion)
-+ state->header_if_reject = 0;
-
- if (status != 0)
- break;
-@@ -3554,6 +3618,7 @@
- #define SMTPD_CHECK_RESET() { \
- state->recursion = 0; \
- state->warn_if_reject = 0; \
-+ state->header_if_reject = 0; \
- state->defer_if_reject.active = 0; \
- }
-