Re: [Exim] Re: How to implement qmail-ldap like cluster/dist…

Top Page
Delete this message
Reply to this message
Author: Mark A. Hershberger
Date:  
To: xuezs
CC: Exim Users Mailing List
Subject: Re: [Exim] Re: How to implement qmail-ldap like cluster/distributed mail system
<xuezs@???> writes:

> <mah@???> wrote:
>> Doesn't qmail-ldap use the mailHost attribute to say which host is the
>> final delivery point for an address?
>>
>> I set up a LOCALNAME that is set to the hostname of the machine. If
>> this name matches the mailHost attribute, then a local delivery is
>> made. Otherwise, route mail to the mailHost.


> Yes, that it is, but I'm fresh new to Exim, could you please give me
> some more info in details?


Here is are the excerpts of a heavily commented version of how to
accomplish this.

(Note that this is exim3.)

Somewhere near the top:

    # Put your local machine name here:
    THIS_BOX = superman.everybody.org


    ldap_default_servers = THIS_BOX::389


We'll use THIS_BOX to determine if this is the right host to deliver
to later.

A little about how my LDAP store is structured: a domain is kept in
its own branch of the LDAP repository so that can use OpenLDAP's ACLs
to grant a user control over a single domain.

This looks something like:

  DomainDN:
    dc=everybody,dc=org,ou=domains,o=top
    dc=nichework,dc=org,ou=domains,o=top


  EmailDN:
    mail=mah@???,ou=users,dc=everybody,dc=org,ou=domains,o=top
    cn=webmaster,ou=users,dc=slideshow,dc=org,ou=domains,o=top


Emails can be specified using either the mail attribute (for a user's
primary address) or the mailAlternateAddress (if they have other
local_parts).

I want to make sure that someone who controls the everybody.org
domain can't add a @nichework.com address and have it routed, so I
have to ensure that the domain of the recipient sits under the right
part of the tree. To do this, I split $domain into components and
look only under that part of the tree:

    # Split the domain up:
    DOMAIN2DC = dc=${sg{$domain}{\\.}{,dc=}}


Since I repeat the same user lookup in several places, I just define
that at the top:

    USER_LOOKUP = ldap:///ou=Users,DOMAIN2DC,ou=Domains,o=top??    \
                  sub?(|(mail=$local_part@$domain)                 \
                        (mailAlternateAddress=$local_part@$domain))


(That's all one line in my config file, though.)

    # Hide from the hackers a little
    smtp_banner = $primary_hostname ESMTP
    primary_hostname = THIS_BOX


    local_domains = localhost: \
            ldap;ldap::///dc=${sg{$key}{\\.}{,dc=}},ou=Domains,o=top


The above is needed for local_domains so that exim can lookup whether
or not we deliver for the domain being requested.

In my transports section, I look up the uid, gid, and maildir for the
user for delivery on the local box.

    local_delivery_maildir:
        driver = appendfile
        create_directory = true
        mode = 0700
        maildir_format = true
        directory = ${extract {mailMessageStore}{${lookup ldap{USER_LOOKUP}}}}
        user      = ${extract {uidNumber}{${lookup ldap{USER_LOOKUP}}}}
        group     = ${extract {gidNumber}{${lookup ldap{USER_LOOKUP}}}}


If the email is local to our network of machines, but the user's
mailHost is not this box, then I use this transport:

    local_smtp:
        driver = smtp
        max_rcpt = 1
        hosts_override = true
        hosts = ${extract {mailHost}{${lookup ldap{USER_LOOKUP}}}}


Aliases are kept in the mailForwardingAddress attribute.

    expand_alias:
        driver = forwardfile
        check_local_user = false
        local_parts = ${lookup ldap{USER_LOOKUP}{$local_part}}
        data = ${sg{${lookup ldap{USER_LOOKUP}}}                 \
            {mailForwardingAddress=(\S*)|\\S+="[^"]*"|\\S+=\\S*}{$1, }}


This little director checks to see if we can do a local delivery. If
not (mailHost != THIS_BOX), then we send the address to the
local_smtp transport (above) and it directs the mail to the mailHost.

    local_addr_to_remote:
        driver = smartuser
        local_parts = ${if !eq {THIS_BOX} \
            {${extract {mailHost}{${lookup ldap{USER_LOOKUP}}}}} \
            {$local_part}}
        transport = local_smtp


Otherwise, we do a local delivery on this box.

    local_addr_to_local:
        driver = smartuser
        local_parts = ${lookup ldap{USER_LOOKUP}{$local_part}}
        transport = local_delivery_maildir
        require_files = ${extract {uidNumber}
                          {${lookup ldap{USER_LOOKUP}}}}:
                        ${extract {mailMessageStore}
                          {${lookup ldap{USER_LOOKUP}}}}


Hope that helps,

Mark.


--
As long as you have mystery you have health; when you destroy mystery
you create morbidity.                 -- G.K. Chesterson