The Date: and Message-Id: headers should normally be *appended* to a message,
[exim.git] / src / src / receive.c
index 734ca7737c1a3827e8dbef2c4578e94699b5f06e..54575fe6243a24fb1825b3c78872aa9bb810a570 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.46 2009/06/10 07:34:04 tom Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.54 2010/06/03 05:40:27 pdp Exp $ */
 
 /*************************************************
 *     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. */
@@ -1067,7 +1067,7 @@ unsigned long mbox_size;
 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);
 
@@ -1285,7 +1285,8 @@ not. */
 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)?
@@ -2335,10 +2336,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
@@ -2603,12 +2607,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
-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))
-  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 */
 
@@ -2993,14 +3000,48 @@ 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) break;
+
+            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)