You are currently offline, waiting for your internet to reconnect

How to programmatically get the size of mailboxes in Exchange

This article was previously published under Q320071
This article has been archived. It is offered "as is" and will no longer be updated.
SUMMARY
This article describes how to programmatically retrieve information about the size of mailboxes on a server that is running Microsoft Exchange by using Microsoft Visual C, Microsoft Visual C++, Microsoft Visual Basic, and Microsoft Visual Basic Scripting Edition (VBScript).
MORE INFORMATION

Extended MAPI approach

Programming Languages Available: Visual C, Visual C++
Exchange Server Versions: Exchange Server 5.5, Exchange 2000, and Exchange 2003

Extended MAPI provides the IExchangeManageStore interface to obtain management information from an Exchange information store. This interface provides the GetMailboxTable function, which returns an IMAPITable interface that contains information about the mailboxes on a particular server. Note that this function requires administrative access to the server that is running Exchange Server.

This table includes a column that provides information about the size of each mailbox. The PR_MESSAGE_SIZE property contains the size (in bytes) of the mailbox.

For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
200160 How to loop through mailboxes on Exchange using GetMailboxTable

CDO 1.21 approach

Programming Languages Available: VBScript, Visual Basic, Visual C, Visual C++
Exchange Server Versions: Exchange Server 5.5, Exchange 2000, and Exchange 2003

You can use Collaboration Data Objects (CDO) 1.21 to check the same property on a user mailbox store through the CDO InfoStore object. In this approach, your application must log on to a mailbox before the application can check this property. This means that your application must have access to all mailboxes on the server. This approach also requires that you generate a list of mailboxes on the server and then loop through them in code.

The following sample is a simple VBScript code sample that can check this property on a mailbox. To use this sample, paste the following code in a new text file, and then name the file Mailboxsize.vbs:
'This script logs on to a server that is running Exchange Server and'displays the current number of bytes that are used in the user's'mailbox and the number of messages.' USAGE: cscript MailboxSize.vbs SERVERNAME MAILBOXNAME' This requires that CDO 1.21 is installed on the computer.' This script is provided AS IS. It is intended as a SAMPLE only.' Microsoft offers no warranty or support for this script.  ' Use at your own risk.' Get command line arguments.Dim obArgsDim cArgsSet obArgs = WScript.ArgumentscArgs = obArgs.CountMainSub Main()   Dim oSession   Dim oInfoStores   Dim oInfoStore   Dim StorageUsed   Dim NumMessages   Dim strProfileInfo   Dim sMsg   On Error Resume Next   If cArgs <> 2 Then      WScript.Echo "Usage: cscript MailboxSize.vbs SERVERNAME MAILBOXNAME"      Exit Sub   End If   'Create Session object.   Set oSession = CreateObject("MAPI.Session")   if Err.Number <> 0 Then      sMsg = "Error creating MAPI.Session."      sMsg = sMsg & "Make sure CDO 1.21 is installed. "      sMsg = sMsg & Err.Number & " " & Err.Description      WScript.Echo sMsg      Exit Sub   End If       strProfileInfo = obArgs.Item(0) & vbLf & obArgs.Item(1)   'Log on.   oSession.Logon , , False, True, , True, strProfileInfo   if Err.Number <> 0 Then      sMsg = "Error logging on: "      sMsg = sMsg & Err.Number & " " & Err.Description      WScript.Echo sMsg      WScript.Echo "Server: " & obArgs.Item(0)      WScript.Echo "Mailbox: " & obArgs.Item(1)      Set oSession = Nothing      Exit Sub   End If   'Grab the information stores.   Set oInfoStores = oSession.InfoStores   if Err.Number <> 0 Then      sMsg = "Error retrieving InfoStores Collection: "      sMsg = sMsg & Err.Number & " " & Err.Description      WScript.Echo sMsg      WScript.Echo "Server: " & obArgs.Item(0)      WScript.Echo "Mailbox: " & obArgs.Item(1)      Set oInfoStores = Nothing      Set oSession = Nothing      Exit Sub   End If       'Loop through information stores to find the user's mailbox.   For Each oInfoStore In oInfoStores      If InStr(1, oInfoStore.Name, "Mailbox - ", 1) <> 0 Then         '&HE080003 = PR_MESSAGE_SIZE         StorageUsed = oInfoStore.Fields(&HE080003)         if Err.Number <> 0 Then            sMsg = "Error retrieving PR_MESSAGE_SIZE: "            sMsg = sMsg & Err.Number & " " & Err.Description            WScript.Echo sMsg            WScript.Echo "Server: " & obArgs.Item(0)            WScript.Echo "Mailbox: " & obArgs.Item(1)            Set oInfoStore = Nothing            Set oInfoStores = Nothing            Set oSession = Nothing            Exit Sub         End If                  '&H33020003 = PR_CONTENT_COUNT         NumMessages = oInfoStore.Fields(&H36020003)         if Err.Number <> 0 Then            sMsg = "Error Retrieving PR_CONTENT_COUNT: "            sMsg = sMsg & Err.Number & " " & Err.Description            WScript.Echo sMsg            WScript.Echo "Server: " & obArgs.Item(0)            WScript.Echo "Mailbox: " & obArgs.Item(1)            Set oInfoStore = Nothing            Set oInfoStores = Nothing            Set oSession = Nothing            Exit Sub         End If         sMsg = "Storage Used in " & oInfoStore.Name         sMsg = sMsg & " (bytes): " & StorageUsed         WScript.Echo sMsg         WScript.Echo "Number of Messages: " & NumMessages      End If   Next   ' Log off.   oSession.Logoff   ' Clean up memory.   Set oInfoStore = Nothing   Set oInfoStores = Nothing   Set oSession = Nothing End Sub				

ActiveX Data Objects (ADO) approach

Programming Languages Available: VBScript, Visual Basic, Visual C, Visual C++
Exchange Server Versions: Exchange 2000 and Exchange 2003

In Exchange 2000 and Exchange 2003, you can access the Exchange information store through ActiveX Data Objects (ADO). No property that is stored on the mailbox contains the total size. However, each folder in a user mailbox has its size stored in a field that is named http://schemas.microsoft.com/mapi/proptag/x0e080003. This corresponds to the MAPI property, PR_MESSAGE_SIZE.

By adding the size of all of the folders in a user mailbox, the total size of the mailbox can be computed. To do this, you use a SHALLOW traversal to recursively traverse the folders in the mailbox. Although you can use a DEEP traversal, this approach is avoided because of the issues that DEEP traversal raises. For additional information about the issues with a DEEP traversal, click the following article number to view the article in the Microsoft Knowledge Base:
216076 Accessing Information Store folders may become slow
In this approach, you must run your code on the server that is running Exchange 2000. OLE DB Provider for Exchange (EXOLEDB) cannot access mailboxes remotely.

The following sample is a simple VBScript code sample that can retrieve the size of a mailbox. To use this sample, paste the following code in a new text file, and then name the file Mailboxsize.vbs:
'This script logs on to a server that is running Exchange 2000 or 2003 and'displays the current number of bytes that are used in the user's'mailbox.' USAGE: cscript MailboxSize.vbs DOMAINNAME MAILBOXNAME' You must run this code on the computer that is running Exchange 2000 or 2003.' This script is provided AS IS. It is intended as a SAMPLE only.' Microsoft offers no warranty or support for this script.  ' Use at your own risk.' Get command line argumentsDim obArgsDim cArgsDim iSizeSet obArgs = WScript.ArgumentscArgs = obArgs.CountMainSub Main()   Dim sConnString   On Error Resume Next   If cArgs <> 2 Then      WScript.Echo "Usage: cscript MailboxSize.vbs DOMAINNAME MAILBOXNAME"      Exit Sub   End If   ' Set up connection string to mailbox.   sConnString = "file://./backofficestorage/" & obArgs.Item(0)   sConnString = sConnString & "/mbx/" & obArgs.Item(1) & "/NON_IPM_SUBTREE"   WScript.Echo sConnString   iSize = 0   RecurseFolder(sConnString)   WScript.Echo "Mailbox Size: " & iSizeEnd SubPublic Sub RecurseFolder(sConnString)   Dim oConn   Dim oRecSet   Dim sSQL   ' Set up SQL SELECT statement.   sSQL = "SELECT ""http://schemas.microsoft.com/mapi/proptag/x0e080003"", "   sSQL = sSQL & """DAV:href"", "   sSQL = sSQL & """DAV:hassubs"" "   sSQL = sSQL & "FROM SCOPE ('SHALLOW TRAVERSAL OF """ & sConnString   sSQL = sSQL & """') WHERE ""DAV:isfolder"" = true"   WScript.Echo sSQL   ' Create Connection object.   Set oConn = CreateObject("ADODB.Connection")   if Err.Number <> 0 then      WScript.Echo "Error creating ADO Connection object: " & Err.Number & " " & Err.Description   end if   ' Create RecordSet object.   Set oRecSet = CreateObject("ADODB.Recordset")   if Err.Number <> 0 then      WScript.Echo "Error creating ADO RecordSet object: " & Err.Number & " " & Err.Description      Set oConn = Nothing      Exit Sub   end if   ' Set provider to EXOLEDB.   oConn.Provider = "Exoledb.DataSource"   ' Open connection to folder.   oConn.Open sConnString   if Err.Number <> 0 then      WScript.Echo "Error opening connection: " & Err.Number & " " & Err.Description      Set oRecSet = Nothing      Set oConn = Nothing      Exit Sub   end if   ' Open Recordset of all subfolders in folder.   oRecSet.CursorLocation = 3   oRecSet.Open sSQL, oConn.ConnectionString   if Err.Number <> 0 then      WScript.Echo "Error opening recordset: " & Err.Number & " " & Err.Description      oRecSet.Close      oConn.Close      Set oRecSet = Nothing      Set oConn = Nothing      Exit Sub   end if   if oRecSet.RecordCount = 0 then      oRecSet.Close      oConn.Close      Set oRecSet = Nothing      Set oConn = Nothing      Exit Sub   end if   ' Move to first record.   oRecSet.MoveFirst   if Err.Number <> 0 then      WScript.Echo "Error moving to first record: " & Err.Number & " " & Err.Description      oRecSet.Close      oConn.Close      Set oRecSet = Nothing      Set oConn = Nothing      Exit Sub   end if   ' Loop through all of the records, and then add the size of the    ' subfolders to obtain the total size.   While oRecSet.EOF <> True      ' Increment size.      iSize = iSize + oRecSet.Fields.Item("http://schemas.microsoft.com/mapi/proptag/x0e080003")            ' If the folder has subfolders, recursively call RecurseFolder to process them.      If oRecSet.Fields.Item("DAV:hassubs") = True then         RecurseFolder oRecSet.Fields.Item("DAV:href")      End If      ' Move to next record.      oRecSet.MoveNext      if Err.Number <> 0 then         WScript.Echo "Error moving to next record: " & Err.Number & " " & Err.Description         Set oRecSet = Nothing         Set oConn = Nothing         Exit Sub      end if   wend   ' Close Recordset and Connection.   oRecSet.Close   if Err.Number <> 0 then      WScript.Echo "Error closing recordset: " & Err.Number & " " & Err.Description      Set oRecSet = Nothing      Set oConn = Nothing      Exit Sub   end if   oConn.Close   if Err.Number <> 0 then      WScript.Echo "Error closing connection: " & Err.Number & " " & Err.Description      Set oRecSet = Nothing      Set oConn = Nothing      Exit Sub   end if   ' Clean up memory.   Set oRecSet = Nothing   Set oConn = NothingEnd Sub				
For additional information about this topic and a Visual C++ sample that retrieves the size of mailboxes, click the following article number to view the article in the Microsoft Knowledge Base:
291368 How to determine the size of Exchange 2000 Server mailbox with ADO in C++

WebDAV approach

Languages: VBScript, Visual Basic, Visual C
Exchange Server Versions: Exchange 2000 and Exchange 2003

You can also use WebDAV similarly to the ADO approach. The property and the algorithm are the same in that you can add the values of http://schemas.microsoft.com/mapi/proptag/x0e080003 from all of the subfolders in a mailbox. One advantage of using WebDAV instead of ADO is that the code does not have to run on the computer that is running Exchange 2000 or Exchange 2003.

To use this sample, paste the following code in a new text file, and then name the file Mailboxsize.vbs:
'This script logs on to a server that is running Exchange Server and'displays the current number of bytes that are used in the user's'mailbox.' USAGE: cscript MailboxSize.vbs SERVERNAME MAILBOXNAME USERNAME PASSWORD' SERVERNAME: Name of your Exchange Server' MAILBOXNAME: Your alias (Note: depending on your environment, you may need to use the portion of your ' SMTP address left of the '@' symbol instead of your alias.' USERNAME: Your domainname\username '' PASSWORD: Your domain password ' This script is provided AS IS. It is intended as a SAMPLE only.' Microsoft offers no warranty or support for this script. ' Use at your own risk. ' Get command line arguments.Dim obArgsDim cArgsDim iSumSet obArgs = WScript.ArgumentscArgs = obArgs.CountMainSub Main()   Dim sUrl   Dim sMsg   On Error Resume Next   iSum = 0   ' Check argument count.   If cArgs <> 4 Then      sMsg = "Usage: cscript MailboxSize.vbs "      sMsg = sMsg & "SERVERNAME MAILBOXNAME USERNAME PASSWORD"      WScript.Echo sMsg       Exit Sub   End If   sUrl = "http://" & obArgs.Item(0) & "/exchange/" & obArgs.Item(1) & "/NON_IPM_SUBTREE"   wscript.echo sUrl   RecurseFolder(sUrl)   WScript.Echo "Mailbox Size: " & iSumEnd SubPublic Sub RecurseFolder(sUrl)   Dim oXMLHttp   Dim oXMLDoc   Dim oXMLSizeNodes   Dim oXMLHREFNodes   Dim oXMLHasSubsNodes   Dim sQuery   Set oXMLHttp = CreateObject("Microsoft.xmlhttp")   If Err.Number <> 0 Then      WScript.Echo "Error Creating XML object"      WScript.Echo Err.Number & ": " & Err.Description      Set oXMLHttp = Nothing   End If   ' Open DAV connection.   oXMLHttp.open "SEARCH", sUrl, False, obArgs.Item(2), obArgs.Item(3)   If Err.Number <> 0 Then      WScript.Echo "Error opening DAV connection"      WScript.Echo Err.Number & ": " & Err.Description      Set oXMLHttp = Nothing   End If   ' Set up query.   sQuery = "<?xml version=""1.0""?>"   sQuery = sQuery & "<g:searchrequest xmlns:g=""DAV:"">"   sQuery = sQuery & "<g:sql>SELECT ""http://schemas.microsoft.com/"   sQuery = sQuery & "mapi/proptag/x0e080003"", ""DAV:hassubs"" FROM SCOPE "   sQuery = sQuery & "('SHALLOW TRAVERSAL OF """ & sUrl & """') "   sQuery = sQuery & "WHERE ""DAV:isfolder"" = true"   sQuery = sQuery & "</g:sql>"   sQuery = sQuery & "</g:searchrequest>"   ' Set request headers.   oXMLHttp.setRequestHeader "Content-Type", "text/xml"   oXMLHttp.setRequestHeader "Translate", "f"   oXMLHttp.setRequestHeader "Depth", "0"   oXMLHttp.setRequestHeader "Content-Length", "" & Len(sQuery)   ' Send request.   oXMLHttp.send sQuery   If Err.Number <> 0 Then      WScript.Echo "Error Sending Query"      WScript.Echo Err.Number & ": " & Err.Description      Set oXMLHttp = Nothing   End If    ' Load XML.   Set oXMLDoc = oXMLHttp.responseXML   ' Get the XML nodes that contain the individual sizes.   Set oXMLSizeNodes = oXMLDoc.getElementsByTagName("d:x0e080003")   ' Get the XML nodes that contain the individual HREFs.   Set oXMLHREFNodes = oXMLDoc.getElementsByTagName("a:href")   ' Get the XML nodes that contain the individual HasSubs.   Set oXMLHasSubsNodes = oXMLDoc.getElementsByTagName("a:hassubs")   ' Loop through the nodes, and then add all of the sizes.   For i = 0 to oXMLSizeNodes.length - 1      WScript.Echo oXMLHREFNodes.Item(i).nodeTypedValue      WScript.Echo "Size: " & oXMLSizeNodes.Item(i).nodeTypedValue      iSum = iSum + oXMLSizeNodes.Item(i).nodeTypedValue      ' If the folder has subfolders, call your recursive function to       ' process subfolders.      If oXMLHasSubsNodes.Item(i).nodeTypedValue = True Then         RecurseFolder oXMLHREFNodes.Item(i).nodeTypedValue      End If   Next   ' Clean up.   Set oXMLSizeNodes = Nothing   Set oXMLDoc = Nothing   Set oXMLHttp = NothingEnd Sub				

Note In addition to the programmatic methods that are described in this section, you can also export folder size information to a text file by using Exchange System Manager.
Properties

Article ID: 320071 - Last Review: 12/07/2015 09:26:15 - Revision: 6.5

Microsoft Exchange Server 2003 Enterprise Edition, Microsoft Exchange Server 2003 Standard Edition, Microsoft Exchange 2000 Server Standard Edition, Microsoft Exchange Server 5.5 Standard Edition

  • kbnosurvey kbarchive kbhowto KB320071
Feedback