Scripting Exchange Using VBScript and ADSI (Part 2)



If you missed the other articles in this series please read:

 

 

 

Creation

 

You can use ADSI to access an object and also to create one but the Exchange operations involved, such as mailbox enabling a user, cannot be done with ADSI alone. Instead, CDOEXM, an interface created for Exchange management operations is used. When creating a new mailbox enabled user in Active Directory using scripting you can either start with ADSI and then use CDOEXM to complete the job or use just CDOEXM for both user and mailbox creation.

 

A user will need a name, a login name, a password. To mailbox enable the user you will need to know the database, storage group, server name, administrator group, organization name and domain name.

 

The following subroutine creates a mailbox-enabled user using ADSI and CDOEXM.

 

 

Sub ADSICreateMailBoxEnabledUser _
(MDBName,StorageGroup,Server,AdminGroup,Organization,DomainName,emailname,FirstName,LastName)

 

‘split the domain name to get the directory name for it
DomainDN     = “dc=” & Replace(DomainName,”.”,”,dc=”)

 

recip = “CN=” & emailname

 

‘ get the container
Set objContainer = GetObject(“LDAP://CN=users,” & DomainDN)

 

‘ create a recipient
Set objUser = objContainer.Create(“User”, recip)
objUser.Put “samAccountName”, emailname
objUser.Put “sn”, LastName
objUser.Put “givenName”, FirstName
objUser.Put “userPrincipalName”, emailname

 

objUser.SetInfo
objUser.SetPassword “123456”
objUser.AccountDisabled = False

 

Set objMailbox = objUser

 

                objMailbox.CreateMailbox “LDAP://CN=” & MDBName & _
“,CN=” & StorageGroup & _
“,CN=InformationStore” & _
“,CN=” & Server & _
“,CN=Servers” & _
“,CN=” & AdminGroup & _
“,CN=Administrative Groups” & _
“,CN=” & Organization & _
“,CN=Microsoft Exchange,CN=Services” & _
“,CN=Configuration,” & DomainDN

 

objUser.SetInfo

 

End Sub

 

At first, the domain name is parsed. The “.” character is replaced by “,cn=” and another “cn=” is added to the beginning of the string. This will create the directory name “cn=domain,cn=local” from the domain name “domain.local”.

 

Similarly, “CN=” is added to the object name designated by “emailname” to enable its creation later on in the script.

 

Now we get the container, in this case the “users” container. Please note that you can change this script so that the user will be created in a container or OU of your choosing. The “Create” command is run to create an object of type “User” in the container and then a list of properties is entered.

 

Now comes the strange looking line “Set objMailbox = objUser”. This creates a new blank pointer object pointing to the ADSI user object just created. The first method implemented for this object, “CreateMailbox”, will designate the pointer as accessing the “IMailboxStore” interface of a CDO.Person object.

 

Once the mailbox is created the ADSI user object “SetInfo” method is run and the user is created and mailbox enabled.

 

The following line I used when writing the final version of the above subroutine can be used to give you an idea of how to run it:

 

 

ADSICreateMailboxEnabledUser “Mailbox Store (EX2003)”,”First Storage Group”, “EX2003”, _
“First Administrative Group”, “Sunnydale”,”sunnydale.muni”, _
“testuser” ,”Test”,”User”

 

Creating a mailbox enabled user using just CDOEXM is not much different.

 

 

Sub CDOCreateMailBoxRecipient(MDBName, DomainName, _
exchangeOrg, adminGroup, _
storageGroup, storeName, _
ServerName, emailname, _
firstName, lastName)

 

‘split the domain name to get the directory name for it

 

DomainDN  = “dc=” & Replace(DomainName,”.”,”,dc=”)

 

Set objPerson = CreateObject(“CDO.Person”)

 

 ‘ First, create the user in Active Directory.
objPerson.FirstName = FirstName
objPerson.LastName  = LastName
objPerson.Fields(“userPrincipalName”) = LastName
objPerson.Fields(“userAccountControl”) = 512
objPerson.Fields(“userPassword”) = “password”
objPerson.Fields.Update
objPerson.DataSource.SaveTo “LDAP://CN=” & MDBName & _
“,CN=” & emailname & _
“,CN=users,” & domainDN

 

 ‘ Now, create a mailbox in a specified location.

 

 Set objMailbox = objPerson.GetInterface(“IMailboxStore”)
objMailbox.CreateMailbox “LDAP://CN=” & _
MDBName & _
“,CN=” & _
StoreName & _
“,CN=” & _
StorageGroup & “,CN=InformationStore,CN=” & _
ServerName & _
“,CN=Servers,CN=” & _
AdminGroup & “,” & _
“CN=Administrative Groups,CN=” & _
ExchangeOrg & “,” & _
“CN=Microsoft Exchange,CN=Services,” & _
“CN=Configuration,” & domainDN

 

 objPerson.DataSource.Save

 

End Sub

 

CDOEXM is a bit more of a sophisticated interface. It doesn’t require you to use a pointer to the parent OU or Container for the user. But still, like in the ADSI script, you have one pointer to the Active Directory user properties (objPerson), and the other (objMailbox) for creating the mailbox itself.

 

You might notice that the CDOEXM script has a single property which was not in the ADSI one. The “userAccountControl” controls all kinds of account options. This script simply sets the user as “Normal Account” but there are a lot options that you can put. For more information about this property read the interesting Microsoft KB 305144.

 

Accessing E-mail Addresses

 

Exchange was created to be a flexible messaging server. Keeping that in mind the designers of Exchange decided that the e-mail addresses of an object will be an array of addresses. This array could contain any type of e-mail to fit any e-mail system even though Exchange originally was based on the X.400 standard. Connecting Exchange to a foreign e-mail system meant amongst others that each user could add another type of e-mail address to “speak” natively to that system. The Internet was originally such a foreign e-mail system and each user had an SMTP addresses to the default X.400 address, possibly more than one.

 

These days of course Internet e-mail addresses are the most important mail addresses a user has seeing that Exchange 2000/3 transfer messages using SMTP between servers and to the Internet. Some organizations might even send more e-mail to the Internet than internally.

 

In Active Directory without the Exchange schema extension, each user has a single e-mail address, stored using the attribute “mail”. This attribute had no real use in the day to day workings of Active Directory but you could have scripted it for any purpose.

 

With Exchange 2000/3 this property points to the primary SMTP address of an object. A primary SMTP addresses is the one specified in the “Reply-To” field of e-mails. So an Exchange recipient can receive e-mails for multiple addresses but when sending e-mail to the Internet is represented only by the primary SMTP address.

 

The primary SMTP address itself is not stored in the “mail” attribute. Instead, it is stored in the proxyAddresses field as part of the e-mail array.

 

 

 

The primary e-mail address of each type is in uppercase, for example: “SMTP:[email protected]”. Additional addresses will be stored with the e-mail type in lowercase.

 

 

 

The following sample script reads the e-mails of an object in Active Directory:

 

 

Set MyUser = GetObject (“LDAP://CN=Administrator,CN=Users,DC=sunnydale,DC=muni”)
For each email in MyUser.proxyAddresses
WScript.Echo email
Next

 

It displays all of the e-mail addresses and their types. Here is a more advanced script displaying the primary SMTP addresses and then the secondary ones.

 

 

Set MyUser = GetObject (“LDAP://CN=Administrator,CN=Users,DC=sunnydale,DC=muni”)
Secondary = “”
For each email in MyUser.proxyAddresses
If Left (email,5) = “SMTP:” Then
WScript.Echo “Primary e-mail address: ” & Mid (email,6)
ElseIf Left (email,5) = “smtp:” Then
Secondary = Secondary & “,” & Mid (email,6)
End If
Next
If Secondary  <> “”  Then WScript.Echo “Other e-mail addresses: ” & Mid (Secondary,2)

 

It uses the Left function to determine if the e-mail is of type SMTP and the Mid function to extract the actual e-mail.

 

If you want to search for a particular e-mail in Active Directory you can do so by forming an LDAP query using the proxyAddresses attribute. This attribute is indexed so you can search inside the e-mail array of object when you execute the query.

 

 

Set rootDSE = GetObject(“LDAP://RootDSE”)
domainContainer =  rootDSE.Get(“defaultNamingContext”)
Set conn = CreateObject(“ADODB.Connection”)
conn.Provider = “ADSDSOObject”
conn.Open “ADs Provider”
Email = “smtp:[email protected]
LDAPStr = “<LDAP://” & DomainContainer &  “>;(&(objectCategory=person)(proxyAddresses=” & email & “));adspath;subtree”
Set rs = conn.Execute(LDAPStr)
If rs.RecordCount = 1 Then
Set oPerson = GetObject(rs.Fields(0).Value)
WScript.Echo oPerson.displayName
End If

 

This type of search is not case sensitive so it does not matter whether you search for “smtp:[email protected]” or “SMTP:[email protected]”.

 

Adding an E-mail Address

 

Manipulating the e-mail addresses list of an Exchange recipient requires some array manipulation functions.

 

The UBound function retrieves the number of objects stored in an array. In order to add an e-mail address to athe proxyAddresses array of a recipient you would need to expand the number of objects stored in the array.

 

The Redim Preserve function allows you to expand an array while preserving its contents.

 

 

    Set oUser = GetObject (“LDAP://CN=Buffy Summers,OU=Scoobies,DC=sunnydale,DC=muni”)
Set objRecip = oUser
sAddress = “smtp:[email protected]
bIsFound = False
vProxyAddresses = objRecip.ProxyAddresses
nProxyAddresses = UBound(vProxyAddresses)
i = 0
Do While i <= nProxyAddresses
If vProxyAddresses(i) = sAddress  Then
bIsFound = True
Exit Do
End If
i = i + 1
Loop
If Not bIsFound Then
ReDim Preserve vProxyAddresses(nProxyAddresses + 1)
vProxyAddresses(nProxyAddresses + 1) = sAddress
objRecip.ProxyAddresses = vProxyAddresses
oUser.SetInfo
End If

 

The script obtains a pointer to a user, the user’s e-mail addresses array and the length of the array. It then checks whether the e-mail address already exists for the user. If it does not then it increases the length of the array so that there will be room for an additional e-mail address and finally adds the e-mail address itself.

 

You might also decide to add an e-mail and make it the primary e-mail address.

 

 

    Dim objRecip
Dim mycontact’ As ContactItem
Dim proxies
‘On Error Resume Next
Set oUser = GetObject (“LDAP://CN=Buffy Summers,OU=Scoobies,DC=sunnydale,DC=muni”)
Set objRecip = oUser
sAddress = “SMTP:[email protected]
bIsFound = False
vProxyAddresses = objRecip.ProxyAddresses
nProxyAddresses = UBound(vProxyAddresses)
i = 0
Do While i <= nProxyAddresses
email = vProxyAddresses(i)
If Left (email,5) = “SMTP:” Then
vProxyAddresses (i) = “smtp:” & Mid (email,6)
End If
If vProxyAddresses(i) = sAddress  Then
bIsFound = True
Exit Do
End If
i = i + 1
Loop
If Not bIsFound Then
ReDim Preserve vProxyAddresses(nProxyAddresses + 1)
vProxyAddresses(nProxyAddresses + 1) = sAddress
objRecip.ProxyAddresses = vProxyAddresses
oUser.SetInfo
End If

 

In this script I used the Left function to find which of the e-mail addresses is the primary SMTP address. Then the script manipulated it using the Mid function so it will begin with “smtp:” instead of “SMTP:”, designating it as a secondary e-mail address.

 

Make sure that when you add an e-mail address it is properly formatted because Active Directory does not check that the format of the e-mail address is valid. You might get some really strange results if you add an improperly formatted e-mail address.

 

Removing an E-mail Address

 

Removing an e-mail address from a recipient is as important as adding one. Adding an e-mail address to, say a bunch of users, can be done using Exchange System Manager by changing or adding a recipient policy.

 

 

 

 

 

 

This will add to a each user another secondary e-mail address.

 

 

 

But what happens when we change Default Policy so that now there will be only one SMTP address (“sunnydale.org”)?

 

 

 

 

As you can see the old e-mail address is not deleted when the recipient policy is changed so you get redundant e-mail addresses. These e-mail addresses can be deleted by using the following script:

 

 

Dim NewProxies ()
Set rootDSE = GetObject(“LDAP://RootDSE”)
DomainContainer =  rootDSE.Get(“defaultNamingContext”)
Set conn = CreateObject(“ADODB.Connection”)
conn.Provider = “ADSDSOObject”
conn.Open “ADs Provider”
emaildomain = “sunnydale.muni”
LDAPStr = “<LDAP://” & DomainContainer &  “>;(&(objectCategory=person)(proxyAddresses=*@” _
& emaildomain & “));adspath;subtree”
Set rs = conn.Execute(LDAPStr)
While Not rs.EOF
Set oRecipient = GetObject(rs.Fields(0).Value)
bIsFound = False
proxies = oRecipient.ProxyAddresses
nProxies = UBound(proxies)
i = 0
n = 0
Do While i < nProxies
checkproxy = proxies (i)
AddProxy = False
If (LCase(Left(proxies(i),5)) <> “smtp:”) Then
AddProxy = True
Else
TempAr = Split (proxies(i),”@”)
If (TempAr (1) <> emaildomain) Then AddProxy = True

 

                 End If
If AddProxy = True Then
ReDim Preserve NewProxies (n)
NewProxies (n) = checkproxy
n = n + 1
End If
i = i + 1
Loop

 

           oRecipient.PutEx 2,”ProxyAddresses”,NewProxies
oRecipient.SetInfo

 

          rs.movenext
Wend

 

The script obtains the current domain then performs an LDAP search for all the recipients which has an e-mail address that ends with the specified e-mail domain, in this case “sunnydale.muni”. It then extracts current e-mail array into “proxies” and then goes through this array.

 

The Split function is used to split the email address into an array with two members. The second member is the e-mail domain. The script then adds all the e-mails that do not end with the e-mail domain into the new array “NewProxies”.

 

Please note that “i” is the counter used for the original proxyAddresses array and “n” is used as a counter for the target array.

 

 

 

Now all the old e-mail addresses are gone. As you might notice it also deleted the custom e-mail address that the user had before ([email protected]). If you don’t want this to happen, a more complex script is in order.

 

 

Dim NewProxies ()
Set rootDSE = GetObject(“LDAP://RootDSE”)
DomainContainer =  rootDSE.Get(“defaultNamingContext”)
Set conn = CreateObject(“ADODB.Connection”)
conn.Provider = “ADSDSOObject”
conn.Open “ADs Provider”
emaildomain = “sunnydale.muni”
newemaildomain = “sunnydale.org”
LDAPStr = “<LDAP://” & DomainContainer &  “>;(&(objectCategory=person)(proxyAddresses=*@” _
& emaildomain & “));adspath;subtree”
Set rs = conn.Execute(LDAPStr)
While Not rs.EOF
Set oRecipient = GetObject(rs.Fields(0).Value)
bIsFound = False
proxies = oRecipient.ProxyAddresses
nProxies = UBound(proxies)
i = 0
n = 0
Do While i <= nProxies
checkproxy = proxies (i)
AddProxy = False
If (LCase(Left(proxies(i),5)) <> “smtp:”) Then
AddProxy = True
Else
TempAr = Split (proxies(i),”@”)
If (TempAr (1) = emaildomain) Then
checkproxy = TempAr(0) & “@” & newemaildomain
If Not (ExistsInProxies(checkproxy,proxies)) Then AddProxy = True
Else
checkproxy = True
End If
End If
If AddProxy = True Then
ReDim Preserve NewProxies (n)
NewProxies (n) = checkproxy
n = n + 1
End If
i = i + 1
Loop

 

           oRecipient.PutEx 2,”ProxyAddresses”,NewProxies
oRecipient.SetInfo

 

          rs.movenext
Wend

 

Function ExistsInProxies (proxy,arProxies)
ExistsInProxies = False
m= UBound (arProxies)
j = 0
Do While j <= m
If arProxies (j) = proxy  Then
ExistInProxies = True
Exit Do
End If
j = j + 1
Loop
End Function

 

The revised script adds a function that checks whether an e-mail address exists in the array. This is useful because now SMTP e-mail addresses are deleted if they have an e-mail suffix that you want to delete only if an alternative e-mail with the new suffix already exists. For example, [email protected] is deleted because [email protected] exists. However, [email protected] is not deleted. Instead it is changed to [email protected].

 

Conclusion

 

We covered in this article, creation of a mailbox enabled recipient using ADSI and CDOEXM, and went in great detail into various scripts that can access e-mail addresses, add and remove them. The scripts grew in complexity as we progressed but were created with simplicity in mind. I would recommend playing with those scripts in the lab and perhaps writing what each command does on a piece of paper so that you can analyze the various loop and if structures. Getting on top of the logic of these scripts can help you understand Active Directory and Exchange better and also allow you to modify and customize the script to perform endless e-mail manipulations.

 

If you missed the other articles in this series please read:

 

 

 

About The Author

Leave a Comment

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top