On Monday 13 December 2010 21:58:10 Michael Lampe wrote:
> The whole thing is this:
> 
> -----
> 
> # LDAP Router
> 
> LDAP_USER="uid=mail,ou=System-User,dc=localhost"
> LDAP_PASS=xxxxxxxxxxxxxxxxxxxx
> LDAP_URL=ldapi://${quote_ldap_dn:/var/run/ldapi}
> LDAP_LOCALPART_ATT=mailLocalAddress
> LDAP_MAIL_GROUP=E-Mail
> LDAP_UID_QUERY=${lookup ldapm {user=LDAP_USER pass=LDAP_PASS \ 
> LDAP_URL/ou=People,dc=localhost?uid?sub?(LDAP_LOCALPART_ATT=${quote_ldap_dn
> :$local_part})}} 
> LDAP_GROUP_QUERY=${lookup ldapm {user=LDAP_USER
>  pass=LDAP_PASS \
>          LDAP_URL/cn=LDAP_MAIL_GROUP,ou=Groups,dc=localhost?cn?base?\
>                  (uniqueMember=uid=$item,ou=People,dc=localhost)}}
> 
> ldap_user:
>    debug_print = "R: ldap_user for $local_p...@$domain"
>    driver = accept
>    domains = +local_domains
>    local_parts = ! root
>    local_part_suffix = +*
>    local_part_suffix_optional
>    address_data = ${filter {<\n
> LDAP_UID_QUERY}{eq{LDAP_GROUP_QUERY}{LDAP_MAIL_GROUP}}}
>    condition = ${if >{${strlen:${filter {<\n
> LDAP_UID_QUERY}{eq{LDAP_GROUP_QUERY}{LDAP_MAIL_GROUP}}}} }{0}}
>    transport = pipe_delivery_cyrus
>    cannot_route_message = ldap_user: mail address $local_part does not
>  exist
 
Right then (apologies if you know this already):
  - Based on what you've shown above LDAP_UID_QUERY looks up the uid(s) of 
user(s) who's addresses match the current $local_part.
  -The filter then basically checks if these uids are members of the "E-mail" 
group.

There's a couple if strange things (someone correct me if I'm wrong about 
anything):
  - LDAP_GROUP_QUERY uses ldapm (multiple matches separated by newlines). 
However, if there are in fact multiple matches (a uid is a member of more than 
one group), then the filter's eq{}{} will fail to match and membership of "E-
mail" won't get the mail delivered. That leads me to think that there's only 
one possible group in the ldap database, the E-mail group, making it (at least 
partly) redundant (it could still be used to 'enable' or 'disable' a user's 
address.

  - An email address can map to more than one uid. I suppose it's one way to 
do multiple recipients for role accounts etc. However, you would usually do 
that sort of thing in a rewrite router, not directly in the delivery router. 
It's easier (IMHO) to track issues that way. 

  - Since this is an accept router, and the transport is called 
"pipe_delivery_cyrus" I'm guessing the transport uses the cyrus 'deliver' 
command through a pipe. I'd like to take a look at it, since my guess is that 
it uses $address_data to choose mailbox(es) to deliver to. The way the old 
admin has written the command should show whether he/she thought it'd be 
handling multiple deliveries for an individual message. Also check if 
"batch_max" is set. If not (default is 1, i.e. individual deliveries) then 
it's one user per mailbox and address, so the $filter isn't needed (or it's a 
bug)

So, your options (in no particular order):
  - If no users have the same email address you can get rid of ${filter} 
completely. Switch to ldap (from ldapm) if you want and then change the 
condition so that essentially LDAP_UID_QUERY replaces $item in 
LDAP_GROUP_QUERY. 

  - If there IS the possibility of different uids having the same $local_part, 
you should be able to get filter's behaviour by a bit of regex magic and a 
"dynamic" LDAP_GROUP_QUERY. Given a newline separated list of uids from 
LDAP_UID_QUERY, the following should (might) work as a drop in replacement for 
LDAP_GROUP_QUERY:

LDAP_GROUP_QUERY=${lookup ldapm {user=LDAP_USER pass=LDAP_PASS \
        LDAP_URL/cn=LDAP_MAIL_GROUP,ou=Groups,dc=localhost?cn?base?\
        (|\
          ${sg{\
                ${tr{LDAP_UID_QUERY}{\n}{ }}}\
                {\N(\S+)\N}\
                {(uniqueMember=uid=\$1,ou=People,dc=localhost)}\
          }\
        )

Basically, it takes LDAP_UID_QUERY and strips out newlines, replacing with 
spaces. The $sg then takes all the non whitespace character groups and  wraps 
them with some stuff to make an ldap query "OR" string. Thinking about it, 
this may actually be faster than using $filter for a long list of uids, since 
no matter how long the list, only one lookup is ever done. Is there a maximum 
string length in exim? Doubt it'd be a problem in this case, but who knows. 
Note that some of the above might need ${quote_ldap:}ing and stuff. I've not 
tested it in an actual lookup, but the expansion works.

  - Use a perl function/external program/something else to do the splitting 
for you.
 
That should give you some ideas. I would advise however that  (as Bill said), 
you need to test this sort of thing very thoroughly if it's a production 
environment. Also, give us a gander at the transport.

Finally, don't assume that the way the configuration is at the moment is the 
correct way to do things (it may appear to be working, but just give it a 
while, I guarantee that bugs will appear). If you can give us the details that 
Bill asked about, I'm sure we'll have some ideas. 

Hope that helps.

Ben



-- 
## List details at http://lists.exim.org/mailman/listinfo/exim-users 
## Exim details at http://www.exim.org/
## Please use the Wiki with this list - http://wiki.exim.org/

Reply via email to