Took a bit of debugging and strange router construction (can we please
get logwrite to somehow be called inside a router), but I wanted to
document what I found in relation to what happens to $address_data
during routing, redirects and child routing.
I had very specific use case and the documentation explained what the
pieces did, but not when I put them all together in a very specific way.
----
In our system a user account can be a mailbox account, a forwarding (1
or more addresses) account or both.
In our router config at the point where we would redirect to any
forwarding addresses, we test whether the on_forward bit is on AND
then also test whether the on_fwd_keep bit is on and that test result
is expanded for the unseen option for that router.
FYI This is PSEUDO router code.
For brevity's sake where you see: $address_data->field, in the actual
config it looks something like this:
${extract{field}{$address_data}{$value}{0}}
and $is_local_address is something like:
>{${extract{user_id}{$address_data}{$value}{0}}}{0}
forward:
no_verify
condition = $is_local_address AND ($address_data->on_forward > 0)
driver = redirect
check_ancestor
qualify_preserve_domain
data = ${lookup mysql{SELECT forward FROM users \
WHERE user_id = $rcpt_db_userid}{$value}{}}
unseen = ($address_data->on_fwd_keep > 0)
local_user:
no_verify
condition = $is_local_address AND ($address_data->smtpdir != "")
driver = accept
retry_use_local_part
transport = virtual_delivery
address_data = $address_data
# pass on the entire record to the transport. let it extract
# smtpdir and quota as necessary
mx_deliver:
condition = !$is_local_address
driver = dnslookup
transport = remote_smtp
e.g. AddrA -> AddrB,AddrC (on_forward and on_fwd_keep are both set to
ONE)
When exim is running an address through the routers and hits a
redirect router that accepts the address, as documented, it starts a
new routing chain going back to the top of the routers and starts
testing each address returned by the "data" option of that original
redirect router.
If you've set the $address_data variable at any point then at the
beginning of each child router run, $address_data is populated with
the value it had from the parent at the point of the redirect. In my
setup, I'm doing a db lookup at the very first non-verifying router
and setting $address_data to those results like so:
lookup_user_data:
no_verify
driver = redirect
address_data = ${lookup mysql{SELECT
user_id,on_forward,user_quota,on_fwd_keep,smtpdir \
FROM users WHERE username=$local_part AND domain=$domain }}
data =
...at this point $address_data has either the db field values for that
users record or empty if the address in question is not a local domain
What I really wanted to know was if I had set $address_data on each
child routing run and unseen was set on the parent address, what was
in $address_data after the child(ren) routing chains were completed
and exim came back from the call chain to continue routing the parent
address for addresses where unseen was set in the positive.
Empirical results:
-- $address_data gets set at beginning of each child run to the
parent value, regardless of what it is set to during a child run.
-- $address_data retains it's original value for the parent when
returning from child routing runs to finish the original routing
process.
This makes my setup work very well, as looking up and setting
$address_data at the very first router gives and maintains the data I
went to the db for and I can rely on that data being there at the
appropriate time.
This is a very specific instance, but I thought seeing it all laid out
beginning to end might help someone later on even if you aren't doing
this exact same thing.
Brian