From 759502e5af0acfb310b8571f056d2dbf59adb1d3 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sat, 29 Feb 2020 16:30:35 +0000 Subject: [PATCH] Add variables for wildcard portion of local-part affix. Bug 281 --- doc/doc-docbook/spec.xfpt | 36 ++++++++++++++++++++++-- doc/doc-txt/NewStuff | 4 ++- src/src/deliver.c | 4 +++ src/src/expand.c | 2 ++ src/src/functions.h | 4 +-- src/src/globals.c | 4 +++ src/src/globals.h | 2 ++ src/src/receive.c | 5 ++-- src/src/route.c | 53 ++++++++++++++++++++++++++---------- src/src/structs.h | 2 ++ src/src/transport.c | 6 ++-- test/confs/0015 | 6 ++-- test/confs/0016 | 5 +++- test/mail/0015.CALLER | 2 ++ test/mail/0015.userx | 7 +++++ test/mail/0016.userx | 6 ++++ test/scripts/0000-Basic/0016 | 1 + 17 files changed, 120 insertions(+), 29 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index bba71b76d..f9bdbd8ec 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -1399,16 +1399,21 @@ If the &%domains%& option is set, the domain of the address must be in the set of domains that it defines. .next .vindex "&$local_part_prefix$&" +.vindex "&$local_part_prefix_v$&" .vindex "&$local_part$&" .vindex "&$local_part_suffix$&" +.vindex "&$local_part_suffix_v$&" .cindex affix "router precondition" If the &%local_parts%& option is set, the local part of the address must be in the set of local parts that it defines. If &%local_part_prefix%& or &%local_part_suffix%& is in use, the prefix or suffix is removed from the local part before this check. If you want to do precondition tests on local parts that include affixes, you can do so by using a &%condition%& option (see below) -that uses the variables &$local_part$&, &$local_part_prefix$&, and -&$local_part_suffix$& as necessary. +.new +that uses the variables &$local_part$&, &$local_part_prefix$&, +&$local_part_prefix_v$&, &$local_part_suffix$& +and &$local_part_suffix_v$& as necessary. +.wen .next .vindex "&$local_user_uid$&" .vindex "&$local_user_gid$&" @@ -12447,12 +12452,19 @@ the retrieved data. .wen .vindex "&$local_part_prefix$&" +.vindex "&$local_part_prefix_v$&" .vindex "&$local_part_suffix$&" +.vindex "&$local_part_suffix_v$&" .cindex affix variables If a local part prefix or suffix has been recognized, it is not included in the value of &$local_part$& during routing and subsequent delivery. The values of any prefix or suffix are in &$local_part_prefix$& and &$local_part_suffix$&, respectively. +.new +If the affix specification included a wildcard then the portion of +the affix matched by the wildcard is in +&$local_part_prefix_v$& or &$local_part_suffix_v$& as appropriate. +.wen When a message is being delivered to a file, pipe, or autoreply transport as a result of aliasing or forwarding, &$local_part$& is set to the local part of @@ -12506,12 +12518,26 @@ When an address is being routed or delivered, and a specific prefix for the local part was recognized, it is available in this variable, having been removed from &$local_part$&. +.new +.vitem &$local_part_prefix_v$& +.vindex "&$local_part_prefix_v$&" +When &$local_part_prefix$& is valid and the prefix match used a wildcard, +the portion matching the wildcard is available in this variable. +.wen + .vitem &$local_part_suffix$& .vindex "&$local_part_suffix$&" When an address is being routed or delivered, and a specific suffix for the local part was recognized, it is available in this variable, having been removed from &$local_part$&. +.new +.vitem &$local_part_suffix_v$& +.vindex "&$local_part_suffix_v$&" +When &$local_part_suffix$& is valid and the suffix match used a wildcard, +the portion matching the wildcard is available in this variable. +.wen + .new .vitem &$local_part_verified$& .vindex "&$local_part_verified$&" @@ -18785,6 +18811,12 @@ command for LMTP, SMTP, and BSMTP deliveries has the prefix removed by default. This behaviour can be overridden by setting &%rcpt_include_affixes%& true on the relevant transport. +.new +.vindex &$local_part_prefix_v$& +If wildcarding (above) was used then the part of the prefix matching the +wildcard is available in &$local_part_prefix_v$&. +.wen + When an address is being verified, &%local_part_prefix%& affects only the behaviour of the router. If the callout feature of verification is in use, this means that the full address, including the prefix, will be used during the diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 3cef43c32..fb6e444d3 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -39,7 +39,9 @@ Version 4.94 9. Items specified for the router and transport headers_remove option can use a trailing asterisk to specify globbing. -10. New "queue_size" variable. +10. New $queue_size variable. + +11. New variables $local_part_{pre,suf}fix_v. diff --git a/src/src/deliver.c b/src/src/deliver.c index 467813800..5c5167b3a 100644 --- a/src/src/deliver.c +++ b/src/src/deliver.c @@ -220,7 +220,9 @@ if (!addr->next) deliver_localpart = addr->local_part; deliver_localpart_prefix = addr->prefix; + deliver_localpart_prefix_v = addr->prefix_v; deliver_localpart_suffix = addr->suffix; + deliver_localpart_suffix_v = addr->suffix_v; for (addr_orig = addr; addr_orig->parent; addr_orig = addr_orig->parent) ; deliver_domain_orig = addr_orig->domain; @@ -260,7 +262,9 @@ if (!addr->next) else if (deliver_localpart[0] == '|') address_pipe = addr->local_part; deliver_localpart = addr->parent->local_part; deliver_localpart_prefix = addr->parent->prefix; + deliver_localpart_prefix_v = addr->parent->prefix_v; deliver_localpart_suffix = addr->parent->suffix; + deliver_localpart_suffix_v = addr->parent->suffix_v; } } diff --git a/src/src/expand.c b/src/src/expand.c index 661959306..660fe98cf 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -589,7 +589,9 @@ static var_entry var_table[] = { { "local_part", vtype_stringptr, &deliver_localpart }, { "local_part_data", vtype_stringptr, &deliver_localpart_data }, { "local_part_prefix", vtype_stringptr, &deliver_localpart_prefix }, + { "local_part_prefix_v", vtype_stringptr, &deliver_localpart_prefix_v }, { "local_part_suffix", vtype_stringptr, &deliver_localpart_suffix }, + { "local_part_suffix_v", vtype_stringptr, &deliver_localpart_suffix_v }, { "local_part_verified", vtype_stringptr, &deliver_localpart_verified }, #ifdef HAVE_LOCAL_SCAN { "local_scan_data", vtype_stringptr, &local_scan_data }, diff --git a/src/src/functions.h b/src/src/functions.h index be929a710..df4b33606 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -421,8 +421,8 @@ extern uschar *rfc2047_decode2(uschar *, BOOL, uschar *, int, int *, int *, uschar **); extern int route_address(address_item *, address_item **, address_item **, address_item **, address_item **, int); -extern int route_check_prefix(const uschar *, const uschar *); -extern int route_check_suffix(const uschar *, const uschar *); +extern int route_check_prefix(const uschar *, const uschar *, unsigned *); +extern int route_check_suffix(const uschar *, const uschar *, unsigned *); extern BOOL route_findgroup(uschar *, gid_t *); extern BOOL route_finduser(const uschar *, struct passwd **, uid_t *); extern BOOL route_find_expanded_group(uschar *, uschar *, uschar *, gid_t *, diff --git a/src/src/globals.c b/src/src/globals.c index a5711c73b..4ce15acaa 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -541,7 +541,9 @@ address_item address_defaults = { .lc_local_part = NULL, .local_part = NULL, .prefix = NULL, + .prefix_v = NULL, .suffix = NULL, + .suffix_v = NULL, .domain = NULL, .address_retry_key = NULL, .domain_retry_key = NULL, @@ -822,7 +824,9 @@ uschar *deliver_localpart_data = NULL; uschar *deliver_localpart_orig = NULL; uschar *deliver_localpart_parent = NULL; uschar *deliver_localpart_prefix = NULL; +uschar *deliver_localpart_prefix_v = NULL; uschar *deliver_localpart_suffix = NULL; +uschar *deliver_localpart_suffix_v = NULL; uschar *deliver_localpart_verified = NULL; uschar *deliver_out_buffer = NULL; int deliver_queue_load_max = -1; diff --git a/src/src/globals.h b/src/src/globals.h index b570078c3..1fea9c9b0 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -490,7 +490,9 @@ extern uschar *deliver_localpart_data; /* From local part lookup */ extern uschar *deliver_localpart_orig; /* The original local part for delivery */ extern uschar *deliver_localpart_parent; /* The parent local part for delivery */ extern uschar *deliver_localpart_prefix; /* The stripped prefix, if any */ +extern uschar *deliver_localpart_prefix_v; /* The stripped-prefix variable portion, if any */ extern uschar *deliver_localpart_suffix; /* The stripped suffix, if any */ +extern uschar *deliver_localpart_suffix_v; /* The stripped-suffix variable portion, if any */ extern uschar *deliver_localpart_verified; /* de-tainted by check_local_part */ extern uschar *deliver_out_buffer; /* Buffer for copying file */ extern int deliver_queue_load_max; /* Different value for queue running */ diff --git a/src/src/receive.c b/src/src/receive.c index f30ffd92d..96a48fe65 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -2907,9 +2907,8 @@ if ( from_header uschar *at = domain ? from_address + domain - 1 : NULL; if (at) *at = 0; - from_address += route_check_prefix(from_address, local_from_prefix); - slen = route_check_suffix(from_address, local_from_suffix); - if (slen > 0) + from_address += route_check_prefix(from_address, local_from_prefix, NULL); + if ((slen = route_check_suffix(from_address, local_from_suffix, NULL)) > 0) { memmove(from_address+slen, from_address, Ustrlen(from_address)-slen); from_address += slen; diff --git a/src/src/route.c b/src/src/route.c index a1426d58f..8b43613ce 100644 --- a/src/src/route.c +++ b/src/src/route.c @@ -335,19 +335,20 @@ wildcard. Arguments: local_part the local part to check prefixes the list of prefixes + vp if set, pointer to place for size of wildcard portion Returns: length of matching prefix or zero */ int -route_check_prefix(const uschar *local_part, const uschar *prefixes) +route_check_prefix(const uschar * local_part, const uschar * prefixes, + unsigned * vp) { int sep = 0; uschar *prefix; const uschar *listptr = prefixes; -uschar prebuf[64]; -while ((prefix = string_nextinlist(&listptr, &sep, prebuf, sizeof(prebuf)))) +while ((prefix = string_nextinlist(&listptr, &sep, NULL, 0))) { int plen = Ustrlen(prefix); if (prefix[0] == '*') @@ -355,10 +356,19 @@ while ((prefix = string_nextinlist(&listptr, &sep, prebuf, sizeof(prebuf)))) prefix++; for (const uschar * p = local_part + Ustrlen(local_part) - (--plen); p >= local_part; p--) - if (strncmpic(prefix, p, plen) == 0) return plen + p - local_part; + if (strncmpic(prefix, p, plen) == 0) + { + unsigned vlen = p - local_part; + if (vp) *vp = vlen; + return plen + vlen; + } } else - if (strncmpic(prefix, local_part, plen) == 0) return plen; + if (strncmpic(prefix, local_part, plen) == 0) + { + if (vp) *vp = 0; + return plen; + } } return 0; @@ -377,31 +387,40 @@ is a wildcard. Arguments: local_part the local part to check suffixes the list of suffixes + vp if set, pointer to place for size of wildcard portion Returns: length of matching suffix or zero */ int -route_check_suffix(const uschar *local_part, const uschar *suffixes) +route_check_suffix(const uschar * local_part, const uschar * suffixes, + unsigned * vp) { int sep = 0; int alen = Ustrlen(local_part); uschar *suffix; const uschar *listptr = suffixes; -uschar sufbuf[64]; -while ((suffix = string_nextinlist(&listptr, &sep, sufbuf, sizeof(sufbuf)))) +while ((suffix = string_nextinlist(&listptr, &sep, NULL, 0))) { int slen = Ustrlen(suffix); if (suffix[slen-1] == '*') { - const uschar *pend = local_part + alen - (--slen) + 1; + const uschar * pend = local_part + alen - (--slen) + 1; for (const uschar * p = local_part; p < pend; p++) - if (strncmpic(suffix, p, slen) == 0) return alen - (p - local_part); + if (strncmpic(suffix, p, slen) == 0) + { + int tlen = alen - (p - local_part); + if (vp) *vp = tlen - slen; + return tlen; + } } else if (alen > slen && strncmpic(suffix, local_part + alen - slen, slen) == 0) + { + if (vp) *vp = 0; return slen; + } } return 0; @@ -1620,9 +1639,9 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) /* Default no affixes and select whether to use a caseful or caseless local part in this router. */ - addr->prefix = addr->suffix = NULL; - addr->local_part = r->caseful_local_part? - addr->cc_local_part : addr->lc_local_part; + addr->prefix = addr->prefix_v = addr->suffix = addr->suffix_v = NULL; + addr->local_part = r->caseful_local_part + ? addr->cc_local_part : addr->lc_local_part; DEBUG(D_route) debug_printf("local_part=%s domain=%s\n", addr->local_part, addr->domain); @@ -1633,10 +1652,12 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) if (r->prefix) { - int plen = route_check_prefix(addr->local_part, r->prefix); + unsigned vlen; + int plen = route_check_prefix(addr->local_part, r->prefix, &vlen); if (plen > 0) { addr->prefix = string_copyn(addr->local_part, plen); + if (vlen) addr->prefix_v = string_copyn(addr->local_part, vlen); addr->local_part += plen; DEBUG(D_route) debug_printf("stripped prefix %s\n", addr->prefix); } @@ -1652,11 +1673,13 @@ for (r = addr->start_router ? addr->start_router : routers; r; r = nextr) if (r->suffix) { - int slen = route_check_suffix(addr->local_part, r->suffix); + unsigned vlen; + int slen = route_check_suffix(addr->local_part, r->suffix, &vlen); if (slen > 0) { int lplen = Ustrlen(addr->local_part) - slen; addr->suffix = addr->local_part + lplen; + addr->suffix_v = addr->suffix + Ustrlen(addr->suffix) - vlen; addr->local_part = string_copyn(addr->local_part, lplen); DEBUG(D_route) debug_printf("stripped suffix %s\n", addr->suffix); } diff --git a/src/src/structs.h b/src/src/structs.h index aa394ac73..7d700fb72 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -553,7 +553,9 @@ typedef struct address_item { uschar *lc_local_part; /* lowercased local part */ uschar *local_part; /* points to cc or lc version */ uschar *prefix; /* stripped prefix of local part */ + uschar *prefix_v; /* variable part of above */ uschar *suffix; /* stripped suffix of local part */ + uschar *suffix_v; /* variable part of above */ const uschar *domain; /* working domain (lower cased) */ uschar *address_retry_key; /* retry key including full address */ diff --git a/src/src/transport.c b/src/src/transport.c index d9eba1621..90789fd60 100644 --- a/src/src/transport.c +++ b/src/src/transport.c @@ -591,14 +591,14 @@ if (include_affixes) return addr->address; } -if (addr->suffix == NULL) +if (!addr->suffix) { - if (addr->prefix == NULL) return addr->address; + if (!addr->prefix) return addr->address; return addr->address + Ustrlen(addr->prefix); } at = Ustrrchr(addr->address, '@'); -plen = (addr->prefix == NULL)? 0 : Ustrlen(addr->prefix); +plen = addr->prefix ? Ustrlen(addr->prefix) : 0; slen = Ustrlen(addr->suffix); return string_sprintf("%.*s@%s", (int)(at - addr->address - plen - slen), diff --git a/test/confs/0015 b/test/confs/0015 index 8c62e2e08..b1472da06 100644 --- a/test/confs/0015 +++ b/test/confs/0015 @@ -83,7 +83,8 @@ local_delivery: file = DIR/test-mail/${bless:$local_part} return_path_add headers_add = X-local_part: $local_part\n\ - X-local_part_prefix: $local_part_prefix + X-local_part_prefix: $local_part_prefix\n\ + X-local_part_prefix_v: $local_part_prefix_v local_delivery_b: driver = appendfile @@ -94,7 +95,8 @@ local_delivery_b: return_path_add use_bsmtp headers_add = X-local_part: $local_part\n\ - X-local_part_prefix: $local_part_prefix + X-local_part_prefix: $local_part_prefix\n\ + X-local_part_prefix_v: $local_part_prefix_v delivery_s: driver = smtp diff --git a/test/confs/0016 b/test/confs/0016 index dcc005f0b..9e190d8eb 100644 --- a/test/confs/0016 +++ b/test/confs/0016 @@ -39,8 +39,11 @@ local_delivery: user = CALLER delivery_date_add envelope_to_add - file = DIR/test-mail/${bless:$local_part} + headers_add = X-local_part: $local_part\n\ + X-local_part_suffix: $local_part_suffix\n\ + X-local_part_suffix_v: $local_part_suffix_v return_path_add + file = DIR/test-mail/${bless:$local_part} address_reply: driver = autoreply diff --git a/test/mail/0015.CALLER b/test/mail/0015.CALLER index aa2e0d9ca..e01024b97 100644 --- a/test/mail/0015.CALLER +++ b/test/mail/0015.CALLER @@ -17,6 +17,7 @@ Message-Id: Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: CALLER X-local_part_prefix: +X-local_part_prefix_v: --NNNNNNNNNN-eximdsn-MMMMMMMMMM Content-type: text/plain; charset=us-ascii @@ -73,6 +74,7 @@ Message-Id: Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: CALLER X-local_part_prefix: +X-local_part_prefix_v: --NNNNNNNNNN-eximdsn-MMMMMMMMMM Content-type: text/plain; charset=us-ascii diff --git a/test/mail/0015.userx b/test/mail/0015.userx index 29b1e9a95..870f58015 100644 --- a/test/mail/0015.userx +++ b/test/mail/0015.userx @@ -11,6 +11,7 @@ From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: userx X-local_part_prefix: page+ +X-local_part_prefix_v: page Some message text. @@ -30,6 +31,7 @@ From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: userx X-local_part_prefix: +X-local_part_prefix_v: callpager -r 108 PAGE:Some message text. @@ -46,6 +48,7 @@ From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: userx X-local_part_prefix: page+ +X-local_part_prefix_v: page Some more message text. @@ -65,6 +68,7 @@ From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: userx X-local_part_prefix: +X-local_part_prefix_v: callpager -r 108 PAGE:Some more message text. @@ -83,6 +87,7 @@ From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: userx X-local_part_prefix: b+ +X-local_part_prefix_v: Text. . @@ -100,6 +105,7 @@ From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: userx X-local_part_prefix: +X-local_part_prefix_v: . MAIL FROM: @@ -116,5 +122,6 @@ From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 X-local_part: userx X-local_part_prefix: x+ +X-local_part_prefix_v: x . diff --git a/test/mail/0016.userx b/test/mail/0016.userx index 8e33c3631..5889f68ed 100644 --- a/test/mail/0016.userx +++ b/test/mail/0016.userx @@ -9,6 +9,9 @@ Received: from CALLER by the.local.host.name with local (Exim x.yz) Message-Id: From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 +X-local_part: userx +X-local_part_suffix: +page +X-local_part_suffix_v: page Some message text. @@ -26,6 +29,9 @@ Auto-Submitted: auto-replied Message-Id: From: CALLER_NAME Date: Tue, 2 Mar 1999 09:44:33 +0000 +X-local_part: userx +X-local_part_suffix: +X-local_part_suffix_v: callpager -r 108 PAGE:Some message text. diff --git a/test/scripts/0000-Basic/0016 b/test/scripts/0000-Basic/0016 index d2b07d281..a3cf1168c 100644 --- a/test/scripts/0000-Basic/0016 +++ b/test/scripts/0000-Basic/0016 @@ -1,3 +1,4 @@ # local part suffix exim -odi userx+page Some message text. +**** -- 2.30.2