Merge branch 'debian'
[hcoop/debian/exim4.git] / src / routers / rf_get_errors_address.c
CommitLineData
420a0d19
CE
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
2ea97746 5/* Copyright (c) University of Cambridge 1995 - 2018 */
420a0d19
CE
6/* See the file NOTICE for conditions of use and distribution. */
7
8#include "../exim.h"
9#include "rf_functions.h"
10
11
12/*************************************************
13* Get errors address for a router *
14*************************************************/
15
16/* This function is called by routers to sort out the errors address for a
17particular address. If there is a setting in the router block, then expand and
18verify it, and if it works, use it. Otherwise use any setting that is in the
19address itself. This might be NULL, meaning unset (the message's sender is then
20used). Verification isn't done when the original address is just being
21verified, as otherwise there might be routing loops if someone sets up a silly
22configuration.
23
24Arguments:
25 addr the input address
26 rblock the router instance
27 verify v_none / v_recipient / v_sender / v_expn
28 errors_to point the errors address here
29
30Returns: OK if no problem
31 DEFER if verifying the address caused a deferment
32 or a big disaster (e.g. expansion failure)
33*/
34
35int
36rf_get_errors_address(address_item *addr, router_instance *rblock,
37 int verify, uschar **errors_to)
38{
39uschar *s;
40
2ea97746 41*errors_to = addr->prop.errors_address;
420a0d19
CE
42if (rblock->errors_to == NULL) return OK;
43
44s = expand_string(rblock->errors_to);
45
46if (s == NULL)
47 {
2ea97746 48 if (f.expand_string_forcedfail)
420a0d19
CE
49 {
50 DEBUG(D_route)
51 debug_printf("forced expansion failure - ignoring errors_to\n");
52 return OK;
53 }
54 addr->message = string_sprintf("%s router failed to expand \"%s\": %s",
55 rblock->name, rblock->errors_to, expand_string_message);
56 return DEFER;
57 }
58
59/* If the errors_to address is empty, it means "ignore errors" */
60
61if (*s == 0)
62 {
2ea97746 63 addr->prop.ignore_error = TRUE; /* For locally detected errors */
420a0d19
CE
64 *errors_to = US""; /* Return path for SMTP */
65 return OK;
66 }
67
68/* If we are already verifying, do not check the errors address, in order to
69save effort (but we do verify when testing an address). When we do verify, set
70the sender address to null, because that's what it will be when sending an
71error message, and there are now configuration options that control the running
72of routers by checking the sender address. When testing an address, there may
73not be a sender address. We also need to save and restore the expansion values
74associated with an address. */
75
76if (verify != v_none)
77 {
78 *errors_to = s;
79 DEBUG(D_route)
80 debug_printf("skipped verify errors_to address: already verifying\n");
81 }
82else
83 {
2ea97746 84 BOOL save_address_test_mode = f.address_test_mode;
420a0d19
CE
85 int save1 = 0;
86 int i;
2ea97746
CE
87 const uschar ***p;
88 const uschar *address_expansions_save[ADDRESS_EXPANSIONS_COUNT];
420a0d19
CE
89 address_item *snew = deliver_make_addr(s, FALSE);
90
91 if (sender_address != NULL)
92 {
93 save1 = sender_address[0];
94 sender_address[0] = 0;
95 }
96
97 for (i = 0, p = address_expansions; *p != NULL;)
98 address_expansions_save[i++] = **p++;
2ea97746 99 f.address_test_mode = FALSE;
420a0d19
CE
100
101 /* NOTE: the address is verified as a recipient, not a sender. This is
102 perhaps confusing. It isn't immediately obvious what to do: we want to have
103 some confidence that we can deliver to the address, in which case it will be
104 a recipient, but on the other hand, it will be passed on in SMTP deliveries
105 as a sender. However, I think on balance recipient is right because sender
106 verification is really about the *incoming* sender of the message.
107
108 If this code is changed, note that you must set vopt_fake_sender instead of
109 vopt_is_recipient, as otherwise sender_address may be altered because
110 verify_address() thinks it is dealing with *the* sender of the message. */
111
112 DEBUG(D_route|D_verify)
113 debug_printf("------ Verifying errors address %s ------\n", s);
114 if (verify_address(snew, NULL,
115 vopt_is_recipient /* vopt_fake_sender is the alternative */
116 | vopt_qualify, -1, -1, -1, NULL, NULL, NULL) == OK)
117 *errors_to = snew->address;
118 DEBUG(D_route|D_verify)
119 debug_printf("------ End verifying errors address %s ------\n", s);
120
2ea97746 121 f.address_test_mode = save_address_test_mode;
420a0d19
CE
122 for (i = 0, p = address_expansions; *p != NULL;)
123 **p++ = address_expansions_save[i++];
124
125 if (sender_address != NULL) sender_address[0] = save1;
126 }
127
128return OK;
129}
130
131/* End of rf_get_errors_address.c */