Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

My client has got many sub-offices, and one head office. The headoffice has a domain name:

All users in the many sub-offices need to have a headoffice email address: Anyone not in the head office will need the email forwarded to an external email address. All users in the head office will have their email delivered to Microsoft Exchange. Users are listed in Active Directory under two different OU's: HeadOffice or SubOffice.

Is this something able to be configured? I've done some googling, but I can't find any examples or businesses set up this way.

Edit: Postfix will accept all email, will need to determine to forward the email to an external account or alternatively have it delivered to MS Exchange.

I've done some reading about MS Exchange and that you can 'mail-enable' contacts for forwarding - but I don't know if each AD account requires an Exchange CAL?

The end goal is to forward email to external accounts to sub offices or accept email for head office.

Maybe I don't need to worry about Postfix to perform this task.....

"What about client access licenses (CALs)? You need one CAL per user who will connect to Exchange. Although it might not be 100 percent precise, I prefer to think of it as one CAL per mailbox; there are exceptions for users outside your organization, automated tools that use mailboxes, and so on. Exchange doesn't enforce this limit, so it's on you to ensure that you have the correct number of CALs for the set of clients you support."

share|improve this question
You generally do not "mix" email servers. Not only that if you did, it's not like Exchange would play nicely with other email servers anyway. Take it from experience, that getting exchange to work nicely with say qmail is a nightmare. You're better off doing a migration to postfix and dropping exchange. If you need AD then move to OpenLDAP or just use a DC. – jersten Jul 2 '12 at 1:15
It would be helpful to know more about your topology. Where does postfix fit in to the flow of email? Where is Exchange exactly. Is it postfix on Windows or *nix? Does postfix's server communicate with Active Directory? A lot is unclear. – Wesley Jul 2 '12 at 5:26
Postfix would accept all email for delivery, check whether it needs to forward to an internal exchange server, or forward out to an external email account. – itwb Jul 2 '12 at 6:09

Whilst not strictly speaking answering your question, what you are trying to achieve should be fairly easy with a few modifications to the perl script below.

The perl script queries active directory and returns a list of email addresses within the specified OU matching the patterns in the script, and then regenerates the configuration file that postfix uses to determine valid email addresses that it needs to accept email for.

The perl script is called by a bash script, which is initiated via cron.

With some work, it should be fairly easy to tweak the scripts to allow you to do what you need.

Note that you will need to create a user in AD with the details specified in the perl script, and that user account requires read access to the relevant objects in your AD.

$hqbase determines the container that will be searched for email addresses.

Create the following bash script, which is initiated via cron:

# Get the email addresses from AD, if it fails exit the script
/root/ || exit
# Now convert the list into a file that postfix can understand
/usr/sbin/postmap /etc/postfix/exchange_recipients

The following is the file, which is called from the above shell script. You will need to modify this to get the results you are looking for.

use Net::LDAP;
use Net::LDAP::Control::Paged;
use Net::LDAP::Constant ( "LDAP_CONTROL_PAGED" );

$VALID = "/etc/postfix/exchange_recipients";




$ldap = Net::LDAP->new($dc1) or
if ($noldapserver == 1)  {
   $ldap = Net::LDAP->new($dc2) or
      die "Error connecting to specified domain controllers $@ \n";

$mesg = $ldap->bind ( dn => $user,
                     password =>$passwd);
if ( $mesg->code()) {
    die ("error:", $mesg->code(),"\n","error name: ",$mesg->error_name(),
        "\n", "error text: ",$mesg->error_text(),"\n");

$page = Net::LDAP::Control::Paged->new( size => 990 );

@args = ( base     => $hqbase,
         filter => "(& (mailnickname=*) (| (&(objectCategory=person)
                    (objectCategory=group)(objectCategory=publicFolder)(objectClass=msExchDynamicDistributionList) ))",
          control  => [ $page ],
          attrs  => "proxyAddresses",

my $cookie;
while(1) {
  # Perform search
  my $mesg = $ldap->search( @args );

  foreach my $entry ( $mesg->entries ) {
    my $name = $entry->get_value( "cn" );
    # LDAP Attributes are multi-valued, so we have to print each one.
    foreach my $mail ( $entry->get_value( "proxyAddresses" ) ) {
     # Test if the Line starts with one of the following lines:
     # proxyAddresses: [smtp|SMTP]:
     # and also discard this starting string, so that $mail is only the
     # address without any other characters...
     if ( ( $mail =~ s/^(smtp|SMTP)://gs ) &&
          ( ( $mail =~ m/ ) ||
            ( $mail =~ m/ ) ||
            ( $mail =~ m/ ) ||
            ( $mail =~ m/ ) ) ) {
       push(@valid, $mail." OK\n");

  # Only continue on LDAP_SUCCESS
  $mesg->code and last;

  # Get cookie from paged control
  my($resp)  = $mesg->control( LDAP_CONTROL_PAGED ) or last;

  $cookie    = $resp->cookie or last;

  # Set cookie in paged control

if ($cookie) {
  # We had an abnormal exit, so let the server know we do not want any more
  $ldap->search( @args );
  # Also would be a good idea to die unhappily and inform OP at this point
     die("LDAP query unsuccessful");
open VALID, ">$VALID" or die "CANNOT OPEN $VALID $!";
print VALID @valid;

close VALID;

Hopefully this will be of some help to you.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.