[Exim] Multiple routers for a single message

Top Page
Delete this message
Reply to this message
Author: Nathan Ollerenshaw
Date:  
To: exim-users
Subject: [Exim] Multiple routers for a single message
Hi all,

Some background. I've got a qmail-ldap install with a few thousand
domains and the management of this beast is becoming impossible. I've
decided to migrate to Exim. When I posted about this last, some of you
helped me with sending some example qmail-ldap based exim configs.
Thanks, its been a great help and started me in the right direction.

Now, I have some problems.

qmail-ldap supports various possibilities when it comes to delivery.

- local delivery (delivery to a mailbox)
- forwarding (so, a mailing list/alias)
- autoreplies (non RFC compliant, sent from the address of the auto
responder)

Plus, you can have a catchall where any mail to a nonexistant address
@domain gets tried against catchall@domain - there is more to it than
this, but I don't need to support everything, just this method.

Now, you can assign any of the 'features' to any account. Nothing in
the schema prevents this, so you can quite happily have a catchall that
has a mailbox, forwards to 100 addresses and has an autoreply! I
recently had someone do a dictionary attack against one of our customer
domains set up like this ... as you can imagine, mayhem ensued.

So, I don't want to support more than one forwarder on a catchall, and
I don't want to support autoreplies on catchalls either.

But, I do need to support all these features on a non-catchall account
(people are using them). So, I configured a bunch of routers:

--------- Cut ---------

dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
no_more

autoreply:
driver = accept
condition = GET_AUTOREPLY_TEXT
transport = autoreply_local

forwardonly:
driver = redirect
data = GET_FORWARDONLY_ADDRESSES
headers_add = X-Q-Mailing-List: $local_part@$domain

# Checks to see if there is a message store defined for a particular
account.
# Uses deliveryMode in conjunction with this. If condition succeeds,
send to
# the local_delivery transport.
deliverlocal:
driver = accept
condition = GET_MAIL_MESSAGE_STORE
transport = local_delivery
cannot_route_message = There is no such mailbox on this server.

# Checks ldap to see if there is a catchall@$domain with deliveryMode:
forwardonly
catchall_forwardonly:
driver = redirect
data = GET_CATCHALL_FORWARDONLY_ADDRESSES
headers_add = X-Q-Mailing-List: $local_part@$domain

# Checks ldap to see if there is a catchall@$domain with deliveryMode:
localdelivery
catchall_deliverlocal:
driver = accept
condition = GET_CATCHALL_MAIL_MESSAGE_STORE
transport = local_delivery_catchall
cannot_route_message = There is no such mailbox on this server.

--------- Cut ---------

Transports aren't important here.

The macros are all just LDAP queries that grab the associated account
detals for $local_part@$domain. The queries all work fine, and I can
put lots of logic into the queries, but I would prefer to keep them
simple.

What I would like is to have the autoreply router to accept the message
and send the autoreply, then pass it onto the forwardonly and
deliverlocal routers in case the account also has these features, but
NOT do a 550 if they fail, which is what happens if I set 'unseen =
true'.

Also, if autoreply, forwardonly and deliverlocal can't handle the
message, it will obviously fall through, but then I want the same
behaviour for the catchall accounts.

Now, I could set up a separate router for each and every case, but
then, how do I get it to pass the message through to the correct
transports? Should I define all the possible combinations at the top of
the routers definition, and then have them somehow 'fall through' to a
string of routers that are configured with unseen in the correct order.

For example:

--------- Cut ---------

mailbox_forward_autoreply:
driver = pass (??? doesn't work)
pass_router = mfa_mailbox

mailbox_forward:
driver = pass
pass_router = mf_mailbox

{ETC}

#### Mailboxed Forwarded Autoreplies

mfa_mailbox:
driver = accept
# do delivery to the mailbox
unseen = true

mfa_forward:
driver = redirect
# forward the mail onward
unseen = true

mfa_autoreply:
driver = accept
# do the autoreply
no_more

### Mailboxed Forwarders

mfa_forward:
driver = redirect
# forward the mail onward
unseen = true

mfa_autoreply:
driver = accept
# do the autoreply
no_more

{ETC}

--------- Cut ---------

Now, obviously this won't work (pass doesn't work like that) but you
can see what I'm trying to do here. What is the correct way to
implement complex mail flow like this? Am I a complete spanner and in
my tired state missing something completely bleedingly obvious?

One of the following would work:

1) getting a router to be able to push into multiple transports
2) having a router be able to branch out to different routers based on
some condition
3) being able to have a transport do its thing then pass the message
back to a particular router
4) something else that I've missed

I've been scouring the documentation, and I'm either missing something
or I'm a complete dolt. Probably both.

Thanks, and apologies for the long email.

Nathan.

--
Nathan Ollerenshaw - Unix Systems Engineer
ValueCommerce - http://www.valuecommerce.ne.jp/