Skip to content
Cron script to export Exchange emails addresses from Active Directory to a Postfix map (in case of an antimalware frontend)
Python Shell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Cron script to export Exchange emails addresses from Active Directory to a Postfix map (in case of an antimalware frontend)

Fighting backscatter

Why did I write this script ? Simple answer: most of Postfix frontends protecting email servers (Exchange :D) are badly configured. There're exposed to backscattering ( because of their domain-based configuration instead of recipient adresses.

In a few lines, what is backscattering:

  1. Spammers sends a forged email with random sender address to a random recipient
  2. Your frontend accepts the email because the recipient matches
  3. The email gets forwarded to your Exchange server
  4. Exchange receives the email but is not a valid recipient
  5. Exchange issues a sender non-delivery notification to the orginal forged sender address
  6. You get blacklisted because these kind of message get caught by honeypot like

Actually, the problem is easy to understand: your postfix frontend accepts emails for * instead of accepting only valid recipient addresses.

How to handle that ?

Most of people do something like this in their frontend configuration:

root@server:~# cat /etc/postfix/transport
# Exchange	        smtp:

It's fine but if you want to avoid backscattering your Postfix server needs to know which addresses are valid and then use this list to reject invalid users.

The script

This project is a Python3 script that connects to Active Directory using LDAP protocol and extracts from there every email address found in Exchange related attributes. Then it will turn this into a Postfix map and uses it as a whitelist for "smtpd_recipient_restrictions" postfix configuration setting.

I included some comments to configure postfix as well as a very safe cron job to update this map automatically.

Here is --help output:

usage: [-h] -H HOSTNAMES [HOSTNAMES ...]
                                            -B BASE_DN -u USER -p PASSWD -d
                                            DOMAINS [DOMAINS ...] -x EXCLUDES
                                            [EXCLUDES ...] -w WRITE

Extract list of valid Exchange addresses from ActiveDirectory to Postfix map

optional arguments:
  -h, --help            show this help message and exit
                        Active Directory host to check (using LDAP on port
                        389), can be specified multiple times, ie: --hostnames
  -B BASE_DN, --base-dn BASE_DN
                        LDAP root to search for Exchange attributes, ie:
                        --base 'ou=Corp,dc=corp,dc=com'
  -u USER, --user USER  LDAP user to use for binding, NTML format, ie: --user
  -p PASSWD, --passwd PASSWD
                        LDAP user password
  -d DOMAINS [DOMAINS ...], --domains DOMAINS [DOMAINS ...]
                        List of email domains you want to export data for, ie:
  -x EXCLUDES [EXCLUDES ...], --excludes EXCLUDES [EXCLUDES ...]
                        DN you want to exclude (BE SURE TO MATCH EXACTLY
                        WHAT'S IN AD, NO ADDITIONAL SPACES....), ie:
  -w WRITE, --write WRITE
                        Output file (postfix hashmap format), ie: --write

Known bugs

Email starting with '#' will be considered as comment by Postfix (yes Exchange allows this crap...). I haven't been able to found a way to get Postfix recognize theses addresses, no success with quotes, backslashes....

Exclude pattern is picky: I do a simple str.lower()-in-str.lower() test so whitespaces must match exactly. If someone knows an easy way to compare LDAP DNs... All I found for ldap3 modules is this: but it's pretty un-documented and all the try I gave failed.

There's no SSL/TLS support for LDAP connection, but it's trivial to add if needed.

You can’t perform that action at this time.