Programming Microsoft Outlook and Microsoft Exchange 2003, Third Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming Microsoft Outlook and Microsoft Exchange 2003, Third Edition [Electronic resources] - نسخه متنی

Thomas Rizzo

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید

A Sample ADSI Application

The best way to learn about using ADSI to program with the Exchange Server directory is to examine a sample application. I developed one that demonstrates how to create custom recipients, query distribution lists, and query for recipient directory information such as user's names, addresses, and phone numbers.


Setting Up the Application


Before you can install the application, you must have a Windows 2000 Server and a client with the software listed in Table 13-1 installed.



























Table 13-1: Installation Requirements for the ADSI Application

Minimum Software Requirements


Installation Notes


Exchange Server 2000 or later


Microsoft Internet Information Services (IIS) 5.0 or later with ASP


ADSI 2.0 or later


Active Directory Client Extensions (ADSI 2.5) is available as a free download from [ http://www.microsoft.com/adsi ]. Windows 2000 and 2003 install ADSI 2.5 by default.


Microsoft ActiveX Data Objects (ADO)


IIS 5.0 installs ADO by default. Visual Basic 6.0 installs ADO 2.0. For more information on ADO, go to [ http:/www.microsoft.com/data/ ].


For the client:

Microsoft Internet Explorer 4.0 or later


You can run the client software on the same machine or on a separate machine.


To install the ADSI application, first copy the ADSI folder from the companion content to the Web server where you want to run the application. Start the IIS administration program. Create a virtual directory that points to the location where you copied the ADSI files, and name the virtual directory adsi. Be sure to turn off anonymous access to the virtual directory and enable either NTLM or Basic authentication. You should be able to use the following URL to access your ADSI application: http://<yourservername>/adsi.

The first page displayed in the ADSI application is the logon page, as shown in Figure 13-1. Once a user enters logon information and verifies the dynamically generated Exchange Server information, the application presents a menu of available administrative options for the user, as shown in Figure 13-2.


Figure 13-1: The logon page for the ADSI application


Figure 13-2: The main menu of the ADSI application

Now let's step through the actual code that makes up these menu items and see how to use the ADSI object library with an Exchange Server directory.


Logging On to ADSI


The most common operation in the code for the menu items is the object binding code for ADSI. This binding code is dispersed throughout all the code modules in the application rather than being centralized and performed only once. This makes it easier for you to browse the code and understand exactly what is happening.

To bind successfully to an object in the Exchange Server directory using ADSI when you don't want to pass a path directly to the GetObject function, you must use the GetObject method to set an object variable to the ADSI library and then call the OpenDSObject method. The OpenDSObject method takes four parameters:

AdsPathThe path of the object you want to bind to. You saw how to create this path earlier in the chapter.

The Windows usernameThis is used to attempt authentication against the directory service.

The password for the Windows username you specify

A flag that specifies the binding option to useThe &H00000001 flag specifies use of secure authentication, &H00000010 specifies use of encryption, and &H00000200 specifies use of server binding if you pass the name of a server in your LDAP path instead of using rootDSE. There are also other flags you can use in ADSI. See the Platform SDK for information about them.

Depending on the provider used, the flags that specify the binding option might or might not be supported. On the LDAP provider, if you set the secure authentication and the encryption flags and pass in a user name and a password, ADSI will perform a simple bind over Secure Sockets Layer (SSL) sessions, which is a secure authentication over a secure channel. The sample application does not use OpenDSObject for most of its operations; instead, it uses GetObject and passes the directory path in GetObject. If you use OpenDSObject and do not use either of those flags, a 0 will be passed in as the value for the final parameter to indicate that no encryption and no secure authentication should be used.

The following code shows how to set an object variable to the LDAP provider and log on using the OpenDSObject method, as well as how to use the GetObject method with a path:

Set oIADs = GetObject("LDAP:")
oIADs.OpenDSObject(AdsPath, UserName, Password, 0)
Set oIADs2 = GetObject("LDAP://servername")


Querying for Information from an Existing Mailbox


The ADSI application also shows how to query for information from an existing Exchange Server mailbox. The user interface, shown in Figure 13-3, allows the user to type the first name of the user to find the mailbox.


Figure 13-3: The user can type the first name of the user in the directory to locate the mailbox.

After the user types a name, the application uses ADO to query the directory service using LDAP. You might wonder why ADO is used rather than the OpenDSObject method you saw earlier. The reason is that if you use the OpenDSObject method, the user must know the exact name of the desired object in the directory. ADO is more forgiving; the user can simply type a portion of the first name. Also, users often do not know the alias of users they are querying, so forcing them to type aliases does not make sense. The code to create the ADO object and perform the query is shown here:

bstrSearchCriteria = Request.Form("UserName")
bstrServer = Session("Server")
'Create an ADO object
Set ADOconn = CreateObject("ADODB.Connection")
If Err.Number = 0 Then
ADOconn.Provider = "ADSDSOObject"
ADOconn.Open "ADs Provider"
'Create a query using ADO to find all users across all containers
bstrADOQueryString = "<LDAP://" + bstrServer & _
">;(&(objectClass=organizationalPerson)(cn=" & _
bstrSearchCriteria & "*));cn,adspath;subtree"
Set objRS = ADOconn.Execute(bstrADOQueryString)
If Err.Number = 0 Then
If objRS.RecordCount > 0 Then %>
<p>Please select one of the following names from the
list of names.</p>
<p><em><strong>Returned Names:</strong></em></p>
<SELECT NAME='MailboxPath'>
<%
'Builds the select control of the queried records
While Not objRS.EOF
bstrSelectStatement = bstrSelectStatement & _
"<OPTION VALUE='" & objRS.Fields(iCN).Value & _
"'>" & objRS.Fields(iADSPATH)
objRS.MoveNext
Wend
Response.Write bstrSelectStatement & "</SELECT>"
Else %>
<B><I>No entries match your search criteria.
Try again using a different value.</I></B>
<%
End If
Else
If Hex(Err.Number) = 80070044 Then
Response.Write "<FONT FACE='Arial, Helvetica' " & _
"SIZE=2>Error " & Hex(Err.Number) & _
": Too many entries match your search " & _
"criteria!</FONT>"
Err.Clear
Else
%>
<SCRIPT LANGUAGE="JavaScript">
alert("Error Number: <%=Hex(Err.Number)%> \n
Error Description: <%=Err.Description%>")
history.back()
</SCRIPT>
<%
Err.Clear
End If
End If
Else
%>
<SCRIPT LANGUAGE="JavaScript">
alert("Error Number: <%=Hex(Err.Number)%> \nError Description:
<%=Err.Description%>")
history.back()
</SCRIPT>
<%
Err.Clear
End If
%>

This code creates an ADO Connection object and sets the Provider property to ADSDSOObject, which specifies the LDAP provider for ADSI. You can specify any string for the connection string argument to the Open method of the ADO Connection object. In this case, the application specifies ADs Provider as the argument. The code then creates an LDAP query, which consists of four elements separated by semicolons. This is the format:

<LDAP://server/adsidn>;ldapfilter;attributescsv;scope

The server argument specifies the name or the IP address of the server where the directory is hosted. The adsidn argument specifies the distinguished name in the directory where we want to start our query. You should pass in a correctly formed path, which you saw how to create earlier in the chapter. The filter parameter specifies the LDAP filter string to use. In this case, the LDAP filter states that the object class must be organizationalPerson and the name of the object must match the letters typed by the user. The next argument, attributescsv, is a list of attribute names, separated by commas, that you want returned for each row in the recordset. In our application, we want the name of the person and the AdsPath to the object that corresponds to that person returned so we can place this information in the HTML form, as shown in Figure 13-4. The final argument, scope, informs the directory service how deeply in the hierarchy to search for the information being queried. The scope argument can be one of three values: base, onelevel, or subtree. We want to query for all mailboxes that match our specified criteria across all recipient containers in the directory, so we specified subtree for this argument. The subtree argument causes the directory service to search for the information in every subtree under the starting object. The base argument searches only the currently specified object, and onelevel searches one level below the current object in the hierarchy.


Figure 13-4: After the query runs, the HTML form is populated with the corresponding records so a user can select the person she wants more information about.

If the query successfully returns records that match the filter, the code uses the standard ADO methods to scroll through the recordset and place the records in the HTML form.

After the user selects the name of the person she wants more information about in the HTML form, the application opens the directory object for that person and retrieves information such as the address, phone number, manager, and direct reports. This information is represented using a DHTML tabbed dialog box in the browser, as shown in Figure 13-5.


Figure 13-5: The tabbed dialog box that shows the directory information for a specific person

The next section of code retrieves the information about the specific person from the directory. I intentionally left out some of the DHTML code from the listing to highlight how ADSI is used in the code. Also, only a portion of the ADSI code is shown here because the structure of the code throughout this part of the application is similar. Only the specific properties retrieved from the directory using ADSI are different. The full code is included with the companion content.

On Error Resume Next
If Request.QueryString("Path") = " Then
bstrMailboxPath = Request.Form("MailboxPath")
Else
bstrMailboxPath = Request.Querystring("Path")
End If
bstrServer = Session("Server")
Set objIADs = GetObject(bstrMailboxPath)

<TR>
<TD VALIGN=MIDDLE ALIGN=RIGHT><FONT FACE="Arial, Helvetica" SIZE=2>
First Name:</TD>
<TD VALIGN=TOP><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("givenName"))%></B></FONT>
</TD>
<TD VALIGN=MIDDLE ALIGN=RIGHT><FONT FACE="Arial, Helvetica" SIZE=2>
Initials:</TD>
<TD VALIGN=TOP><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("initials"))%></B></FONT>
</TD>
<TD VALIGN=MIDDLE ALIGN=RIGHT><FONT FACE="Arial, Helvetica" SIZE=2>
Last Name:</TD>
<TD VALIGN=TOP><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("sn"))%></B></FONT></TD>
</TR>
<TR>
<TD VALIGN=MIDDLE ALIGN=RIGHT><FONT FACE="Arial, Helvetica" SIZE=2>
Display Name:</TD>
<TD VALIGN=TOP><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("cn"))%></B></FONT></TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD VALIGN=MIDDLE ALIGN=RIGHT><FONT FACE="Arial, Helvetica" SIZE=2>
Alias:</TD>
<TD VALIGN=TOP><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("mailNickname"))%></B></FONT>
</TD>
</TR>
<TR>
<td width="100%" colspan="10">&nbsp;<hr>
</TD>
</TR>
<TR>
<TD VALIGN=TOP ALIGN=RIGHT><FONT FACE="Arial, Helvetica" SIZE=2>
Address:</FONT></TD>
<TD VALIGN=TOP><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("streetAddress"))%></B></FONT>
</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Title:</FONT></TD>
<TD ALIGN=LEFT><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEncode(objIADs.Get("title"))
%></B></FONT></TD>
</TR>
<TR>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Company:</FONT>
</TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("Company"))%></B></FONT>
</TD>
</TR>
<TR><TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>City:</FONT>
</TD>
<TD VALIGN=TOP><FONT FACE="Arial, Helvetica"
SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("l"))%></B></FONT></TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Department:</FONT>
</TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B><%=Server.HTMLEn
code(objIADs.Get("department"))%></B></FONT>
</TD>
</TR>
<TR>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>State:</FONT></TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<%=Server.HTMLEncode(objIADs.Get("st"))%></B></FONT></TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Office:</FONT></TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<%=Server.HTMLEncode(objIADs.Get("physicalDeliveryOfficeName"))%>
</B></FONT></TD>
</TR>
<TR>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Zip Code:</FONT>
</TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<%=Server.HTMLEncode(objIADs.Get("postalCode"))
%></B></FONT></TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Assistant:</FONT>
</TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<%=Server.HTMLEncode(objIADs.Get("secretary"))
%></B></FONT></TD>
</TR>
<TR><TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Country:</FONT>
</TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<%=Server.HTMLEncode(objIADs.Get("co"))%></B></FONT></TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD ALIGN=RIGHT><FONT FACE="Arial, Helvetica"
SIZE=2>Phone:</FONT></TD>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<%=Server.HTMLEncode(objIADs.Get("telephoneNumber")
)%></B></FONT></TD>
</TR>
</TABLE>
</DIV>

The mailbox that the user wants to query is passed to the ASP page. Using the GetObject method, the code opens the mailbox in the Exchange Server directory and sets an object variable, objIADs, to that mailbox. Throughout much of the remaining code, the Get method of the objIADs object is used to retrieve specific attributes on the mailbox.

The most interesting pieces of code besides the code for retrieving attributes include those that retrieve the person's manager and direct reports from the directory. In the application, the manager's name is displayed as a hyperlink on the Organization tab so users can quickly look up the manager's directory information. The person's direct reports are also displayed as hyperlinks on the Organization tab so users can look at the direct report's directory information as well. Figure 13-6 shows a sample of these hyperlinks.


Figure 13-6: The Organization tab for a queried mailbox displays the manager and direct reports as hyperlinks.

The following code implements the hyperlink functionality:

<TABLE border=0>
<TR>
<TD ALIGN=LEFT NoWrap><FONT FACE="Arial, Helvetica" SIZE=2>
Manager Name:</FONT></TD>
<TR>&nbsp;</TR>
<%
strManager = objIADs.Get("manager")
strManagerPath = "LDAP://" & Session("Server") & "/" & strManager
Set oIADsManager = GetObject(strManagerPath)
strManagercn = Server.HTMLEncode(oIADsManager.Get("cn"))
%>
<TR>
<TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<A Href='MBINFOTABS.ASP?Path=<%=strManagerPath
%>'><%=strManagercn%></A>
</B></FONT></TD>
</TR>
<TR><TD>&nbsp;</TD></TR>
<TR><TD ALIGN=LEFT><FONT FACE="Arial, Helvetica"
SIZE=2>Direct Reports:</
FONT></TD></TR>
<%
Err.clear
strReports = objIADs.GetEx("directReports")
If lBound(strReports) <0 Then
%>
<TR><TD><FONT FACE="Arial, Helvetica"
SIZE=2><B>&nbsp;
No Direct Reports Found
</B></FONT></TD></TR>
<%
Else
For i = LBound(strReports) To UBound(strReports)
'Get each DS object to return the friendly name
strDirectPath = "LDAP://" & Session("Server") & _
"/" & strReports(i)
Set oIADsReports = GetObject(strDirectPath)
strReportscn = Server.HTMLEncode(oIADsReports.Get("cn"))
%>
<TR><TD><FONT FACE="Arial, Helvetica" SIZE=2><B>
<img src="mailboxs.jpg" ALIGN="Middle">&nbsp;
<A Href='MBINFOTABS.ASP?Path=<%=strDirectPath%>'>
<%=strReportscn%></A>
</B></FONT></TD></TR>
<%
Next
End If
%>
</TR>
</TABLE>

When you retrieve the manager property from the Exchange Server directory, the directory returns the distinguished name of the manager. To retrieve the display name of the manager, the code uses the distinguished name to create a full AdsPath to the directory object that corresponds to the manager. Then the code opens that object and retrieves the display name of the manager.

To retrieve the direct reports, the code uses the GetEx method in ADSI. (Recall that the reports attribute is a multivalued property. You must use GetEx when you retrieve multivalued properties from Active Directory.) The GetEx code returns an array of distinguished names for all of the person's direct reports. The code loops through each direct report in the array and displays as a hyperlink an image and the full name of each direct report.


Creating a Custom Recipient


Creating a custom recipient is straightforward. A custom recipient has contact as the object class, and you must set the targetAddress property of the custom recipient, which specifies the actual e-mail address of the recipient.

The following code creates a custom recipient using ADSI:

On Error Resume Next
Err.Clear
smtp = Request.Form("SMTP")
fn = Request.Form("FN")
ln = Request.Form("LN")
dn = Request.Form("DN")
al = Request.Form("AL")
Set oIADs = GetObject("LDAP:")
bstr1 = "LDAP://" + Session("Server") + "/CN=" + Session("CN") + _
"," + Session("DC")
bstr2 = Session("bstr2")
bstr3 = Session("bstr3")
Set oContainer = GetObject(bstr1)
Set oIADs = oContainer.Create("contact", "cn=" + CStr(dn))
oIADs.Put "mail", CStr(SMTP)
oIADs.Put "targetAddress", CStr(SMTP)
oIADs.Put "givenName", CStr(fn)
oIADs.Put "sn", CStr(ln)
oIADs.Put "displayName", CStr(dn)
oIADs.SetInfo


Displaying the Members of a Distribution List


The sample application allows you to display the members of a distribution list in an HTML table, as shown in Figure 13-7. This table is generated by using a For…Each construct to scroll through the collection returned by the Members method of the IADsGroup interface. After retrieving the object that corresponds to each member, the code checks the object class and displays the correct identifier for each member, such as mailbox, distribution list, or custom recipient. Remember that distribution lists can hold different types of objects. The code that displays the members of a distribution list is shown here:


Figure 13-7: An HTML table of the members in a specific distribution list

<HTML>
<HEAD>
<TITLE>Display Users in a DL</TITLE>
</HEAD>
<BODY>
<h1>The members of this DL are:</h1>
<hr>
<form METHOD="POST" NAME="INFO" ACTION=">
<input TYPE="button" VALUE="Back to Main Menu"
OnClick='window.location="menu.asp";'>
<input TYPE="button" VALUE="Select different container"
OnClick='window.loca
tion="logon.asp?diffcont=1";'>
</FORM>
<P>
<TABLE BORDER=1 bgcolor="#79AA86">
<%
Dim oIADs
Dim MyContainer
Dim objRecipients
Dim item
On Error Resume Next
Err.Clear
strDLName = Request.Form ("DLSELECT")
Set oIADs = GetObject("LDAP:")
bstr1 = strDLName
bstr2 = Session("bstr2")
bstr3 = Session("bstr3")
Set objDL = GetObject(bstr1)
Response.Write "<TR><TD><B>Class</TD><TD
><B>Display Name</TD><TD><B>Alias</
TD><TD><B>Directory Name</TD></TR>"
For Each item In objDL.Members
Set objitem = GetObject(item.ADSPath)
strClass = objitem.Get("class")
Select Case strClass
Case "organizationalPerson"
Response.Write "<TD>MailBox</TD><TD>" & objitem.Get("cn") & _
"</TD><TD>" & objitem.Mail & "</TD><TD>" & _
objitem.Name & "</TD></TR>"
Case "person"
Response.Write "<TD>Custom Recipient</TD><TD>" & _
objitem.Get("cn") & "</TD><TD>" & _
objitem.Get("mailNickname") & "</TD><TD>" & _
objitem.Name & "</TD></TR>"
Case "group"
Response.Write "<TD>Distribution List</TD><TD>" & _
objitem.Get("cn") & "</TD><TD>" & _
objitem.Get("mailNickname") & "</TD><TD>" & _
objitem.Name & "</TD></TR>"
Case Else
Response.Write "<TD>" & item.Class & "</TD><TD>" & _
objitem.Get("cn") & "</TD><TD>" & _
objitem.get("mailNickname") & "</TD><TD>" & _
objitem.Name & "</TD></TR>"
End Select
Next
%>
</TABLE>





Note

By default, Active Directory returns only 100 results, so you might want to increase the number of results returned for LDAP queries. If you are using ADO with the Active Directory OLEDB provider, you can do this by increasing the PageSize property.


/ 227