Limit retry_interval_max to 24h to avoid overflow problems.
[exim.git] / src / src / filter.c
index 3c95af800317cd4a9e886471a65291c65e642a8e..e94cbd135b4b46171f590f6f1b36e7b32a218098 100644 (file)
@@ -1,10 +1,10 @@
-/* $Cambridge: exim/src/src/filter.c,v 1.3 2005/01/04 10:00:42 ph10 Exp $ */
+/* $Cambridge: exim/src/src/filter.c,v 1.9 2006/02/07 11:19:00 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2005 */
+/* Copyright (c) University of Cambridge 1995 - 2006 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -1907,7 +1907,7 @@ while (commands != NULL)
     if (log_mode == -1) log_mode = 0600;
     if (log_fd >= 0)
       {
-      close(log_fd);
+      (void)close(log_fd);
       log_fd = -1;
       }
     log_filename = expargs[0];
@@ -2207,12 +2207,17 @@ while (commands != NULL)
     else
       {
       uschar *tt;
+      uschar *log_addr = NULL;
       uschar *to = commands->args[mailarg_index_to].u;
+      int size = 0;
+      int ptr = 0;
+      int badflag = 0;
+
       if (to == NULL) to = expand_string(US"$reply_address");
       while (isspace(*to)) to++;
 
-      for (tt = to; *tt != 0; tt++)     /* Get rid of newlines so that */
-        if (*tt == '\n') *tt = ' ';     /* the eventual log line is OK */
+      for (tt = to; *tt != 0; tt++)     /* Get rid of newlines */
+        if (*tt == '\n') *tt = ' ';
 
       DEBUG(D_filter)
         {
@@ -2235,10 +2240,59 @@ while (commands != NULL)
           }
         }
 
-      /* Create the "address" for the autoreply */
+      /* Create the "address" for the autoreply. This is used only for logging,
+      as the actual recipients are extracted from the To: line by -t. We use the
+      same logic here to extract the working addresses (there may be more than
+      one). Just in case there are a vast number of addresses, stop when the
+      string gets too long. */
+
+      tt = to;
+      while (*tt != 0)
+        {
+        uschar *ss = parse_find_address_end(tt, FALSE);
+        uschar *recipient, *errmess;
+        int start, end, domain;
+        int temp = *ss;
+
+        *ss = 0;
+        recipient = parse_extract_address(tt, &errmess, &start, &end, &domain,
+          FALSE);
+        *ss = temp;
+
+        /* Ignore empty addresses and errors; an error will occur later if
+        there's something really bad. */
+
+        if (recipient != NULL)
+          {
+          log_addr = string_cat(log_addr, &size, &ptr,
+            (log_addr == NULL)? US">" : US",", 1);
+          log_addr = string_cat(log_addr, &size, &ptr, recipient,
+            Ustrlen(recipient));
+          }
+
+        /* Check size */
+
+        if (ptr > 256)
+          {
+          log_addr = string_cat(log_addr, &size, &ptr, US", ...", 5);
+          break;
+          }
 
-      addr = deliver_make_addr(string_sprintf(">%.256s", to), FALSE);
-      setflag(addr, af_pfr);
+        /* Move on past this address */
+
+        tt = ss + (*ss? 1:0);
+        while (isspace(*tt)) tt++;
+        }
+
+      if (log_addr == NULL)
+        {
+        log_addr = string_sprintf(">**bad-reply**");
+        badflag = af_bad_reply;
+        }
+      else log_addr[ptr] = 0;
+
+      addr = deliver_make_addr(log_addr, FALSE);
+      setflag(addr, (af_pfr|badflag));
       if (commands->noerror) setflag(addr, af_ignore_error);
       addr->next = *generated;
       *generated = addr;
@@ -2321,14 +2375,42 @@ header_line *h;
 int to_count = 2;
 int from_count = 9;
 
-/* If any header line in the message starts with "List-", it is not
-a personal message. */
+/* If any header line in the message is a defined "List-" header field, it is
+not a personal message. We used to check for any header line that started with
+"List-", but this was tightened up for release 4.54. The check is now for
+"List-Id", defined in RFC 2929, or "List-Help", "List-Subscribe", "List-
+Unsubscribe", "List-Post", "List-Owner" or "List-Archive", all of which are
+defined in RFC 2369. We also scan for "Auto-Submitted"; if it is found to
+contain any value other than "no", the message is not personal (RFC 3834).
+Previously the test was for "auto-". */
 
 for (h = header_list; h != NULL; h = h->next)
   {
-  if (h->type != htype_old && h->slen > 5 &&
-      strncmpic(h->text, US"List-", 5) == 0)
-    return FALSE;
+  uschar *s;
+  if (h->type == htype_old) continue;
+
+  if (strncmpic(h->text, US"List-", 5) == 0)
+    {
+    s = h->text + 5;
+    if (strncmpic(s, US"Id:", 3) == 0 ||
+        strncmpic(s, US"Help:", 5) == 0 ||
+        strncmpic(s, US"Subscribe:", 10) == 0 ||
+        strncmpic(s, US"Unsubscribe:", 12) == 0 ||
+        strncmpic(s, US"Post:", 5) == 0 ||
+        strncmpic(s, US"Owner:", 6) == 0 ||
+        strncmpic(s, US"Archive:", 8) == 0)
+      return FALSE;
+    }
+
+  else if (strncmpic(h->text, US"Auto-submitted:", 15) == 0)
+    {
+    s = h->text + 15;
+    while (isspace(*s)) s++;
+    if (strncmpic(s, US"no", 2) != 0) return FALSE;
+    s += 2;
+    while (isspace(*s)) s++;
+    if (*s != 0) return FALSE;
+    }
   }
 
 /* Set up "my" address */
@@ -2384,7 +2466,6 @@ yield =
     "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
     "^owner-[^@]+@", self, self_from, psself, psself_from) &&
 
-  header_match(US"auto-submitted:", FALSE, FALSE, NULL, 1, "auto-") &&
   header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
 
   (sender_address == NULL || sender_address[0] != 0);
@@ -2500,7 +2581,7 @@ if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
 /* Close the log file if it was opened, and kill off any numerical variables
 before returning. Reset the header decoding charset. */
 
-if (log_fd >= 0) close(log_fd);
+if (log_fd >= 0) (void)close(log_fd);
 expand_nmax = -1;
 filter_running = FALSE;
 headers_charset = save_headers_charset;