Fix incorrect use of local user name for trusted submissions.
[exim.git] / src / src / receive.c
index e4ce9cb233862b775ad5c4c83c782cca0cb73948..75447499bfe9713e52ccbb080f5d332a5dd1cdb1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.12 2005/03/08 15:32:02 tom Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.23 2005/09/07 10:15:33 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -303,8 +303,8 @@ if (spool_name[0] != 0)
 
 /* Now close the file if it is open, either as a fd or a stream. */
 
-if (data_file != NULL) fclose(data_file);
-  else if (data_fd >= 0) close(data_fd);
+if (data_file != NULL) (void)fclose(data_file);
+  else if (data_fd >= 0) (void)close(data_fd);
 
 /* Attempt to close down an SMTP connection tidily. */
 
@@ -351,8 +351,9 @@ if (smtp_input)
   msg = US"SMTP incoming data timeout";
   log_write(L_lost_incoming_connection,
             LOG_MAIN, "SMTP data timeout (message abandoned) on connection "
-            "from %s",
-            (sender_fullhost != NULL)? sender_fullhost : US"local process");
+            "from %s F=<%s>",
+            (sender_fullhost != NULL)? sender_fullhost : US"local process",
+            sender_address);
   }
 else
   {
@@ -510,7 +511,7 @@ for (count = 0; count < recipients_count; count++)
     {
     if ((--recipients_count - count) > 0)
       memmove(recipients_list + count, recipients_list + count + 1,
-              (recipients_count - count)*sizeof(recipient_item));
+        (recipients_count - count)*sizeof(recipient_item));
     return TRUE;
     }
   }
@@ -864,7 +865,7 @@ if (error_handling == ERRORS_SENDER)
     error_rc = EXIT_FAILURE;
   }
 else fprintf(stderr, "exim: %s%s\n", text2, text1);  /* Sic */
-fclose(f);
+(void)fclose(f);
 exim_exit(error_rc);
 }
 
@@ -1007,6 +1008,149 @@ return s;
 
 
 
+#ifdef WITH_CONTENT_SCAN
+
+/*************************************************
+*       Run the MIME ACL on a message            *
+*************************************************/
+
+/* This code is in a subroutine so that it can be used for both SMTP
+and non-SMTP messages. It is called with a non-NULL ACL pointer.
+
+Arguments:
+  acl                The ACL to run (acl_smtp_mime or acl_not_smtp_mime)
+  smtp_yield_ptr     Set FALSE to kill messages after dropped connection
+  smtp_reply_ptr     Where SMTP reply is being built
+  blackholed_by_ptr  Where "blackholed by" message is being built
+
+Returns:             TRUE to carry on; FALSE to abandon the message
+*/
+
+static BOOL
+run_mime_acl(uschar *acl, BOOL *smtp_yield_ptr, uschar **smtp_reply_ptr,
+  uschar **blackholed_by_ptr)
+{
+FILE *mbox_file;
+uschar rfc822_file_path[2048];
+unsigned long mbox_size;
+header_line *my_headerlist;
+uschar *user_msg, *log_msg;
+int mime_part_count_buffer = -1;
+int rc;
+
+memset(CS rfc822_file_path,0,2048);
+
+/* check if it is a MIME message */
+my_headerlist = header_list;
+while (my_headerlist != NULL) {
+  /* skip deleted headers */
+  if (my_headerlist->type == '*') {
+    my_headerlist = my_headerlist->next;
+    continue;
+  };
+  if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) {
+    DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n");
+    goto DO_MIME_ACL;
+  };
+  my_headerlist = my_headerlist->next;
+};
+
+DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
+return TRUE;
+
+DO_MIME_ACL:
+/* make sure the eml mbox file is spooled up */
+mbox_file = spool_mbox(&mbox_size);
+if (mbox_file == NULL) {
+  /* error while spooling */
+  log_write(0, LOG_MAIN|LOG_PANIC,
+         "acl_smtp_mime: error while creating mbox spool file, message temporarily rejected.");
+  Uunlink(spool_name);
+  unspool_mbox();
+  smtp_respond(451, TRUE, US"temporary local problem");
+  message_id[0] = 0;            /* Indicate no message accepted */
+  *smtp_reply_ptr = US"";       /* Indicate reply already sent */
+  return FALSE;                 /* Indicate skip to end of receive function */
+};
+
+mime_is_rfc822 = 0;
+
+MIME_ACL_CHECK:
+mime_part_count = -1;
+rc = mime_acl_check(acl, mbox_file, NULL, &user_msg, &log_msg);
+(void)fclose(mbox_file);
+
+if (Ustrlen(rfc822_file_path) > 0) {
+  mime_part_count = mime_part_count_buffer;
+
+  if (unlink(CS rfc822_file_path) == -1) {
+    log_write(0, LOG_PANIC,
+         "acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
+      goto END_MIME_ACL;
+  };
+};
+
+/* check if we must check any message/rfc822 attachments */
+if (rc == OK) {
+  uschar temp_path[1024];
+  int n;
+  struct dirent *entry;
+  DIR *tempdir;
+
+  (void)string_format(temp_path, 1024, "%s/scan/%s", spool_directory,
+    message_id);
+
+ tempdir = opendir(CS temp_path);
+ n = 0;
+ do {
+   entry = readdir(tempdir);
+   if (entry == NULL) break;
+    if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) {
+      (void)string_format(rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
+     debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
+     break;
+    };
+ } while (1);
+ closedir(tempdir);
+
+  if (entry != NULL) {
+    mbox_file = Ufopen(rfc822_file_path,"rb");
+    if (mbox_file == NULL) {
+      log_write(0, LOG_PANIC,
+         "acl_smtp_mime: can't open RFC822 spool file, skipping.");
+      unlink(CS rfc822_file_path);
+      goto END_MIME_ACL;
+    };
+    /* set RFC822 expansion variable */
+    mime_is_rfc822 = 1;
+    mime_part_count_buffer = mime_part_count;
+    goto MIME_ACL_CHECK;
+  };
+};
+
+END_MIME_ACL:
+add_acl_headers(US"MIME");
+if (rc == DISCARD)
+  {
+  recipients_count = 0;
+  *blackholed_by_ptr = US"MIME ACL";
+  }
+else if (rc != OK)
+  {
+  Uunlink(spool_name);
+  unspool_mbox();
+  if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
+    *smtp_yield_ptr = FALSE;    /* No more messsages after dropped connection */
+  *smtp_reply_ptr = US"";       /* Indicate reply already sent */
+  message_id[0] = 0;            /* Indicate no message accepted */
+  return FALSE;                 /* Cause skip to end of receive function */
+  };
+
+return TRUE;
+}
+
+#endif  /* WITH_CONTENT_SCAN */
+
 
 /*************************************************
 *                 Receive message                *
@@ -1196,11 +1340,9 @@ received_count = 1;     /* For the one we will add */
 
 if (thismessage_size_limit <= 0) thismessage_size_limit = INT_MAX;
 
-/* While reading the message, body_linecount and body_zerocount is computed.
-The full message_ linecount is set up only when the headers are read back in
-from the spool for delivery. */
+/* While reading the message, the following counts are computed. */
 
-body_linecount = body_zerocount = 0;
+message_linecount = body_linecount = body_zerocount = 0;
 
 #ifdef EXPERIMENTAL_DOMAINKEYS
 /* Call into DK to set up the context. Check if DK is to be run are carried out
@@ -1430,7 +1572,11 @@ for (;;)
   /* End of header line reached */
 
   EOL:
-  receive_linecount++;          /* For BSMTP errors */
+
+  /* Keep track of lines for BSMTP errors and overall message_linecount. */
+
+  receive_linecount++;
+  message_linecount++;
 
   /* Now put in the terminating newline. There is always space for
   at least two more characters. */
@@ -2192,35 +2338,62 @@ Sender: if it is required. */
 
 if (from_header == NULL && (sender_host_address == NULL || submission_mode))
   {
+  uschar *oname = US"";
+
+  /* Use the originator_name if this is a locally submitted message and the
+  caller is not trusted. For trusted callers, use it only if -F was used to
+  force its value or if we have a non-SMTP message for which -f was not used
+  to set the sender. */
+
+  if (sender_host_address == NULL)
+    {
+    if (!trusted_caller || sender_name_forced ||
+         (!smtp_input && !sender_address_forced))
+      oname = originator_name;
+    }
+
+  /* For non-locally submitted messages, the only time we use the originator
+  name is when it was forced by the /name= option on control=submission. */
+
+  else
+    {
+    if (submission_name != NULL) oname = submission_name;
+    }
+
   /* Envelope sender is empty */
 
   if (sender_address[0] == 0)
     {
+    uschar *fromstart, *fromend;
+
+    fromstart = string_sprintf("%sFrom: %s%s", resent_prefix,
+      oname, (oname[0] == 0)? "" : " <");
+    fromend = (oname[0] == 0)? US"" : US">";
+
     if (sender_local || local_error_message)
       {
-      header_add(htype_from, "%sFrom: %s%s%s@%s%s\n", resent_prefix,
-        originator_name,
-        (originator_name[0] == 0)? "" : " <",
-        local_part_quote(originator_login),
-        qualify_domain_sender,
-        (originator_name[0] == 0)? "" : ">");
+      header_add(htype_from, "%s%s@%s%s\n", fromstart,
+        local_part_quote(originator_login), qualify_domain_sender,
+        fromend);
       }
     else if (submission_mode && authenticated_id != NULL)
       {
       if (submission_domain == NULL)
         {
-        header_add(htype_from, "%sFrom: %s@%s\n", resent_prefix,
-          local_part_quote(authenticated_id), qualify_domain_sender);
+        header_add(htype_from, "%s%s@%s%s\n", fromstart,
+          local_part_quote(authenticated_id), qualify_domain_sender,
+          fromend);
         }
       else if (submission_domain[0] == 0)  /* empty => whole address set */
         {
-        header_add(htype_from, "%sFrom: %s\n", resent_prefix,
-          authenticated_id);
+        header_add(htype_from, "%s%s%s\n", fromstart, authenticated_id,
+          fromend);
         }
       else
         {
-        header_add(htype_from, "%sFrom: %s@%s\n", resent_prefix,
-          local_part_quote(authenticated_id), submission_domain);
+        header_add(htype_from, "%s%s@%s%s\n", fromstart,
+          local_part_quote(authenticated_id), submission_domain,
+          fromend);
         }
       from_header = header_last;    /* To get it checked for Sender: */
       }
@@ -2232,15 +2405,12 @@ if (from_header == NULL && (sender_host_address == NULL || submission_mode))
 
   else
     {
-    if (!smtp_input || sender_local)
-      header_add(htype_from, "%sFrom: %s%s%s%s\n",
-        resent_prefix, originator_name,
-        (originator_name[0] == 0)? "" : " <",
-        (sender_address_unrewritten == NULL)?
-          sender_address : sender_address_unrewritten,
-        (originator_name[0] == 0)? "" : ">");
-    else
-      header_add(htype_from, "%sFrom: %s\n", resent_prefix, sender_address);
+    header_add(htype_from, "%sFrom: %s%s%s%s\n", resent_prefix,
+      oname,
+      (oname[0] == 0)? "" : " <",
+      (sender_address_unrewritten == NULL)?
+        sender_address : sender_address_unrewritten,
+      (oname[0] == 0)? "" : ">");
 
     from_header = header_last;    /* To get it checked for Sender: */
     }
@@ -2321,12 +2491,27 @@ if (from_header != NULL &&
 
   if (make_sender)
     {
-    if (submission_mode)
+    if (submission_mode && submission_name == NULL)
       header_add(htype_sender, "%sSender: %s\n", resent_prefix,
         generated_sender_address);
     else
       header_add(htype_sender, "%sSender: %s <%s>\n",
-        resent_prefix, originator_name, generated_sender_address);
+        resent_prefix,
+        submission_mode? submission_name : originator_name,
+        generated_sender_address);
+    }
+
+  /* Ensure that a non-null envelope sender address corresponds to the
+  submission mode sender address. */
+
+  if (submission_mode && sender_address[0] != 0)
+    {
+    if (sender_address_unrewritten == NULL)
+      sender_address_unrewritten = sender_address;
+    sender_address = generated_sender_address;
+    log_write(L_address_rewrite, LOG_MAIN,
+      "\"%s\" from env-from rewritten as \"%s\" by submission mode",
+      sender_address_unrewritten, generated_sender_address);
     }
   }
 
@@ -2442,8 +2627,8 @@ if (data_fd < 0)
 /* Make sure the file's group is the Exim gid, and double-check the mode
 because the group setting doesn't always get set automatically. */
 
-fchown(data_fd, exim_uid, exim_gid);
-fchmod(data_fd, SPOOL_MODE);
+(void)fchown(data_fd, exim_uid, exim_gid);
+(void)fchmod(data_fd, SPOOL_MODE);
 
 /* We now have data file open. Build a stream for it and lock it. We lock only
 the first line of the file (containing the message ID) because otherwise there
@@ -2472,7 +2657,7 @@ if (next != NULL)
   {
   uschar *s = next->text;
   int len = next->slen;
-  fwrite(s, 1, len, data_file);
+  (void)fwrite(s, 1, len, data_file);
   body_linecount++;                 /* Assumes only 1 line */
   }
 
@@ -2490,6 +2675,7 @@ if (!ferror(data_file) && !(receive_feof)() && message_ended != END_DOT)
   else message_ended = read_message_data(data_file);
 
   receive_linecount += body_linecount;  /* For BSMTP errors mainly */
+  message_linecount += body_linecount;
 
   /* Handle premature termination of SMTP */
 
@@ -2662,7 +2848,7 @@ if (extract_recip && (bad_addresses != NULL || recipients_count == 0))
   if (recipients_count == 0 || error_handling == ERRORS_STDERR)
     {
     Uunlink(spool_name);
-    fclose(data_file);
+    (void)fclose(data_file);
     exim_exit(error_rc);
     }
   }
@@ -2754,127 +2940,13 @@ else
 #endif
 
 #ifdef WITH_CONTENT_SCAN
-     /* MIME ACL hook */
-    if (acl_smtp_mime != NULL && recipients_count > 0)
-      {
-      FILE *mbox_file;
-      uschar rfc822_file_path[2048];
-      unsigned long mbox_size;
-      header_line *my_headerlist;
-      uschar *user_msg, *log_msg;
-      int mime_part_count_buffer = -1;
-
-      memset(CS rfc822_file_path,0,2048);
-
-      /* check if it is a MIME message */
-      my_headerlist = header_list;
-      while (my_headerlist != NULL) {
-        /* skip deleted headers */
-        if (my_headerlist->type == '*') {
-          my_headerlist = my_headerlist->next;
-          continue;
-        };
-        if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) {
-          DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n");
-          goto DO_MIME_ACL;
-        };
-        my_headerlist = my_headerlist->next;
-      };
-
-      DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
-      goto NO_MIME_ACL;
-
-      DO_MIME_ACL:
-      /* make sure the eml mbox file is spooled up */
-      mbox_file = spool_mbox(&mbox_size);
-      if (mbox_file == NULL) {
-        /* error while spooling */
-        log_write(0, LOG_MAIN|LOG_PANIC,
-               "acl_smtp_mime: error while creating mbox spool file, message temporarily rejected.");
-        Uunlink(spool_name);
-        unspool_mbox();
-        smtp_respond(451, TRUE, US"temporary local problem");
-        message_id[0] = 0;            /* Indicate no message accepted */
-        smtp_reply = US"";            /* Indicate reply already sent */
-        goto TIDYUP;                  /* Skip to end of function */
-      };
-
-      mime_is_rfc822 = 0;
-
-      MIME_ACL_CHECK:
-      mime_part_count = -1;
-      rc = mime_acl_check(mbox_file, NULL, &user_msg, &log_msg);
-      fclose(mbox_file);
-
-      if (Ustrlen(rfc822_file_path) > 0) {
-        mime_part_count = mime_part_count_buffer;
-
-        if (unlink(CS rfc822_file_path) == -1) {
-          log_write(0, LOG_PANIC,
-               "acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
-            goto END_MIME_ACL;
-        };
-      };
-
-      /* check if we must check any message/rfc822 attachments */
-      if (rc == OK) {
-        uschar temp_path[1024];
-        int n;
-        struct dirent *entry;
-        DIR *tempdir;
-
-        snprintf(CS temp_path, 1024, "%s/scan/%s", spool_directory, message_id);
-
-       tempdir = opendir(CS temp_path);
-       n = 0;
-       do {
-         entry = readdir(tempdir);
-         if (entry == NULL) break;
-          if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) {
-            snprintf(CS rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
-           debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
-           break;
-          };
-       } while (1);
-       closedir(tempdir);
-
-        if (entry != NULL) {
-          mbox_file = Ufopen(rfc822_file_path,"r");
-          if (mbox_file == NULL) {
-            log_write(0, LOG_PANIC,
-               "acl_smtp_mime: can't open RFC822 spool file, skipping.");
-            unlink(CS rfc822_file_path);
-            goto END_MIME_ACL;
-          };
-          /* set RFC822 expansion variable */
-          mime_is_rfc822 = 1;
-          mime_part_count_buffer = mime_part_count;
-          goto MIME_ACL_CHECK;
-        };
-      };
-
-      END_MIME_ACL:
-      add_acl_headers(US"MIME");
-      if (rc == DISCARD)
-        {
-        recipients_count = 0;
-        blackholed_by = US"MIME ACL";
-        }
-      else if (rc != OK)
-        {
-        Uunlink(spool_name);
-        unspool_mbox();
-        if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
-          smtp_yield = FALSE;    /* No more messsages after dropped connection */
-        smtp_reply = US"";       /* Indicate reply already sent */
-        message_id[0] = 0;       /* Indicate no message accepted */
-        goto TIDYUP;             /* Skip to end of function */
-        };
-      }
-
-    NO_MIME_ACL:
+    if (acl_smtp_mime != NULL &&
+        !run_mime_acl(acl_smtp_mime, &smtp_yield, &smtp_reply, &blackholed_by))
+      goto TIDYUP;
 #endif /* WITH_CONTENT_SCAN */
 
+    /* Check the recipients count again, as the MIME ACL might have changed
+    them. */
 
     if (acl_smtp_data != NULL && recipients_count > 0)
       {
@@ -2906,39 +2978,56 @@ else
   /* Handle non-SMTP and batch SMTP (i.e. non-interactive) messages. Note that
   we cannot take different actions for permanent and temporary rejections. */
 
-  else if (acl_not_smtp != NULL)
+  else
     {
-    uschar *user_msg, *log_msg;
-    rc = acl_check(ACL_WHERE_NOTSMTP, NULL, acl_not_smtp, &user_msg, &log_msg);
-    if (rc == DISCARD)
-      {
-      recipients_count = 0;
-      blackholed_by = US"non-SMTP ACL";
-      if (log_msg != NULL) blackhole_log_msg = string_sprintf(": %s", log_msg);
-      }
-    else if (rc != OK)
+
+#ifdef WITH_CONTENT_SCAN
+    if (acl_not_smtp_mime != NULL &&
+        !run_mime_acl(acl_not_smtp_mime, &smtp_yield, &smtp_reply,
+          &blackholed_by))
+      goto TIDYUP;
+#endif /* WITH_CONTENT_SCAN */
+
+    if (acl_not_smtp != NULL)
       {
-      Uunlink(spool_name);
-      log_write(0, LOG_MAIN|LOG_REJECT, "F=<%s> rejected by non-SMTP ACL: %s",
-        sender_address, log_msg);
-      if (user_msg == NULL) user_msg = US"local configuration problem";
-      if (smtp_batched_input)
+      uschar *user_msg, *log_msg;
+      rc = acl_check(ACL_WHERE_NOTSMTP, NULL, acl_not_smtp, &user_msg, &log_msg);
+      if (rc == DISCARD)
         {
-        moan_smtp_batch(NULL, "%d %s", 550, user_msg);
-        /* Does not return */
+        recipients_count = 0;
+        blackholed_by = US"non-SMTP ACL";
+        if (log_msg != NULL)
+          blackhole_log_msg = string_sprintf(": %s", log_msg);
         }
-      else
+      else if (rc != OK)
         {
-        fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
-        give_local_error(ERRMESS_LOCAL_ACL, user_msg,
-          US"message rejected by non-SMTP ACL: ", error_rc, data_file,
-            header_list);
-        /* Does not return */
+        Uunlink(spool_name);
+#ifdef WITH_CONTENT_SCAN
+        unspool_mbox();
+#endif
+        log_write(0, LOG_MAIN|LOG_REJECT, "F=<%s> rejected by non-SMTP ACL: %s",
+          sender_address, log_msg);
+        if (user_msg == NULL) user_msg = US"local configuration problem";
+        if (smtp_batched_input)
+          {
+          moan_smtp_batch(NULL, "%d %s", 550, user_msg);
+          /* Does not return */
+          }
+        else
+          {
+          fseek(data_file, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
+          give_local_error(ERRMESS_LOCAL_ACL, user_msg,
+            US"message rejected by non-SMTP ACL: ", error_rc, data_file,
+              header_list);
+          /* Does not return */
+          }
         }
+      add_acl_headers(US"non-SMTP");
       }
-    add_acl_headers(US"non-SMTP");
     }
 
+  /* The applicable ACLs have been run */
+
   if (deliver_freeze) frozen_by = US"ACL";     /* for later logging */
   if (queue_only_policy) queued_by = US"ACL";
 
@@ -3345,7 +3434,7 @@ if (message_logs && blackholed_by == NULL)
       {
       log_write(0, LOG_MAIN|LOG_PANIC, "Couldn't fdopen message log %s: %s",
         spool_name, strerror(errno));
-      close(fd);
+      (void)close(fd);
       }
     else
       {
@@ -3355,7 +3444,7 @@ if (message_logs && blackholed_by == NULL)
         frozen_by);
       if (queue_only_policy) fprintf(message_log,
         "%s no immediate delivery: queued by %s\n", now, queued_by);
-      fclose(message_log);
+      (void)fclose(message_log);
       }
     }
   }
@@ -3387,8 +3476,8 @@ possible for fclose() to fail - but what to do? What has happened to the lock
 if this happens? */
 
 TIDYUP:
-process_info[process_info_len] = 0;          /* Remove message id */
-if (data_file != NULL) fclose(data_file);    /* Frees the lock */
+process_info[process_info_len] = 0;                /* Remove message id */
+if (data_file != NULL) (void)fclose(data_file);    /* Frees the lock */
 
 /* Now reset signal handlers to their defaults */
 
@@ -3413,8 +3502,9 @@ if (smtp_input)
     {
     if (smtp_reply == NULL)
       {
-      if (fake_reject)
-        smtp_respond(550,TRUE,fake_reject_text);
+      if (fake_response != OK)
+        smtp_respond(fake_response == DEFER ? 450 : 550,
+                     TRUE, fake_response_text);
       else
         smtp_printf("250 OK id=%s\r\n", message_id);
       if (host_checking)
@@ -3423,8 +3513,9 @@ if (smtp_input)
       }
     else if (smtp_reply[0] != 0)
       {
-      if (fake_reject && (smtp_reply[0] == '2'))
-        smtp_respond(550,TRUE,fake_reject_text);
+      if (fake_response != OK && (smtp_reply[0] == '2'))
+        smtp_respond(fake_response == DEFER ? 450 : 550,
+                     TRUE, fake_response_text);
       else
         smtp_printf("%.1024s\r\n", smtp_reply);
       }