Find (and delete) orphaned delegate rules

When a user adds someone as a delegate of his/her mailbox and selects the option to have meeting requests go to the delegate, a hidden rule is created in the Inbox of the delegator. When you remove the delegate from the list the rule is deleted. But if the delegate isn’t removed before the delegee’s mailbox is deleted (presumably due to termination), the rule isn’t deleted. The delegate is removed from the Delegates tab so you can’t remove the rule, effectively orphaning the rule. Because the rule still exists, meeting requests will still be sent to the delegate. Since the mailbox doesn’t exist anymore, the meeting requestor will receive an NDR from a person they didn’t even invite to the meeting.

Microsoft’s solution is to use MDBView and go through the hidden items in the inbox until you find the corresponding rule and manually delete it. You can also use the better tool, MFCMapi, to do it. I wanted a better way to do it, and one that admins who don’t delve into raw MAPI viewers could use. So I wrote this WebDAV script that queries the target mailbox for the hidden items in the inbox, displays them in a table, and allows you No. to delete the message from the results window.

The delegate rule’s Rule Provider Content value is “Schedule+ EMS Interface.” If the delegator has multiple delegates who receive meeting requests (not that common) you won’t see multiple rules. There is only one rule, regardless of the number of recipients. If you don’t see an item with the Rule Provider Content Value above, then the user doesn’t have any delegates who receive meeting requests.

The script uses Exchange 2003 SP1’s ability to use the SMTP address in the URL, negating the need for a virtual directory for each SMTP namespace in your org. So you need SP1 for this to function. Just change the values near the top for the protocol and server name of your front-end or back-end server. I wrapped the script in a web page so it can be hosted on an IIS server and then you can just browse to it from anywhere. Note that it is not a server-side script. The code will be executed by the client and will prompt for credentials. Putting it in a web page is just a convenience. Just copy and paste it into a file, or download it here.

<script language='VBScript'>
Dim objXMLHTTP, objXMLDoc
' Define your protocol; http or https
strProtocol = "http"
' Define your server name
strServername = "[server]"
' Define your local name for 'Inbox'
strInbox = "Inbox"
Sub getMessages_OnClick()
	strUsername = document.all.mailbox.value
	If strUsername <> "" Then
		strInboxURL = strProtocol & "://" & strServername & "/Exchange/"
		strInboxURL = strInboxURL & strUsername & "/" & strInbox
		Set objXMLHTTP = CreateObject("Microsoft.XMLHTTP")
		objXMLHTTP.Open "SEARCH", strInboxURL, True
		objXMLHTTP.setRequestHeader "Content-type:", "text/xml"
		objXMLHTTP.setRequestHeader "Depth", "1"
		objXMLHTTP.onReadyStateChange = getRef("checkXMLHTTPState")
		strXML = "<?xml version='1.0' ?>" & _
			"<a:searchrequest xmlns:a='DAV:'><a:sql>" & _
			"SELECT" & _
			" ""DAV:displayname""" & _
			",""<a href=""></a>""" & _
			" FROM scope('shallow traversal of """ & strInboxURL & """')" & _
			" WHERE ""DAV:ishidden""=True" & _
			" AND ""DAV:isfolder""=False" & _
	End If
End Sub

Sub checkXMLHTTPState
	If objXMLHTTP.readyState = 4 Then
		ResponseStatus.innerHTML = "Server Response: " & objXMLHTTP.Status & " - " & objXMLHTTP.StatusText
		Set objXMLDoc = objXMLHTTP.ResponseXML
		XSLDiv.innerHTML = objXMLDoc.TransformNode(responseXSL.documentElement)
		Set objXMLHTTP = Nothing
		Set objXMLDoc = Nothing
	End If
End Sub

Function deleteMessage(strURL)
	strUsername = document.all.mailbox.value
	strInboxURL = strProtocol & "://" & strServername & "/Exchange/"
	strInboxURL = strInboxURL & strUsername & "/" & strInbox
	strItemURL = strInboxURL & "/" & Replace(strURL, chr(34), "")
	Set objDelete = CreateObject("Microsoft.XMLHTTP")
	objDelete.Open "DELETE", strItemURL, False
	If (objDelete.Status >=200 And objDelete.Status <300) Then
		MsgBox "Successful deletion."
		MsgBox "Delete request failed."
	End If
	Set objDelete = Nothing
	Call getMessages_OnClick()
End Function

<xml id='responseXSL'>
xmlns:xsl='uri:xsl' xmlns:a='DAV:' xmlns:d='urn:schemas:httpmail:'
<table width='75%' border='1'>
<td align='center'><font size='2'><b>Action</b></font></td>
<td width='40%' align='center'><font size='2'><b>Message Subject</b></font></td>
<td align='center'><font size='2'><b>Rule Provider Content</b></font></td>
<xsl:for-each select='a:multistatus/a:response'>
<td align='center'>
<xsl:attribute name='type'>button</xsl:attribute>
<xsl:attribute name='name'>deleteMessage1</xsl:attribute>
<xsl:attribute name='value'>Delete</xsl:attribute>
select='string(a:propstat/a:prop/a:displayname)' />")
<td><font size='2'><xsl:value-of select='a:propstat/a:prop/a:displayname' /></font></td>
<td><font size='2'><xsl:value-of select='a:propstat/a:prop/mapitag:x65eb001f' /></font></td>

<font face='Verdana' size='2'>SMTP Address:<br>
<input type='text' name='mailbox'><br>
<input type='button' name='getMessages' value='Retrieve'><br><br>
<div id='responseStatus'></div>
<div id='XSLDiv'></div>

3 thoughts on “Find (and delete) orphaned delegate rules

  1. Error 12007 means that the server name could not be resolved. Verify the server name specified in line 8 of the code. If you are using a short name, try changing it to the FQDN of the web server.

  2. Awesome work! We had to remove a bunch of people at a client site post-downsizing and they were plagued by the phantom delegate issue. Your script made short work of finding the culprit. Many thanks!!

Leave a Reply

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