1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) The Exim Maintainers 2021 - 2022 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
10 #include "rf_functions.h"
13 /*************************************************
14 * Get additional headers for a router *
15 *************************************************/
17 /* This function is called by routers to sort out the additional headers
18 and header remove list for a particular address.
21 addr the input address
22 rblock the router instance
23 extra_headers points to where to hang the header chain
24 remove_headers points to where to hang the remove list
26 Returns: OK if no problem
27 DEFER if expanding a string caused a deferment
28 or a big disaster (e.g. expansion failure)
32 rf_get_munge_headers(address_item *addr, router_instance *rblock,
33 header_line **extra_headers, uschar **remove_headers)
35 /* Default is to retain existing headers */
36 *extra_headers = addr->prop.extra_headers;
38 if (rblock->extra_headers)
40 const uschar * list = rblock->extra_headers;
45 while ((s = string_nextinlist(&list, &sep, NULL, 0)))
46 if (!(s = expand_string(t = s)))
48 if (!f.expand_string_forcedfail)
50 addr->message = string_sprintf(
51 "%s router failed to expand add_headers item \"%s\": %s",
52 rblock->name, t, expand_string_message);
56 else if ((slen = Ustrlen(s)) > 0)
58 /* Expand succeeded. Put extra headers at the start of the chain because
59 further down it may point to headers from other routers, which may be
60 shared with other addresses. The output function outputs them in reverse
63 header_line * h = store_get(sizeof(header_line), GET_UNTAINTED);
65 /* We used to use string_sprintf() to add the newline if needed, but that
66 causes problems if the header line is exceedingly long (e.g. adding
67 something to a pathologically long line). So avoid it. */
69 if (s[slen-1] == '\n')
73 h->text = store_get(slen+2, s);
74 memcpy(h->text, s, slen);
75 h->text[slen++] = '\n';
79 h->next = *extra_headers;
80 h->type = htype_other;
86 /* Default is to retain existing removes */
87 *remove_headers = addr->prop.remove_headers;
89 /* Expand items from colon-sep list separately, then build new list */
90 if (rblock->remove_headers)
92 const uschar * list = rblock->remove_headers;
98 g = string_cat(NULL, *remove_headers);
100 while ((s = string_nextinlist(&list, &sep, NULL, 0)))
101 if (!(s = expand_string(t = s)))
103 if (!f.expand_string_forcedfail)
105 addr->message = string_sprintf(
106 "%s router failed to expand remove_headers item \"%s\": %s",
107 rblock->name, t, expand_string_message);
112 g = string_append_listele(g, ':', s);
115 *remove_headers = g->s;
123 /* End of rf_get_munge_headers.c */