diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index ed00537775..53fc7dc807 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -8119,9 +8119,6 @@ domain, host, address and local part lists. .cindex "expansion" "of lists" Each list is expanded as a single string before it is used. -&'Exception: the router headers_remove option, where list-item -splitting is done before string-expansion.'& - The result of expansion must be a list, possibly containing empty items, which is split up into separate items for matching. By default, colon is the separator character, @@ -18647,7 +18644,8 @@ avoided. The &%repeat_use%& option of the &%redirect%& router may be of help. This option specifies a list of text headers, colon-separated (by default, changeable in the usual way &<>&), that is associated with any addresses that are accepted by the router. -Each item is separately expanded, at routing time. However, this +The whole list is expanded before splitting, at routing time. If an item +ends in *, it will match any header with the same prefix. However, this option has no effect when an address is just being verified. The way in which the text is used to remove header lines at transport time is described in section &<>&. Header lines are not actually removed until diff --git a/src/src/transport.c b/src/src/transport.c index ed3dcf0af7..0ce5e8b326 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -727,21 +727,29 @@ for (header_line * h = header_list; h; h = h->next) if (h->type != htype_old) { int sep = ':'; /* This is specified as a colon-separated list */ uschar *s, *ss; + /* expand the list first, so we can include expandos that return lists too */ + if (i == 0) + if (!(list = expand_string(list)) && !f.expand_string_forcedfail) + { + errno = ERRNO_CHHEADER_FAIL; + return FALSE; + } while ((s = string_nextinlist(&list, &sep, NULL, 0))) { int len; - if (i == 0) - if (!(s = expand_string(s)) && !f.expand_string_forcedfail) - { - errno = ERRNO_CHHEADER_FAIL; - return FALSE; - } len = s ? Ustrlen(s) : 0; - if (strncmpic(h->text, s, len) != 0) continue; - ss = h->text + len; - while (*ss == ' ' || *ss == '\t') ss++; - if (*ss == ':') break; + if (len && s[len-1] == '*') + { + if (strncmpic(h->text, s, len-1) == 0) break; + } + else + { + if (strncmpic(h->text, s, len) != 0) continue; + ss = h->text + len; + while (*ss == ' ' || *ss == '\t') ss++; + if (*ss == ':') break; + } } if (s) { include_header = FALSE; break; } }