Microsoft KB Archive/263520

= How To Programmatically Create a Distribution List Using ADSI =

Article ID: 263520

Article Last Modified on 7/1/2004

-

APPLIES TO


 * Microsoft Exchange Server 5.5 Standard Edition
 * Microsoft Active Directory Service Interfaces 2.5

-



This article was previously published under Q263520



SUMMARY
ADSI can be used to create or modify Distribution Lists on Microsoft Exchange Servers. This article provides sample code to create a Distribution List with multiple members.

NOTE: In this article, the processes of creating a Distribution List and then adding members are separated so that they can be used individually for Distribution List management.



MORE INFORMATION
 Create a new Microsoft Visual Basic standard EXE project. In the Project References dialog box, check the references for the following:  Active DS Type Library ADsSecurity 2.5 Type Library

 On the default Form1, add three CommandButtons: CommandButton1, CommandButton2, and CommandButton3.  Add the following code to the form's code module: Option Explicit

Const RIGHT_DS_MODIFY_USER_ATT = &H2 Const RIGHT_MAIL_SEND_AS = &H8 Const RIGHT_MAIL_RECEIVE_AS = &H10

' Custom type for Distribution List properties. Private Type DLTemplate Domain as String       ' Network domain name. Server As String       ' Microsoft Exchange server name. Org As String          ' Microsoft Exchange Organization name. Site As String         ' Microsoft Exchange Site name, Container As String    ' such as Recipients. Name As String DisplayName As String  ' DL's Display name. Alias As String        ' DL's Alias name. DirectoryName As String ' DL's Directory name. UserName As String     ' User's logon name and domain. Password As String     ' User's domain password. SMTPAddr As String X400Addr As String Owner As String Hide As Boolean        ' Hide DL from address book. OtherAddresses(10) As String Members(10) As String  ' Increase array elements for more members. End Type

Dim NewDL As DLTemplate    ' Public to all procedures in module.

Private Sub CommandButton1_Click ' Fill Distribution List &quot;template&quot;.

' Set vars to get container. '*** change Domain, Server, Org and Site information as appropriate. NewDL.Domain = &quot;myDomain.com&quot; NewDL.Server = &quot;myServer&quot; NewDL.Org = &quot;Orgname&quot;    ' Microsoft Exchange Organization NewDL.Site = &quot;sitename&quot;  ' Microsoft Exchange Site

' Place new DL in Recipients container. NewDL.Container = &quot;Recipients&quot;

'*** set DL named properties as appropriate. NewDL.Alias = &quot;DL47&quot; NewDL.DisplayName = &quot;Distribution List 47&quot; NewDL.SMTPAddr = NewDL.Alias & &quot;@&quot; & NewDL.Domain NewDL.Hide = False 'default is False ' Use distinguished name of owner. NewDL.Owner = &quot;cn=user1,cn=Recipients,ou=NORTHAMERICA,o=DS Messaging&quot;

'Set required X400 address 'Create a DL manually and use properties as a guide '  Country (c) is required '  ADMD (a) is required, the default is a zero-length string &quot;&quot; '  PRMD (p) is not required, but if included the default is a zero-length string '  Surname (s) is required '  the trailing semi-colon is required NewDL.X400Addr = &quot;c=US;a= ;p=&quot; & CStr(NewDL.Org) & &quot;;o=&quot; & Str(NewDL.Site)& &quot;;s=&quot; & CStr(NewDL.Alias) & &quot;;&quot;

NewDL.OtherAddresses(0) = CStr(&quot;MS$&quot; + NewDL.Org + &quot;/&quot; + NewDL.Site + &quot;/&quot; + NewDL.Alias) NewDL.OtherAddresses(1) = CStr(&quot;CCMAIL$&quot; + NewDL.Alias + &quot; at &quot; + NewDL.Site)

' Fill array of addresses (i.e. MSMail, CCMail). Dim OtherAddresses(1) OtherAddresses(0) = CStr(&quot;MS$&quot; + NewDL.Org + &quot;/&quot; + NewDL.Site + &quot;/&quot; + NewDL.Alias) OtherAddresses(1) = CStr(&quot;CCMAIL$&quot; + NewDL.Alias + &quot; at &quot; + NewDL.Site)

' Set Members using their Distinguished Names. NewDL.Members(0) = &quot;LDAP://myServer/o=myOrg/ou=mySite/cn=Recipients/cn=confrm11&quot; NewDL.Members(1) = &quot;LDAP://myServer/o=myOrg/ou=mySite/cn=Recipients/cn=confrm12&quot; NewDL.Members(1) = &quot;LDAP://myServer/o=myOrg/ou=mySite/cn=Recipients/cn=confrm13&quot;

End Sub

Private Sub CommandButton2_Click ' This routine creates a distribution list, but it does not add members.

' Call function to create DL. ' Uses global DLTemplate previously filled.

Dim lResult As Long lResult = CreateDL(NewDL, True) Select Case lResult Case -1: ' Succeeded. MsgBox &quot;DL created&quot; Case 0: ' Failed, unknown error. MsgBox &quot;Unknown error creating DL&quot; Case Else: ' Get error number from return value. Select Case Hex(lResult) Dim strText As String, strTitle As String Case 80071392: 'already exists strText = &quot; - Item Alredy Exists&quot; Case Else: 'unknown error strText = &quot;- Unknown&quot; End Select strTitle = &quot;Error creating DL&quot; strText = &quot;Error: &quot; & lResult & &quot; (&quot; & Hex(lResult) & &quot;)&quot; & strText MsgBox strText, vbExclamation, strTitle End Select

End Sub

Private Sub CommandButton3_Click

' Call function to add DL members. ' Uses DLTemplate previously filled.

Dim lResult As Long lResult = AddDLMembers(NewDL, True) Select Case lResult Case -1: ' Succeeded. MsgBox &quot;Members added&quot; Case 0: ' Failed, unknown error. MsgBox &quot;Unknown error adding members&quot; Case Else: ' Get error number from return value. MsgBox &quot;Error adding members: &quot; & lResult End Select

End Sub

Private Function AddDLMembers(DL As DLTemplate, DebugMode As Boolean) As Long

AddDLMembers = 1 'default value

Dim strADsPath As String Dim DistList As Object

On Error GoTo Error_AddMembers

'-- Build adspath to container, usually Recipient container: '  LDAP://myserver/O=Org/OU=Site/CN=Recipients strADsPath = &quot;LDAP://&quot; + DL.Server strADsPath = strADsPath + &quot;/O=&quot; & DL.Org strADsPath = strADsPath + &quot;/OU=&quot; & DL.Site strADsPath = strADsPath + &quot;/CN=&quot; & DL.Container strADsPath = strADsPath + &quot;/CN=&quot; & DL.Alias

If DebugMode Then Debug.Print &quot;ADsPath: &quot; & strADsPath

' Get reference to Distribution List. Set DistList = GetObject(strADsPath) Debug.Print DistList.Name

' Loop through Members array until null found. Dim i As Integer Do Until DL.Members(i) = &quot;&quot; ' Add user to Distribution List. DistList.Add DL.Members(i) ' If the entry is already a member of the DL, ' error 8007200d occurs. If DebugMode Then Debug.Print &quot;Adding Member: &quot; & i       Debug.Print &quot;Member: &quot; & DL.Members(i) If Err.Number = 0 Then Debug.Print &quot;Member added&quot; Else: ' Error. Debug.Print &quot;Error occurred: &quot; & Err.Number Debug.Print &quot;Reason: &quot; & Err.Description End If   End If    i = i + 1 Loop

Exit_AddDLMembers: ' Explicitly release objects. Set DistList = Nothing Exit Function

Error_AddMembers: ' Set return value for known error. If Err.Number = &H8007200D Then MsgBox &quot;Already a member: &quot; & DL.Members(i) End If   AddDLMembers = Err.Number If DebugMode Then Debug.Print &quot;Error in AddDLMembers: &quot; & Err.Number Debug.Print &quot;Error Description: &quot; & Err.Description End If   Resume Exit_AddDLMembers

End Function

Private Function CreateDL(DL As DLTemplate, DebugMode As Boolean) As Long

' Vars used to get container. Dim strADsPath As String Dim objContainer As Object Dim objNewDL As Object

' Set default value for failed, unknown error. CreateDL = 0

On Error GoTo Err_CreateDL

'-- Build adspath to container, usually Recipient container: '  LDAP://myserver/O=Org/OU=Site/CN=Recipients strADsPath = &quot;LDAP://&quot; + DL.Server strADsPath = strADsPath + &quot;/O=&quot; & DL.Org strADsPath = strADsPath + &quot;/OU=&quot; & DL.Site strADsPath = strADsPath + &quot;/CN=&quot; & DL.Container

If DebugMode Then Debug.Print &quot;ADsPath: &quot; & strADsPath

' Get container. Set objContainer = GetObject(strADsPath) If DebugMode Then Debug.Print &quot;Got container: &quot; & objContainer.Name

' Create a new DL in the container. ' A Distribution List is known as a &quot;groupOfNames&quot;. Set objNewDL = objContainer.Create(&quot;groupOfNames&quot;, &quot;cn=&quot; & DL.Alias) If DebugMode Then Debug.Print &quot;objNewDL created for: &quot; & DL.Alias

' Set the DL props from the custom type structure. objNewDL.Put &quot;cn&quot;, CStr(DL.DisplayName)  ' cStr may be required to make Unicode values. If DebugMode Then Debug.Print &quot;set DisplayName property: &quot; & DL.DisplayName

objNewDL.Put &quot;uid&quot;, CStr(DL.Alias) If DebugMode Then Debug.Print &quot;set Alias property: &quot; & DL.Alias objNewDL.Put &quot;Owner&quot;, CStr(DL.Owner) If DebugMode Then Debug.Print &quot;set Owner property: &quot; & DL.Owner

' Alternate way to set property using simplest assignment technique. objNewDL.mail = DL.SMTPAddr If DebugMode Then Debug.Print &quot;set SMTP Address property: &quot; & DL.SMTPAddr

'set required X400 address objNewDL.Put &quot;textencodedORaddress&quot;, CStr(DL.X400Addr) If DEBUGMODE Then Debug.Print &quot;set X400 Address property: &quot; & DL.X400Addr

' Set optional properties only if not default values. If DL.Hide Then objNewDL.Put &quot;Hide-DL-Membership&quot;, DL.Hide If DebugMode Then Debug.Print &quot;set Hide from GAL property: &quot; & DL.Hide

' Use array to hold multi-value property values. ' Use Put to set the multi-values (overwrite whatever was there). ' Use PutEx to append additional values, etc.

' Create other addresses (ie. MSMail, CCMail).

'objNewDL.PutEx ADS_PROPERTY_APPEND, &quot;otherMailbox&quot;, aOtherMailbox 'objNewDL.Put &quot;OtherMailbox&quot;, DL.OtherAddresses

Dim aOtherMailbox(1) aOtherMailbox(0) = CStr(DL.OtherAddresses(0)) aOtherMailbox(1) = CStr(DL.OtherAddresses(1)) 'objNewDL.PutEx ADS_PROPERTY_APPEND, &quot;otherMailbox&quot;, aOtherMailbox objNewDL.Put &quot;OtherMailbox&quot;, aOtherMailbox If DebugMode Then Debug.Print &quot;set other addresses property&quot;

' NOTE: members are not added as the DL is created. ' Members are added separately.

objNewDL.SetInfo ' Save changes. If DebugMode Then Debug.Print &quot;New DL saved&quot; ' '-- SET PERMISSION ON THE OWNER TO MODIFY AND SEND AS/RECEIVE '-- REQUIRES THE ADSI RESOURCE TOOL KIT INSTALL (IADsSecurity) '- strADsPath = strADsPath + &quot;/cn=&quot; & DL.Alias If DebugMode Then Debug.Print &quot;Add owner: &quot; & DL.Owner

Dim sec As New ADsSecurity ' You can also use -- Set sec = CreateObject(&quot;ADsSecurity&quot;) for late binding. Dim sd As IADsSecurityDescriptor Dim dacl As IADsAccessControlList Dim ace As New AccessControlEntry

Set sd = sec.GetSecurityDescriptor(strADsPath) ' An error in the ADsPath may cause a fatal error in Set dacl line! If DebugMode Then Debug.Print &quot;SD.Owner: &quot; & sd.Owner Set dacl = sd.DiscretionaryAcl

ace.AccessMask = RIGHT_DS_MODIFY_USER_ATT Or RIGHT_MAIL_SEND_AS Or RIGHT_MAIL_RECEIVE_AS ace.Trustee = &quot;mydomain\user2&quot; dacl.AddAce ace sd.DiscretionaryAcl = dacl sec.SetSecurityDescriptor sd

' Set return value for success. CreateDL = -1

Exit_CreateDL: ' Explicitly release objects. Set sd = Nothing Set dacl = Nothing Set objNewDL = Nothing Set objContainer = Nothing Exit Function

Err_CreateDL: ' Set return value for known error. CreateDL = Err.Number If DebugMode Then Debug.Print &quot;Error in CreateDL: &quot; & Err.Number & &quot; (&quot; & Hex(Err.Number) & &quot;)&quot; Debug.Print &quot;Error Description: &quot; & Err.Description End If   Resume Exit_CreateDL

End Function </li> In the CommandButton1_Click procedure, change the values for server, organization, site, and so on, to match your environment and the properties of the Distribution List to be created.</li> Save and then run the project. Use the first button to fill the Distribution List template. Use the second button to create the Distribution List, without members. Use the third button to add members.</li></ol>

Additional query words: xmrp

Keywords: kbhowto kbmsg KB263520

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.