Add the add_header modifier for use with all ACL verbs.
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 6 Mar 2006 16:05:12 +0000 (16:05 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 6 Mar 2006 16:05:12 +0000 (16:05 +0000)
14 files changed:
doc/doc-txt/ChangeLog
doc/doc-txt/NewStuff
src/src/acl.c
src/src/globals.c
src/src/globals.h
src/src/receive.c
src/src/smtp_in.c
test/confs/0532 [new file with mode: 0644]
test/confs/4000
test/log/0532 [new file with mode: 0644]
test/mail/0532.rcptok [new file with mode: 0644]
test/rejectlog/0532 [new file with mode: 0644]
test/scripts/0000-Basic/0532 [new file with mode: 0644]
test/stdout/0532 [new file with mode: 0644]

index 6266ed5..348ed48 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.321 2006/03/02 12:25:48 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.322 2006/03/06 16:05:12 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -275,6 +275,9 @@ PH/53 This is related to PH/52, but is more general: for any failing address,
 PH/54 Added control=allow_auth_unadvertised, as it seems there are clients that
       do this, and (what is worse) MTAs that accept it.
 
+PH/55 Added the add_header modified to ACLs. The use of "message" with "warn"
+      will now be deprecated.
+
 
 Exim version 4.60
 -----------------
index 06c6760..065ddd3 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/NewStuff,v 1.94 2006/03/02 12:25:48 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/NewStuff,v 1.95 2006/03/06 16:05:12 ph10 Exp $
 
 New Features in Exim
 --------------------
@@ -118,6 +118,54 @@ PH/17 The ACL modifier control=allow_auth_unadvertised can be used to permit a
 
       This control is permitted only in the connection and HELO ACLs.
 
+PH/18 There is a new ACL modifier called "add_header" which does what its name
+      implies. It specifies one of more header lines that are to be added to an
+      incoming message, assuming, of course, that the message is ultimately
+      accepted.
+
+      This modifier is permitted in the MAIL, RCPT, PREDATA, DATA, MIME, and
+      non-SMTP ACLs (in other words, those that are concerned with accepting a
+      message). Added header lines are accumulated during the MAIL, RCPT, and
+      PREDATA ACLs, with any duplicates being discarded. They are then added to
+      the message before processing the DATA and MIME ACLs, during which
+      further added header lines are accumulated, again with duplicates
+      discarded. Thus, it is possible to add two identical header lines to an
+      SMTP message, but only if one is added before DATA and one after.
+
+      In the case of non-SMTP messages, new headers are accumulated during the
+      non-SMTP ACL, and added to the message at the end.
+
+      The add_header modifier is available for use with all ACL verbs. In the
+      case of the WARN verb, add_header supersedes the use of "message" for
+      this purpose; for the other verbs, it provides a new facility. If both
+      add_header and "message" are present on a WARN verb, both are processed
+      according to their specifications.
+
+      The add_header modifier acts immediately it is encountered during the
+      processing of an ACL. This is different to the (now-deprecated) use of
+      "message" on a WARN verb, where the action is taken only if all the
+      conditions are true. Notice the difference between these two cases on a
+      RCPT ACL:
+
+         deny add_header = ADDED: some text
+              <some condition>
+
+         deny <some condition>
+              add_header = ADDED: some text
+
+      In the first case, the header is always added, whether or not the current
+      recipient is rejected. In the second case, the header is added only if
+      the recipient is rejected.
+
+      If add_header appears more than once on an ACL statement, multiple
+      headers are added, provided that they have different content. (In the
+      case of WARN with "message", only the last value of "message" is used.)
+
+      The facility for specifying where the new header is to be inserted, as
+      described for WARN with "message" in section 39.19 of the 4.60 manual, is
+      supported.
+
+
 
 Version 4.60
 ------------
index 2a7b5af..9df6339 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/acl.c,v 1.56 2006/03/02 12:25:48 ph10 Exp $ */
+/* $Cambridge: exim/src/src/acl.c,v 1.57 2006/03/06 16:05:12 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -32,13 +32,17 @@ static uschar *verbs[] =
 static int msgcond[] = { FAIL, OK, OK, FAIL, OK, FAIL, OK };
 
 /* ACL condition and modifier codes - keep in step with the table that
-follows. */
+follows, and the cond_expand_at_top and uschar cond_modifiers tables lower
+down. */
 
-enum { ACLC_ACL, ACLC_AUTHENTICATED,
+enum { ACLC_ACL,
+       ACLC_ADD_HEADER,
+       ACLC_AUTHENTICATED,
 #ifdef EXPERIMENTAL_BRIGHTMAIL
        ACLC_BMI_OPTIN,
 #endif
-ACLC_CONDITION, ACLC_CONTROL,
+       ACLC_CONDITION,
+       ACLC_CONTROL,
 #ifdef WITH_CONTENT_SCAN
        ACLC_DECODE,
 #endif
@@ -54,8 +58,14 @@ ACLC_CONDITION, ACLC_CONTROL,
        ACLC_DK_SENDERS,
        ACLC_DK_STATUS,
 #endif
-       ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS,
-       ACLC_HOSTS, ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE,
+       ACLC_DNSLISTS,
+       ACLC_DOMAINS,
+       ACLC_ENCRYPTED,
+       ACLC_ENDPASS,
+       ACLC_HOSTS,
+       ACLC_LOCAL_PARTS,
+       ACLC_LOG_MESSAGE,
+       ACLC_LOGWRITE,
 #ifdef WITH_CONTENT_SCAN
        ACLC_MALWARE,
 #endif
@@ -68,7 +78,9 @@ ACLC_CONDITION, ACLC_CONTROL,
 #ifdef WITH_CONTENT_SCAN
        ACLC_REGEX,
 #endif
-       ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET,
+       ACLC_SENDER_DOMAINS,
+       ACLC_SENDERS,
+       ACLC_SET,
 #ifdef WITH_CONTENT_SCAN
        ACLC_SPAM,
 #endif
@@ -83,6 +95,7 @@ but always return TRUE. They are used for their side effects. */
 
 static uschar *conditions[] = {
   US"acl",
+  US"add_header",
   US"authenticated",
 #ifdef EXPERIMENTAL_BRIGHTMAIL
   US"bmi_optin",
@@ -189,6 +202,7 @@ at the outer level. In the other cases, expansion already occurs in the
 checking functions. */
 
 static uschar cond_expand_at_top[] = {
+  TRUE,    /* add_header */
   TRUE,    /* acl */
   FALSE,   /* authenticated */
 #ifdef EXPERIMENTAL_BRIGHTMAIL
@@ -246,6 +260,7 @@ static uschar cond_expand_at_top[] = {
 /* Flags to identify the modifiers */
 
 static uschar cond_modifiers[] = {
+  TRUE,    /* add_header */
   FALSE,   /* acl */
   FALSE,   /* authenticated */
 #ifdef EXPERIMENTAL_BRIGHTMAIL
@@ -307,10 +322,15 @@ to specify the negation of a small number of allowed times. */
 static unsigned int cond_forbids[] = {
   0,                                               /* acl */
 
+  (unsigned int)
+  ~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)|      /* add_header */
+    (1<<ACL_WHERE_PREDATA)|(1<<ACL_WHERE_DATA)|
+    (1<<ACL_WHERE_MIME)|(1<<ACL_WHERE_NOTSMTP)),
+
   (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_CONNECT)|   /* authenticated */
     (1<<ACL_WHERE_HELO),
 
-#ifdef EXPERIMENTAL_BRIGHTMAIL
+  #ifdef EXPERIMENTAL_BRIGHTMAIL
   (1<<ACL_WHERE_AUTH)|                             /* bmi_optin */
     (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
     (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_MIME)|
@@ -318,7 +338,7 @@ static unsigned int cond_forbids[] = {
     (1<<ACL_WHERE_MAILAUTH)|
     (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
     (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_PREDATA),
-#endif
+  #endif
 
   0,                                               /* condition */
 
@@ -327,19 +347,19 @@ static unsigned int cond_forbids[] = {
 
   0,                                               /* control */
 
-#ifdef WITH_CONTENT_SCAN
+  #ifdef WITH_CONTENT_SCAN
   (unsigned int)
   ~(1<<ACL_WHERE_MIME),                            /* decode */
-#endif
+  #endif
 
   0,                                               /* delay */
 
-#ifdef WITH_OLD_DEMIME
+  #ifdef WITH_OLD_DEMIME
   (unsigned int)
   ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)),   /* demime */
-#endif
+  #endif
 
-#ifdef EXPERIMENTAL_DOMAINKEYS
+  #ifdef EXPERIMENTAL_DOMAINKEYS
   (1<<ACL_WHERE_AUTH)|                             /* dk_domain_source */
     (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
     (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
@@ -387,7 +407,7 @@ static unsigned int cond_forbids[] = {
     (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
     (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
     (1<<ACL_WHERE_VRFY),
-#endif
+  #endif
 
   (1<<ACL_WHERE_NOTSMTP),                          /* dnslists */
 
@@ -408,28 +428,28 @@ static unsigned int cond_forbids[] = {
 
   0,                                               /* logwrite */
 
-#ifdef WITH_CONTENT_SCAN
+  #ifdef WITH_CONTENT_SCAN
   (unsigned int)
   ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)),   /* malware */
-#endif
+  #endif
 
   0,                                               /* message */
 
-#ifdef WITH_CONTENT_SCAN
+  #ifdef WITH_CONTENT_SCAN
   (unsigned int)
   ~(1<<ACL_WHERE_MIME),                            /* mime_regex */
-#endif
+  #endif
 
   0,                                               /* ratelimit */
 
   (unsigned int)
   ~(1<<ACL_WHERE_RCPT),                            /* recipients */
 
-#ifdef WITH_CONTENT_SCAN
+  #ifdef WITH_CONTENT_SCAN
   (unsigned int)
   ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)|    /* regex */
     (1<<ACL_WHERE_MIME)),
-#endif
+  #endif
 
   (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|      /* sender_domains */
     (1<<ACL_WHERE_HELO)|
@@ -445,18 +465,18 @@ static unsigned int cond_forbids[] = {
 
   0,                                               /* set */
 
-#ifdef WITH_CONTENT_SCAN
+  #ifdef WITH_CONTENT_SCAN
   (unsigned int)
   ~((1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_NOTSMTP)),   /* spam */
-#endif
+  #endif
 
-#ifdef EXPERIMENTAL_SPF
+  #ifdef EXPERIMENTAL_SPF
   (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|      /* spf */
     (1<<ACL_WHERE_HELO)|
     (1<<ACL_WHERE_MAILAUTH)|
     (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
     (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY),
-#endif
+  #endif
 
   /* Certain types of verify are always allowed, so we let it through
   always and check in the verify function itself */
@@ -826,6 +846,115 @@ return yield;
 
 
 /*************************************************
+*         Set up added header line(s)            *
+*************************************************/
+
+/* This function is called by the add_header modifier, and also from acl_warn()
+to implement the now-deprecated way of adding header lines using "message" on a
+"warn" verb. The argument is treated as a sequence of header lines which are
+added to a chain, provided there isn't an identical one already there.
+
+Argument:   string of header lines
+Returns:    nothing
+*/
+
+static void
+setup_header(uschar *hstring)
+{
+uschar *p, *q;
+int hlen = Ustrlen(hstring);
+
+/* An empty string does nothing; otherwise add a final newline if necessary. */
+
+if (hlen <= 0) return;
+if (hstring[hlen-1] != '\n') hstring = string_sprintf("%s\n", hstring);
+
+/* Loop for multiple header lines, taking care about continuations */
+
+for (p = q = hstring; *p != 0; )
+  {
+  uschar *s;
+  int newtype = htype_add_bot;
+  header_line **hptr = &acl_added_headers;
+
+  /* Find next header line within the string */
+
+  for (;;)
+    {
+    q = Ustrchr(q, '\n');
+    if (*(++q) != ' ' && *q != '\t') break;
+    }
+
+  /* If the line starts with a colon, interpret the instruction for where to
+  add it. This temporarily sets up a new type. */
+
+  if (*p == ':')
+    {
+    if (strncmpic(p, US":after_received:", 16) == 0)
+      {
+      newtype = htype_add_rec;
+      p += 16;
+      }
+    else if (strncmpic(p, US":at_start_rfc:", 14) == 0)
+      {
+      newtype = htype_add_rfc;
+      p += 14;
+      }
+    else if (strncmpic(p, US":at_start:", 10) == 0)
+      {
+      newtype = htype_add_top;
+      p += 10;
+      }
+    else if (strncmpic(p, US":at_end:", 8) == 0)
+      {
+      newtype = htype_add_bot;
+      p += 8;
+      }
+    while (*p == ' ' || *p == '\t') p++;
+    }
+
+  /* See if this line starts with a header name, and if not, add X-ACL-Warn:
+  to the front of it. */
+
+  for (s = p; s < q - 1; s++)
+    {
+    if (*s == ':' || !isgraph(*s)) break;
+    }
+
+  s = string_sprintf("%s%.*s", (*s == ':')? "" : "X-ACL-Warn: ", q - p, p);
+  hlen = Ustrlen(s);
+
+  /* See if this line has already been added */
+
+  while (*hptr != NULL)
+    {
+    if (Ustrncmp((*hptr)->text, s, hlen) == 0) break;
+    hptr = &((*hptr)->next);
+    }
+
+  /* Add if not previously present */
+
+  if (*hptr == NULL)
+    {
+    header_line *h = store_get(sizeof(header_line));
+    h->text = s;
+    h->next = NULL;
+    h->type = newtype;
+    h->slen = hlen;
+    *hptr = h;
+    hptr = &(h->next);
+    }
+
+  /* Advance for next header line within the string */
+
+  p = q;
+  }
+}
+
+
+
+
+/*************************************************
 *               Handle warnings                  *
 *************************************************/
 
@@ -833,6 +962,9 @@ return yield;
 the message's headers, and/or writes information to the log. In each case, this
 only happens once (per message for headers, per connection for log).
 
+** NOTE: The header adding action using the "message" setting is historic, and
+its use is now deprecated. The new add_header modifier should be used instead.
+
 Arguments:
   where          ACL_WHERE_xxxx indicating which ACL this is
   user_message   message for adding to headers
@@ -844,8 +976,6 @@ Returns:         nothing
 static void
 acl_warn(int where, uschar *user_message, uschar *log_message)
 {
-int hlen;
-
 if (log_message != NULL && log_message != user_message)
   {
   uschar *text;
@@ -895,99 +1025,10 @@ if (where > ACL_WHERE_NOTSMTP)
   return;
   }
 
-/* Treat the user message as a sequence of one or more header lines. */
-
-hlen = Ustrlen(user_message);
-if (hlen > 0)
-  {
-  uschar *text, *p, *q;
-
-  /* Add a final newline if not present */
-
-  text = ((user_message)[hlen-1] == '\n')? user_message :
-    string_sprintf("%s\n", user_message);
-
-  /* Loop for multiple header lines, taking care about continuations */
-
-  for (p = q = text; *p != 0; )
-    {
-    uschar *s;
-    int newtype = htype_add_bot;
-    header_line **hptr = &acl_warn_headers;
-
-    /* Find next header line within the string */
-
-    for (;;)
-      {
-      q = Ustrchr(q, '\n');
-      if (*(++q) != ' ' && *q != '\t') break;
-      }
+/* The code for setting up header lines is now abstracted into a separate
+function so that it can be used for the add_header modifier as well. */
 
-    /* If the line starts with a colon, interpret the instruction for where to
-    add it. This temporarily sets up a new type. */
-
-    if (*p == ':')
-      {
-      if (strncmpic(p, US":after_received:", 16) == 0)
-        {
-        newtype = htype_add_rec;
-        p += 16;
-        }
-      else if (strncmpic(p, US":at_start_rfc:", 14) == 0)
-        {
-        newtype = htype_add_rfc;
-        p += 14;
-        }
-      else if (strncmpic(p, US":at_start:", 10) == 0)
-        {
-        newtype = htype_add_top;
-        p += 10;
-        }
-      else if (strncmpic(p, US":at_end:", 8) == 0)
-        {
-        newtype = htype_add_bot;
-        p += 8;
-        }
-      while (*p == ' ' || *p == '\t') p++;
-      }
-
-    /* See if this line starts with a header name, and if not, add X-ACL-Warn:
-    to the front of it. */
-
-    for (s = p; s < q - 1; s++)
-      {
-      if (*s == ':' || !isgraph(*s)) break;
-      }
-
-    s = string_sprintf("%s%.*s", (*s == ':')? "" : "X-ACL-Warn: ", q - p, p);
-    hlen = Ustrlen(s);
-
-    /* See if this line has already been added */
-
-    while (*hptr != NULL)
-      {
-      if (Ustrncmp((*hptr)->text, s, hlen) == 0) break;
-      hptr = &((*hptr)->next);
-      }
-
-    /* Add if not previously present */
-
-    if (*hptr == NULL)
-      {
-      header_line *h = store_get(sizeof(header_line));
-      h->text = s;
-      h->next = NULL;
-      h->type = newtype;
-      h->slen = hlen;
-      *hptr = h;
-      hptr = &(h->next);
-      }
-
-    /* Advance for next header line within the string */
-
-    p = q;
-    }
-  }
+setup_header(user_message);
 }
 
 
@@ -2395,9 +2436,13 @@ for (; cb != NULL; cb = cb->next)
 
   switch(cb->type)
     {
+    case ACLC_ADD_HEADER:
+    setup_header(arg);
+    break;
+
     /* A nested ACL that returns "discard" makes sense only for an "accept" or
     "discard" verb. */
-\
+
     case ACLC_ACL:
     rc = acl_check_internal(where, addr, arg, level+1, user_msgptr, log_msgptr);
     if (rc == DISCARD && verb != ACL_ACCEPT && verb != ACL_DISCARD)
@@ -2415,7 +2460,7 @@ for (; cb != NULL; cb = cb->next)
         TRUE, NULL);
     break;
 
-#ifdef EXPERIMENTAL_BRIGHTMAIL
+    #ifdef EXPERIMENTAL_BRIGHTMAIL
     case ACLC_BMI_OPTIN:
       {
       int old_pool = store_pool;
@@ -2424,7 +2469,7 @@ for (; cb != NULL; cb = cb->next)
       store_pool = old_pool;
       }
     break;
-#endif
+    #endif
 
     case ACLC_CONDITION:
     if (Ustrspn(arg, "0123456789") == Ustrlen(arg))     /* Digits, or empty */
@@ -2577,11 +2622,11 @@ for (; cb != NULL; cb = cb->next)
       }
     break;
 
-#ifdef WITH_CONTENT_SCAN
+    #ifdef WITH_CONTENT_SCAN
     case ACLC_DECODE:
     rc = mime_decode(&arg);
     break;
-#endif
+    #endif
 
     case ACLC_DELAY:
       {
@@ -2625,14 +2670,14 @@ for (; cb != NULL; cb = cb->next)
       }
     break;
 
-#ifdef WITH_OLD_DEMIME
+    #ifdef WITH_OLD_DEMIME
     case ACLC_DEMIME:
       rc = demime(&arg);
     break;
-#endif
+    #endif
 
-#ifdef EXPERIMENTAL_DOMAINKEYS
-  case ACLC_DK_DOMAIN_SOURCE:
+    #ifdef EXPERIMENTAL_DOMAINKEYS
+    case ACLC_DK_DOMAIN_SOURCE:
     if (dk_verify_block == NULL) { rc = FAIL; break; };
     /* check header source of domain against given string */
     switch (dk_verify_block->address_source) {
@@ -2648,9 +2693,10 @@ for (; cb != NULL; cb = cb->next)
         rc = match_isinlist(US"none", &arg, 0, NULL,
                             NULL, MCL_STRING, TRUE, NULL);
       break;
-    }
-  break;
-  case ACLC_DK_POLICY:
+      }
+    break;
+
+    case ACLC_DK_POLICY:
     if (dk_verify_block == NULL) { rc = FAIL; break; };
     /* check policy against given string, default FAIL */
     rc = FAIL;
@@ -2660,28 +2706,32 @@ for (; cb != NULL; cb = cb->next)
     if (dk_verify_block->testing)
       rc = match_isinlist(US"testing", &arg, 0, NULL,
                           NULL, MCL_STRING, TRUE, NULL);
-  break;
-  case ACLC_DK_SENDER_DOMAINS:
+    break;
+
+    case ACLC_DK_SENDER_DOMAINS:
     if (dk_verify_block == NULL) { rc = FAIL; break; };
     if (dk_verify_block->domain != NULL)
       rc = match_isinlist(dk_verify_block->domain, &arg, 0, &domainlist_anchor,
                           NULL, MCL_DOMAIN, TRUE, NULL);
     else rc = FAIL;
-  break;
-  case ACLC_DK_SENDER_LOCAL_PARTS:
+    break;
+
+    case ACLC_DK_SENDER_LOCAL_PARTS:
     if (dk_verify_block == NULL) { rc = FAIL; break; };
     if (dk_verify_block->local_part != NULL)
       rc = match_isinlist(dk_verify_block->local_part, &arg, 0, &localpartlist_anchor,
                           NULL, MCL_LOCALPART, TRUE, NULL);
     else rc = FAIL;
-  break;
-  case ACLC_DK_SENDERS:
+    break;
+
+    case ACLC_DK_SENDERS:
     if (dk_verify_block == NULL) { rc = FAIL; break; };
     if (dk_verify_block->address != NULL)
       rc = match_address_list(dk_verify_block->address, TRUE, TRUE, &arg, NULL, -1, 0, NULL);
     else rc = FAIL;
-  break;
-  case ACLC_DK_STATUS:
+    break;
+
+    case ACLC_DK_STATUS:
     if (dk_verify_block == NULL) { rc = FAIL; break; };
     if (dk_verify_block->result > 0) {
       switch(dk_verify_block->result) {
@@ -2713,10 +2763,10 @@ for (; cb != NULL; cb = cb->next)
           rc = match_isinlist(US"bad", &arg, 0, NULL,
                               NULL, MCL_STRING, TRUE, NULL);
         break;
+        }
       }
-    }
-  break;
-#endif
+    break;
+    #endif
 
     case ACLC_DNSLISTS:
     rc = verify_check_dnsbl(&arg);
@@ -2798,7 +2848,7 @@ for (; cb != NULL; cb = cb->next)
       }
     break;
 
-#ifdef WITH_CONTENT_SCAN
+    #ifdef WITH_CONTENT_SCAN
     case ACLC_MALWARE:
       {
       /* Seperate the regular expression and any optional parameters. */
@@ -2818,12 +2868,12 @@ for (; cb != NULL; cb = cb->next)
     break;
 
     case ACLC_MIME_REGEX:
-      rc = mime_regex(&arg);
+    rc = mime_regex(&arg);
     break;
-#endif
+    #endif
 
     case ACLC_RATELIMIT:
-      rc = acl_ratelimit(arg, log_msgptr);
+    rc = acl_ratelimit(arg, log_msgptr);
     break;
 
     case ACLC_RECIPIENTS:
@@ -2831,11 +2881,11 @@ for (; cb != NULL; cb = cb->next)
       &recipient_data);
     break;
 
-#ifdef WITH_CONTENT_SCAN
-   case ACLC_REGEX:
-      rc = regex(&arg);
+    #ifdef WITH_CONTENT_SCAN
+    case ACLC_REGEX:
+    rc = regex(&arg);
     break;
-#endif
+    #endif
 
     case ACLC_SENDER_DOMAINS:
       {
@@ -2863,7 +2913,7 @@ for (; cb != NULL; cb = cb->next)
       }
     break;
 
-#ifdef WITH_CONTENT_SCAN
+    #ifdef WITH_CONTENT_SCAN
     case ACLC_SPAM:
       {
       /* Seperate the regular expression and any optional parameters. */
@@ -2881,13 +2931,13 @@ for (; cb != NULL; cb = cb->next)
         }
       }
     break;
-#endif
+    #endif
 
-#ifdef EXPERIMENTAL_SPF
+    #ifdef EXPERIMENTAL_SPF
     case ACLC_SPF:
       rc = spf_process(&arg, sender_address);
     break;
-#endif
+    #endif
 
     /* If the verb is WARN, discard any user message from verification, because
     such messages are SMTP responses, not header additions. The latter come
index 5d898d5..b9f5667 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.c,v 1.52 2006/03/02 12:25:48 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.c,v 1.53 2006/03/06 16:05:12 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -162,6 +162,7 @@ int address_expansions_count = sizeof(address_expansions)/sizeof(uschar **);
 
 /* General global variables */
 
+header_line *acl_added_headers = NULL;
 tree_node *acl_anchor          = NULL;
 uschar *acl_not_smtp           = NULL;
 #ifdef WITH_CONTENT_SCAN
@@ -186,7 +187,6 @@ uschar *acl_smtp_vrfy          = NULL;
 BOOL    acl_temp_details       = FALSE;
 uschar *acl_var[ACL_CVARS + ACL_MVARS];
 uschar *acl_verify_message     = NULL;
-header_line *acl_warn_headers  = NULL;
 string_item *acl_warn_logged   = NULL;
 
 /* Names of SMTP places for use in ACL error messages, and corresponding SMTP
index 114f859..555d68e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/globals.h,v 1.36 2006/03/02 12:25:48 ph10 Exp $ */
+/* $Cambridge: exim/src/src/globals.h,v 1.37 2006/03/06 16:05:12 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -104,6 +104,7 @@ extern uschar **address_expansions[ADDRESS_EXPANSIONS_COUNT];
 /* General global variables */
 
 extern BOOL    accept_8bitmime;        /* Allow *BITMIME incoming */
+extern header_line *acl_added_headers; /* Headers added by an ACL */
 extern tree_node *acl_anchor;          /* Tree of named ACLs */
 extern uschar *acl_not_smtp;           /* ACL run for non-SMTP messages */
 #ifdef WITH_CONTENT_SCAN
@@ -128,7 +129,6 @@ extern uschar *acl_smtp_vrfy;          /* ACL run for VRFY */
 extern BOOL    acl_temp_details;       /* TRUE to give details for 4xx error */
 extern uschar *acl_var[ACL_CVARS+ACL_MVARS]; /* User ACL variables */
 extern uschar *acl_verify_message;     /* User message for verify failure */
-extern header_line *acl_warn_headers;  /* Warning headers added by ACL */
 extern string_item *acl_warn_logged;   /* Logged lines */
 extern int     acl_wherecodes[];       /* Response codes for ACL fails */
 extern uschar *acl_wherenames[];       /* Names for messages */
index e11c96d..f711e9c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.26 2006/02/14 15:11:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.27 2006/03/06 16:05:12 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -899,10 +899,10 @@ add_acl_headers(uschar *acl_name)
 header_line *h, *next;
 header_line *last_received = NULL;
 
-if (acl_warn_headers == NULL) return;
+if (acl_added_headers == NULL) return;
 DEBUG(D_receive|D_acl) debug_printf(">>Headers added by %s ACL:\n", acl_name);
 
-for (h = acl_warn_headers; h != NULL; h = next)
+for (h = acl_added_headers; h != NULL; h = next)
   {
   next = h->next;
 
@@ -964,7 +964,7 @@ for (h = acl_warn_headers; h != NULL; h = next)
   DEBUG(D_receive|D_acl) debug_printf("  %s", header_last->text);
   }
 
-acl_warn_headers = NULL;
+acl_added_headers = NULL;
 DEBUG(D_receive|D_acl) debug_printf(">>\n");
 }
 
index 9df0f59..224eba9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/smtp_in.c,v 1.34 2006/03/02 12:25:48 ph10 Exp $ */
+/* $Cambridge: exim/src/src/smtp_in.c,v 1.35 2006/03/06 16:05:12 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -808,7 +808,7 @@ rcpt_count = rcpt_defer_count = rcpt_fail_count =
   raw_recipients_count = recipients_count = recipients_list_max = 0;
 message_linecount = 0;
 message_size = -1;
-acl_warn_headers = NULL;
+acl_added_headers = NULL;
 queue_only_policy = FALSE;
 deliver_freeze = FALSE;                              /* Can be set by ACL */
 freeze_tell = freeze_tell_config;                    /* Can be set by ACL */
diff --git a/test/confs/0532 b/test/confs/0532
new file mode 100644 (file)
index 0000000..42d613b
--- /dev/null
@@ -0,0 +1,80 @@
+# Exim test configuration 0532
+
+CONNECTCOND=
+
+exim_path = EXIM_PATH
+host_lookup_order = bydns
+primary_hostname = myhost.test.ex
+rfc1413_query_timeout = 0s
+spool_directory = DIR/spool
+log_file_path = DIR/spool/log/%slog
+gecos_pattern = ""
+gecos_name = CALLER_NAME
+
+# ----- Main settings -----
+
+acl_smtp_connect = connect
+acl_smtp_mail = mail
+acl_smtp_rcpt = rcpt
+acl_smtp_predata = predata
+acl_smtp_data = data
+acl_not_smtp = notsmtp
+
+qualify_domain = test.ex
+trusted_users = CALLER
+
+
+# ----- ACL -----
+
+begin acl
+
+connect:
+  accept CONNECTCOND
+
+mail:
+  accept add_header = MAIL: one
+         senders    = mailok@test.ex
+         add_header = MAIL: two\nMAIL: three
+  accept
+
+rcpt:
+  accept add_header  = RCPT: one
+         add_header  = DUP: duplicate
+         local_parts = rcptok
+         add_header  = RCPT: two\n  continued\n
+  deny   add_header  = RCPT: denied $local_part
+
+
+predata:
+  warn   add_header = PREDATA-WARN: added with add_header
+         message    = PREDATA-WARN: added with message
+  accept add_header = PREDATA: recipients are $recipients
+
+data:
+  accept add_header = DATA: one
+         add_header = DUP: duplicate
+         condition  = ${if eq{$h_cond:}{accept}}
+
+notsmtp:
+  accept add_header = NOTSMTP: $recipients
+
+
+# ----- Routers -----
+
+begin routers
+
+r1:
+  driver = accept
+  transport = t1
+
+
+# ----- Transports -----
+
+begin transports
+
+t1:
+  driver = appendfile
+  file = DIR/test-mail/$local_part
+  user = CALLER
+
+# End
index cc08c71..1b33ff7 100644 (file)
@@ -49,19 +49,19 @@ check_data:
 
 check_mime:
   warn     decode  = default
-           message = X-$mime_part_count-content-type: $mime_content_type\n\
-                     X-$mime_part_count-filename: $mime_filename\n\
-                     X-$mime_part_count-charset: $mime_charset\n\
-                     X-$mime_part_count-boundary: $mime_boundary\n\
-                     X-$mime_part_count-content-disposition: $mime_content_disposition\n\
-                     X-$mime_part_count-content-transfer-encoding: $mime_content_transfer_encoding\n\
-                     X-$mime_part_count-content-id: $mime_content_id\n\
-                     X-$mime_part_count-content-description: $mime_content_description\n\
-                     X-$mime_part_count-is-multipart: $mime_is_multipart\n\
-                     X-$mime_part_count-is-coverletter: $mime_is_coverletter\n\
-                     X-$mime_part_count-is-rfc822: $mime_is_rfc822\n\
-                     X-$mime_part_count-decode-filename: $mime_decoded_filename\n\
-                     X-$mime_part_count-content-size: $mime_content_size
+           add_header = X-$mime_part_count-content-type: $mime_content_type\n\
+                        X-$mime_part_count-filename: $mime_filename\n\
+                        X-$mime_part_count-charset: $mime_charset\n\
+                        X-$mime_part_count-boundary: $mime_boundary\n\
+                        X-$mime_part_count-content-disposition: $mime_content_disposition\n\
+                        X-$mime_part_count-content-transfer-encoding: $mime_content_transfer_encoding\n\
+                        X-$mime_part_count-content-id: $mime_content_id\n\
+                        X-$mime_part_count-content-description: $mime_content_description\n\
+                        X-$mime_part_count-is-multipart: $mime_is_multipart\n\
+                        X-$mime_part_count-is-coverletter: $mime_is_coverletter\n\
+                        X-$mime_part_count-is-rfc822: $mime_is_rfc822\n\
+                        X-$mime_part_count-decode-filename: $mime_decoded_filename\n\
+                        X-$mime_part_count-content-size: $mime_content_size
 
   accept
 
diff --git a/test/log/0532 b/test/log/0532
new file mode 100644 (file)
index 0000000..57a1520
--- /dev/null
@@ -0,0 +1,8 @@
+1999-03-02 09:44:33 U=CALLER F=<mailok@test.ex> rejected RCPT <notok@test.ex>
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= mailok@test.ex U=CALLER P=local-smtp S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 => rcptok <rcptok@test.ex> R=r1 T=t1
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= CALLER@test.ex U=CALLER P=local S=sss
+1999-03-02 09:44:33 10HmaY-0005vi-00 => rcptok <rcptok@test.ex> R=r1 T=t1
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 U=CALLER temporarily rejected connection in "connect" ACL: cannot test add_header condition in connection ACL
diff --git a/test/mail/0532.rcptok b/test/mail/0532.rcptok
new file mode 100644 (file)
index 0000000..e669ef7
--- /dev/null
@@ -0,0 +1,37 @@
+From mailok@test.ex Tue Mar 02 09:44:33 1999
+Received: from CALLER by myhost.test.ex with local-smtp (Exim x.yz)
+       (envelope-from <mailok@test.ex>)
+       id 10HmaX-0005vi-00
+       for rcptok@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+cond: accept
+Message-Id: <E10HmaX-0005vi-00@myhost.test.ex>
+From: mailok@test.ex
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+MAIL: one
+MAIL: two
+MAIL: three
+RCPT: one
+DUP: duplicate
+RCPT: two
+  continued
+RCPT: denied notok
+PREDATA-WARN: added with add_header
+PREDATA-WARN: added with message
+PREDATA: recipients are rcptok@test.ex
+DATA: one
+DUP: duplicate
+
+Test message
+
+From CALLER@test.ex Tue Mar 02 09:44:33 1999
+Received: from CALLER by myhost.test.ex with local (Exim x.yz)
+       (envelope-from <CALLER@test.ex>)
+       id 10HmaY-0005vi-00
+       for rcptok@test.ex; Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmaY-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+NOTSMTP: rcptok@test.ex
+
+Test non-SMTP message.
+
diff --git a/test/rejectlog/0532 b/test/rejectlog/0532
new file mode 100644 (file)
index 0000000..7a20d07
--- /dev/null
@@ -0,0 +1,2 @@
+1999-03-02 09:44:33 U=CALLER F=<mailok@test.ex> rejected RCPT <notok@test.ex>
+1999-03-02 09:44:33 U=CALLER temporarily rejected connection in "connect" ACL: cannot test add_header condition in connection ACL
diff --git a/test/scripts/0000-Basic/0532 b/test/scripts/0000-Basic/0532
new file mode 100644 (file)
index 0000000..80124ce
--- /dev/null
@@ -0,0 +1,18 @@
+# add_header modifier in ACLs
+exim -bs -odi
+mail from:<mailok@test.ex>
+rcpt to:<rcptok@test.ex>
+rcpt to:<notok@test.ex>
+data
+cond: accept
+
+Test message
+.
+quit
+****
+exim -odi rcptok@test.ex
+Test non-SMTP message.
+****
+exim -bs -odi -DCONNECTCOND="add_header=CONNECT: won't do this"
+****
+no_msglog_check
diff --git a/test/stdout/0532 b/test/stdout/0532
new file mode 100644 (file)
index 0000000..7d79c1e
--- /dev/null
@@ -0,0 +1,8 @@
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250 OK\r
+250 Accepted\r
+550 Administrative prohibition\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmaX-0005vi-00\r
+221 myhost.test.ex closing connection\r
+451 Temporary local problem - please try later\r