ADSI, Exchange, and Python |
 
Python's adsi access works really well with Exchange (late or early binding since you can read microsoft's type library). To get started, you will need to download adsi from microsoft: Microsoft ADSI. Microsoft has documentation for using languages other than python in the sdk.
Before doing anything else you need to go through the next two steps:
Task | Description |
---|---|
Create Global Providers Object | adsi = win32com.client.Dispatch('ADsNameSpaces') |
Create LDAP Provider Object | ldap = adsi.getobject("","LDAP:") |
Task | Description |
---|---|
Specify Login and Domain | logon_ex='cn=wilma, dc=bedrock' |
Specify password | password='dino' |
Login to Server | myDSObject = ldap.OpenDSObject(ex_path,logon_ex,password,0) |
The ex_path in the above example specifies the resource you are trying to access. For example:
Task | Description |
---|---|
Specific User | ex_path="LDAP://server/cn=fredflintsone,cn=Recipients,ou=rubble,o=bedrock" |
Mailing List | ex_path="LDAP://server/cn=bedrock,cn=Recipients,ou=rubble,o=bedrock" |
All Recipients | ex_path="LDAP://server/cn=Recipients,ou=rubble,o=bedrock" |
Adding a user to exchange
# Adding a new account to exchange is simple except for one thing. # You need to associate an NT account with an exchange account. # To do so at this point requires some c++ to produce some hex SID # and trustee information that adsi can use. # At this point assume we have C++ magic # # Note we are accessing Recipients directly now ex_path="LDAP://server/cn=Recipients,ou=rubble,o=bedrock" logon_ex='cn=wilma,dc=bedrock' password='dino' myDSObject = ldap.OpenDSObject(ex_path,logon_ex,password,0) newobj = myDSObject.create("OrganizationalPerson", "cn=betty") newobj.put('MailPreferenceOption', 0) # etc . . . add whatever else you want. There are a few required fields. # Now the part to get exchange associated with NT # The Magic is here import win32pipe assoc_nt=win32pipe.popen('getsid bedrock\\fredflint') nt_security=win32pipe.popen('gettrustee bedrock\\fredflint') newobj.put('NT-Security-Descriptor',assoc_nt) newobj.put('NT-Security-Descriptor',nt_security) newobj.SetInfoGetting/Modify user info
ex_path="LDAP://server/cn=fredflint,cn=Recipients,ou=rubble,o=bedrock" myDSObject = ldap.OpenDSObject(ex_path,logon_ex,password,0) myDSObject.Getinfo() # To access a user's data try: attribute = myDSObject.Get('Extension-Attribute-1') print attribute # To modify a user try: myDSObject.Put('Extension-Attribute-1','barney was here') myDSObject.Setinfo() Comments Note -- To make any changes permanent setinfo is required.Deleting a user from exchange
#Here we connect to Recipients and then #delete a user #This is a more complete example. #data is a dictionary that contains info #that may be dynamic like the domain, #admin login, or exchange server #notice I am using a try/except clause here #to catch any exceptions try: #ADSI here # Create the Global Providers object logon_ex='cn='+data['NT_admin']+', dc='+data['NT_domain']+',cn=admin' ex_list_path="LDAP://"+data['EX_site_srv']+"/cn=Recipients,ou="\ +data['ou']+",o="+data['o'] adsi = win32com.client.Dispatch('ADsNameSpaces') # # Now get the LDAP Provider object ldap = adsi.getobject("","LDAP:") dsobj = ldap.OpenDSObject(ex_list_path,logon_ex,data['NT_password'],0); dsobj.Getinfo() dsobj.Delete("OrganizationalPerson", "cn="+login) dsobj.Setinfo() except: print 'Error deleting '+login, sys.exc_type , sys.exc_value
Adding to a distribution list
# I used putex instead of put because it has more options # The '3' value means append. The SDK has specific info on it ex_list_path="LDAP://"+server+"/cn="+list+",cn=Recipients,ou="+ou+",o="+o dsobj = ldap.OpenDSObject(ex_list_path,logon_ex,password,0); dsobj.Getinfo() list_member='cn='+user+',cn=Recipients,ou='+ou+',o='+o append_list=[list_member] dsobj.putEx(3,'Member',append_list); dsobj.SetInfo()Recursively listing all unique members of a distribution list
#This function looks for all Organizational persons to add to a dictionary #If it gets a groupOfNames, it needs to parse that and call the function again #to get the members of the groupOfNames def getmembers(path=''): user_dict={} logon_ex='cn=fred, dc=bedrock' password='dino' server='flintstone' ldap = win32com.client.Dispatch('ADsNameSpaces').getobject("","LDAP:") dsobj = ldap.OpenDSObject(path,logon_ex,password,0) dsobj.Getinfo() if dsobj.Class=='organizationalPerson': user_dict[string.capitalize(dsobj.cn)]=dsobj.uid elif dsobj.Class=='groupOfNames': for i in dsobj.Members(): if i.Class=='organizationalPerson': user_dict[string.capitalize(i.cn)]=i.uid elif type(i.member)==types.TupleType: for j in i.member: newpath='LDAP://'+server+'/'+j getmembers(newpath) elif type(i.member)==types.StringType: newpath='LDAP://'+server+'/'+i.member getmembers(newpath) elif dsobj.Class=='Remote-Address': User_dict[string.capitalize(dsobj.cn)]=dsobj.uid elif dsobj.Class=='Public-Folder': pass else: print 'skipped',dsobj.Class,dsobj.uid return user_dict
ADSI, Exchange, and Python |