Bugzilla 1041: pull patch id=425, DCC fixes.
[exim.git] / src / src / receive.c
index ee95cc98120aea90b184c9a9bc76a52bb6ca2748..914b1d2811b6a5801e92157c3e769ade0033da8b 100644 (file)
@@ -1,22 +1,18 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.38 2007/06/22 14:38:58 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.55 2010/06/05 11:13:30 pdp Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2007 */
+/* Copyright (c) University of Cambridge 1995 - 2009 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Code for receiving a message and setting up spool files. */
 
 #include "exim.h"
 
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Code for receiving a message and setting up spool files. */
 
 #include "exim.h"
 
-#ifdef EXPERIMENTAL_DOMAINKEYS
-#define RECEIVE_GETC dk_receive_getc
-#define RECEIVE_UNGETC dk_receive_ungetc
-#else
-#define RECEIVE_GETC receive_getc
-#define RECEIVE_UNGETC receive_ungetc
+#ifdef EXPERIMENTAL_DCC
+extern int dcc_ok;
 #endif
 
 /*************************************************
 #endif
 
 /*************************************************
@@ -178,7 +174,7 @@ else
     }
   }
 
     }
   }
 
-/* We now have the patch; do the business */
+/* We now have the path; do the business */
 
 memset(&statbuf, 0, sizeof(statbuf));
 
 
 memset(&statbuf, 0, sizeof(statbuf));
 
@@ -283,12 +279,14 @@ that case is done by setting a flag to cause the log functions to call this
 function if there is an ultimate disaster. That is why it is globally
 accessible.
 
 function if there is an ultimate disaster. That is why it is globally
 accessible.
 
-Arguments:   SMTP response to give if in an SMTP session
+Arguments:
+  reason     text reason to pass to the not-quit ACL
+  msg        default SMTP response to give if in an SMTP session
 Returns:     it doesn't
 */
 
 void
 Returns:     it doesn't
 */
 
 void
-receive_bomb_out(uschar *msg)
+receive_bomb_out(uschar *reason, uschar *msg)
 {
 /* If spool_name is set, it contains the name of the data file that is being
 written. Unlink it before closing so that it cannot be picked up by a delivery
 {
 /* If spool_name is set, it contains the name of the data file that is being
 written. Unlink it before closing so that it cannot be picked up by a delivery
@@ -306,20 +304,16 @@ if (spool_name[0] != 0)
 if (data_file != NULL) (void)fclose(data_file);
   else if (data_fd >= 0) (void)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. */
+/* Attempt to close down an SMTP connection tidily. For non-batched SMTP, call
+smtp_notquit_exit(), which runs the NOTQUIT ACL, if present, and handles the
+SMTP response. */
 
 if (smtp_input)
   {
 
 if (smtp_input)
   {
-  if (!smtp_batched_input)
-    {
-    smtp_printf("421 %s %s - closing connection.\r\n", smtp_active_hostname,
-      msg);
-    mac_smtp_fflush();
-    }
-
-  /* Control does not return from moan_smtp_batch(). */
-
-  else moan_smtp_batch(NULL, "421 %s - message abandoned", msg);
+  if (smtp_batched_input)
+    moan_smtp_batch(NULL, "421 %s - message abandoned", msg);  /* No return */
+  smtp_notquit_exit(reason, US"421", US"%s %s - closing connection.",
+    smtp_active_hostname, msg);
   }
 
 /* Exit from the program (non-BSMTP cases) */
   }
 
 /* Exit from the program (non-BSMTP cases) */
@@ -362,7 +356,7 @@ else
             LOG_MAIN, "timed out while reading local message");
   }
 
             LOG_MAIN, "timed out while reading local message");
   }
 
-receive_bomb_out(msg);   /* Does not return */
+receive_bomb_out(US"data-timeout", msg);   /* Does not return */
 }
 
 
 }
 
 
@@ -384,7 +378,8 @@ local_scan_timeout_handler(int sig)
 sig = sig;    /* Keep picky compilers happy */
 log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function timed out - "
   "message temporarily rejected (size %d)", message_size);
 sig = sig;    /* Keep picky compilers happy */
 log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function timed out - "
   "message temporarily rejected (size %d)", message_size);
-receive_bomb_out(US"local verification problem");   /* Does not return */
+/* Does not return */
+receive_bomb_out(US"local-scan-timeout", US"local verification problem");
 }
 
 
 }
 
 
@@ -405,7 +400,8 @@ local_scan_crash_handler(int sig)
 {
 log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function crashed with "
   "signal %d - message temporarily rejected (size %d)", sig, message_size);
 {
 log_write(0, LOG_MAIN|LOG_REJECT, "local_scan() function crashed with "
   "signal %d - message temporarily rejected (size %d)", sig, message_size);
-receive_bomb_out(US"local verification problem");   /* Does not return */
+/* Does not return */
+receive_bomb_out(US"local-scan-error", US"local verification problem");
 }
 
 
 }
 
 
@@ -442,7 +438,7 @@ else
     }
   }
 
     }
   }
 
-receive_bomb_out(msg);    /* Does not return */
+receive_bomb_out(US"signal-exit", msg);    /* Does not return */
 }
 
 
 }
 
 
@@ -572,7 +568,7 @@ if (!dot_ends)
   {
   register int last_ch = '\n';
 
   {
   register int last_ch = '\n';
 
-  for (; (ch = (RECEIVE_GETC)()) != EOF; last_ch = ch)
+  for (; (ch = (receive_getc)()) != EOF; last_ch = ch)
     {
     if (ch == 0) body_zerocount++;
     if (last_ch == '\r' && ch != '\n')
     {
     if (ch == 0) body_zerocount++;
     if (last_ch == '\r' && ch != '\n')
@@ -614,7 +610,7 @@ if (!dot_ends)
 
 ch_state = 1;
 
 
 ch_state = 1;
 
-while ((ch = (RECEIVE_GETC)()) != EOF)
+while ((ch = (receive_getc)()) != EOF)
   {
   if (ch == 0) body_zerocount++;
   switch (ch_state)
   {
   if (ch == 0) body_zerocount++;
   switch (ch_state)
@@ -728,8 +724,9 @@ read_message_data_smtp(FILE *fout)
 {
 int ch_state = 0;
 register int ch;
 {
 int ch_state = 0;
 register int ch;
+register int linelength = 0;
 
 
-while ((ch = (RECEIVE_GETC)()) != EOF)
+while ((ch = (receive_getc)()) != EOF)
   {
   if (ch == 0) body_zerocount++;
   switch (ch_state)
   {
   if (ch == 0) body_zerocount++;
   switch (ch_state)
@@ -749,6 +746,9 @@ while ((ch = (RECEIVE_GETC)()) != EOF)
       {
       ch_state = 0;
       body_linecount++;
       {
       ch_state = 0;
       body_linecount++;
+      if (linelength > max_received_linelength)
+        max_received_linelength = linelength;
+      linelength = -1;
       }
     else if (ch == '\r')
       {
       }
     else if (ch == '\r')
       {
@@ -759,6 +759,9 @@ while ((ch = (RECEIVE_GETC)()) != EOF)
 
     case 2:                             /* After (unwritten) CR */
     body_linecount++;
 
     case 2:                             /* After (unwritten) CR */
     body_linecount++;
+    if (linelength > max_received_linelength)
+      max_received_linelength = linelength;
+    linelength = -1;
     if (ch == '\n')
       {
       ch_state = 0;
     if (ch == '\n')
       {
       ch_state = 0;
@@ -800,6 +803,7 @@ while ((ch = (RECEIVE_GETC)()) != EOF)
   next. */
 
   message_size++;
   next. */
 
   message_size++;
+  linelength++;
   if (fout != NULL)
     {
     if (fputc(ch, fout) == EOF) return END_WERROR;
   if (fout != NULL)
     {
     if (fputc(ch, fout) == EOF) return END_WERROR;
@@ -1063,7 +1067,7 @@ unsigned long mbox_size;
 header_line *my_headerlist;
 uschar *user_msg, *log_msg;
 int mime_part_count_buffer = -1;
 header_line *my_headerlist;
 uschar *user_msg, *log_msg;
 int mime_part_count_buffer = -1;
-int rc;
+int rc = OK;
 
 memset(CS rfc822_file_path,0,2048);
 
 
 memset(CS rfc822_file_path,0,2048);
 
@@ -1090,13 +1094,16 @@ return TRUE;
 
 DO_MIME_ACL:
 /* make sure the eml mbox file is spooled up */
 
 DO_MIME_ACL:
 /* make sure the eml mbox file is spooled up */
-mbox_file = spool_mbox(&mbox_size);
+mbox_file = spool_mbox(&mbox_size, NULL);
 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();
 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();
+#ifdef EXPERIMENTAL_DCC
+  dcc_ok = 0;
+#endif
   smtp_respond(US"451", 3, TRUE, US"temporary local problem");
   message_id[0] = 0;            /* Indicate no message accepted */
   *smtp_reply_ptr = US"";       /* Indicate reply already sent */
   smtp_respond(US"451", 3, TRUE, US"temporary local problem");
   message_id[0] = 0;            /* Indicate no message accepted */
   *smtp_reply_ptr = US"";       /* Indicate reply already sent */
@@ -1176,6 +1183,9 @@ else if (rc != OK)
   {
   Uunlink(spool_name);
   unspool_mbox();
   {
   Uunlink(spool_name);
   unspool_mbox();
+#ifdef EXPERIMENTAL_DCC
+  dcc_ok = 0;
+#endif
   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 */
   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 */
@@ -1281,7 +1291,8 @@ not. */
 BOOL
 receive_msg(BOOL extract_recip)
 {
 BOOL
 receive_msg(BOOL extract_recip)
 {
-int  i, rc;
+int  i;
+int  rc = FAIL;
 int  msg_size = 0;
 int  process_info_len = Ustrlen(process_info);
 int  error_rc = (error_handling == ERRORS_SENDER)?
 int  msg_size = 0;
 int  process_info_len = Ustrlen(process_info);
 int  error_rc = (error_handling == ERRORS_SENDER)?
@@ -1380,10 +1391,9 @@ if (thismessage_size_limit <= 0) thismessage_size_limit = INT_MAX;
 message_linecount = body_linecount = body_zerocount =
   max_received_linelength = 0;
 
 message_linecount = body_linecount = body_zerocount =
   max_received_linelength = 0;
 
-#ifdef EXPERIMENTAL_DOMAINKEYS
-/* Call into DK to set up the context. Check if DK is to be run are carried out
-   inside dk_exim_verify_init(). */
-dk_exim_verify_init();
+#ifndef DISABLE_DKIM
+/* Call into DKIM to set up the context. */
+if (smtp_input && !smtp_batched_input && !dkim_disable_verify) dkim_exim_verify_init();
 #endif
 
 /* Remember the time of reception. Exim uses time+pid for uniqueness of message
 #endif
 
 /* Remember the time of reception. Exim uses time+pid for uniqueness of message
@@ -1434,7 +1444,7 @@ next->text. */
 
 for (;;)
   {
 
 for (;;)
   {
-  int ch = (RECEIVE_GETC)();
+  int ch = (receive_getc)();
 
   /* If we hit EOF on a SMTP connection, it's an error, since incoming
   SMTP must have a correct "." terminator. */
 
   /* If we hit EOF on a SMTP connection, it's an error, since incoming
   SMTP must have a correct "." terminator. */
@@ -1498,7 +1508,7 @@ for (;;)
   if (ch == '\n')
     {
     if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = FALSE;
   if (ch == '\n')
     {
     if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = FALSE;
-      else if (first_line_ended_crlf) RECEIVE_UNGETC(' ');
+      else if (first_line_ended_crlf) receive_ungetc(' ');
     goto EOL;
     }
 
     goto EOL;
     }
 
@@ -1513,13 +1523,13 @@ for (;;)
 
   if (ptr == 0 && ch == '.' && (smtp_input || dot_ends))
     {
 
   if (ptr == 0 && ch == '.' && (smtp_input || dot_ends))
     {
-    ch = (RECEIVE_GETC)();
+    ch = (receive_getc)();
     if (ch == '\r')
       {
     if (ch == '\r')
       {
-      ch = (RECEIVE_GETC)();
+      ch = (receive_getc)();
       if (ch != '\n')
         {
       if (ch != '\n')
         {
-        RECEIVE_UNGETC(ch);
+        receive_ungetc(ch);
         ch = '\r';              /* Revert to CR */
         }
       }
         ch = '\r';              /* Revert to CR */
         }
       }
@@ -1547,7 +1557,7 @@ for (;;)
 
   if (ch == '\r')
     {
 
   if (ch == '\r')
     {
-    ch = (RECEIVE_GETC)();
+    ch = (receive_getc)();
     if (ch == '\n')
       {
       if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE;
     if (ch == '\n')
       {
       if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE;
@@ -1557,7 +1567,7 @@ for (;;)
     /* Otherwise, put back the character after CR, and turn the bare CR
     into LF SP. */
 
     /* Otherwise, put back the character after CR, and turn the bare CR
     into LF SP. */
 
-    ch = (RECEIVE_UNGETC)(ch);
+    ch = (receive_ungetc)(ch);
     next->text[ptr++] = '\n';
     message_size++;
     ch = ' ';
     next->text[ptr++] = '\n';
     message_size++;
     ch = ' ';
@@ -1642,14 +1652,14 @@ for (;;)
 
   if (ch != EOF)
     {
 
   if (ch != EOF)
     {
-    int nextch = (RECEIVE_GETC)();
+    int nextch = (receive_getc)();
     if (nextch == ' ' || nextch == '\t')
       {
       next->text[ptr++] = nextch;
       message_size++;
       continue;                      /* Iterate the loop */
       }
     if (nextch == ' ' || nextch == '\t')
       {
       next->text[ptr++] = nextch;
       message_size++;
       continue;                      /* Iterate the loop */
       }
-    else if (nextch != EOF) (RECEIVE_UNGETC)(nextch);   /* For next time */
+    else if (nextch != EOF) (receive_ungetc)(nextch);   /* For next time */
     else ch = EOF;                   /* Cause main loop to exit at end */
     }
 
     else ch = EOF;                   /* Cause main loop to exit at end */
     }
 
@@ -1905,7 +1915,7 @@ for (h = header_list->next; h != NULL; h = h->next)
     /* Record whether a Date: or Resent-Date: header exists, as appropriate. */
 
     case htype_date:
     /* Record whether a Date: or Resent-Date: header exists, as appropriate. */
 
     case htype_date:
-    date_header_exists = !resents_exist || is_resent;
+    if (!resents_exist || is_resent) date_header_exists = TRUE;
     break;
 
     /* Same comments as about Return-Path: below. */
     break;
 
     /* Same comments as about Return-Path: below. */
@@ -2332,10 +2342,13 @@ if (msgid_header == NULL &&
       }
     }
 
       }
     }
 
-  /* Add the header line */
+  /* Add the header line
+   * Resent-* headers are prepended, per RFC 5322 3.6.6.  Non-Resent-* are
+   * appended, to preserve classical expectations of header ordering. */
 
 
-  header_add(htype_id, "%sMessage-Id: <%s%s%s@%s>\n", resent_prefix,
-    message_id_external, (*id_text == 0)? "" : ".", id_text, id_domain);
+  header_add_at_position(!resents_exist, NULL, FALSE, htype_id,
+    "%sMessage-Id: <%s%s%s@%s>\n", resent_prefix, message_id_external,
+    (*id_text == 0)? "" : ".", id_text, id_domain);
   }
 
 /* If we are to log recipients, keep a copy of the raw ones before any possible
   }
 
 /* If we are to log recipients, keep a copy of the raw ones before any possible
@@ -2543,9 +2556,10 @@ if (from_header != NULL &&
     if (sender_address_unrewritten == NULL)
       sender_address_unrewritten = sender_address;
     sender_address = generated_sender_address;
     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);
+    if (Ustrcmp(sender_address_unrewritten, generated_sender_address) != 0)
+      log_write(L_address_rewrite, LOG_MAIN,
+        "\"%s\" from env-from rewritten as \"%s\" by submission mode",
+        sender_address_unrewritten, generated_sender_address);
     }
   }
 
     }
   }
 
@@ -2599,12 +2613,15 @@ changes in RFC 2822, this was dropped in November 2003. */
 /* If there is no date header, generate one if the message originates locally
 (i.e. not over TCP/IP) and suppress_local_fixups is not set, or if the
 submission mode flag is set. Messages without Date: are not valid, but it seems
 /* If there is no date header, generate one if the message originates locally
 (i.e. not over TCP/IP) and suppress_local_fixups is not set, or if the
 submission mode flag is set. Messages without Date: are not valid, but it seems
-to be more confusing if Exim adds one to all remotely-originated messages. */
+to be more confusing if Exim adds one to all remotely-originated messages.
+As per Message-Id, we prepend if resending, else append.
+*/
 
 if (!date_header_exists &&
       ((sender_host_address == NULL && !suppress_local_fixups)
         || submission_mode))
 
 if (!date_header_exists &&
       ((sender_host_address == NULL && !suppress_local_fixups)
         || submission_mode))
-  header_add(htype_other, "%sDate: %s\n", resent_prefix, tod_stamp(tod_full));
+  header_add_at_position(!resents_exist, NULL, FALSE, htype_other,
+    "%sDate: %s\n", resent_prefix, tod_stamp(tod_full));
 
 search_tidyup();    /* Free any cached resources */
 
 
 search_tidyup();    /* Free any cached resources */
 
@@ -2964,12 +2981,99 @@ else
   if (smtp_input && !smtp_batched_input)
     {
 
   if (smtp_input && !smtp_batched_input)
     {
 
-#ifdef EXPERIMENTAL_DOMAINKEYS
-    dk_exim_verify_finish();
-#endif
+#ifndef DISABLE_DKIM
+    if (!dkim_disable_verify)
+      {
+      /* Finish verification, this will log individual signature results to
+         the mainlog */
+      dkim_exim_verify_finish();
+
+      /* Check if we must run the DKIM ACL */
+      if ((acl_smtp_dkim != NULL) &&
+          (dkim_verify_signers != NULL) &&
+          (dkim_verify_signers[0] != '\0'))
+        {
+        uschar *dkim_verify_signers_expanded =
+          expand_string(dkim_verify_signers);
+        if (dkim_verify_signers_expanded == NULL)
+          {
+          log_write(0, LOG_MAIN|LOG_PANIC,
+            "expansion of dkim_verify_signers option failed: %s",
+            expand_string_message);
+          }
+        else
+          {
+          int sep = 0;
+          uschar *ptr = dkim_verify_signers_expanded;
+          uschar *item = NULL;
+          uschar *seen_items = NULL;
+          int     seen_items_size = 0;
+          int     seen_items_offset = 0;
+          uschar itembuf[256];
+          /* Default to OK when no items are present */
+          rc = OK;
+          while ((item = string_nextinlist(&ptr, &sep,
+                                           itembuf,
+                                           sizeof(itembuf))) != NULL)
+            {
+            /* Prevent running ACL for an empty item */
+            if (!item || (item[0] == '\0')) continue;
+            /* Only run ACL once for each domain or identity, no matter how often it
+               appears in the expanded list. */
+            if (seen_items != NULL)
+              {
+              uschar *seen_items_list = seen_items;
+              if (match_isinlist(item,
+                    &seen_items_list,0,NULL,NULL,MCL_STRING,TRUE,NULL) == OK)
+                {
+                DEBUG(D_receive)
+                  debug_printf("acl_smtp_dkim: skipping signer %s, already seen\n", item);
+                continue;
+                }
+              seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,":");
+              }
+
+            seen_items = string_append(seen_items,&seen_items_size,&seen_items_offset,1,item);
+            seen_items[seen_items_offset] = '\0';
+
+            DEBUG(D_receive)
+              debug_printf("calling acl_smtp_dkim for dkim_cur_signer=%s\n", item);
+
+            dkim_exim_acl_setup(item);
+            rc = acl_check(ACL_WHERE_DKIM, NULL, acl_smtp_dkim, &user_msg, &log_msg);
+
+            if (rc != OK)
+              {
+                DEBUG(D_receive)
+                  debug_printf("acl_smtp_dkim: acl_check returned %d on %s, skipping remaining items\n", rc, item);
+                break;
+              }
+            }
+          add_acl_headers(US"DKIM");
+          if (rc == DISCARD)
+            {
+            recipients_count = 0;
+            blackholed_by = US"DKIM ACL";
+            if (log_msg != NULL)
+              blackhole_log_msg = string_sprintf(": %s", log_msg);
+            }
+          else if (rc != OK)
+            {
+            Uunlink(spool_name);
+            if (smtp_handle_acl_fail(ACL_WHERE_DKIM, 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 */
+            }
+          }
+        }
+      }
+#endif /* DISABLE_DKIM */
 
 #ifdef WITH_CONTENT_SCAN
 
 #ifdef WITH_CONTENT_SCAN
-    if (acl_smtp_mime != NULL &&
+    if (recipients_count > 0 &&
+        acl_smtp_mime != NULL &&
         !run_mime_acl(acl_smtp_mime, &smtp_yield, &smtp_reply, &blackholed_by))
       goto TIDYUP;
 #endif /* WITH_CONTENT_SCAN */
         !run_mime_acl(acl_smtp_mime, &smtp_yield, &smtp_reply, &blackholed_by))
       goto TIDYUP;
 #endif /* WITH_CONTENT_SCAN */
@@ -2993,6 +3097,9 @@ else
         Uunlink(spool_name);
 #ifdef WITH_CONTENT_SCAN
         unspool_mbox();
         Uunlink(spool_name);
 #ifdef WITH_CONTENT_SCAN
         unspool_mbox();
+#endif
+#ifdef EXPERIMENTAL_DCC
+       dcc_ok = 0;
 #endif
         if (smtp_handle_acl_fail(ACL_WHERE_DATA, rc, user_msg, log_msg) != 0)
           smtp_yield = FALSE;    /* No more messsages after dropped connection */
 #endif
         if (smtp_handle_acl_fail(ACL_WHERE_DATA, rc, user_msg, log_msg) != 0)
           smtp_yield = FALSE;    /* No more messsages after dropped connection */
@@ -3032,6 +3139,9 @@ else
         Uunlink(spool_name);
 #ifdef WITH_CONTENT_SCAN
         unspool_mbox();
         Uunlink(spool_name);
 #ifdef WITH_CONTENT_SCAN
         unspool_mbox();
+#endif
+#ifdef EXPERIMENTAL_DCC
+       dcc_ok = 0;
 #endif
         /* The ACL can specify where rejections are to be logged, possibly
         nowhere. The default is main and reject logs. */
 #endif
         /* The ACL can specify where rejections are to be logged, possibly
         nowhere. The default is main and reject logs. */
@@ -3069,6 +3179,11 @@ else
 unspool_mbox();
 #endif
 
 unspool_mbox();
 #endif
 
+#ifdef EXPERIMENTAL_DCC
+dcc_ok = 0;
+#endif
+
+
 /* The final check on the message is to run the scan_local() function. The
 version supplied with Exim always accepts, but this is a hook for sysadmins to
 supply their own checking code. The local_scan() function is run even when all
 /* The final check on the message is to run the scan_local() function. The
 version supplied with Exim always accepts, but this is a hook for sysadmins to
 supply their own checking code. The local_scan() function is run even when all
@@ -3358,7 +3473,8 @@ if ((log_extra_selector & LX_tls_certificate_verified) != 0 &&
   s = string_append(s, &size, &sptr, 2, US" CV=",
     tls_certificate_verified? "yes":"no");
 if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_peerdn != NULL)
   s = string_append(s, &size, &sptr, 2, US" CV=",
     tls_certificate_verified? "yes":"no");
 if ((log_extra_selector & LX_tls_peerdn) != 0 && tls_peerdn != NULL)
-  s = string_append(s, &size, &sptr, 3, US" DN=\"", tls_peerdn, US"\"");
+  s = string_append(s, &size, &sptr, 3, US" DN=\"",
+    string_printing(tls_peerdn), US"\"");
 #endif
 
 if (sender_host_authenticated != NULL)
 #endif
 
 if (sender_host_authenticated != NULL)
@@ -3502,8 +3618,8 @@ if (smtp_input && sender_host_address != NULL && !sender_host_notsocket &&
 
   if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0)
     {
 
   if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0)
     {
-    int c = (RECEIVE_GETC)();
-    if (c != EOF) (RECEIVE_UNGETC)(c); else
+    int c = (receive_getc)();
+    if (c != EOF) (receive_ungetc)(c); else
       {
       uschar *msg = US"SMTP connection lost after final dot";
       smtp_reply = US"";    /* No attempt to send a response */
       {
       uschar *msg = US"SMTP connection lost after final dot";
       smtp_reply = US"";    /* No attempt to send a response */