WEBDAV 101 -rev 1.6

advertisement
EXCHANGE WebDAV 101
Exchange WebDAV 101
danba
Last Revised: 6/28/06
Revision 1.6
Note:
This information is provided as-is and is not official Microsoft Documentation.
It’s intended to be for educational purposes only and the samples should only be used against a test system for.
WebDAV 101. Last Revised 6/28/06. Version 1.6
1
EXCHANGE WebDAV 101
I. Introduction
If you are not familiar with WebDAV for its use against Exchange, you may be wondering “What is WebDAV and
what is it good for?”
What it comes down to HTTP requests being done against an IIS virtual server mapped into Exchange. XML is
usually passed to Exchange in the call in order to perform some specific action on an item in an Exchange store.
XML is often returned, which contains requested information and possibly other data. It can also be used to read
and write items directly into folders. WebDAV itself is an ISAPI filter, so calls to Exchange are done to IIS virtual
directories on the Exchange server.
WebDAV is good for doing many different things (creating and reading items), however not everything is
documented. WebDAV does support working with items such as messages, contacts, folders, etc. You can create,
delete, modify, move (within a store) or copy (within a store) an item. Also, you will be able to use it to upload files
to the exchange stores. WebDAV is often used when there is no ability to run code on the exchange server or the
code needs to be executed outside of the network. It will work with MAPI and non-MAPI stores. HTTP and HTTPS
are supported along with different authentication methods (Basic, Windows, etc). Note that WebDAV is available for
both Exchange 2000 and 2003 - however it is not available for Exchange 5.5.
For .NET applications accessing Exchange items off the Exchange Server, only WebDAV is supported - unless you
can run the code directly on the Exchange server. WebDAV calls are thread-safe where as many messaging APIs
are not or have other issues which make them not supported under .NET code. Please review the following:
Support Policy for Microsoft Exchange APIs with .NET Framework Applications
http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B813349
With WebDAV, you will be able to interact with Exchange items with the code running on any machine which can do
an HTTP call and pass the needed information. This allows the code to run from pretty much any device or OS.
Most things such as working with calendar items, email, permissions and such can be handled via WebDAV.
However, some things such as Outlook specific items (tasks, etc) are not supported. One downside which people
run into is the need to learn XML in order to do the call. While needing to know some basic XML is needed, it’s not
too hard to pickup the needed skill. WebDAVs strengths are working with properties and items in Exchange Stores
– however, WebDAV itself has no business-logic built-in – its up to the developer to provide that.
WebDAV can be used by both Outlook and Outlook Express. With Outlook Express, its usage is very limited since
you’ll pretty much be limited to messages. Other applications such as BizTalk can also talk to Exchange via
WebDAV. As time goes by, you are likely to see more applications which will use WebDAV. In Exchange 12,
WebDAV is deemphasized and Web Services are the suggested API to use instead.
WebDAV 101. Last Revised 6/28/06. Version 1.6
2
EXCHANGE WebDAV 101
II. WebDAV
Basics
In order to do WebDAV development, you will need to know some basics. First we will go over the basics of a
WebDAV call. Next, you should know the basics of the XML language and how it is used in different languages.
After that, you should understand the basic WebDAV verbs used to perform different actions. Next, it’s important to
understand authentication.
A. The Request
WebDAV calls are performed by an HTTP request. The request can be done by any component
capable of doing an HTTP call – this means that non-Microsoft components can be used to do the call.
In non-managed applications, the XML DOM is often used to create the request object (Example:
MSXML2.ServerXMLHTTP30). .NET applications should use the native HttpWebRequest class for the
request.
Using non-.NET languages:
For non .net applications, you should use the XML DOM. For .NET applications, you should use .NET classes.
The XML DOM is the Microsoft XML parser COM object and can be called from any language which is COM
enabled. .NET has its own classes for working with XML and doing WebDAV requests, so its better to user
these for WebDAV.
What is the XML DOM?
http://msdn.microsoft.com/library/en-us/xmlsdk/html/DOM_What_Is_XML_DOM.asp?frame=true
A Beginner's Guide to the XML DOM
http://msdn.microsoft.com/library/en-us/dnxml/html/beginner.asp?frame=true
Communicating XML Data over the Web with WebDAV
http://msdn.microsoft.com/library/en-us/dnxmlweb/html/xmlandwebdav.asp?frame=true
Using .NET languages:
For .NET applications, you should use system.net and system.xml.
system.xml
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemxml.asp
system.net - HttpWebRequest
http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemnethttpwebrequestclasstopic.asp?frame=true
Server Versus WinInet
With the XML DOM you can use Server or WinInet http requests for webdav calls. MSDN
recommends using the server object for the call in re of WinInet on a server.
Server:
MSXML2.ServerXMLHTTP30
WinInet:
Msxml2.XMLHTTP30
B. A Basic WebDAV Call
Below is a sample showing how to do a GET against an email an exchange server (a GET returns the
stream of an item). While this call is very basic, it should give you an idea of how a call is done.
Dim sHREF
Dim sResponse
Dim HttpWebRequest
WebDAV 101. Last Revised 6/28/06. Version 1.6
3
EXCHANGE WebDAV 101
sHREF = "http://myserver/exchange/Administrator/Inbox/MyEmail.EML"
set HttpWebRequest = CreateObject("microsoft.xmlhttp")
HttpWebRequest.Open "GET", sHREF, False
HttpWebRequest.setRequestHeader "Content-type:", "text/xml"
HttpWebRequest.setRequestHeader "Translate:", "f"
' TODO: Uncomment for Exchange access
HttpWebRequest.Send
sResponse
= HttpWebRequest.ResponseText
' Returns as text
Set HttpWebRequest = Nothing
wscript.echo sResponse
sHREF is set to the URL of a mail item in the Administrator’s Inbox. “myserver” is the name of the
exchange server and “exchange” is the IIS virtual directory which is mapped into Exchange. Before
the request can be done, a connection needs to be opened. When this is done, authentication
credentials are passed. If no credentials are sent, then an access attempt using windows authentication
will ultimately be done by default. Different types of WebDAV verbs require different headers to be
set in different situations – in this case, a header of “Translate” is set to “f” in order properly get back
the stream of the item. When the request is sent, the send may or may not need to be passed additional
information – such as XML to process or string containing a stream of information to use. After the
request is done, the request text (ResponseText) can then be used to get the result of the call.
C. Synchronous vs Asynchronous Processing
There are two ways requests can be processed - asynchronous and synchronously. Synchronous calls will
cause the code to halt until a response is returned. Asynchronous calls allow the code to execute and the
response to be processed later. Asynchronous will have higher performance and will help avoid lockups when
the DAV request is taking a long time. However, synchronous is easier to write and debug.
With Asynchronous calls, setting waitForResponse will cause the code to wait for the specified time period for
the HTTP response. While this is going on, it will pump messages so that the application will not hang.
With the XML DOM, Synchronous calls are specified by setting the third parameter of the open method for the
http request to false. A setting of True will cause the call to be asynchronously. Below are examples of these
calls:
VB Example – Synchronous:
sXMLReq
= “…..”
oXMLHTTP.open "PROPFIND", sUrl, False, sMyUser, sMyPassword
oXMLHTTP.setRequestHeader "Content-Type", "text/xml"
oXMLHTTP.send sXMLReq
Debug.Print oXMLHTTP.responseText
VB Example - Asynchronous:
VB Example - Asynchronous:
oXMLHTTP.open "PROPFIND", sUrl, True, sMyUser, sMyPassword
oXMLHTTP.setRequestHeader "Content-Type", "text/xml"
oXMLHTTP.send sXMLReq
While oXMLHTTP.readyState <> 4
oXMLHTTP.waitForResponse 1000
Wend
Debug.Print oXMLHTTP.responseText
C++ Example - Asynchronous:
pIXMLHTTPRequest.CreateInstance(__uuidof(ServerXMLHTTP30));
WebDAV 101. Last Revised 6/28/06. Version 1.6
4
EXCHANGE WebDAV 101
…
string strUrl = "http://myexserver/exchweb/bin/auth/owaauth.dll";
hr=pIXMLHTTPRequest->open("PROPFIND", _bstr_t((char *)strUrl.c_str()), false);
string strXML = “…………”;
…
hr=pIXMLHTTPRequest->send(_bstr_t((char *)strXML.c_str()));
// waitForResponse will have code execution wait until the code response is aquired AND
// it will also pump messages so that it won't cause a lockup while its waiting.
VARIANT Timeout;
VariantInit(&Timeout);
Timeout.vt = VT_I4;
Timeout.lVal = 60; // Timeout value of 60 seconds.
long readyState = READYSTATE_UNINITIALIZED;
readyState = pIXMLHTTPRequest->GetreadyState();
while (readyState != READYSTATE_COMPLETE)
{
//Passing vtMissing as the first parameter sets the timeout value to infinite.
// waitForResponse works as a message pump while waiting for the response,
// this way the app won't lock up the system.
hr = pIXMLHTTPRequest->waitForResponse(Timeout);
readyState = pIXMLHTTPRequest->GetreadyState();
}
long status = pIXMLHTTPRequest->status;
printf("Status of the request is: %d\n",status);
_bstr_t t = pIXMLHTTPRequest->getAllResponseHeaders();
printf("Response headers are: %s\n",(char *)t);
D. Authentication
WebDAV supports several types of authentication including Windows, NTLM, Basic and FBA(forms based).
Each has it benefits and limitations. Due to NTLM being outdated, it will not be covered here.
The authentication methods supported are largely controlled by the virtual directory permissions. “exchange”
and “public” are the most often used folders – you should set permissions carefully. The authentication method
of the virtual directory being accessed must match that of the WebDAV code or the call will not work.
If you have OWA or another application which relies on these settings, you may want to create different
directory which maps to the exact same settings as these. By doing this, you can have a directory with
permissions specific to your application. If Anonymous is turned on, the WebDAV calls will fail since
Anonymous will be used instead of any other specified protocol. Please note that you should make
modifications to virtual directory settings using ESM and not IIS directly.
WebDAV 101. Last Revised 6/28/06. Version 1.6
5
EXCHANGE WebDAV 101
F
1 . Basic Authentication
A Basic Authentication call will pass credentials in clear text. Because of this, its not a good idea to be used
in unsecured networks to remote machines or if SSL is not being used.
With the XML DOM, you would pass the credentials in the open statement:
HttpWebRequest.Open "GET", sHREF, False, sUserName, sPassword
For .NET, you would create a credential cache and add credential s to the HttpWebRequestsimilar to the
following:
myCred = New NetworkCredential(m_Connection.UserName, m_Connection.Password)
MyCredentialCache = New CredentialCache
MyCredentialCache.Add(myUri, "Basic", myCred)
HttpWRequest.Credentials = MyCredentialCache
2. Windows Authentication:
With the XMLDOM, you do not need to pass the user and password.
In VB:
HttpWebRequest.Open "GET", sHREF, False
WebDAV 101. Last Revised 6/28/06. Version 1.6
6
EXCHANGE WebDAV 101
Or in C++:
hr=pIXMLHTTPRequest->open("PROPFIND", _bstr_t((char *)strUrl.c_str()), false);
For .NET, you would create a credential cache and add credential similar to the following:
HttpWRequest.Credentials = CredentialCache.DefaultCredentials
Note that besides the network using Kerberos and all machines involved being under the same domain, you
must have “Enable Integrated Windows Authentication” checked under Internet Options/Advanced tab in
Internet Explorer in addition to the IIS virtual directory settings. The reason for this is that WebDAV will use
the settings of IE in its call.
If this code is running in an ASPX page and you wish to have the following in the web.config file:
<authentication mode="Windows" />
<identity impersonate="true"/>
Further, if the web page is neither on the Exchange server nor the client machine, the Exchange server will
need to be setup to be trusted for authentication by the Exchange server’s DC. This is required in order to
get around issues with passing credentials. This is known as the double-hop credential problem. This can
be done though AD on the DC.
3. FBA:
If FBA is enabled in the Exchange System Manager (ESM), then WebDAV will need to authenticate using
FBA authentication. In order to use FBA, SSL should be to configured and enabled in addition to turning on
WebDAV 101. Last Revised 6/28/06. Version 1.6
7
EXCHANGE WebDAV 101
FBA in ESM. Please note that the machine running the WebDAV code with an SSL URL will need to have
the certificate installed on it.
Enabling FBA is controlled by checking the “Enable Forms Based Authentication” found under the properties
of the HTTP protocol for the Exchange server in the Exchange System Manager.
You may be prompted to setup SSL if it’s not already. If you don’t want to setup SSL, there is a
work-around. Even though it’s not advised, you can use FBA without SSL. This is not advised
because credentials will be passed in clear text – which could be sniffed. To configure FBA to
work without SSL for your development environment follow these steps:
1. Open the registry editor (run regedit.exe)
2. If it doesn’t exist already add an OWA key under:
HKLM\System\CurrentControlSet\Services\MSExchangeWeb
3. Under the OWA key add a DWord value named “AllowRetailHTTPAuth”
4. Set the value of this DWord to “1”
The following article is a sample of using FBA with WebDAV:
891748 How to programmatically access your Exchange Server 2003 Inbox using
http://support.microsoft.com/?id=891748
This is generally how it works:
1 An HTTP POST is done to /exchweb/bin/auth/owaauth.dll with an authentication string.
2) The authentication string looks like this:
Dim strServerName as string = “Myserver”
Dim strDomain as string = “myserverdomain.something.com”
Dim strUserName as string = “myuser”
Dim strPassword as string = “mypassword”
Dim strPostFields As String = "destination=https%3A%2F%2F" & strServerName &
"%2Fexchange%2F" + strUserName + "%2F&username=" + strDomain + "%5C" + strUserName +
"&password=" + strPassword + "&SubmitCreds=Log+On&forcedownlevel=0&trusted=0"
3) WebReq.KeepAlive and AllowAutoRedirect should be set to True on the request.
4) Note: If you are doing an asynchronous call, you need to wait for the response – or the code will fail.
For .NET you could setup a callback.
WebDAV 101. Last Revised 6/28/06. Version 1.6
8
EXCHANGE WebDAV 101
5) In the response from the POST, you will get back cookie strings in the headers. These strings need
to be extracted and placed into one string. This will hold your credentials for future WebDAV calls.
These credentials will be good for a period of time (most often 20 minutes depending upon
settings).
6) Now that you have the credentials, a header of “Cookie" with the data consisting of the combined
cookie strings in each WebDAV call you make.
WebDAVRequest.Headers.Add("Cookie", strReusableCookies)
7) If you get a response from the WebDAV call saying "The operation has timed-out.", then the
credentials have expired. You will need to get new credentials (start with step 1) and do the
WebDAV call again.
4. In Closing:
If you use a network monitoring tool such as Netmon, you will see that each time a WebDAV call is done,
there is an initial check to see if Anonymous is valid – this is normal and will happen even when you have
specified the authentication protocol. Anonymous overrides other protocols, so it really should never be
enabled on the exchange virtual. If Anonymous is enabled, authenticating with the protocols will not work.
So, the WebDAV call will likely fail. The reason for this is that connecting to stores such as mailboxes
requires that you access using a domain account with permissions to the store (ex: mailbox).
If you run into problems, it’s a good idea to try using OWA to see if the problem reproduces. If Basic is only
selected on the virtual directory, you should get prompted for credentials with a windows login box.
Windows authentication should never prompt you. FBA authentication should direct you to a logon form.
E. XML and Verbs
XML is a structured storage data description language. It uses tags similar to HTML. WebDAV uses XML to
specify data to process and returns XML data from most of its responses. In order to use WebDAV in most
situations, you will need to understand basic XML. Below are some links to help you get started if you are not
familiar with XML.
Understanding XML Technologies
http://msdn.microsoft.com/XML/Understanding/
XML Developer Center
http://msdn.microsoft.com/xml/default.aspx
The example below is used in a PROPFIND in order to get a list of all properties for an item. Here you will see
“<D:propfind xmlns:D="DAV:">”. The “propfind” indicates the command parameters will be passed. The “xmlns”
indicates the namespace being used – you could think of it as a way of specifying an alias for part of a property
name. In this case, D will be synonymous to “DAV:”. Each WebDAV command will require specific formatting
to match what the WebDAV verb being used requires.
<?xml version="1.0" ?>
<D:propfind xmlns:D="DAV:">
<D:allprop/>
</D:propfind>
From this, it should be apparent that the XML used in calls must match-up to the WebDAV Verb being used.
Because of this, you will want to be careful with how the XML is formed. A lot of errors programmers encounter
revolve around bad XML.
Verbs:
WebDAV 101. Last Revised 6/28/06. Version 1.6
9
EXCHANGE WebDAV 101
WebDAV has many different verbs. Each performs a specific task. Some work on single items, while others
work with batches of items. Below are some of the most common verbs used by WebDAV against Exchange:
GET
PUT
DELETE
MKCOL
DELCOL
PROPFIND
PROPPATCH
COPY
MOVE
SEARCH
X-MS-ENUMATTS
Retrieves the stream of an item. This is often used for extracting the text of
item or the MIME of things such as a message.
Writes stream content to a URI. IT can be used to write text to a file or MIME
content.
Deletes an item.
Used to create folders. .
Use DELETE. There is some false documentation with this verb on the web.
This retrieves properties on an item as XML. This uses an XML list of
properties to return from a specified item.
Sets properties on an item. This uses an XML list of properties to set on an
item.
Copies items within a store. Note that copying between stores is not
supported.
Moves items within a store. Note that moving between stores is not
supported.
Searches for item based-upon SQL search. Note that the only SQL verb
supported with WebDav is SEARCH. The list of properties to search for is
contained in XML. This can be used in retrieving items based-upon ranges (a
piece at a time). Searches can be for the immediate folder or on child folders
(DEEP). Note that DEEP searches are not supported on public folders (KB
320071demonstrates how to work around this limitation).
This enumerates attachments. Its used to get a listing of attachments on an
item. The results are returned as XML. In order to get at the attachments
themselves, you will need to do a WebDAV GET using the URI of the item
attachment. X-MS-ENUMATTS gets you the URI to the attachment.
Here is a more complete list and information for the WebDAV verbs:
WebDAV Methods
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_methods.asp?frame=true
WebDAV Batch Methods
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wss/wss/_esdk_arch_webdav_bmethods.asp
WebDAV 101. Last Revised 6/28/06. Version 1.6
10
EXCHANGE WebDAV 101
III. Specifics To Watch Out For
A. Searching Appointments:
If you want to search for appointments & recurring within a period of time, you should use a WebDAV SEARCH
- this will show all appointments. A PROPFIND should only be used when you know that the URI being used
points to an appointment EML which you know to be valid.
B. Recurring Appointments:
For non-recurring appointments, you can use PROPFIND to read the specific appointment's information. You
should use a SEARCH for reading recurring appointments. PROPFIND works against existing EML files.
Recurring appointments have the recurrence patterns stored in the master appointment (original appointment).
Several things can cause expansion of this appointment information into separate EML files.
While it may look like a good idea to use a PROPFIND against these EML, it is not – if the expansion has not
happened for the dates you are wanting recurring appointment information on, you will not get back any
information for these days. Since a SEARCH will return the information reliably, it’s best to use the SEARCH
statement for appointments within a specified date/time period.
C. Recurring Appointment Exceptions:
Recurrence patterns and the exceptions to recurring appointments are stored in the master appointment. If you
want to read the exceptions list, you will need to use a WebDAV GET in order to read back the mime text. After
doing this, the mime will need to be programmatically parsed. You will see the exception information as
VCALENDAR data from the Master Appointments stream. Look for the sections marked BEGIN:EVENT and
END:EVENT. The reason for this is that the exceptions are stored within the master appointment.
How To Retrieve Exception Information of a Recurring Appointment using WebDAV
http://support.microsoft.com/?id=309699
RFC 2447 (RFC2447)
http://www.faqs.org/rfcs/rfc2447.html
D. Recurring Appointment Pattern:
Just like exceptions to recurring appointments, the recurrence pattern is stored in the master appointment. You
will need to do a WebDAV GET in order to read back the mime text. After doing this, the mime will need to be
programmatically parse the MIME stream and extract the pattern.
How To Retrieve Exception Information of a Recurring Appointment using WebDAV
http://support.microsoft.com/?id=309699
RFC 2447 (RFC2447)
http://www.faqs.org/rfcs/rfc2447.html
E. Searching for Recurring Appointments:
If you modify an Outlook recurring appointment to have an exception, all instances will appear when performing
a WebDAV search. However, if you do not make changes to a recurring appointment, only the master
appointment item will appear in the WebDAV search. Then, how do you programmatically retrieve a recurring
appointment's individual instances via WebDAV even if the instances are not exceptions to the appointment
recurrence?
You can programmatically retrieve the individual instances of a recurring appointment by performing a time
framed WebDAV search. The following code demonstrates how to perform a time framed search via WebDAV.
Note that the following will code will return n+1 items for a recurring appointment with n instances. The
additional result is the master item.
Sub GetApptsInTimeFrame()
Const SERVERNAME = "server"
Const MAILBOXNAME = "mbx"
Const UserName = "domain\user"
Const Password = "password"
WebDAV 101. Last Revised 6/28/06. Version 1.6
11
EXCHANGE WebDAV 101
Const folder = "Calendar"
sUrl = "http://" & SERVERNAME & "/exchange/" & MAILBOXNAME & "/" & folder
sStartTime = "2004-06-06T00:00:00.000Z" ‘ Note: Watch the format of the dates.
sEndTime = "2004-06-11T00:00:00.000Z"
‘ Note: Watch the format of the dates.
Debug.Print sUrl
Dim strPropReq As String
strPropReq = "<?xml version='1.0'?>" & _
"<d:searchrequest" & _
" xmlns:d=""DAV:""" & _
" xmlns:cal=""urn:schemas:calendar:"" >"
strPropReq = strPropReq & "<d:sql> SELECT ""DAV:href"", ""urn:schemas:calendar:dtstart"",
""urn:schemas:calendar:dtend"" " & _
"FROM Scope('SHALLOW TRAVERSAL OF """ & sUrl & """ ')" & _
"WHERE ""DAV:contentclass"" = 'urn:content-classes:appointment'" & _
"AND ""urn:schemas:calendar:dtstart"" <= CAST(""" & sEndTime & """ AS ""dateTime.tz"")" &
_
"AND ""urn:schemas:calendar:dtend"" >= CAST(""" & sStartTime & """ AS ""dateTime.tz"")"
strPropReq = strPropReq & "</></>"
Dim oXMLHttp As XMLHTTPRequest
Set oXMLHttp = CreateObject("Microsoft.XMLHTTP")
With oXMLHttp
.Open "SEARCH", sUrl, False, UserName, Password
.setRequestHeader "Content-type:", "text/xml"
.setRequestHeader "Depth", "1,noroot"
.setRequestHeader "Translate", "f"
.setRequestHeader "Content-Length", "" & Len(strPropReq)
.Send (strPropReq)
Debug.Print .Status
strOutPutFile = Environ("USERPROFILE") & "\Desktop\XMLOutput.xml"
Open strOutPutFile For Output As #1
Print #1, .responseText
Close #1
End With
Debug.Print "Done processing"
End Sub
F. Use ESM for Virtual Directory Settings:
The security settings of IIS and those found under ESM should always tie together – if the settings are changed
via ESM. The docs say changes to the virtual directory settings for Exchange should be done through ESM and
not IIS. These setting should always tie together… so use ESM to make the proper settings.
For Exchange 2003:
ESM authentication settings will update IIS authentication settings.
IIS authentication settings will not update ESM authentication settings.
The IIS authentication settings will be used over ESM authentication settings.
As a rule, don’t have IIS and ESM up at the same time, or you may not see ESM changes reflected in
IIS… also, it can be confusing.
For Exchange 2000:
The same rules apply as for Exchange 2003, however you may need to refresh IIS settings after
changing them in ESM.
G. Headers:
Headers make a great difference for most WebDAV calls. Its important to be sure that you are using the proper
headers for each verb, so its best to review the documentation for the verb related to the call you are doing.
GET or PUT may fail if the “Translate” header is not set. MOVE or GET may fail if “Overwrite” is not set and the
item already exists in the destination. Different verbs require different settings for the “Content-type” header.
WebDAV 101. Last Revised 6/28/06. Version 1.6
12
EXCHANGE WebDAV 101
These headers can also change how much will be affected or returned in a call with headers such as “Depth”.
Its important to understand how different headers will affect the call you are doing. If you don’t pay attention to
these headers, the code may fail or even worse make mass changes which you did not want to happen.
WebDAV Headers
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_headers.asp?frame=true
WebDAV Methods
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_methods.asp?frame=true
WebDAV Batch Methods
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wss/wss/_esdk_arch_webdav_bmethods.asp
H. URLScan:
URLScan is used to help secure an Exchange Server. However, attention needs to be paid when using URL
Scan. URLScan by default will lock-out several of the WebDAV verbs (such as BPROPFIND). URLscan uses a
config files which sets the allowed verbs to use. So, you may need to add the needed verbs to the AllowVerbs
section of the appropriate config file.
309508 IIS lockdown and URLscan configurations in an Exchange environment
http://support.microsoft.com/default.aspx?scid=kb;en-us;309508
Fine-tuning and known issues when you use the Urlscan utility in an Exchange 2003 environment
http://support.microsoft.com/default.aspx?scid=kb;en-us;823175
How to configure the URLScan Tool
http://support.microsoft.com/default.aspx?scid=kb;en-us;326444
WebDAV 101. Last Revised 6/28/06. Version 1.6
13
EXCHANGE WebDAV 101
IV. WebDAV No-No’s
OK, WebDAV can do quite a bit, however there are some things WebDAV cannot do. There are some workarounds supported and unsupported. One method is to use CDOEX make available via a web service or COM+
service. Optionally, CDO 1.21 or MAPI may be used to perform some of these tasks - however this also not suite
you.
A. Unsupported OWA Commands:
If these will not work for you, there are OWA commands which can be called via WebDAV... the problem here is
that they are not supported (except for getting Free/Busy information).
Customizing Microsoft Outlook Web Access
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=6532E454-073E-4974-A800-1490A7CB358F
B. Topics:
1. Reading The GAL.
You will need ADSI, CDO 1.21 or Extended MAPI for this. Also, you may use an OWA command to get this
information.
Format of the OWA call:
sServerURL = "http://"+ sServerURL + "/public/?Cmd=galfind
Information on the unsupported call is covered in the following article:
Customizing Microsoft Outlook Web Access
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=6532E454-073E-4974-A800-1490A7CB358F
Here are the supported methods:
CDO 1.21:
How To Work with Distribution Lists Using CDO (1.x) from Visual Basic
http://support.microsoft.com/?id=178787
ADSI:
241474 HOWTO: Render the Global Address List with ADSI
http://support.microsoft.com/?id=241474
Extended MAPI:
166106 HOWTO: Getting the Contents of the Exchange Global Address List
http://support.microsoft.com/?id=166106
2. Read The Table:
The Mailbox Table in Exchange holds a list of Mailboxes and related mailbox information. Reading this
table can only be done with Extended MAPI or WMI can be used on an Exchange 2003 server. Nothing
else can do this.
Extended MAPI can be used with Exchange 5.5 and later.
XCLN: How to Retrieve Last Logon Time of Exchange Users Using Extended MAPI
http://support.microsoft.com/default.aspx?scid=kb;en-us;259570
IExchangeManageStore::GetMailboxTable
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/exchserv/html/intrface_24it.asp
With Exchange 2003 and later, you can use WMI:
LastLogonTime Property
http://msdn.microsoft.com/library/default.asp?url=/library/enus/e2k3/e2k3/_wmiref_pr_Exchange_MailboxLastLogonTime.asp?frame=true
WebDAV 101. Last Revised 6/28/06. Version 1.6
14
EXCHANGE WebDAV 101
3. Deleting Attachments. –
The DELETE verb only works on Exchange 2003 SP1 - it will not work on any earlier version/service pack.
CDOEX, CDO 1.21, Extended MAPI, etc can do this on Exchange 2000 or 2003.
One possible work-around is to read the message stream using a WebDAV GET, modify the stream to
remove the attachment and then do a PUT to write it back. You will want to watch-out to be sure that you
do not lose any custom properties which you have set.
Also, you may use an unsupported OWA command to delete the attachment with Exchange 2000 and 2003.
To do this, send a POST and "?Cmd=editattach". Again, OWA commands such as this should be avoided
since they may not work in future versions of Exchange.
4. Adding Attachments. –
There is no mechanism to add an attachment in WebDAV. You will need to create/recreate the item using a
WebDAV PUT. The text you would be putting would be the mime of the item, which also contains the
attachment. It’s useful here to use CDOSYS to create a message and add an attachment – then extract the
MIME from the message and use it for the WEBDAV PUT. You will need a header of "translate" set to "f".
If the message already exists, you will need to, you must do a GET on the message stream, which will give
you the message + attachments in a string. Next, modify the stream to include a new attachment. After
this, the string can be used in a PUT statement to write the attachment.
5. Get Free/Busy Information.
CDO 1.21, CDOEX, etc can do this, however WebDAV cannot directly. You may use a GET against OWA
to get this information.
Here are some things to be aware of:
 Free/Busy information is stored in the public store under the NON_IPM_SUBTREE folder
related for the user.
 Published Free/Busy information can range between 2 and 36 months.
 Outlook will publish this information based-upon its settings – this is most often set to 15 or 45
minutes; the default varies between versions of Outlook. MADFB will publish Free/Busy information
for OWA – about every 15 minutes.
 MADFB runs under the System Attendant process.
 Tentative appointments do not create Schedule+ Free Busy Messages in the Schedule+ Free Busy
Folder (See kb 232380).
 The outlook switch /cleanfreebusy can be used to reset free/busy information.
The OWA call is in this format (no line breaks):
http: // {server} /public/?cmd=freebusy & start= {ISO8601 start time} &end= {ISO8601 end time}
&interval= {interval block in minutes} &u= {SMTP address of organizer/attendee} [&u=user2&u=user3.]
In code, it might look like this:
sHREF="http://myexserver/public/?Cmd=freebusy&start=2005-03-17T00:00:0007:00&end=2005-03-19T00:00:0007:00&interval=10&u=SMTP:Administrator@mydomain.extest.microsoft.com"
Here is a sample from the SDK:
http://msdn.microsoft.com/library/en-us/wss/wss/_esdk_checking_free_busy_status_http.asp
Checking Free/Busy Status (HTTP):
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_esdk_checking_free_busy_status_http.asp
Checking Free/Busy Status (CDO)
http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_checking_free_busy_status.asp?frame=true
WebDAV 101. Last Revised 6/28/06. Version 1.6
15
EXCHANGE WebDAV 101
There is one other way to get this information with WebDAV, although it will take some work. You can do a
search on a person's calendar to determine if they will be free or busy.... The problem with this is that the
code will need to log-on to the person's mailbox - this will require that the code is running under a user with
permission to the mailbox.
Processing time will also be a factor when doing this for many users. Here are the steps:
1) Use a WebDAV SEARCH on the person’s appointments between two dates.
2) Parse and convert this information into a useful format by your application.
6. Canceling Appointments.
Unfortunately, there is no facility to cancel a meeting via WebDAV. You may be able to delete an
appointment directly from a calendar if there are no attendees. A meeting is pretty much an appointment
with attendees. If you have an appointment with attendees (i.e. it’s a meeting), you cannot just delete it and
expect the attendees to get notified – no cancellation emails are sent. However, there are two ways to
work around this.
a. Use CDOEX: You will need to use CDOEX on the Exchange server. The code can be called via a web
service/web method.
Calendars in Exchange 2000 Server
http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_calendars_in_exchange.asp?frame=true
The Calendar Object Model
http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_understanding_the_calendar_object_model.asp?frame=true
Canceling a Meeting
http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_canceling_an_appointment_as_the_organizer.asp?frame=true
Sending Meeting Updates
http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_sending_appointment_updates.asp?frame=true
b. Reverse Engineer: You can try to reverse engineer the cancellation emails by capturing network traffic
when cancellation email is sent via OWA and construct emails for cancellation of the appointment item.
Next send these cancellation emails and delete the original appt from the person who made it. There is
no public documentation available for the format of Exchange iCalendar cancellation emails.
Calendars on the Internet
http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_calendars_on_the_internet.asp?frame=true
Internet Calendaring and Scheduling Core Object Specification (iCalendar)
http://www.ietf.org/rfc/rfc2445.txt
RFC 2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar)
http://www.faqs.org/rfcs/rfc2445.html
7. Tasks:
WebDAV was not designed for working with outlook specific items such as Tasks. To work with tasks, you
will to reverse-engineer the solution and in order to construct the proper XML to be used for a
PROPPATCH.
8. Item and Folder Permissions:
Permissions to folders and items can be read and changed via WebDAV using an XML descriptor. It’s also
possible to use other APIs such as ADO update security settings. An XML descriptor is an XML document
in a string which describes security permissions to an item or folder. A PROPFIND is used to read security
information. PROPPATCH is used to update the permission.
Here is what a descriptor looks like:
Example Descriptor in XML
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_example_descriptor_in_xml.asp?frame=true
WebDAV 101. Last Revised 6/28/06. Version 1.6
16
EXCHANGE WebDAV 101
This is the format of the descriptor:
Exchange Store XML Security Descriptor Format
http://msdn.microsoft.com/library/enus/e2k3/e2k3/_exch2k_web_storage_system_xml_security_descriptor_format.asp?frame=true
Before starting to use the XML descriptor, it’s important to have an understanding of security…
Security
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_web_storage_system_security.asp?frame=true
Here are some basic examples on usage:
Getting an Item's XML Security Descriptor
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_getting_an_item_s_xml_security_descriptor.asp?frame=true
How to add an access control entry to a folder item in Exchange 2000 Web Storage System by coding
in Exchange 2000 Server.
http://support.microsoft.com/?id=317891
Note: ADO can also be used instead of WebDAV…
How To Deny a User Read Permissions on a Mail Item (ADO)
http://support.microsoft.com/default.aspx?kbid=289879
Here is some additional information on the subject:
Web Storage System Security Roles
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmes2k/html/secroles1.asp
9. Creating Delegates:
You cannot create delegates through WebDAV.
It is possible to read delegates. An example is supplied at the end of this document.
10. Deep Searches
DEEP searches are not supported on public folders. KB 320071 demonstrates how to work around this
limitation.
How to programmatically get the size of mailboxes in Exchange
http://support.microsoft.com/default.aspx?scid=kb;en-us;320071
11. Changing OOF Text:
This cannot be done with WebDAV. It “may” be possible to reverse-engineer the actions of OWA using a
network trace; however this would be unsupported and unwise. For getting around this, consider using
Extended MAPI.
WebDAV 101. Last Revised 6/28/06. Version 1.6
17
EXCHANGE WebDAV 101
V. Debugging and Testing:
For testing and debugging WebDAV code, there are some tools and techniques which can be used to help resolve
problems.
There are several tools and a lot of information in the Exchange SDK, so it’s a good idea to have it installed.
Exchange 2003 SDK Documentation and Samples March 2005
http://www.microsoft.com/downloads/details.aspx?FamilyID=a865936f-50da-47a0-9dce-f24e8307f38d&displaylang=en
Exchange SDK Development Tools
http://www.microsoft.com/downloads/details.aspx?FamilyID=4afe3504-c209-4a73-ac5d-ff2a4a3b48b7&displaylang=en
A. Check the Response:
First, always check the response code and response text to see what you are getting back. The status codes
can be looked-up to find an indication of the problem. You will see more specifics in the response text – so be
sure to always check it.
WebDAV Protocol Status Codes - So the can check for problems
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_webstore_http_webdav_protocol_errors.asp?frame=true
B. Exchange Explorer:
This a very useful tool used for looking at Exchange stores in an interface which looks similar to Windows
Explorer. This tool is part of the Exchange SDK and uses WebDAV to do its own work. Its useful for testing
things like permissions and can be used to set properties.
Exchange Explorer
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wss/wss/wsst_web_storage_system_schema_designer.asp
C. MFC MAPI:
This is an awesome tool for looking at and working with items in Exchange. One great use is for finding
properties on items. The source code is available – it is written in C and uses Extended MAPI. This is useful for
looking at any properties and for viewing the MIME stream of an item.
WebDAV 101. Last Revised 6/28/06. Version 1.6
18
EXCHANGE WebDAV 101
SAMPLE: MFCMAPI Demonstrates MAPI Client Code
http://support.microsoft.com/default.aspx?scid=kb;en-us;291794
D. Network Monitor (Netmon):
Netmon can be used to sniff the traffic during a WebDAV call. It’s useful for checking what actually is going on
during the WebDAV Call. You will be able to see issues like network errors show-up in it. It’s also useful for
seeing the WebDAV calls done by OWA to get an idea on how to write your own WebDAV calls.
WebDAV 101. Last Revised 6/28/06. Version 1.6
19
EXCHANGE WebDAV 101
About Network Monitor 2.0
http://msdn.microsoft.com/library/en-us/netmon/netmon/about_network_monitor_2_0.asp?frame=true
Monitoring Network Traffic
http://msdn.microsoft.com/library/en-us/dnw2kmag01/html/NetworkTraffic.asp?frame=true
Here are some points to remember:
Netcap is a utility which can also capture network activity – this is optional support tool found on the XP
install CD. Logs captured via Netcap can be read by Netmon.
When capturing traffic, its best to capture all traffic for several seconds prior and after a WebDAV call.
When you review the logs, you will see in initial anonymous call. This call should fail and return a list of
supported protocols. After this, you should see another call using the designated protocol (Windows, Basic,
etc). The second call should work.
When capturing traffic, an initial test should be done from the machine running the code. After the log is
reviewed, it may be helpful capture traffic from the Exchange server.
Some things to look for would be: Incorrect protocol being used, errors, excessive traffic, long delays
between request and response.
WebDAV 101. Last Revised 6/28/06. Version 1.6
20
EXCHANGE WebDAV 101
E. WebDAV Sample Application:
The WebDAV Sample application comes with the Exchange SDK Documentation. It is an HTML file used to do
WebDAV calls and can be used for testing as well as a source of sample code.
WebDAV 101. Last Revised 6/28/06. Version 1.6
21
EXCHANGE WebDAV 101
F. Tests
In addition to the tools, there are some basic tests which you can perform depending upon what the issue is.
1. Basic GET: For checking access and permissions.
Do a basic GET against a text file in a non-Exchange virtual directory in order to verify t.hat WebDAV is
functioning. This can also be used to be sure that WebDAV is working with SSL
dim
dim
dim
dim
Dim
sHREF
sUserName
sPassword
sResponse
HttpWebRequest
'sHREF = "http://myserver/webdav/myfile.txt" ' TODO: change - this is for non exchange.
sHREF = "http:// myserver /exchange/Administrator/Inbox/MyEmail.EML" ' TODO: Change - this is
for Exchange.
sUserName = "domain\user"
sPassword = "userpassword"
' TODO: change for Basic Authentication
' TODO: change for Basic Authentication
set HttpWebRequest = CreateObject("microsoft.xmlhttp")
'Set HttpWebRequest = New Msxml2.XMLHTTP30
'HttpWebRequest.ContentType = "text/xml"
HttpWebRequest.Open "GET", sHREF, False, sUserName, sPassword ' TODO: Use for Basic
Authentication
' HttpWebRequest.Open "GET", sHREF, False
' TODO: Use for Windows authentication
‘HttpWebRequest.setRequestHeader "Content-type:", "text/xml" ' TODO: Uncomment for Exchange
access
‘HttpWebRequest.setRequestHeader "Translate:", "f"
' TODO: Uncomment for Exchange access
HttpWebRequest.Send
sResponse = HttpWebRequest.ResponseText ' Returns as text
'ReadAnAttatchment = HttpWebRequest.responseBody ' Returns as encoded
Set HttpWebRequest = Nothing
wscript.echo sResponse
2. Verify WebDAV is Enabled:
WebDAV Enabled? WebDAV can be disabled by the user, so you may want to check it if its not working.
Under IIS on a Windows 2003, be sure that WebDAV is enabled, otherwise you will not be able to use
WebDAV on that box.
Windows 2000:
241520 How to disable WebDAV for IIS 5.0
http://support.microsoft.com/?id=241520
3. Do a PROPFIND
PROPFIND with “” - Do a PROPFIND with “” for the XML. If you do a PROPFIND against an item and pass
an empty string (“”) or use a PROPALL command, you will get back all of the registered properties (pretty
much everything) for that item in XML. This can be useful to verify that the basic PROPFIND is working
properly on that system. Use this to tell if it’s the XML being used with the PROPFIND or the actual use of
the PROPFIND which is causing the problem.
4. Try it in OWA.
If you think the problem you are having is related to permissions you should try to see if OWA has the same
problem. If it fails in a manner similar to the code, then its probably not the code having the problem.
G. Common Errors:
When you get an error from a WebDAV call, you should always know the exact number and text of the error.
There are variations on each error message and this information can help pinpoint the problem.
WebDAV 101. Last Revised 6/28/06. Version 1.6
22
EXCHANGE WebDAV 101
1. 400 – Bad Request
a. This is usually caused by one of the following:
1) Bad XML syntax - Be sure that the syntax is correct. Its usually this problem. Problems formatting
dates are common.
2) Schema changes - Try accessing a different folders and different items
3) ISAPI filters - Try turning them off and test.
4) I would think folder permissions would give a permission denied, but its best to check them.
5) If you are using SSL, you will need to configure it properly.
290625 How To Configure SSL in a Windows 2000 IIS 5.0 Test Environment by Using
http://support.microsoft.com/?id=290625
6) Having more than 256 connections open can cause a 400 error:
PRB: Unable to Make More Than 256 Connections to Different Mailboxes Over a Short Period of
Time
http://support.microsoft.com/default.aspx?scid=kb;en-us;305619
7) If you have colons or other special characters in the path:
http://support.microsoft.com/?id=826437
Note You may also receive this error message if the URL contains the following characters: * % & #
b. Things to try:
1) Verify that the path is correct.
2) Try a simpler call like just read the HREF from an item only and see if you get the same error. This
will point in a direction.
3) Verify that you can reach the folder via OWA.
4) Be sure that WEBDAV is turned on under the IIS server as well as data connectors.
5) Try using Basic Authentication.
6) Find out the exact error message returning
7) If the error message is like: 400 - Bad Request (Request Header Too Long),
This would be caused by a user belonging to so many groups it bloats header.
c.
Also, refer to the following:
HOW TO: Limit the Header Size of the HTTP Transmission That IIS Accepts from a Client in Windows
2000"
<http://support.microsoft.com/?id=310156>
Kerberos authentication may not work if user is a member of many groups
<http://support.microsoft.com/default.aspx?kbid=280830
Unable to Negotiate Kerberos Authentication After Upgrading to Internet Explorer 6
<http://support.microsoft.com/default.aspx?kbid=299838
Internet Explorer Logon Fails Due to an Insufficient Buffer for Kerberos
http://support.microsoft.com/default.aspx?kbid=277741
2. 401 – unauthorized
Some of the biggest things to look for with unauthorized errors are as follows:
a. The protocol which is being used by the application needs to be enabled under the IIS virtual folder
being accessed.
b. Anonymous should NOT be enabled - if this is turned on, credentials will NOT be passed.
c. If the wrong URL is used, then the code may be pointing to something which it does not have
permission.
d. The DC must have the protocol enabled. For instance, if Kerberos is to be used, then it must be enabled
and functional.
e. Protocols use different ports. If a firewall or other application filters network traffic to these ports, then
the protocol will not work. Firewalls, routers and filtering software have been known to cause problems
in this area.
WebDAV 101. Last Revised 6/28/06. Version 1.6
23
EXCHANGE WebDAV 101
f.
The credentials must be correct. If your using Kerberos, the code must be using a user account with a
valid mail box on that server. If credentials are specified (for instance with Basic authentication), then
they need to be able to resolve to that user's mailbox.
g. If another user's mailbox is accessed, then the account used to run the code must have permissions to
that mailbox. If you get an error accessing another user's mailbox, then try having the code access the
mailbox that the code is running under and verify that it can do so. If it can, then add permission to the
other user's mailbox so that the account used to run the code has appropriate permission.
3. 403 – Forbidden
This means you do not have permission to the item. Check permissions being passed. Perhaps SSL is
required and you don’t have a certificate. Not having permission to the mailbox or store may be another
cause.
4. 404 - Resource Not Found
The properties or item specified are not found. If an item specified in the XML request does not exist, you
will likely get this error.
You can suppress this by adding an “Brief” set to “t” in a header to the request.
HttpWRequest.Headers.Set("Brief", "t")
5. 409 - Conflict
The URL is messed-up and/or not formatted correctly for the verb.
a. If foreign characters or special characters are in the URL, the URL may need to be URL encoded in
order to work properly.
If you have colons or other special characters in the path:
http://support.microsoft.com/?id=826437
b. The 409 errors may be coming from the parent level directories not existing.
So, if the following folder does not exist…
http://myserver/Public/Public%20Folders/All%20Public%20Folders/Corporate/
…when creating “MyFolder” to have a folder of…
http://myserver/Public/Public%20Folders/All%20Public%20Folders/Corporate/MyFolder
…you will get a 409 error. Note that a 405 error would indicate that the folder was already created (405
basically means not allowed – check the response for details).
c.
If the URL is not correct for the verb being used, it may fail with this error. An example of this would be
doing a PUT to the URL of the folder - without specifying a file.
d. For troubleshooting, I’d suggest doing a GET on the URL. (Be sure to use a header of “translate” set to
“f”. If this fails, verify that the message exists by using OWA. If OWA works with that message URL,
then try URL encoding the URL when doing the GET. You should also consider using Exchange
Explorer for testing the URL.
WebDAV 101. Last Revised 6/28/06. Version 1.6
24
EXCHANGE WebDAV 101
VI. Questions and Answers
A. Mailbox Access
Question:
How to use WebDAV to access mailboxes across Exchange servers?
Answer:
If there is a front-end server setup, you can access by opening a connection using HTTP or HTTPS and to
WebDAV they would seem seamless - i.e. one server. This is what I have seen used almost all of the time.
Using Microsoft Exchange 2000 Front-End Servers
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=AFAD8426-572E-40F8-99DA-EB7198F374C4
You may also be able to access a server using <\\.\BackOfficeStorage>. This path only is good for the
Exchange server where the code must be running from. The <\\.\BackOfficeStorage> path is not normally
used with WebDAV and it is what the M: drive is mapped to on Exchange 2000. The M: drive is not mapped
to this with Exchange 2003. Accessing files directly with file system access through the M: drive or
<\\.\BackOfficeStorage> is not supported. I see this method used for access using CDOEX/ADO most of
the time and almost never for WebDAV.
XADM: How to Use \\.\ Namespace to Gain Access to the Information Store
http://support.microsoft.com/?id=239743
The File: URL Scheme
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_the_file_url_scheme.asp?frame=true
Accessing two mailboxes on two different servers with WebDAV should use the same path that you would
enter into OWA for accessing them from the web using IE. What you would use for an HTTP/HTTPS path is
a matter of Exchange and domain configuration.
Getting the Host Domain Name
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_getting_the_host_domain_name.asp?frame=true
The HTTP: URL Scheme
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_the_http_url_scheme.asp?frame=true
B. WebDAV Across Stores
Question:
Why can't I COPY or MOVE items across stores - i.e. mailboxes, public folders, servers?
Answer:
COPY and MOVE will fail with a 502 error when trying to work across stores - not supported. You could
read the MIME of messages with a GET and use PUT to write the contents to the new location - this will
simulate a COPY. Custom properties and storage properties will likely not get copied. You can try using a
PROPFIND and PROPPATCH to copy over the custom properties.
C. Administrative Mailbox Access
Question:
Can we create an administrative account that has access to mailboxes on both Sites?
Are these in one or two domains?
Answer:
Please review the article below…
XADM: How to Get Service Account Access to All Mailboxes in Exchange 2000
WebDAV 101. Last Revised 6/28/06. Version 1.6
25
EXCHANGE WebDAV 101
http://support.microsoft.com/default.aspx?scid=kb;en-us;262054
D. Set Public Folder Limits
Question:
I'm unable to set properties such as folder limits on public folders. How do I do this?
Answer:
You will need to set certain properties such as folder limits using a URL containing the Administrative Virtual
Root. Note that the exadmin virtual directory in the Exchange servers IIS Server will need to have the
appropriate Directory Security settings for the type of access you are doing (Basic, Windows, NTLM, etc).
Using the Administrative Virtual Root
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_exch2k_the_administrative_vroot.asp
How To Set Public Folder Storage Limit Properties
http://support.microsoft.com/default.aspx?scid=kb;en-us;294671
E. Delays in WebDAV Calls
Question:
I'm getting a delay when doing a WebDAV call against a server through a firewall.
Answer:
If both Basic and Windows authentication is turned-on for the Exchange virtual directory on the Exchange
server, and WebDAV code tries to access the Exchange box through a firewall having port 88 blocked, you
will get a long delay.
The reason for the delay is that a Basic call will first attempt Anonymous communication first. When it fails,
it uses the response it got back from the server to determine the next attempt. A failed Anonymous check
will respond with the protocols supported by the virtual directory. Since the virtual directory supports
Windows authentication, the client WebDAV call will try to do authentication against the DC it was told about
with the response of the Anonymous check... this is the delay... After the delay, Basic Authentication is then
performed - which will work... The credentials are then cached for a short period - which is why additional
WebDAV calls done right after the first one will authenticate quickly.
If this is the scenario, the following are the options available:
1) Open port 88
2) Have ONLY Basic turned on for the Exchange virtual directory.
3) Create a secondary virtual directory which has the same settings as the Exchange virtual directory;
however you will need to be sure that the only difference is that Basic ONLY is enabled on this new virtual
directory. One idea is to call this new virtual directory “ExchangeBasic” or perhaps “Exchange2”.
F. SSL with WebDAV
Question:
How do I use SSL with WebDAV?
Answer:
SSL can be used with WebDAV for added security. Below is an article on setting-up SSL:
Q290625 HOWTO: IIS5: How to Configure SSL in a Windows 2000 IIS 5
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q290625
G. Increasing performance
Question:
WebDAV 101. Last Revised 6/28/06. Version 1.6
26
EXCHANGE WebDAV 101
How can I Increase Performance?
Answer:
There are many different things which can impact performance. Here are a few of them.
1) When working with lots of data, first search to get the HREFS of the items, then use the HREFS to work
with the individual items. The batch processing verbs (BPROPFIND, BPROPPATCH, etc) work well
with these. -this will usually give much better performance.
2
When at all possible, use of batch methods: BPROPFIND, BPROPATCH, etc.
3) Don't “SELECT * ” when doing searches. This is costly performance wise. Only retrieve back what you
need.
4) Sniff OWA to see how it does its searches and the types of WebDAV calls it does.
5) Avoid searching non-indexed fields.
6) Indexed fields have urn:schemas-microsoft-com:exch-data:isindexed set to true.
7) Authentication communication:
a) Firewall, exchange virtual directory and authentication method being used need to be lined-up for
optimal performance.
b) Have the virtual directory used in the DAV call support only the protocol you are using.
If the virtual directory has both windows and basic authentication turn on and port 88 is blocked, you will
run into a delay.
c) If you use the XML DOM, you should use the XMLServer HTTP and not INet (client) if the DAV code is
running from a server. SSL has a slight slowing effect.
d) Asynchronous vs Synchronous communication: Asynchronous will have higher performance and will
help avoid lockups when the DAV processing is taking a long time. Synchronous is easier to write and
debug.
e) Network issues can slow calls.
8) In terms of speed in doing the calls, you should get the best performance with .NET, followed by the
XML DOM and then SAX
9) .NET has additional Credential Caching capabilities and has additional authentication settings - see the
PreAuthenticate property of the web request for more information.
10) You may want to consider using full text index searches. Below is an article covering this.
XWEB: How to Perform Full-Text Searching Using WebDAV
http://support.microsoft.com/?kbid=259849
H. NTLM Double-hop
Question:
How to use WebDAV to access mailboxes using NTLM in a double-hop?
Answer:
You will need to do something else, such as:
1) Use Kerberos
2) Use Basic Authentication
3) Run the IIS site under an account with credentials to the mailbox.
I.
WebDAV Transactions
Question:
Does WebDAV handle Transactions?
Answer:
Yes it does. Information on this is in the Exchange SDK.
WebDAV Transactions
http://msdn.microsoft.com/library/en-us/wss/wss/_esdk_arch_webdav_transactions.asp?frame=true
Transaction Header
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_transaction_header.asp?frame=true
WebDAV 101. Last Revised 6/28/06. Version 1.6
27
EXCHANGE WebDAV 101
LOCK Method
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_lock.asp?frame=true
J. Set Folder Permissions
Question:
Can WebDAV be used to see and/or set permissions on folders?
Answer:
Yes.
The articles below cover this subject. A PROPFIND will get you an XML doc with the security identifier in
XML. A PROPPATCH can set it.
Item Access Rights
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_item_access_rights.asp?frame=true
How to add an access control entry to a folder item in Exchange 2000 Web Storage System by coding in
Exchange 2000 Server
http://support.microsoft.com/?id=317891
How to work with items in Exchange 2000 by using WebDAV in Visual Basic .NET
http://support.microsoft.com/?id=314181
How To Deny a User Read Permissions on a Mail Item
http://support.microsoft.com/kb/289879
Web Storage System Security Roles
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmes2k/html/secroles1.asp
K. Accessing OWA Options
Question:
You are wanting to get Start Of Day and End Of Day fields which show as under Options in OWA. How can
WebDAV be used to extract this information?
Answer:
This information is stored under the root folder of the mailbox. A PROPFIND against the root folder will reveal
this information. As an example, a PROPFIND against http://myexchangeserver/exchange/Administrator for the
two properties would give the needed information.
workdaystarttime Field
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_cdo_schema_exchange_workdaystarttime.asp
workdayendtime Field
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_cdo_schema_exchange_workdayendtime.asp
NOTE: A WebDAV PROPFIND with a blank string (“”) against the mailbox folder will show you many of the
fields from the OWA Options window.
NOTE: Not all the options settings in OWA are reachable via WebDAV. OWA uses a POST with a special
command which changes these with code which runs on the server.
WebDAV 101. Last Revised 6/28/06. Version 1.6
28
EXCHANGE WebDAV 101
VII. Samples
Here are some basic samples:
A. VBS - SEARCH
dim strExchangeURL
dim strApptStartDate
dim strUser
dim strPassword
strUser = "Administrator"
strPassword = "test"
strExchangeURL = "http://myexserver/exchange/Administrator/Calendar/"
strApptStartDate = "2004-04-09T15:00:00Z"
Dim sRet
strQuery = "<?xml version='1.0'?>" & _
"<g:searchrequest xmlns:g='DAV:' >" & _
"<g:sql>SELECT " & vbCrLf & _
"""urn:schemas:calendar:alldayevent"", " & vbCrLf & _
"""urn:schemas:calendar:duration"", " & vbCrLf & _
"""urn:schemas:calendar:dtstart"", " & vbCrLf & _
"""urn:schemas:calendar:dtend"", " & vbCrLf & _
"""urn:schemas:httpmail:displayto"", " & vbCrLf & _
"""urn:schemas:httpmail:displaycc"", " & vbCrLf & _
"""urn:schemas:httpmail:textdescription"", " & vbCrLf & _
"""urn:schemas:calendar:location"", " & vbCrLf & _
"""urn:schemas:httpmail:subject"" " & vbCrLf & _
"FROM SCOPE('SHALLOW TRAVERSAL OF """ & strExchangeURL & """') " & vbCrLf & _
"WHERE (""urn:schemas:calendar:dtstart"" >= CAST(""" & strApptStartDate & """ as
'dateTime')) "
& vbCrLf & _
"</g:sql>" & vbCrLf & _
"</g:searchrequest>" & vbCrLf
Wscript.Echo "about to call ServerDav"
sRet = DoServerDavRequest("SEARCH", strQuery, strExchangeURL, strUser, strPassword)
Wscript.Echo sRet
Function DoServerDavRequest(sType, sQuery, sHREF, sUserName, sPassword)
' Create the SQL query textnode and append it to document.
Set docRequest = Createobject("MSXML2.DomDocument")
Set xndQuery = docRequest.createTextNode(strQuery)
' Create the XMLHTTP object.
Set davRequest = CreateObject("MSXML2.SERVERXMLHTTP")
davRequest.open sType, sHREF, False, "Administrator", "test"
davRequest.setRequestHeader "Content-Type", "text/xml"
davRequest.setRequestHeader "Translate", "f"
' Send the SEARCH request.
if sQuery = "" then
davRequest.send
else
davRequest.send (sQuery)
end if
WebDAV 101. Last Revised 6/28/06. Version 1.6
29
EXCHANGE WebDAV 101
DoServerDavRequest = davRequest.responsetext
End Function
SEARCH Using Range Headers
Public Function GetItemListXML(sHREF, sUserName, sPassword, sDepth)
Dim sQuery ' As String
Dim sText 'As String
sQuery = "<?xml version='1.0'?>" & _
"<g:searchrequest xmlns:g='DAV:'>" & _
"<g:sql>SELECT ""DAV:displayname"", " & _
"""DAV:href"" " & _
"FROM SCOPE('SHALLOW TRAVERSAL OF """ & sHREF & """')" & _
" WHERE ""DAV:isfolder"" = false AND ""DAV:ishidden"" = false" & _
"</g:sql>" & _
"</g:searchrequest>"
sText = DoDavRequest("SEARCH", sQuery, sHREF, sUserName, sPassword, sDepth)
GetItemListXML = sText
End Function
Public Function DoDavRequest(sType, sQuery, sHREF, sUserName, sPassword, sDepth)
Dim HttpWebRequest 'As MSXML2.XMLHTTP30
Set HttpWebRequest = CreateObject("microsoft.xmlhttp") ' = New MSXML2.XMLHTTP30
Dim sText 'As String
' Open the folder
HttpWebRequest.open sType, sHREF, False, sUserName, sPassword
' Set up request headers
HttpWebRequest.setRequestHeader "Content-Type", "text/xml"
HttpWebRequest.setRequestHeader "Depth", "0"
HttpWebRequest.setRequestHeader "Range", sDepth
'HttpWebRequest.setRequestHeader "Range", "rows=10-20,40-50" ' Example of multiple
ranges
' Send the query
HttpWebRequest.send (sQuery)
sText = HttpWebRequest.ResponseText
Set HttpWebRequest = Nothing
DoDavRequest = sText
End Function
Dim
Dim
Dim
Dim
sHREF
sUserName
sPassword
sRet
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
sHREF = "http://myexserver/exchange/administrator/inbox" ' TODO: change
sDepth = "rows=0-3"
sRet = GetItemListXML(sHREF, sUserName, sPassword, sDepth)
wscript.echo sRet
sDepth = "rows=4-7"
sRet = GetItemListXML(sHREF, sUserName, sPassword, sDepth)
wscript.echo sRet
WebDAV 101. Last Revised 6/28/06. Version 1.6
30
EXCHANGE WebDAV 101
B. VBS - PROPFIND
dim
dim
dim
dim
Dim
dim
sHREF
sUserName
sPassword
sResponse
HttpWebRequest
sReq ' Body Proppatch statement
sHREF = "https://myexserver/exchange/Administrator/Inbox/testabcd.EML" ' TODO: change
‘ If only the folder is specified, all items will have a PROPFIND done on them
‘sHREF = "http://myexserver/exchange/administrator/Inbox/" ' TODO: change
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
set HttpWebRequest = CreateObject("microsoft.xmlhttp")
'Set HttpWebRequest = New Msxml2.XMLHTTP30
HttpWebRequest.Open "PROPFIND", sHREF, False, sUserName, sPassword
HttpWebRequest.setRequestHeader "Content-Type", "text/xml"
'HttpWebRequest.setRequestHeader "Depth:","0"
HttpWebRequest.setRequestHeader "Depth:","1"
sReq
sReq
sReq
sReq
sReq
sReq
=
=
=
=
=
=
""
"<?xml
sReq &
sReq &
sReq &
sReq &
version='1.0'?>"
"<d:propertyupdate xmlns:d='DAV:' xmlns:m='urn:schemas:mailheader:'>"
"<d:set><d:prop>"
"<m:subject>" & "test1" & "</m:subject>"
"</d:prop></d:set></d:propertyupdate>"
sReq = "<?xml version='1.0'?>" & _
"<a:propfind xmlns:a='DAV:' xmlns:m='urn:schemas:mailheader:'
xmlns:n='urn:schemas:httpmail:'>" & _
"<a:prop>" & _
"<m:subject/>" & _
"<m:to/>" & _
"<m:from/>" & _
"<m:cc/>" & _
"<m:bcc/>" & _
"<n:date/>" & _
"<n:datereceived/>" & _
"<n:importance/>" & _
"<n:textdescription/>" & _
"<n:htmldescription/>" & _
"<a:isfolder/>" & _
"<a:displayname/>" & _
"<a:href/>" & _
"</a:prop>" & _
"</a:propfind>"
HttpWebRequest.Send sReq
sResponse = HttpWebRequest.ResponseText ' Returns as text
'ReadAnAttatchment = HttpWebRequest.responseBody ' Returns as encoded
wscript.echo sResponse
Set HttpWebRequest = Nothing
C. VBS - PROPPATCH
dim sHREF
dim sUserName
WebDAV 101. Last Revised 6/28/06. Version 1.6
31
EXCHANGE WebDAV 101
dim
dim
Dim
dim
sPassword
sResponse
HttpWebRequest
sReq ' Body Proppatch statement
sHREF = "https://myexserver/exchange/Administrator/Inbox/testabcd.EML"
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
' TODO: change
set HttpWebRequest = CreateObject("microsoft.xmlhttp")
'Set HttpWebRequest = New Msxml2.XMLHTTP30
HttpWebRequest.Open "PROPPATCH", sHREF, False, sUserName, sPassword
HttpWebRequest.setRequestHeader "Content-Type", "text/xml"
HttpWebRequest.setRequestHeader "Depth:","0"
sReq
sReq
sReq
sReq
sReq
=
=
=
=
=
"<?xml
sReq &
sReq &
sReq &
sReq &
version='1.0'?>"
"<d:propertyupdate xmlns:d='DAV:' xmlns:m='urn:schemas:mailheader:'>"
"<d:set><d:prop>"
"<m:subject>" & "test1" & "</m:subject>"
"</d:prop></d:set></d:propertyupdate>"
wscript.echo sReq
HttpWebRequest.Send sReq
sResponse = HttpWebRequest.ResponseText ' Returns as text
'ReadAnAttatchment = HttpWebRequest.responseBody ' Returns as encoded
Set HttpWebRequest = Nothing
D. VBS - DELETE
dim
dim
dim
dim
Dim
sHREF
sUserName
sPassword
sResponse
HttpWebRequest
sHREF = "http://myexserver/exchange/Administrator/Inbox/testabcd.EML"
sUserName = "Administrator"
sPassword = "test"
set HttpWebRequest = CreateObject("microsoft.xmlhttp")
HttpWebRequest.Open "DELETE", sHREF, False, sUserName , sPassword
HttpWebRequest.Send
sResponse
= HttpWebRequest.ResponseText
' Returns as text
Set HttpWebRequest = Nothing
wscript.echo sResponse
E. VBS - GET
dim sHREF
dim sUserName
dim sPassword
dim sResponse
Dim HttpWebRequest
sHREF = "http://myexserver/exchange/Administrator/Inbox/testabcd.EML"
change
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
WebDAV 101. Last Revised 6/28/06. Version 1.6
' TODO:
32
EXCHANGE WebDAV 101
set HttpWebRequest = CreateObject("microsoft.xmlhttp")
HttpWebRequest.Open "GET", sHREF, False, sUserName, sPassword
HttpWebRequest.setRequestHeader "Content-type:", "text/xml"
HttpWebRequest.setRequestHeader "Translate:", "f"
HttpWebRequest.Send
sResponse
= HttpWebRequest.ResponseText
' Returns as text
Set HttpWebRequest = Nothing
wscript.echo sResponse
F. VBS - PUT
' This example shows how to do a PUT of a message to a folder.
' Use Outlook Express to create a message and save it as c:\MyTestEmail.eml
' Do the TODO Sections
'----------------------------------------------------------------------------------' ReadFileText - Used to PUT (write) an item to a file in a folder.
' Parameters:
'
sFile - The file to read
'
' Returns:
'
A string containing the content of the file.
'----------------------------------------------------------------------------------Function ReadFileText (sFile)
Dim objFSO 'As FileSystemObject
dim oTS
dim sText
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oTS = objFSO.OpenTextFile(sFile)
sText = oTS.ReadAll
oTS.close
set oTS = nothing
Set objFSO = nothing
ReadFileText = sText
end Function
'----------------------------------------------------------------------------------' DoWebdavPut- Used to PUT (write) an item to a file in a folder.' Parameters:
' sFolder
- The complete URI to PUT the item (includes item name).
' sText
- The contents to write in the file.
' sUser
- User ID for logging in. Set to "" if using windows authentication
' sPassword
- Password for logging in. Set to "" if using windows authentication
' Returns:
'
Status response text
'-------------------------------------------------------------------------------Private Function DoWebdavPut(sFolder, sText, sUser, sPassword)
Dim oXMLHttp 'As New MSXML2.XMLHTTP30
Dim bSucess 'As Boolean
Dim iStatus 'As Integer
Dim sStatus 'As String
Dim sResponse 'As String
set oXMLHttp = CreateObject("microsoft.xmlhttp")
If sUser <> "" Then
oXMLHttp.Open "PUT", sFolder, False, sUser, sPassword
WebDAV 101. Last Revised 6/28/06. Version 1.6
33
EXCHANGE WebDAV 101
Else
oXMLHttp.Open "PUT", sFolder, False ', sUser, sPassword
End If
oXMLHttp.setRequestHeader "translate", "f" ' Set this to prevent stream problems
oXMLHttp.Send sText ' Send the stream across
bSucess = False
iStatus = oXMLHttp.Status
sStatus = oXMLHttp.statusText
If (iStatus >= 200 And iStatus < 300) Then
wscript.echo "PUT: Success!
" & "Results = " & iStatus & ": " & sStatus
bSucess = True
ElseIf iStatus = 401 Then
wscript.echo "PUT: You don't have permission to do the job! Please check your
permissions on this item."
Else
wscript.echo "PUT: Request Failed. Results = " & iStatus & ": " & sStatus
End If
Set oXMLHttp = Nothing
DoWebdavPut = sStatus
End Function
Dim
Dim
Dim
Dim
Dim
sHREF
'As String
sUserName
'As String
sPassword
'As String
sFile 'As String
sRet 'As String
sHREF = "http://myexserver/exchange/Administrator/Inbox/testabcdxx.EML"
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
sFile = "c:\MyTestEmail.eml" ' TODO: change
sRet = ""
' TODO: change
sString = ReadFileText(sFile)
sRet = DoWebdavPut(sHREF, sString, sUserName, sPassword)
wscript.echo sRet
G. VBS - MOVE
Some things to note:
 Copying or Moving items across stores is not supported
 You will get a 404 (Resource Not Found) if the source item does not exist.
 A status204 (No Content) will be returned if the destination item already exists
 To force an overwrite of an existing item, add a header of “Overwrite” set to “T”.
 Be careful specifying the destination – Example: Using a message as the source and a folder as a
destination may mess-up the folder.
'--------------------------------------------------------------------------------' DoCopyMove - Used to move an item from one folder to another in the same store.
' sSourceURL
- item being moved/copied
' sDestinationURL - the URL it is going to
' bCopy
- TRUE if copying or FALSE if moving
' sUser
- User ID for logging in. Set to "" if using windows authentication
' sPassword
- Password for logging in. Set to "" if using windows authentication
' NOTE:
'
Copying or Moving items across stores is not supported
'
You will get a 404 (Resource Not Found) if the source item does not exist.
'
A status204 (No Content) will be returned if the destination item already exists
'--------------------------------------------------------------------------------
WebDAV 101. Last Revised 6/28/06. Version 1.6
34
EXCHANGE WebDAV 101
Function DoCopyMove(sSourceURL, sDestinationURL, bCopy, sUser, sPassword )
Set oXMLHttp = CreateObject("microsoft.xmlhttp") ' = New MSXML2.XMLHTTP30
Dim sVerb
If bCopy = True Then
sVerb = "COPY"
Else
sVerb = "MOVE"
End If
If sUser <> "" Then
oXMLHttp.Open sVerb, sSourceURL, False, sUser, sPassword
Else
oXMLHttp.Open sVerb, sSourceURL, False ', sUser, sPassword
End If
oXMLHttp.setRequestHeader "Destination", sDestinationURL
' Send the stream across
oXMLHttp.Send
If (oXMLHttp.Status >= 200 And oXMLHttp.Status < 300) Then
wscript.echo "Success!
" & "Results = " & oXMLHttp.Status & ": " &
oXMLHttp.statusText
ElseIf oXMLHttp.Status = 401 Then
wscript.echo "You don't have permission to do the job! Please check your
permissions on this item."
Else
wscript.echo "Request Failed. Results = " & oXMLHttp.Status & ": " &
oXMLHttp.statusText
End If
DoCopyMove = oXMLHttp.statusText
Set oXMLHttp = Nothing
End Function
Dim
Dim
Dim
Dim
Dim
sSourceURL
sDestinationURL
sUserName
sPassword
sRet
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
sSourceURL= "http://myexserver/exchange/Administrator/Inbox/testabcd.EML" ' TODO: change
sDestinationURL = "http://myexserver/exchange/Administrator/Inbox/test/testabcd.EML" '
TODO: change
sRet = DoCopyMove(sSourceURL, sDestinationURL, False, sUserName, sPassword)
wscript.echo sRet
H. VBS - COPY
Some things to note:
 Copying or Moving items across stores is not supported
 You will get a 404 (Resource Not Found) if the source item does not exist.
 A status204 (No Content) will be returned if the destination item already exists
 To force an overwrite of an existing item, add a header of “Overwrite” set to “T”.
 Be careful specifying the destination – Example: Using a message as the source and a folder as a
destination may mess-up the folder.
'--------------------------------------------------------------------------------' DoCopyMove - Used to move an item from one folder to another in the same store.
WebDAV 101. Last Revised 6/28/06. Version 1.6
35
EXCHANGE WebDAV 101
' sSourceURL
- item being moved/copied
' sDestinationURL - the URL it is going to
' bCopy
- TRUE if copying or FALSE if moving
' sUser
- User ID for logging in. Set to "" if using windows authentication
' sPassword
- Password for logging in. Set to "" if using windows authentication
'--------------------------------------------------------------------------------Function DoCopyMove(sSourceURL, sDestinationURL, bCopy, sUser, sPassword )
Set oXMLHttp = CreateObject("microsoft.xmlhttp") ' = New MSXML2.XMLHTTP30
Dim sVerb
If bCopy = True Then
sVerb = "COPY"
Else
sVerb = "MOVE"
End If
If sUser <> "" Then
oXMLHttp.Open sVerb, sSourceURL, False, sUser,
Else
oXMLHttp.Open sVerb, sSourceURL, False ', sUser, sPassword
End If
oXMLHttp.setRequestHeader "Destination", sDestinationURL
' Send the stream across
oXMLHttp.Send
If (oXMLHttp.Status >= 200 And oXMLHttp.Status < 300) Then
wscript.echo "Success!
" & "Results = " & oXMLHttp.Status & ": " &
oXMLHttp.statusText
ElseIf oXMLHttp.Status = 401 Then
wscript.echo "You don't have permission to do the job! Please check your
permissions on this item."
Else
wscript.echo "Request Failed. Results = " & oXMLHttp.Status & ": " &
oXMLHttp.statusText
End If
DoCopyMove = oXMLHttp.statusText
Set oXMLHttp = Nothing
End Function
Dim
Dim
Dim
Dim
Dim
sSourceURL
sDestinationURL
sUserName
sPassword
sRet
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
sSourceURL= "http://myexserver/exchange/Administrator/Inbox/testabcd.EML" ' TODO: change
sDestinationURL = "http://myexserver/exchange/Administrator/Inbox/test/testabcd.EML" '
TODO: change
sRet = DoCopyMove(sSourceURL, sDestinationURL, True, sUserName, sPassword)
wscript.echo sRet
I.
VBS - X-MS-ENUMATTS
For listing and reading an attachment, you will first need to get a list of attachments using X-MS_ENUMATTS.
After getting the list of attachments you will need to parse out then the URL from the returned information, you
can then do a GET to read the attachments.
WebDAV 101. Last Revised 6/28/06. Version 1.6
36
EXCHANGE WebDAV 101
First get a list of attachments…
Function GetAttachmentsListXML(ByVal sHREF As String, ByVal sUserName As String,
ByVal sPassword As String) As String
Dim HttpWebRequest As MSXML2.XMLHTTP30
Dim strPropReq As String
Dim strOutPutFile As String
Set HttpWebRequest = New MSXML2.XMLHTTP30
With HttpWebRequest
.Open "X-MS-ENUMATTS", sHREF, False, sUserName, sPassword
.setRequestHeader "Content-type:", "text/xml"
.setRequestHeader "Depth", "1,noroot"
.Send
GetAttachmentsListXML = HttpWebRequest.ResponseText
End With
Set HttpWebRequest = Nothing
End Function
Now read the attachment…
Private Function ReadAnAttatchment(ByVal sHREF As String, ByVal sUserName As String, ByVal sPassword As
String) As Variant
Dim HttpWebRequest As MSXML2.XMLHTTP30
Dim vReturn As Variant
Set HttpWebRequest = New MSXML2.XMLHTTP30
HttpWebRequest.Open "GET", sHREF, False, sUserName, sPassword
HttpWebRequest.Send
ReadAnAttatchment = HttpWebRequest.ResponseText ' Returns as text
'ReadAnAttatchment = HttpWebRequest.responseBody ' Returns as encoded
Set HttpWebRequest = Nothing
End Function
J. VB.NET PROPFIND
‘
‘
‘
‘
‘
VB.NET PROPFIND
TODO: Create a VB.NET winform with a button and a big multiline text box
TODO: Add reverences to System.Web, System.XML and System.IO
TODO: Add the code to the form.
TODO: Do the TODO sections in the code.
Imports System.Net
Imports System.Web
Imports System.IO
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
'Dim sUri As String = "http://myexserver/exchange/User1/Inbox/"
'Dim sUserName As String = "Administrator"
'Dim sPassword As String = "test"
Dim sUserName As String = ""
Dim sPassword As String = ""
Dim strBody As String
WebDAV 101. Last Revised 6/28/06. Version 1.6
37
EXCHANGE WebDAV 101
strBody = "<?xml version='1.0'?>" & _
"<a:propfind xmlns:a='DAV:' " & _
" xmlns:m='urn:schemas:mailheader:' " & _
" xmlns:n='urn:schemas:httpmail:'>" & _
"<a:prop>" & _
" <m:subject/>" & _
" <a:isfolder/>" & _
" <a:displayname/>" & _
" <a:href/>" & _
"</a:prop>" & _
"</a:propfind>"
Dim myUri As System.Uri = New System.Uri(sUri)
Dim HttpWRequest As HttpWebRequest = WebRequest.Create(myUri)
'----------------- Set Credentials -------------------------------------Dim myCred As NetworkCredential
Dim MyCredentialCache As CredentialCache
If sUserName <> "" Then
' Use Basic Authentication
myCred = New NetworkCredential(sUserName, sPassword)
MyCredentialCache = New CredentialCache
MyCredentialCache.Add(myUri, "Basic", myCred)
HttpWRequest.Credentials = MyCredentialCache
HttpWRequest.UnsafeAuthenticatedConnectionSharing = True
Else
' Use Windows Authentication
HttpWRequest.Credentials = CredentialCache.DefaultCredentials
'May need this so you dont get an error on HttpWRequest.GetRequestStream()
‘or double-hop
'HttpWRequest.UnsafeAuthenticatedConnectionSharing = True
End If
' Set Headers
HttpWRequest.KeepAlive = False
HttpWRequest.Headers.Set("Pragma", "no-cache")
HttpWRequest.Headers.Set("Translate", "f")
HttpWRequest.ContentType = "text/xml"
HttpWRequest.ContentLength = strBody.Length
'set the request timeout to 5 min.
HttpWRequest.Timeout = 300000
' set the request method
HttpWRequest.Method = "PROPFIND"
' we need to store the data into a byte array
Dim ByteQuery() As Byte = System.Text.Encoding.ASCII.GetBytes(strBody)
HttpWRequest.ContentLength = ByteQuery.Length
Dim QueryStream As Stream = HttpWRequest.GetRequestStream()
' write the data to be posted to the Request Stream
QueryStream.Write(ByteQuery, 0, ByteQuery.Length)
QueryStream.Close()
' Send Request and Get Response
Dim HttpWResponse As HttpWebResponse = HttpWRequest.GetResponse()
' Get Status and Headers
Dim iStatCode As Integer = HttpWResponse.StatusCode
Dim sStatus As String = iStatCode.ToString()
WebDAV 101. Last Revised 6/28/06. Version 1.6
38
EXCHANGE WebDAV 101
'Console.WriteLine("Status: {0} {1}", sStatus,
HttpWResponse.StatusDescription.ToString())
'Console.WriteLine("Request Headers:")
'Console.WriteLine(HttpWRequest.Headers.ToString())
'Console.WriteLine("Response Headers:")
'Console.WriteLine(HttpWResponse.Headers.ToString())
' Get Response Stream
Dim strm As Stream = HttpWResponse.GetResponseStream()
' Read the Response Steam
Dim sr As StreamReader = New StreamReader(strm)
Dim sText As String = sr.ReadToEnd()
'Console.WriteLine("Response: {0}", sText)
' Close Stream
strm.Close()
' Clean Up
HttpWRequest = Nothing
HttpWResponse = Nothing
MyCredentialCache = Nothing
myCred = Nothing
strm = Nothing
sr = Nothing
TextBox1.Text = sText
End Sub
K. C# Winform - SEARCH
// C# Example to SEARCH a mailbox.
// TODO:
//
Add a button and double click on it
//
Add a multi-line text box and make it big.
//
Add a project reference to System.Xml, an System.Net
//
Paste-in the code below
//
Do the TODO sections in the code.
using System.Xml;
using System.Net;
using System.IO;
private void button1_Click(object sender, System.EventArgs e)
{
string sUri = "http://myemailserver/exchange/auser/inbox/test";
string sUserName = ""; // TODO: Set only for Basic Authentication
string sPassword
= ""; // TODO: Set only if Basic
string sResponse
= "";
sResponse = GetMessageListXML(sUri, sUserName, sPassword);
textBox1.Text = sResponse;
}
private string GetMessageListXML(string sUri, string sUserName, string sPassword)
{
System.Uri myUri
= new System.Uri(sUri);
WebDAV 101. Last Revised 6/28/06. Version 1.6
39
EXCHANGE WebDAV 101
HttpWebRequest HttpWRequest = (HttpWebRequest)WebRequest.Create(myUri);
string sQuery;
sQuery = "<?xml version='1.0'?>" +
"<g:searchrequest xmlns:g='DAV:'>" +
"<g:sql>SELECT \"DAV:displayname\" " +
"FROM SCOPE('SHALLOW TRAVERSAL OF \"" + sUri + "\"') " +
"WHERE \"DAV:isfolder\" = false" +
"</g:sql>" +
"</g:searchrequest>";
NetworkCredential myCred;
CredentialCache myCredentialCache;
myCred = new NetworkCredential(sUserName, sPassword);
myCredentialCache = new CredentialCache();
if (sUserName.Length != 0)
{
myCredentialCache.Add(myUri, "Basic", myCred);
HttpWRequest.Credentials = myCredentialCache;
}
else
{
HttpWRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Next line is for double-hop. This is a winform, so we don’t need it.
//HttpWRequest.UnsafeAuthenticatedConnectionSharing = true;
}
// Set some headers
HttpWRequest.KeepAlive = false;
HttpWRequest.Headers.Set("Pragma", "no-cache");
HttpWRequest.Headers.Set("Translate", "f");
HttpWRequest.Headers.Set("Depth", "0");
HttpWRequest.ContentType = "text/xml";
HttpWRequest.ContentLength = sQuery.Length;
// set the request timeout to 5 min.
HttpWRequest.Timeout = 300000;
//set the request method
HttpWRequest.Method = "SEARCH";
// we need to store the data into a byte array
Byte[] ByteQuery = System.Text.Encoding.ASCII.GetBytes(sQuery);
//HttpWRequest.ContentLength = ByteQuery.Length;
HttpWRequest.ContentLength = ByteQuery.Length;
Stream QueryStream = HttpWRequest.GetRequestStream();
// write the data to be posted to the Request Stream
QueryStream.Write(ByteQuery, 0, ByteQuery.Length);
QueryStream.Close();
//Send Request and Get Response
HttpWebResponse HttpWResponse = (HttpWebResponse)HttpWRequest.GetResponse();
// Get Response Stream
Stream strm = HttpWResponse.GetResponseStream();
//Read the Response Steam;
StreamReader sr = new StreamReader(strm);
WebDAV 101. Last Revised 6/28/06. Version 1.6
40
EXCHANGE WebDAV 101
String sText
= sr.ReadToEnd();
//Close Stream
strm.Close();
// Clean Up
HttpWRequest = null;
HttpWResponse = null;
myCredentialCache = null;
myCred = null;
QueryStream = null;
strm = null;
sr = null;
return sText;
}
L. C# Webform – SEARCH – Double-Hop
Windows authentication credentials are not forwarded between a web server and Exchange server. This is by
design and is referred to as the double-hop credential problem. However, there is a way to get the credentials
forwarded.
In order for Kerberos credential to flow between an IE client, a web server and the Exchange server, several
settings are needed:









The network must use Kerberos.
The code must be running on a web server which is in the same domain as both the IE client machine
and the Exchange server.
IE client must have the setting for use Windows Authentication checked. This is set under in IE under
Tools/Internet Options/Advanced Tab/Security by checking the “Enable Integrated Windows
Authentication” box.
The web server running the code must be trusted for authentication delegation by the Exchange
server’s DC. This is done through AD. NOTE: There is no getting around doing this – it’s a
requirement.
o Add the IIS server as a trusted server.
o Be sure to check the box to trust the IIS server for delegation.
Both the Exchange server and web server running the code will need to have Windows Authentication
enabled.
Anonymous is turned off on to the Exchange server and web server.
The virtual directory used must have Windows Authentication enabled
If Visual Studio 2002 was used to build the code, Framework 1.0 would be used. Visual Studio 2003
uses Framework 1.1 by default. If framework 1.1 is not being used/installed on all three machines, the
following will apply…
You will need to have the current .net service packs installed on your IIS and development box so you
can access the “UnsafeAuthenticatedConnectionSharing” property of the HttpWebRequest object (this
is new for Framework 1.1). The Framework 1.0 can be updated using hot fix for q323683 if SP2 has not
been installed. If SP2 for Framework 1.0 has been installed, you can install q328541 to get the
property. Windows 2003 will have Framework 1.1 installed on it already.
There must be nothing which will block traffic between the machines. Port 80 and 88 will be used at a
minimal. Routers, firewalls and similar hardware/software can block needed traffic – so be aware of any
which may sit or run on the machines involved.
Note that if you have problems:
 Verify that the requirements (above) have been covered.

Do a simple test by trying to access OWA from the user’s machine; if they cannot access it using IE
then the IE settings probably need to be changed.
WebDAV 101. Last Revised 6/28/06. Version 1.6
41
EXCHANGE WebDAV 101

Try using Basic Authentication from the Web Server while logged-in as a domain user with a mailbox on
the Exchange Server. Try accessing that user’s mailbox.

Try using Basic Authentication from the Web Server while logged-in as a domain user with a mailbox on
the Exchange Server. Try accessing that user’s mailbox.

Try to repro using OWA from the IE client and web server.
If OWA works and WEBDAV does not:
Recheck your Exchange IIS and trust settings.
Recheck the code.
If OWA does not work, then the problem is probably not with the code:\
Try getting OWA to work first.

Use Netmon on the machine running the code and look for errors and correct communication.
As far as code differences between Winform and Webform calls, there are two significant differences:
First, the following setting must be made in addition to using default credentials:
HttpWRequest.UnsafeAuthenticatedConnectionSharing = true;
{
HttpWRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Need this so you don’t get an error with double-hop auth
HttpWRequest.UnsafeAuthenticatedConnectionSharing = true;
}
Second, the web.config file needs to have the correct settings – as follows:
<authentication mode="Windows" />
<identity impersonate="true"/>
Here is what part of a web.config may look like:
//Be sure that Windows authentication is turned on for the virtual directory
//The DC must trust the web server for authentication.
//The IE Browser must be set to use Windows authentication.
//Be sure that the web.config file reflects the following:
<authentication mode="Windows" />
<!--
AUTHORIZATION
This section sets the authorization policies of the application. You can
allow or deny access
to application resources by user or role. Wildcards: "*" mean everyone,
"?" means anonymous
(unauthenticated) users.
-->
<authorization>
<allow users="*" /> <!-- Allow all users -->
<!--
<allow
<deny
users="[comma
roles="[comma
users="[comma
roles="[comma
separated
separated
separated
separated
list
list
list
list
of
of
of
of
users]"
roles]"/>
users]"
roles]"/>
-->
WebDAV 101. Last Revised 6/28/06. Version 1.6
42
EXCHANGE WebDAV 101
</authorization>
<identity impersonate="true"/>
M. VBS - GET FREE/BUSY (OWA Call)
In order to read Free/Busy information, a GET needs to be done against the public folder for the
user’s Mailbox. This request will be processed by OWA. Note that this is currently the only OWA
call supported. It’s important to have the URL corrected, so be careful with the date formatting and
SMTP address. If your wondering why the public folder is being accessed, it’s because that’s where
it is stored – not on the mailbox.
M.1
dim
dim
dim
dim
Dim
VBS - GET FREE/BUSY (OWA Call)
sHREF
sUserName
sPassword
sResponse
HttpWebRequest
sHREF="http://myexserver/public/?Cmd=freebusy&start=2005-03-17T00:00:00-07:00&end=2005-0319T00:00:00-07:00&interval=10&u=SMTP:Administrator@mydomain.extest.microsoft.com" ' TODO:
change
sUserName = "Administrator"
' TODO: change
sPassword = "test"
' TODO: change
set HttpWebRequest = CreateObject("microsoft.xmlhttp")
HttpWebRequest.Open "GET", sHREF , False, sUserName, sPassword
HttpWebRequest.Send
sResponse = HttpWebRequest.ResponseText ' Returns as text
Set HttpWebRequest = Nothing
wscript.echo sResponse
M.2
VB.NET - GET FREE/BUSY (OWA Call)
The .NET way is similar, however you need to be sure to set these headers:
HttpWRequest.Headers.Set("Pragma", "no-cache")
HttpWRequest.KeepAlive = True
HttpWRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR
1.1.4322; .NET CLR 2.0.50727; InfoPath.1)"
N. VB - Send Email With Attachment:
To send an email with WebDAV, you will you will need to create/recreate the item with a WEBDAV PUT using
the MIME of the message. It gets tricky when working with attachments. To get around the complexity of
sending an email with an attachment, you may want to look at using CDOSYS to build the message to send,
then extract the MIME stream (MIME of the message in a string) of the resulting message.
For sending the message, you would use a PUT statement to write the stream to a file in the Drafts folder of the
sending person’s mail box. If you need to set specific properties not set by the MIME, you should do a
PROPPATCH against the message in the Drafts folder. Next, the code should use a WebDAV MOVE in order
WebDAV 101. Last Revised 6/28/06. Version 1.6
43
EXCHANGE WebDAV 101
to place the message into the mailbox’s submission URL. The Submission URL is a special url used for sending
messages. “/##DavMailSubmissionURI##" off of the root of the mailbox is the Submission URL.
' TODO:
' Create a VB Windows program.
' Add a button to the form
' Add references to:
'
Active X Data Objectes
'
Microsoft CDO for Windows 2000 Library
'
Microsoft XML, 3.0
' Paste-in the code below.
' Do the TODO sections in the code.
Option Explicit
Private Sub Command1_Click()
CreateMessageAndWebDAVSubmit
End Sub
'----------------------------------------------------------------------------------' CreateMessageAndWebDAVSubmit - Main method for generating message and using WEBDAV
' to send the message.
'----------------------------------------------------------------------------------Private Sub CreateMessageAndWebDAVSubmit()
Dim sDraftsFolder As String
Dim sSubmissionURL As String
Dim strAttendeeItem As String
Dim dateNow As Date
Dim strMIMEStream As String
Dim bRet As Boolean
Dim sUser As String
Dim sPassword As String
' TODO: Change username and password or set to "" if using windows authentication
sUser = "Administrator"
' TODO: Change
sPassword = "testpassword"
' TODO: Change
' TODO: Change the Drafts folder and submission URLs
sDraftsFolder = "http://myexserver/exchange/Administrator/Drafts/SubmittedMail" & GetUniqueString &
".EML" ' TODO: Change this
sSubmissionURL = "http://myexserver/exchange/Administrator/##DavMailSubmissionURI##" ' TODO: Change
this
' Use CDOSYS to generate the message body parts and such
strMIMEStream = BuildMessageAndGenerateMIMEStream()
bRet = DoWebdavPut(sDraftsFolder, strMIMEStream, sUser, sPassword)
If (bRet = True) Then
' NOTE:
'
At this point, the email is in the drafts folder. If you don't want it sent
'
automatically, you can comment out the line below. If the line below does not
'
execute, you can load the message from Outlook or OWA and send it from there.
DoWebdavCopyMove sDraftsFolder, sSubmissionURL, False, sUser, sPassword ' MOVE IT TO
SUBMISSION !!!
End If
End Sub
'----------------------------------------------------------------------------------' BuildMessageAndGenerateMIMEStream - This will create a CDOSYS message, attach a file
' and return the Mime stream for use with webdav.
'----------------------------------------------------------------------------------Private Function BuildMessageAndGenerateMIMEStream() As String
Dim oBodyPart As CDO.IBodyPart
Dim oMessage As CDO.Message
Dim oConfig As CDO.Configuration
Dim oFields As ADODB.Fields
Dim sFile
As String
Dim strMIMEStream As String
Dim oAttachStream As ADODB.Stream
Dim oMIMEStream As ADODB.Stream
WebDAV 101. Last Revised 6/28/06. Version 1.6
44
EXCHANGE WebDAV 101
Set oMessage = New CDO.Message
Set oConfig = New CDO.Configuration
Set oFields = oConfig.Fields
With oMessage
Set .Configuration = oConfig
.To = "Administrator@mydomain.extest.microsoft.com"
sender
.From = "Administrator@mydomain.extest.microsoft.com"
the mail is going to
.Subject = "Test"
of the message.
.TextBody = "Test adding icon"
the message.
' TODO: Change to the name of the
' TODO: Change to the name the person
' TODO: Change to the subject
' TODO: Change to the body of
.Fields.Update
End With
' The File I'm attaching
sFile = "C:\output.txt"
being sent.
Set oBodyPart = oMessage.AddAttachment(sFile, "", "")
' TODO: Change to the name of the file
' Do Attatchment
' NOTE: For your reference...
'With oBodyPart
'
' Set the content class appropriately
'
'.ContentMediaType = "mage/x-icon" '"text/html"
'
' Get the decoded content stream so we can use it
'
Set oAttachStream = .GetDecodedContentStream()
'End With
' Now get the entire message stream
Set oMIMEStream = oMessage.GetStream()
' Read the text out of it
strMIMEStream = oMIMEStream.ReadText()
Set
Set
Set
Set
oMIMEStream = Nothing
oAttachStream = Nothing
oBodyPart = Nothing
oMessage = Nothing
' And return it
BuildMessageAndGenerateMIMEStream = strMIMEStream
End Function
'----------------------------------------------------------------------------------' GetUniqueString - Used to generate a fairly unique string... used in making a
' Unique file name. This is: Datetime + random + serial value
'----------------------------------------------------------------------------------Private Function GetUniqueString() As String
' I'm in EST, which is GMT - 5, but it's Daylight Savings, to it becomes GMT - 4
Const TimeZoneOffset As Long = 4
Dim sString As String
Dim dateNow As Date
Dim iRnd As Single
Dim lNum As Long
Static lVal As Long
lVal = lVal + 1
If lVal > 50000 Then lVal = 1
iRnd = Rnd(CLng(Format(Now, "mmhhmmss")))
lNum = CLng(iRnd * 10000000)
dateNow = DateAdd("h", TimeZoneOffset, Now())
sString = Format(dateNow, "yyyyMMdd") & "T" & Format(dateNow, "HHmmss") & "Z"
GetUniqueString = sString & CStr(lNum) & lVal ' Datetime + random + serial value
End Function
'----------------------------------------------------------------------------------' DoCopyMove - Used to PUT (write) an item to a file in a folder.
WebDAV 101. Last Revised 6/28/06. Version 1.6
45
EXCHANGE WebDAV 101
' sFolder
- The complete URI to PUT the item (includes item name).
' sText
- The contents to write in the file.
' sUser
- User ID for logging in. Set to "" if using windows authentication
' sPassword
- Password for logging in. Set to "" if using windows authentication
'----------------------------------------------------------------------------------Private Function DoWebdavPut(sFolder As String, sText As String, sUser As String, sPassword As String)
As Boolean
Dim oXMLHttp As New MSXML2.XMLHTTP30
Dim bSucess As Boolean
Dim iStatus As Integer
Dim sStatus As String
Dim sResponse As String
If sUser <> "" Then
oXMLHttp.Open "PUT", sFolder, False, sUser, sPassword
' TODO: Change username and password
Else
oXMLHttp.Open "PUT", sFolder, False ', sUser, sPassword
' TODO: Change username and password
End If
oXMLHttp.setRequestHeader "translate", "f" ' Set this header to prevent DAV from trying to munge
our stream
oXMLHttp.Send sText ' Send the stream across
bSucess = False
iStatus = oXMLHttp.Status
sStatus = oXMLHttp.statusText
If (iStatus >= 200 And iStatus < 300) Then
Debug.Print "PUT: Success!
" & "Results = " & iStatus & ": " & sStatus
bSucess = True
ElseIf iStatus = 401 Then
Debug.Print "PUT: You don't have permission to do the job! Please check your permissions on
this item."
Else
Debug.Print "PUT: Request Failed. Results = " & iStatus & ": " & sStatus
End If
Set oXMLHttp = Nothing
DoWebdavPut = bSucess
End Function
'----------------------------------------------------------------------------------' DoCopyMove - Used to move an item from one folder to another in the same store.
' sSourceURL
- item being moved/copied
' sDestinationURL - the URL it is going to
' bCopy
- TRUE if copying or FALSE if moving
' sUser
- User ID for logging in. Set to "" if using windows authentication
' sPassword
- Password for logging in. Set to "" if using windows authentication
'----------------------------------------------------------------------------------Private Sub DoWebdavCopyMove(ByVal sSourceURL As String, ByVal sDestinationURL As String, ByVal bCopy
As Boolean, sUser As String, sPassword As String)
Dim oXMLHttp As New MSXML2.XMLHTTP30
Dim sVerb As String
If bCopy Then
sVerb = "COPY"
Else
sVerb = "MOVE"
End If
If sUser <> "" Then
oXMLHttp.Open sVerb, sSourceURL, False, sUser, sPassword
' TODO: Change username and password
Else
oXMLHttp.Open sVerb, sSourceURL, False ', sUser, sPassword
' TODO: Change username and
password
End If
oXMLHttp.setRequestHeader "Destination", sDestinationURL
' Send the stream across
oXMLHttp.Send
If (oXMLHttp.Status >= 200 And oXMLHttp.Status < 300) Then
Debug.Print "Success!
" & "Results = " & oXMLHttp.Status & ": " & oXMLHttp.statusText
WebDAV 101. Last Revised 6/28/06. Version 1.6
46
EXCHANGE WebDAV 101
ElseIf oXMLHttp.Status = 401 Then
Debug.Print "You don't have permission to do the job!
Else
Debug.Print "Request Failed. Results = " & oXMLHttp.Status & ": " & oXMLHttp.statusText
End If
Set oXMLHttp = Nothing
End Sub
O. VBS - Reformatting XML
This can be used to make returned XML more easily readable.
' ReformXML - reformats the XML to be more easily readable
Private Function ReformXML(sOriginalXML)
Dim sXML As String
sXML = sOriginalXML
sXML = Replace(sXML, "<", (vbCrLf & "<"))
sXML = Replace(sXML, "/>", ("/>" & vbCrLf))
sXML = Replace(sXML, (vbCrLf & "</"), ("</"))
sXML = Replace(sXML, ("></"), (">" & vbCrLf & "</"))
sXML = Replace(sXML, (">" & vbCrLf & vbCrLf & "</"), (">" & vbCrLf & "</"))
ReformXML = sXML
End Function
P. VBS - ReadFileText
This example will load a text file and return a string.
'----------------------------------------------------------------------------------' ReadFileText - Used to PUT (write) an item to a file in a folder.
' Parameters:
'
sFile - The file to read
'
' Returns:
'
A string containing the content of the file.
'----------------------------------------------------------------------------------Function ReadFileText (sFile)
Dim objFSO 'As FileSystemObject
dim oTS
dim sText
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oTS = objFSO.OpenTextFile(sFile)
sText = oTS.ReadAll
oTS.close
set oTS = nothing
Set objFSO = nothing
ReadFileText = sText
end Function
Q. VBS - WriteFileText
This example will save a string to a file.
'------------------------------------------------------------------------------' WriteFileText - Used to PUT (write) an item to a file in a folder.
' Parameters:
'
sFile - The file to read
'
' Returns:
WebDAV 101. Last Revised 6/28/06. Version 1.6
47
EXCHANGE WebDAV 101
'
A string containing the content of the file.
'------------------------------------------------------------------------------Function WriteFileText(sFilePath, sText)
Dim objFSO 'As FileSystemObject
Dim objTextFile 'As Object
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.CreateTextFile(sFilePath, True)
' Write a line.
objTextFile.Write (sText)
objTextFile.Close
'objTextFile.Close
End Function
R. MIME
The follow is an example message saved from Outlook.
To: "someuser@somecompany.com"
Subject: This is a test
Date: Fri, 17 Jun 2005 13:20:43 -0400
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="----=_NextPart_000_0006_01C5733F.65DD8F40"
X-Priority: 3
X-MSMail-Priority: Normal
X-Unsent: 1
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180
This is a multi-part message in MIME format.
------=_NextPart_000_0006_01C5733F.65DD8F40
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
My Test Email
------=_NextPart_000_0006_01C5733F.65DD8F40
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2900.2668" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>My Test Email</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV> </DIV></BODY></HTML>
WebDAV 101. Last Revised 6/28/06. Version 1.6
48
EXCHANGE WebDAV 101
------=_NextPart_000_0006_01C5733F.65DD8F40--
S. VB - Reading Delegates
Private Sub Command1_Click()
'=====================================================
'DoXML takes the href to a document
'and returns the MAPI PR_ENTRYID property expressed in
'a hexadecimal string format such as is used by CDO 1.21
'Function DoXML(strHref)
Dim objX
Dim objXMLdoc
Dim objNode
Dim strR As String
Dim retXML As String
Dim parseStringtemp As String
Dim parseString As String
strHref = "<<Error! Hyperlink reference not valid.> folders/public folder/subject.eml>"
'<<http://servername/exchange/mailboxname/>>
Set objX = CreateObject("MSXML2.ServerXMLHTTP")
strR = "<?xml version='1.0'?><d:propfind xmlns:d='DAV:'
xmlns:m='http://schemas.microsoft.com/mapi/'>"
strR = strR & "<d:prop><m:dlmembers/></d:prop></d:propfind>"
retXML = DoPropFind(strHref, "<Domain\Username>", "<password>", strR)
' This won't work since we can load "Datatype 'mv.bin.base64'" into the DOM.
'objXMLdoc.setProperty "SelectionNamespaces",
"xmlns:d='http://schemas.microsoft.com/mapi/'"
'Set objNode = objXMLdoc.selectSingleNode("/d:dlmembers")
'MsgBox objNode.Text
parseStringtemp = Right(retXML, InStr(1, retXML, "<c:v>"))
parseString = Left(parseStringtemp, (Len(parseStringtemp) - (InStrRev(parseStringtemp,
"<c:v>"))))
' Insert your generic decoding code here:
'DoXML = BinToHex(Decode64(parseString))
DoXML = Decode64(parseString)
MsgBox DoXML
'End Function
End Sub
'-------------------------------------------------------------' DoPropFind
'
Searches an HREF for content.
' Input
'
sType - "SEARCH", "PROPFIND", etc
'
sQuery - Search to perform (XML query document)
'
sHREF - Http reference to item(s)/folder
'
sUserName - Domain/Username for server
'
sPassword - Password for the account above
' Returns: An XML document resulting from the search
'-------------------------------------------------------------Public Function DoPropFind(ByVal sHREF As String, ByVal sUserName As String, ByVal
sPassword As String, sQuery As String) As String
Dim HttpWebRequest As MSXML2.XMLHTTP30
Set HttpWebRequest = New MSXML2.XMLHTTP30
WebDAV 101. Last Revised 6/28/06. Version 1.6
49
EXCHANGE WebDAV 101
'TO use MSXML 2.0 use the following DIM/SET statements
'Dim HttpWebRequest As XMLHTTP
'Set HttpWebRequest = CreateObject("Microsoft.xmlhttp")
'To use MSXML 4.0 use the folloiwing DIM/SET statements
'Dim HttpWebRequest As MSXML2.XMLHTTP40
'Set HttpWebRequest = CreateObject("Msxml2.XMLHTTP.4.0")
Dim sText As String
' Open the folder
HttpWebRequest.Open "PROPFIND", sHREF, False, sUserName, sPassword
' Set up request headers
HttpWebRequest.setRequestHeader "Content-Type", "text/xml"
' Send the query
HttpWebRequest.send (sQuery)
Debug.Print HttpWebRequest.Status
Debug.Print HttpWebRequest.statusText
Debug.Print HttpWebRequest.responseText
sText = HttpWebRequest.responseText
Set HttpWebRequest = Nothing
DoPropFind = sText
End Function
T. VB - An example to create a public folder with storage limit settings.
In this example, the following properties are set during the folder creation.
outlookfolderclass
contentclass
The warning limit in KB
Prohibit Post at (KB).
Maximum item Size (KB)
addressbookdisplayname
isreadonly
ishidden
When reading and setting certain properties, it’s necessary to use the exchange admin path. This path
provides special admin privileges. An Exchange Admin login must be used when using this path.
Private
Dim
Dim
Dim
Dim
Sub cmdMakeFolder_Click()
XMLreq As New MSXML2.XMLHTTP40
sReq As String
parsePhone As String
sSourceURL As String
Set XMLreq = New MSXML2.XMLHTTP40
sSourceURL = "http:// myexserver /Exadmin/admin/MYDOM.EXTEST.MYCOMP.COM/PUBLIC%20FOLDERS/myfolder"
' Note: This URL is broken down as:
'
myexserver is the Exchange box name
'
MYDOM.EXTEST.MYCOMP.COM is the full domain name the Exchange box is in.
'
Exadmin/admin is a special designation giving the login user higher level privs.
' Exchange explorer may/may not need the %20 in PUBLIC%20FOLDERS
' The account you use to log in with Must have full blown Exchange admin privs and be
' a domain acct.
'XMLreq.open "MKCOL", sSourceURL, False, "Administrator", "Pxxxx"
' If the Exchange is the DC, you probably dont have to specify the DC to login
XMLreq.open "MKCOL", sSourceURL, False, "mydom\myexserver ", "Pxxxxxxx"
' Here Exchange box is not the DC
WebDAV 101. Last Revised 6/28/06. Version 1.6
50
EXCHANGE WebDAV 101
XMLreq.setRequestHeader "Content-Type", "text/xml"
sReq = "<?xml version='1.0'?>"
sReq = sReq & "<a:propertyupdate xmlns:a='DAV:' xmlns:e='http://schemas.microsoft.com/exchange/' "
& _
"xmlns:p='http://schemas.microsoft.com/mapi/proptag/'>"
sReq = sReq & "<a:set><a:prop>" & vbCrLf
sReq = sReq & "<e:outlookfolderclass>IPF.Folder</e:outlookfolderclass>" & vbCrLf
' Folder class for outlook
sReq = sReq & "<a:contentclass>urn:content-classes:folder</a:contentclass>" & vbCrLf
' Folder content class
sReq = sReq & "<a:isreadonly>1</a:isreadonly>" & vbCrLf ' Read only
sReq = sReq & "<a:ishidden>1</a:ishidden>" & vbCrLf
' Hidden
sReq = sReq & "<p:x67790003>1</p:x67790003>" & vbCrLf
'Use the quotas specified by other properties.
sReq = sReq & "<e:storagequotaissuewarninglimit>200</e:storagequotaissuewarninglimit>" & vbCrLf
'Issue warning at (Kb).
sReq = sReq & "<p:x67210003>1</p:x67210003>" & vbCrLf 'Prohibit post at (Kb).
sReq = sReq & "<p:x67220003>1</p:x67220003>" & vbCrLf 'Maximum item size (Kb).
sReq = sReq & "<e:addressbookdisplayname>Something</e:addressbookdisplayname>" & vbCrLf
sReq = sReq & "</a:prop></a:set></a:propertyupdate>"
XMLreq.send sReq
Debug.Print "xmlReq.Status = " & XMLreq.Status
If XMLreq.Status = "201" Or XMLreq.Status = "207" Then
MsgBox "The folder has been created. Status is " & XMLreq.statusText, vbCritical, "Folder
Created!!"
Else
' Note: Error 405 can mean permissions problem on item already exists.
MsgBox "The folder has not been created. Status is " & XMLreq.statusText, vbCritical, " Folder
not Created!!"
End If
End Sub
WebDAV 101. Last Revised 6/28/06. Version 1.6
51
EXCHANGE WebDAV 101
VIII.
REFERENCE
A. Basics.
WebDAV Methods
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_methods.asp?frame=true
WebDAV Batch Methods
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wss/wss/_esdk_arch_webdav_bmethods.asp
Constructing Exchange Store HTTP URLs
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_constructing_web_storage_system_http_urls.asp?frame=true
XADM: How to Use \\.\ Namespace to Gain Access to the Information Store
http://support.microsoft.com/?id=239743
The File: URL Scheme
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_the_file_url_scheme.asp?frame=true
Getting the Host Domain Name
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_getting_the_host_domain_name.asp?frame=true
The HTTP: URL Scheme
http://msdn.microsoft.com/library/en-us/wss/wss/_exch2k_the_http_url_scheme.asp?frame=true
WebDAV Headers
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_headers.asp?frame=true
INFO: Outlook Named Properties Are Not Supported by MAPI/CDO
http://support.microsoft.com/?id=266353
Default Exchange Store Namespaces
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_default_web_storage_system_namespaces.asp?frame=true
Properties by Namespace
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/wss_references_nsproperties.asp?frame=true
Fields
http://msdn.microsoft.com/library/en-us/cdosys/html/_cdosys_fields.asp?frame=true
Contacts fields
http://msdn.microsoft.com/library/en-us/wss/wss/_cdo_schema_contacts.asp?frame=true
Property Data Types
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_property_data_types.asp?frame=true
Property Names and WebDAV
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_property_names_and_http_webdav.asp?frame=true
Exchange Store WebDAV Protocol - WebDAV Reference
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_webdav_web_store_http_webdav_protocol_reference.asp?frame=true
WebDAV Protocol Status Codes - WebDAV Reference
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wss/wss/_webstore_http_webdav_protocol_errors.asp?frame=true
B. Security:
HTTP Security and ASP.NET Web Services
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_property_names_and_http_webdav.asp?frame=true
Authentication and Security Using WebDAV
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_esdk_arch_webdav_security.asp
WebDAV 101. Last Revised 6/28/06. Version 1.6
52
EXCHANGE WebDAV 101
C. Related Topics:
Customizing Microsoft Outlook Web Access
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=6532E454-073E-4974-A800-1490A7CB358F
Customizing Microsoft Outlook Web Access White Paper
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/prodtechnol/exchange/exchange2000/proddocs/articles/custowa/custow
a.asp
HTTP 403 (Forbidden)" error message when Exchange 2003 users try to use Outlook Web Access to
access a freedoc that is located in a public folder
http://support.microsoft.com/default.aspx?scid=kb;en-us;834743
How to use the System.DirectoryServices namespace in ASP.NET
http://support.microsoft.com/?id=329986
PRB: Unable to Make More Than 256 Connections to Different Mailboxes Over a Short Period of Time
http://support.microsoft.com/default.aspx?scid=kb;en-us;305619
INFO: Data Types Supported by the MSXML Parser
http://support.microsoft.com/default.aspx?kbid=289842
D. Further Reading
Background articles:
There is no one ultimate article or book on WebDAV for Exchange. However, there are several very
good articles on the subject. Below are some links to information which will cover the basic nuts and
bolts of this technology.
HTTP/Web Distributed Authoring and Versioning (WebDAV)
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_techsel_tech_9.asp?frame=true
WebDAV
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_e2k3_http_webdav_access.asp?frame=true
WebDAV Methods
http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_methods.asp?frame=true
Communicating XML Data over the Web with WebDAV
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnxmlweb/html/xmlandwebdav.asp
Designing Knowledge Management Solutions with a Web Storage System
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/designkmsols.asp
Develop Web Applications with XML and Exchange 2000
http://msdn.microsoft.com/library/en-us/dnmes2k/html/devwebapps.asp?frame=true
Building Solutions with Microsoft Exchange 2000 Server
http://msdn.microsoft.com/library/en-us/dnmes2k/html/buildingsolutions.asp?frame=true
New Development Features in Microsoft Exchange 2000
http://msdn.microsoft.com/library/en-us/dnmes2k/html/NewDevFeaturesE2K.asp?frame=true
Building XML Web Services for Microsoft Exchange 2000 Contacts
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmes2k/html/cwswp_0001.asp
Developing Applications for the Web Storage System and Outlook Web Access
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmes2k/html/wssdevaccess.asp
Exchange Server RFC and standards compliance
http://support.microsoft.com/?id=262986
WebDAV 101. Last Revised 6/28/06. Version 1.6
53
EXCHANGE WebDAV 101
E. Some things you can do with WebDAV:
There are a many things you can do with WebDAV. Below are articles going over many of the different
things you may wish to do.
320071 HOWTO: Programmatically Get the Size of Mailboxes on Exchange Server
http://support.microsoft.com/?id=320071
Searching Folders (WebDAV)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_exch2k_searching_calendar_folders_webdav.asp
Searching the Exchange Store
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_search_tasks.asp?frame=true
Searching Calendar Folders with WebDAV
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_searching_calendar_folders_webdav.asp?frame=true
Creating a Contact in the Exchange Store (WebDAV)
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_creating_a_contact_webdav.asp?frame=true
Deleting a Contact from the Exchange Store (WebDAV)
http://msdn.microsoft.com/library/en-us/e2k3/e2k3/_exch2k_deleting_a_contact_webdav.asp?frame=true
How to delete objects by using WebDAV in Visual C# .NET on a computer that is running Exchange 2000
http://support.microsoft.com/default.aspx?scid=kb;en-us;313122
HOWTO: Move or Copy Folder Items with WebDAV
http://support.microsoft.com/default.aspx?scid=kb;en-us;290111
How to copy or to move a message from one folder to another folder on a computer that is running
Exchange 2000 by using Visual C# .NET
http://support.microsoft.com/default.aspx?scid=kb;en-us;310289
296713 HOWTO: Send a Message from Visual Basic by Using WebDAV
http://support.microsoft.com/?id=296713
321832 How to Change the Outlook Web Access Logon Page
http://support.microsoft.com/?id=321832
308373 HOWTO: Send a Meeting Request Using WebDAV
http://support.microsoft.com/?id=308373
296126 HOW TO: Create, Modify and Delete Contact Items via WebDAV (PROPPATCH)
http://support.microsoft.com/default.aspx?scid=KB;EN-US;296126
WebDAV 101. Last Revised 6/28/06. Version 1.6
54
Download