1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* Copyright (c) The Exim Maintainers 2020 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
11 #include "rf_functions.h"
14 /*************************************************
15 * Get errors address for a router *
16 *************************************************/
18 /* This function is called by routers to sort out the errors address for a
19 particular address. If there is a setting in the router block, then expand and
20 verify it, and if it works, use it. Otherwise use any setting that is in the
21 address itself. This might be NULL, meaning unset (the message's sender is then
22 used). Verification isn't done when the original address is just being
23 verified, as otherwise there might be routing loops if someone sets up a silly
27 addr the input address
28 rblock the router instance
29 verify v_none / v_recipient / v_sender / v_expn
30 errors_to point the errors address here
32 Returns: OK if no problem
33 DEFER if verifying the address caused a deferment
34 or a big disaster (e.g. expansion failure)
38 rf_get_errors_address(address_item *addr, router_instance *rblock,
39 int verify, uschar **errors_to)
43 *errors_to = addr->prop.errors_address;
44 if (rblock->errors_to == NULL) return OK;
46 s = expand_string(rblock->errors_to);
50 if (f.expand_string_forcedfail)
53 debug_printf("forced expansion failure - ignoring errors_to\n");
56 addr->message = string_sprintf("%s router failed to expand \"%s\": %s",
57 rblock->name, rblock->errors_to, expand_string_message);
61 /* If the errors_to address is empty, it means "ignore errors" */
65 addr->prop.ignore_error = TRUE; /* For locally detected errors */
66 *errors_to = US""; /* Return path for SMTP */
70 /* If we are already verifying, do not check the errors address, in order to
71 save effort (but we do verify when testing an address). When we do verify, set
72 the sender address to null, because that's what it will be when sending an
73 error message, and there are now configuration options that control the running
74 of routers by checking the sender address. When testing an address, there may
75 not be a sender address. We also need to save and restore the expansion values
76 associated with an address. */
82 debug_printf("skipped verify errors_to address: already verifying\n");
86 BOOL save_address_test_mode = f.address_test_mode;
90 const uschar *address_expansions_save[ADDRESS_EXPANSIONS_COUNT];
91 address_item *snew = deliver_make_addr(s, FALSE);
95 save1 = sender_address[0];
96 sender_address[0] = 0;
99 for (i = 0, p = address_expansions; *p;)
100 address_expansions_save[i++] = **p++;
101 f.address_test_mode = FALSE;
103 /* NOTE: the address is verified as a recipient, not a sender. This is
104 perhaps confusing. It isn't immediately obvious what to do: we want to have
105 some confidence that we can deliver to the address, in which case it will be
106 a recipient, but on the other hand, it will be passed on in SMTP deliveries
107 as a sender. However, I think on balance recipient is right because sender
108 verification is really about the *incoming* sender of the message.
110 If this code is changed, note that you must set vopt_fake_sender instead of
111 vopt_is_recipient, as otherwise sender_address may be altered because
112 verify_address() thinks it is dealing with *the* sender of the message. */
114 DEBUG(D_route|D_verify)
115 debug_printf("------ Verifying errors address %s ------\n", s);
116 if (verify_address(snew, NULL,
117 vopt_is_recipient /* vopt_fake_sender is the alternative */
118 | vopt_qualify, -1, -1, -1, NULL, NULL, NULL) == OK)
119 *errors_to = snew->address;
120 DEBUG(D_route|D_verify)
121 debug_printf("------ End verifying errors address %s ------\n", s);
123 f.address_test_mode = save_address_test_mode;
124 for (i = 0, p = address_expansions; *p; )
125 **p++ = address_expansions_save[i++];
127 if (sender_address) sender_address[0] = save1;
133 /* End of rf_get_errors_address.c */