Skip to main content

Adding a Public Contact Folder Search to the OWA 2007 Address book

Public folders are a great thing they increase the functionality of an Exchange server and while they can cause some support issues it’s great to see they will still be included in the next version of Exchange (it would be great to see them embraced as a feature instead of a burden as they provide some unique functionality you don’t get on other mail systems). One thing that Public folders can be used for is shared address lists with Outlook supporting the ability to add a Public Folder as an address list location in the Outlook Address Book. OWA has never provided this same functionality but for 2003 I came up with a small unsupported (hack) customization to add a public folder search option to the find address function see this post. On 2007 OWA was rewritten and WebDAV is no longer used by any of the OWA code but using the same underlying methods a similar public folder search option can be made available in 2007. Like before this involves modifying some of the OWA files which is not supported due to the nature of these files changing when Service packs and rollup/hotfixes are installed. Although you can change the template forms in 2007 there is still no way of controlling the way things get rendered so this method still uses a HTML injection via the document model. There are several places this code could be placed in 2003 I used the script files which would still work in 2007 but if you have looked at the script files in 2007 you will see a lot more code has been crammed into them and they seem to have gone on a diet in terms of the verbosity of naming standards for variables and whitespace I guess this was done to improve performance. So I chose to modify the addressbook.aspx template form which makes this mod a little easier to service.

How does it work?

The mod involves placing a script block of code just before the closing body tag the reason for positioning it down here is that we want this code to run after the page elements have been rendered to aid with this the defer tag is also used which should defer running of the script until the body has loaded. This could have also been done by using the Onload event in the body but this is already used by the other script files so overloading it in the template breaks other things and I wanted to avoid modifying the scripts themselves. I found the method I described above in my limited testing works okay. What this script block does is gets an array of Divs in the body and then searches through them for a div with an id of divEnts. The first div it finds will represent the upper Address Book part of this page so we don’t want to modify this. The second div it finds with this Id should represent the Contacts section which is where we want to inject the html. So what this script does is inject another entry into this list by using the Innerhtml property of the existing divEnts div. The Div that is injected contains the OWA public folderID of the public folder you want to search as well as the displayName of what you want it to appear as. These two parts need to be customized by you if you wish to use this method. To find the OWAID of the public folder you could use a tool like fiddler to look at protocol captures of OWA or I have another method that uses the EWS convertID operation to convert the Hex entry ID which can be easily obtained using the standard EMS Get-PublicFolder cmdlet.

Finding the OWAID for the Public Folder

Using the standard EMS cmdlet Get-PublicFolder you get access the EntryID of the public folder in its Hex form eg

$pfPublicFolderPath = "\Public Contacts"
$pfFolder = get-publicFolder -identity $pfPublicFolderPath

This would get the Public Folder called Public Contacts in the root and then you can access the EntryID from the EntryID property eg $pfFolder.EntryID. Once you have this EntryID you then need to convert it to the OWAID so it can be used in OWA to do this you need to use the Exchange Web Service convertid operation. I’ve added the necessary EWS code to my EWSUtil powershell library to do this so the code you need just to do the conversion looks like.

$null = [Reflection.Assembly]::LoadWithPartialName("System.Web")
$mbMailboxEmail = "”
$ewc = new-object EWSUtil.EWSConnection($mbMailboxEmail,$false, "", "", "","")
$Oulookid = $ewc.convertHexidPublicFolder($pfFolder.Entryid,[EWSUtil.EWS.IdFormatType]::OWAid)

You need to add the email address of the logged on user to the varible $mbMailboxEmail.When you run this code you should see an ID like


Outputted to the commandline you need to copy this ID for use in the OWA addressbook form.

Modifying the Addressbook.aspx file

Before making any changes to the addressbook.aspx file make sure you copy this file to another location so you have a backup of this file incase the modification doesn’t work and you need to roll back the changes.

On the CAS server locate the OWA forms directory and then locate the addressbook.aspx file in the premium directory see

Open this file in Notepad.
Down the bottom of the file the last three entries in this file should look something like

<% RenderEndOfFileDiv(); %>

What we are going to do is put some script in just before the end body tag so the modified end of file should look like

<% RenderEndOfFileDiv(); %>

<script type="text/javascript" language="JavaScript" defer>
var dc=0
var divCollection = document.getElementsByTagName("div");
for (var i=0; i<divCollection.length; i++) {
if(divCollection[i].getAttribute("id") == "divEnts") {
if(dc == 1){
var pfName = "Company Contacts"
var newContactEntry = "<div class=snlEntW><div id=divEnt class=\"snlEnt snlDef\" _onclick=onClkCntFld() _fid=\"" + pfId +"\" type=\"IPF.Contact\"><img src=\"current/themes/base/cntctsmll.gif\"><span id=spn>" + pfName + "</span></div></div>";
divCollection[i].innerHTML = divCollection[i].innerHTML + newContactEntry


The two varibles

var pfName = "Company Contacts"

need to be set to the OWAID you retrieved before and the name of the folder you want.

Thats it the change should be pretty much live as soon as you commit the changes . You need to consider this an untested and unsupported method and only for your own experimentation and testing under lab conditions (make sure your lab has SP1 installed or this wont work). I've put a download of the code to retrieve the OWA public folder ID and the other script change here. For the OWAid code you will need the latest copy of my EWSUtil powershell library

Popular posts from this blog

Export calendar Items to a CSV file using EWS and Powershell

Somebody asked about this last week and while I have a lot of EWS scripts that do access the Calendar I didn't have a simple example that just exported a list of the Calendar events with relevant information to a CSV file so here it is. I've talked on this one before in this howto  but when you query the calendar folder using EWS you need to use a CalendarView which will expand any recurring appointments in a calendar. There are some limits when you use a calendarview in that you can only return a maximum of 2 years of appointments at a time and paging will limit the max number of items to 1000 per call. So if you have a calendar with a very large number of appointments you need to break your query into small date time blocks. In this example script I'm just grabbing the next 7 days of appointments if you want to query a longer period you need to adjust the following lines (keeping in mind what I just mentioned) #Define Date to Query $StartDate = (Get-Date) $EndDate

Downloading a shared file from Onedrive for business using Powershell

I thought I'd quickly share this script I came up with to download a file that was shared using One Drive for Business (which is SharePoint under the covers) with Powershell. The following script takes a OneDrive for business URL which would look like This script is pretty simple it uses the SharePoint CSOM (Client side object Model) which it loads in the first line. It uses the URI object to separate the host and relative URL which the CSOM requires and also the SharePointOnlineCredentials object to handle the Office365 SharePoint online authentication. The following script is a function that take the OneDrive URL, Credentials for Office365 and path you want to download the file to and downloads the file. eg to run the script you would use something like ./spdownload.ps1 '

The MailboxConcurrency limit and using Batching in the Microsoft Graph API

If your getting an error such as Application is over its MailboxConcurrency limit while using the Microsoft Graph API this post may help you understand why. Background   The Mailbox  concurrency limit when your using the Graph API is 4 as per . This is evaluated for each app ID and mailbox combination so this means you can have different apps running under the same credentials and the poor behavior of one won't cause the other to be throttled. If you compared that to EWS you could have up to 27 concurrent connections but they are shared across all apps on a first come first served basis. Batching Batching in the Graph API is a way of combining multiple requests into a single HTTP request. Batching in the Exchange Mail API's EWS and MAPI has been around for a long time and its common, for email Apps to process large numbers of smaller items for a variety of reasons.  Batching in the Graph is limited to a m
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.