InfiniTec - Henning Krauses Blog

Don't adjust your mind - it's reality that is malfunctioning

Retrieving the size of a mailbox via WebDAV

A common question is how to retrieve the size of a given mailbox or the size of a folder structure via WebDAV. There is an example for this task on MSDN (Getting the Size of a Mailbox (WebDAV)). But that example is rather difficult to understand because the WebDAV requests are built using simple string concatenation, which is rather ugly. It is far better to create those requests using the XmlReader and XmlWriter classes (I’ve written about it in the article PROPPATCH requests using XmlReader and XmlWriter, Part 1).

The procedure to retrieve the cumulative folder size is this:

  • Issue a SEARCH request on the root folder of interest (for example the mailbox) and retrieve the size of all messages in that folder
  • Repeat this step for each sub folder.

Here is a C# program which demonstrates this:

   1: using System;
   2: using System.IO;
   3: using System.Net;
   4: using System.Text;
   5: using System.Xml;
   6: using System.Xml.XPath;
   7:  
   8: namespace InfiniTec.Exchange.Examples
   9: {
  10:     internal class Program
  11:     {
  12:         private const string DavNamespace = "DAV:";
  13:         private const string ProptagNamespace = "http://schemas.microsoft.com/mapi/proptag/";
  14:  
  15:  
  16:         public static byte[] GetFolderSizeRequest(string url)
  17:         {
  18:             var settings = new XmlWriterSettings {Encoding = Encoding.UTF8};
  19:  
  20:             using (var stream = new MemoryStream())
  21:             using (XmlWriter writer = XmlWriter.Create(stream, settings))
  22:             {
  23:                 writer.WriteStartElement("searchrequest", DavNamespace);
  24:                 var searchRequest = new StringBuilder();
  25:  
  26:                 searchRequest.AppendFormat("SELECT \"http://schemas.microsoft.com/mapi/proptag/x0e080014\", \"DAV:hassubs\" FROM SCOPE ('HIERARCHICAL TRAVERSAL OF \"{0}\"')", url);
  27:  
  28:                 writer.WriteElementString("sql", searchRequest.ToString());
  29:                 writer.WriteEndElement();
  30:                 writer.WriteEndDocument();
  31:  
  32:                 writer.Flush();
  33:                 return stream.ToArray();
  34:             }
  35:         }
  36:     
  37:         private static long GetMailboxSize(string url, ICredentials credentials)
  38:         {
  39:             XmlReader reader;
  40:  
  41:             byte[] buffer = GetFolderSizeRequest(url);
  42:  
  43:             var request = (HttpWebRequest) WebRequest.Create(url);
  44:             request.Method = "SEARCH";
  45:             request.ContentType = "text/xml";
  46:             request.Credentials = credentials;
  47:             request.Headers.Add("Translate", "f");
  48:             request.Headers.Add("Depth", "1");
  49:             
  50:             using (Stream stream = request.GetRequestStream())
  51:             {
  52:                 stream.Write(buffer, 0, buffer.Length);
  53:             }
  54:  
  55:             using (WebResponse response = request.GetResponse())
  56:             {
  57:                 string content = new StreamReader(response.GetResponseStream()).ReadToEnd();
  58:  
  59:                 reader = XmlReader.Create(new StringReader(content));
  60:  
  61:                 var nsmgr = new XmlNamespaceManager(reader.NameTable);
  62:                 nsmgr.AddNamespace("dav", DavNamespace);
  63:                 nsmgr.AddNamespace("e", ProptagNamespace);
  64:  
  65:                 var doc = new XPathDocument(reader);
  66:                 long result = 0;
  67:                 
  68:                 foreach (XPathNavigator element in doc.CreateNavigator().Select("//dav:response[dav:propstat/dav:status = 'HTTP/1.1 200 OK']", nsmgr))
  69:                 {
  70:                     var size = element.SelectSingleNode("dav:propstat/dav:prop/e:x0e080014", nsmgr).ValueAsLong;
  71:                     string folderUrl = element.SelectSingleNode("dav:href", nsmgr).Value;
  72:  
  73:                     Console.WriteLine("Folder size of {0}: {1:0.00} MB", folderUrl, (double)size / 1048576);
  74:  
  75:                     result += size;
  76:                     bool hasSubs = element.SelectSingleNode("dav:propstat/dav:prop/dav:hassubs", nsmgr).ValueAsBoolean;
  77:  
  78:                     if (hasSubs)
  79:                     {    
  80:                         result += GetMailboxSize(folderUrl, credentials);
  81:                     }
  82:                 }
  83:  
  84:                 return result;
  85:             }
  86:         }
  87:  
  88:         private static void Main()
  89:         {
  90:             long size = GetMailboxSize("http://w2k3srv.contoso.local/exchange/administrator/", new NetworkCredential("administrator", "password"));
  91:  
  92:             Console.Out.WriteLine("Mailboxsize = {0:0.00} MB",(double) size/1048576);
  93:  
  94:             Console.Out.WriteLine("Finished");
  95:             Console.ReadLine();
  96:         }
  97:     }
  98: }

Posted by Henning Krause on Wednesday, June 11, 2008 7:19 PM, last modified on Wednesday, June 11, 2008 7:20 PM
Permalink | Post RSSRSS comment feed