David Hedges

  • Home
  • About
  • Contact
  • Business Blog
  • IT Blog

How to pull MS Exchange email address into your postfix user-list

June 5, 2018 by dhedges Leave a Comment

I’ve used this in the past to limit the amount of SPAM by only allowing relay back to my exchange server of email addresses that are valid.

in /etc/postfix/main.cf you will need to modify “smtpd_recipient_rectrictions” adding the following. I called my file user-list.

  • “check_recipient_access hash:/etc/postfix/user-list.db”

Adding this will accept mail for email addresses that are listed in the file.

On the Windows Exchange server, for this I’ll assume we are using OWA and we can drop the list of addresses within the inetpub directory, allowing us to pick it up using wget.

On the exchange server I use the following script:

'==================================================================================================
'
' VBScript Source File 
'
' NAME: LISTPROXYADDRESSES.VBS
' VERSION: 0.9
' AUTHOR: Bharat Suneja , Bharat Suneja
' CREATE DATE  : 5/06/2004
' LAST MODIFIED : 9/23/2005
'==================================================================================================
' COMMENT: 
'   
'==================================================================================================

'Set up constant for deleting values from multivalued attribute memberOf

Const ADS_PROPERTY_NOT_FOUND  = &h8000500D
Const ADS_UF_ACCOUNTDISABLE = 2                       'For UserAccountControl
Const strX400Search = "X400"
'______________________________________________________

'Set RootDSE
Set objRootDSE = GetObject("LDAP://rootDSE")
strDomain = objRootDSE.Get("defaultNamingContext")
strADPath = "LDAP://" & strDomain
'wscript.Echo strADPath
Set objDomain = GetObject(strADPath)
'wscript.echo "objDomain: " & objDomain.distinguishedName

'Setup ADODB connection
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection

'Execute search command to look for Contacts & Groups
    objCommand.CommandText = _
      "<" & strADPath & ">" & ";(&(|(objectClass=contact)(objectClass=group))(mail=*))" & ";distinguishedName,displayName,mail,proxyAddresses;subtree"

    'Execute search to get Recordset
    Set objRecordSet = objCommand.Execute
    
        
        'Start procedure
        
    strResult = strResult & VbCrLf & "Domain: " & strDomain

    strResult = strResult & VbCrlf &  "#Total Records Found (other accounts): " & objRecordSet.RecordCount & VbCrlf
    AddressCount = 0

       While Not objRecordSet.EOF 'Iterate through the search results
 
            strUserDN = objRecordSet.Fields("distinguishedName")     'Get User's distinguished name from Recordset into a string
            set objUser= GetObject("LDAP://"& strUserDN & "")         'Use string to bind to user object
            


                       strResult = strResult & VbCrlf &  "cn: " & objUser.cn
                       strResult = strResult & VbCrlf &  "mail: " & objUser.mail
                       arrProxyAddresses = objRecordSet.Fields("proxyAddresses")
                       If IsArray(objRecordSet.Fields("proxyAddresses")) Then
                       strResult = strResult & VbCrLf & "Proxy Addresses" 
               
                          For Each ProxyAddress in arrProxyAddresses
                          
                            'Sub: Check X400 
                             If InStr(ProxyAddress, strX400Search) <> 0 Then 
                        		'Wscript.Echo "#This was an x400"
                    		 Else
                                     strResult = strResult & VbCrlf &  proxyAddress
                              End If   'Ends loop for X400 address
                Next

            Else
                strResult = strResult & VbCrlf &  "#Object does not have proxy addresses"
            End If
                strResult = strResult &  VbCrLf

     objRecordSet.MoveNext
Wend

'*************************************
'Begin second query for users
varDisabledCounter = 0                  

'Execute search command to look for user
    objCommand.CommandText = _
      "<" & strADPath & ">" & ";(&(objectClass=user)(mail=*))" & ";distinguishedName,displayName,mail,proxyAddresses;subtree"

    'Execute search to get Recordset
    Set objRecordSet = objCommand.Execute
    
    strResult = strResult & vbCrlf &  "#Users"
    strResult = strResult & VbCrlf &  "#Total Records Found (users): " & objRecordSet.RecordCount & VbCrlf
    


       While Not objRecordSet.EOF 'Iterate through the search results
            strUserDN = objRecordSet.Fields("distinguishedName")     'Get User's distinguished name from Recordset into a string
            set objUser= GetObject("LDAP://"& strUserDN & "")         'Use string to bind to user object
            
            
            If objUser.AccountDisabled = TRUE Then                    'If User account disabled, then skip proxy address enum
               varDisabledCounter = varDisabledCounter + 1
               strResult2 = strResult2 & VbCrLf & varDisabledCounter & " " & objUser.displayName & VbCrLf
               
               strResult2 = strResult2 & "cn: " & objUser.cn
                       strResult2 = strResult2 & VbCrlf &  "mail: " & objUser.mail
                       arrProxyAddresses = objRecordSet.Fields("proxyAddresses")
                       If IsArray(objRecordSet.Fields("proxyAddresses")) Then
                       strResult2 = strResult2 & VbCrLf & "Proxy Addresses" 
                       
               
                          For Each ProxyAddress in arrProxyAddresses
                            'Sub: Check X400
                             If InStr(ProxyAddress, strX400Search) <> 0 Then 
                        		'Wscript.Echo "#This was an x400"
                    		 Else
                        		 strResult2 = strResult2 & VbCrlf &  proxyAddress
                                 AddressCount = AddressCount + 1
                              End If   'Ends loop for X400 address
                          Next
                              Else
                                  strResult2 = strResult2 & VbCrLf &  "#Object does not have proxy addresses"
                          End If
                              strResult2 = strResult2 &  VbCrLf
               
               
               
               
               
            Else
            


                       strResult = strResult & VbCrlf &  "cn: " & objUser.cn
                       strResult = strResult & VbCrlf &  "mail: " & objUser.mail
                       arrProxyAddresses = objRecordSet.Fields("proxyAddresses")
                       If IsArray(objRecordSet.Fields("proxyAddresses")) Then
                       strResult = strResult & VbCrLf & "Proxy Addresses" 
                          
                          For Each ProxyAddress in arrProxyAddresses
                            'Sub: Check X400
                             If InStr(ProxyAddress, strX400Search) <> 0 Then 
                        		'Wscript.Echo "#This was an x400"
                    		 Else
                        		 strResult = strResult & VbCrlf &  proxyAddress
                                 AddressCount = AddressCount + 1
                              End If   'Ends loop for X400 address
                          Next
                              Else
                                  strResult = strResult & VbCrLf &  "#Object does not have proxy addresses"
                          End If
                              strResult = strResult &  VbCrLf
                
          End If   'End check for disabled user 
            
     objRecordSet.MoveNext 
Wend  'End second query for users

              
strResult = "Users, Groups & Contacts" & VbCrLf & "-------------------------" & VbCrLf & strResult
strResult = strResult & VbCrLf & "Disabled Users" & VbCrLf & "-------------------------" & VbCrLf & strResult2
'WScript.Echo strResult

'Output to a text file
Set objFileSystem = CreateObject("Scripting.FileSystemObject")
Set objOutputFile = objFileSystem.CreateTextFile("C:\inetpub\wwwroot\postfix\proxyaddresses.txt")
objOutputFile.Write strResult


     
   


            




You will want to modify the location that it places the file to the correct location for you “Set objOutputFile = objFileSystem.CreateTextFile(“C:\inetpub\wwwroot\postfix\proxyaddresses.txt”)”

After testing this I also created a scheduled task on the exchange server to run this every 15 min. This way when users are added or new email addresses are created they will automatically be placed in a location where they can be picked up by our postfix server.

 

On the postfix server, I created the following script to pull the file from the exchange server and format it correctly for postfix:

 

#!/bin/bash
#pull exhange user email 
#written by David Hedges 

mkdir /tmp/exch-users
cd /tmp/exch-users
wget http://<YOUR SERVER IP or FQDN>/postfix/proxyaddresses.txt

#you may need to add sed statements for other domain extensions if you use one that is not listed
grep -i smtp proxyaddresses.txt |grep -v ADdomain.local |sed 's/smtp://g' |sed 's/SMTP://g'|sed 's/\.com/\.com\tOK/g' |sed 's/\.COM/\.COM\tOK/g' |sed 's/\.net/\.net\tOK/g' |sed 's/\.NET/\.NET\tOK/g' |sed 's/\.tv/\.tv\tOK/g' |sed 's/\.TV/\.TV\tOK/g' |sed 's/\.org/\.org\tOK/g' |sed 's/\.ORG/\.ORG\tOK/g' |sed 's/\.info/\.info\tOK/g' |sed 's/\.INFO/\.INFO\tOK/g' | sed 's/\.us/\.us\tOK/g' | sed 's/\.US/\.US\tOK/g'  >/tmp/exch-users/user-list


/usr/sbin/postmap user-list
mv ./user-list.db /etc/postfix/
mv ./user-list /etc/postfix
cd /tmp
rm -R /tmp/exch-users

This will place both a plain text and a hash file in your /etc/postfix directory.

For this I also created a cron job to run it every 5 min. That way it will pick up the changes as the exchange host publishes them.

Finally, you will need to restart your postfix instance for the change to read the user-list.db file to begin.

 

 

Filed Under: IT Blog

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Copyright © 2025 · Beautiful Pro Theme on Genesis Framework · WordPress · Log in