need a script to display mailbox size and number of items in inbox

Can someone provide a script that I can run against our Exchange 2003 mailbox server, to gather the following information:

1. would like the script to use an input file where i can list the user accounts that i need to collect the data on.
2. script should gather the following information:  a. current mailbox size of users specified in the input file.    b. total number of inbox items the user has.

thanks you very much in advance.

Michael
siber1Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

augwestDirector of Information TechnologyCommented:
0
siber1Author Commented:
Thanks, but I've already seen that KB article.

again, I'm looking for a script that will use an input file [csv or .txt file] that i can list a number of accounts [for example 50]

I would like the script to output the mailbox size [current] and the number of inbox items for each user on the input file.

thx - M.
0
Chris DentPowerShell DeveloperCommented:

Both are available through WMI for Exchange 2003, no need to touch CDO / WebDAV.

I have scripts to produce this kind of output, they don't take input from a CSV though.

PowerShell: http://www.highorbit.co.uk/?p=871
VbScript: http://www.highorbit.co.uk/?p=604

What would you put in your CSV file exactly?

Chris
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

siber1Author Commented:
Thanks Chris.
Ideally, I would like to put in the sAMAccountNames [login name] for each user that i need to pull this data for in the input file.

are you able to modify the vbscript you referenced to use an input file?
that would be great!

thx - Mike
0
Chris DentPowerShell DeveloperCommented:

Sure, I can do that. You'll have to give me a little time though, fairly busy this weekend :)

Chris
0
siber1Author Commented:
sure that would be great!

thx Chris!
0
SubsunCommented:
Here is a simple script which exports the details which you required to "mailboxes.csv".

Change the "Const TOTAL_SERVERS = 2" value as per your requirement if the number of servers are 3 then change 2 to 3.
Replace the "SERVER1" and "SERVER2" with your server names which you want to pull data...
For third server add strComputer(3) = "SERVER3"
Option Explicit
  
' Note this script currently uses On Error Resume Next   
' this isn't best practice - in reality this should be tightly    
' wrapped around the WMI connection logic in the loop rather   
' than up here.   
On Error Resume Next  
 
' TODO: Configure this   
' This is the total number of servers which you   
' will specify for inventory   
Const TOTAL_SERVERS = 2   
  
Dim strComputer()   
ReDim strComputer(TOTAL_SERVERS)   
  
' TODO: Populate this array   
' Enter each server name below as an entry in the array   
' starting with zero   
strComputer(0) = "SERVER1"  
strComputer(1) = "SERVER2"  
  
'==========================================================================   
  
Dim objWMIService   
Dim colItems   
  
Dim fso   
Set fso = CreateObject("Scripting.FileSystemObject")   
  
Dim fil   
Set fil = fso.CreateTextFile("mailboxes.csv")   
  
Dim objItem   
Dim line   
Dim i   
  
' Write a header row to the CSV   
fil.WriteLine """Server"",""Mail Store"",""Display Name"",""Size"",""TotalItems"""
  
For i = 0 To TOTAL_SERVERS - 1   
    Set objWMIService = GetObject("winmgmts:" _   
        & "{impersonationLevel=impersonate}!\\" & strComputer(i) & _   
            "\ROOT\MicrosoftExchangeV2")   
       
    Set colItems = objWMIService.ExecQuery _   
        ("Select * from Exchange_Mailbox")   
       
    For Each objItem in colItems   
        line = """" & objItem.ServerName & """"  
        line = line & ","  
        line = line & """" & objItem.StoreName & """"  
        line = line & ","  
        line = line & """" & objItem.MailboxDisplayName & """"       
        line = line & ","  
        line = line & """" & objItem.Size & """"  
        line = line & ","  
        line = line & """" & objItem.TotalItems & """"  
           
        fil.WriteLine line    
        'WScript.Echo line    
    Next  
Next  
  
fil.Close   
Set fso = Nothing  
Set objWMIService = Nothing

Open in new window

0
siber1Author Commented:
Hi Subsun, is it possible to modify the script so that I could enter a list of user accounts that I need to extract this data for?
it looks like your script would output details on all mailboxes, we have thousands of mailboxes per server. It would be ideal if we could only capture data for the select mailboxes we are looking for [say 50 or so]

thx - M.
0
SubsunCommented:
0
siber1Author Commented:
yes, that script is similiar to the first response i received on this post.

ideally, i'd like a script that would reference an "input" file where i could list 50+ user name. Then the script would cycle through each of the names [sAMAccountNames] on the input file and display the current mailbox size, and number of items in the inbox for each user

thanks in advance,

M.
0
Chris DentPowerShell DeveloperCommented:

Right, I have two scripts for you. This is the first, it's extremely complex, but gives you a great deal of information with very little input.

You can either feed it a list of users on the command line, or from a file. Default output is the short listing of name, mailbox size and number of items. Extended output gives you a CSV file containing all of the values in the original scripts. For those you would tell it a file name to write to (/f:somefile.csv).

I strongly urge you to run this with CScript.exe. You can change the script name, of course :)

Examples of usage:

cscript GetMailboxStatisticsFromList.vbs /l:users.txt
cscript GetMailboxStatisticsFromList.vbs /u:"user1,user2,user3"

Extended output with:

cscript GetMailboxStatisticsFromList.vbs /l:users.txt /f:out.csv

Simple (default) output looks like this:

Name      Size    Number of Items
Mailbox1 1Mb    234
Mailbox2 No Mailbox Data
Mailbox3 230Mb  24503

Lining up the columns is a bit of a pain in the backside which is why I allowed only file output in the original incarnation of this on my blog. Anyway, it's tab delimited so it should pipe to a file easily enough (hopefully).

Chris
' GetMailboxStatisticsFromList.vbs
'
' Retrieves all information relating to mailboxes from Exchange and links in
' relevant information from Active Directory. Only compatible with Exchange 2003 and
' must be run with permission to access WMI, Exchange configuration and AD (read only)
'
' Author: Chris Dent
' Last Modified: 26/05/2009
 
Option Explicit
 
Sub UsageText
 
  Dim strMessage
  strMessage = "Usage:" & VbCrLf & VbCrLf & _
    "cscript " & WScript.ScriptName & " [/l:<UserListFile>] [/u:<UserList>] [/f:<OutputFileName>]" & vbCrlf & vbCrLf & _
      "One of the following parameters must be specified: " & vbCrlf & vbCrLf & _
      "/l      The file containing the list of usernames" & vbCrLf & _
      "/u      A comma delimited list of usernames to execute the script for" & vbCrLf & vbCrLf & _
      "The following parameters are optional:" & vbCrLf & vbCrlf & _
      "/f      File Name for extended output." & vbCrLf
 
  WScript.Echo strMessage
  WScript.Quit
End Sub
 
Sub GetParameters
  Dim objArgsNamed : Set objArgsNamed = WScript.Arguments.Named
 
  If objArgsNamed.Count = 0 Then
    UsageText
  End If
 
  Dim booHasRequiredParam : booHasRequiredParam = False
 
  ' Arguments that may be set. These are mutually exclusive
  If objArgsNamed("l") <> "" Then
    booHasRequiredParam = True
    strUserFile = objArgsNamed("l")
  End If
  If objArgsNamed("u") <> "" Then
    booHasRequiredParam = True
    strUserList = objArgsNamed("u")
  End If
 
  If booHasRequiredParam = False Then
    UsageText
  End If
 
  ' Arguments that are necessary and have default values
  If objArgsNamed("f") <> "" Then
    strFileName = objArgsNamed("f")
  End If
End Sub
 
Function DirectorySearcherFindOne(strLdapPath, strLdapFilter, strPropertiesToLoad)
  ' Returns an array containing the properties returned by the search
 
  Dim objConnection : Set objConnection = CreateObject("ADODB.Connection")
  objConnection.Provider = "ADsDSOObject"
  objConnection.Open "Active Directory Provider"
 
  Dim objRecordSet : Set objRecordSet = objConnection.Execute("<" & strLdapPath & ">;" & _
    strLdapFilter & ";" & strPropertiesToLoad & ";subtree")
 
  Dim arrPropertiesToLoad : arrPropertiesToLoad = Split(strPropertiesToLoad, ",")
 
  If objRecordSet.RecordCount = 1 Then
 
    Dim arrValues()
 
    Dim strProperty, strValue : Dim i : i = 0
    For Each strProperty in arrPropertiesToLoad
      If IsNull(objRecordSet.Fields(strProperty)) Then
        strValue = ""
      Else
        strValue = objRecordSet.Fields(strProperty).Value
        If IsArray(strValue) Then
          strValue = Join(strValue)
        End If
      End If
      ReDim Preserve arrValues(i)
      arrValues(i) = strValue : i = i + 1
    Next
 
    DirectorySearcherFindOne = arrValues
  Else
 
    ReDim arrValues(0) : arrValues(0) = strUsername
    DirectorySearcherFindOne = arrValues
 
  End If
End Function
 
Function GetMailboxFromWMI(strExchServer, strLegacyDN)
  Const WBEM_RETURN_IMMEDIATELY = &h10
  Const WBEM_FORWARD_ONLY = &h20
 
  On Error Resume Next : Err.Clear
  Dim objWMI : Set objWMI = GetObject("winmgmts:\\" & strExchServer & "\root\MicrosoftExchangeV2")
 
  If Err.Number <> 0 Then
    WScript.Echo "WARNING: Failed to connect to Exchange Server " & strExchServer
  Else
    On Error Goto 0
 
    Dim colMailboxes : Set colMailboxes = objWMI.ExecQuery("SELECT * FROM Exchange_Mailbox WHERE " & _
      "LegacyDN='" & strLegacyDN & "'", "WQL", WBEM_RETURN_IMMEDIATELY + WBEM_FORWARD_ONLY)
 
    Dim objMailbox
    For Each objMailbox in colMailboxes
      Set GetMailboxFromWMI = objMailbox
    Next
  End If
 
  ' Return an object regardless. Will test for this in main code.
  If VarType(GetMailboxFromWMI) = vbEmpty Then
    Set GetMailboxFromWMI = CreateObject("Scripting.Dictionary")
  End If
 
  Set objWMI = Nothing
  On Error Goto 0
End Function
 
Sub WriteShortResults(objMailboxesFromWMI, objMailboxesFromAD)
 
  WScript.Echo
  WScript.Echo "Name" & vbTab & "Size" & vbTab & "Number of Items"
 
  Dim strLegacyDN
  For Each strLegacyDN in objMailboxesFromAD
    If objMailboxesFromWMI.Exists(strLegacyDN) Then
      WScript.Echo objMailboxesFromAD(strLegacyDN)(0) & vbTab & _
        ConvertKbToMb(objMailboxesFromWMI(strLegacyDN).Size) & "Mb" & vbTab & _
        objMailboxesFromWMI(strLegacyDN).TotalItems
    Else
      WScript.Echo objMailboxesFromAD(strLegacyDN)(0) & vbTab & "No Mailbox Data"
    End If
  Next
  WScript.Echo
End Sub
 
Sub WriteResults(objMailboxesFromWMI, objMailboxesFromAD, strFileName)
 
  Const ADS_UF_ACCOUNTDISABLE = 2
 
  Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
  On Error Resume Next : Err.Clear
  Dim objFile : Set objFile = objFSO.OpenTextFile(strFileName, 2, True, 0)
  If Err.Number <> 0 Then
    WScript.Echo "The File Name specified appears to be invalid."
    WScript.Quit
  End If
 
  ' Add the header line to the CSV File
 
  objFile.WriteLine "Name,DN,mail,AccountStatus,UseDefaultQuotas,Warn,ProhibitSend," & _
    "ProhibitSendAndReceive,ExchangeServer,Size,TotalItems,MailboxStatus,AssocContentCount," & _
    "DeletedMessageSize,LastLoggedOnUser,LastLogon,LastLogoff,DateDeleted,MailboxDisplayName," & _
    "MailboxGuid,ServerName,StorageGroup,Store,legacyExchangeDN"
 
  Dim strLegacyDN, strLine
  For Each strLegacyDN in objMailboxesFromWMI
    Dim strAccountStatus : strAccountStatus = "Enabled"
    If objMailboxesFromAD(strLegacyDN)(8) And ADS_UF_ACCOUNTDISABLE Then
      strAccountStatus = "Disabled"
    End If
 
    strLine = """" & objMailboxesFromAD(strLegacyDN)(0) & """,""" & _
      objMailboxesFromAD(strLegacyDN)(1) & """," & _
      objMailboxesFromAD(strLegacyDN)(3) & "," & _
      strAccountStatus & "," & _
      objMailboxesFromAD(strLegacyDN)(7) & "," & _
      ConvertKbToMb(objMailboxesFromAD(strLegacyDN)(6)) & "," & _
      ConvertKbToMb(objMailboxesFromAD(strLegacyDN)(5)) & "," & _
      ConvertKbToMb(objMailboxesFromAD(strLegacyDN)(4)) & "," & _
      objMailboxesFromAD(strLegacyDN)(9) & ","
 
    If objMailboxesFromWMI.Exists(strLegacyDN) Then
      strLine = strLine & ConvertKbToMb(objMailboxesFromWMI(strLegacyDN).Size) & "," & _
        objMailboxesFromWMI(strLegacyDN).TotalItems & "," & _
        ConvertStatusToName(objMailboxesFromWMI(strLegacyDN).StorageLimitInfo) & "," & _
        objMailboxesFromWMI(strLegacyDN).AssocContentCount & "," & _
        ConvertKbToMb(objMailboxesFromWMI(strLegacyDN).DeletedMessageSizeExtended) & "," & _
        objMailboxesFromWMI(strLegacyDN).LastLoggedOnUserAccount & "," & _
        ConvertToDate(objMailboxesFromWMI(strLegacyDN).LastLogonTime) & "," & _
        ConvertToDate(objMailboxesFromWMI(strLegacyDN).LastLogoffTime) &" ," & _
        ConvertToDate(objMailboxesFromWMI(strLegacyDN).DateDiscoveredAbsentInDs) & "," & _
        objMailboxesFromWMI(strLegacyDN).MailboxDisplayName & "," & _
        objMailboxesFromWMI(strLegacyDN).MailboxGuid & "," & _
        objMailboxesFromWMI(strLegacyDN).ServerName & ",""" & _
        objMailboxesFromWMI(strLegacyDN).StorageGroupName & """,""" & _
        objMailboxesFromWMI(strLegacyDN).StoreName & """," & _
        strLegacyDN
    Else
 
      strLine = strLine & ",,,,,,,,,,,,,,"
 
    End If
 
    objFile.WriteLine strLine
  Next
End Sub
 
Function ConvertKbToMb(dblValue)
  If Trim(dblValue) = "" Or IsNull(dblValue) Then
    ConvertKbToMb = ""
  Else
    ConvertKbToMb = Round(dblValue / 1024, 2)
  End If
End Function
 
Function ConvertToDate(strDate)
  ' (Slightly) modified function from the MS Scripting guys WMIDateStringToDate
 
  If Trim(strDate) = "" Or IsNull(strDate) Then
    ConvertToDate = ""
  Else
    ConvertToDate = CDate(Mid(strDate, 7, 2) & "/" & _
      Mid(strDate, 5, 2) & "/" & Left(strDate, 4) & " " & _
      Mid(strDate, 9, 2) & ":" & Mid(strDate, 11, 2) & ":" & Mid(strDate, 13, 2))
  End If
End Function
 
Function ConvertStatusToName(intStatus)
  Select Case intStatus
    Case 1  : ConvertStatusToName = "BelowLimit"
    Case 2  : ConvertStatusToName = "IssueWarning"
    Case 4  : ConvertStatusToName = "ProhibitSend"
    Case 8  : ConvertStatusToName = "NoChecking"
    Case 16 : ConvertStatusToName = "MailboxDisabled"
  End Select
End Function
 
'
' Main Code
'
 
Dim strUserList, strUserFile, strFileName
 
GetParameters
 
' Retrieve Mailbox information
 
Dim arrUsers
' If a file is specified
If strUserFile <> "" Then
 
  Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
  Dim objFile : Set objFile = objFSO.OpenTextFile(strUserFile, 1, False, 0)
 
  arrUsers = Split(objFile.ReadAll, vbCrLf)
 
  Set objFile = Nothing
  Set objFSO = Nothing
 
' If a list of users is specified
ElseIf strUserList <> "" Then
 
  arrUsers = Split(strUserList, ",")
 
End If
 
Dim objRootDSE : Set objRootDSE = GetObject("LDAP://RootDSE")
Dim strLdapPath : strLdapPath = "LDAP://" & objRootDSE.Get("defaultNamingContext")
 
Dim objMailboxesFromAD : Set objMailboxesFromAD = CreateObject("Scripting.Dictionary")
Dim objMailboxesFromWMI : Set objMailboxesFromWMI = CreateObject("Scripting.Dictionary")
 
Dim strUsername
For Each strUsername in arrUsers
  If strUsername <> "" Then
 
    Dim strLdapFilter : strLdapFilter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" & _
      strUsername & "))"
 
    Dim strPropertiesToLoad : strPropertiesToLoad = "name,distinguishedName," & _
      "legacyExchangeDN,mail,mDBOverHardQuotaLimit,mDBOverQuotaLimit," & _
      "mDBStorageQuota,mDBUseDefaults,userAccountControl,msExchHomeServerName"
 
    Dim arrProperties : arrProperties = DirectorySearcherFindOne(strLdapPath, strLdapFilter, strPropertiesToLoad)
    If UBound(arrProperties) > 1 Then
      objMailboxesFromAD.Add arrProperties(2), arrProperties
      If arrProperties(9) <> "" Then
        Dim objMailbox
        Set objMailbox = GetMailboxFromWMI(Split(arrProperties(9), "=")(UBound(Split(arrProperties(9), "="))), _
         arrProperties(2))
 
        On Error Resume Next : Err.Clear
        Dim strTemp : strTemp = objMailbox.LegacyDN
        If Err.Number = 0 Then
          objMailboxesFromWMI.Add arrProperties(2), objMailbox
        End If
        On Error Goto 0
      End If
    Else
      WScript.Echo strUsername & ": Not found in AD"
    End If
  End If
Next
 
If strFileName = "" Then
  WriteShortResults objMailboxesFromWMI, objMailboxesFromAD
Else
  WriteResults objMailboxesFromWMI, objMailboxesFromAD, strFileName
  WScript.Echo "Script Complete. Output written to " & strFileName
End If

Open in new window

0
Chris DentPowerShell DeveloperCommented:

And this is the short version, dropping out everything except the really necessary bits. It only returns the mailbox name, size and number of items. No command line parameters, fill in the constants at the top and run it. I still recommend using "cscript" as it will drop output to the command line with that.

If you will only ever need the size and item count this is much more appropriate.

Chris
Option Explicit
 
Const FILE_NAME = "users.txt"
Const EXCHANGE_SERVER = "YourExchangeServer"
 
Function GetObjectDN(strObject, strDomain)
  ' Return Type: String
  '
  ' Returns a Distinguished Name for an Object from it's NT SAM ID.
  ' This will only function for valid object types within an NT Domain structure.
 
  Const ADS_NAME_INITTYPE_GC = 3
  Const ADS_NAME_TYPE_1779 = 1
  Const ADS_NAME_TYPE_NT4 = 3
 
  If strDomain = "" Then
    Dim objNetwork : Set objNetwork = CreateObject("WScript.Network")
    strDomain = objNetwork.UserDomain
    Set objNetwork = Nothing
  End If
 
  On Error Resume Next : Err.Clear
  Dim objNameTranslate : Set objNameTranslate = CreateObject("NameTranslate")
 
  objNameTranslate.Init ADS_NAME_INITTYPE_GC, ""
  objNameTranslate.Set ADS_NAME_TYPE_NT4, strDomain & "\" & strObject
  Dim strObjectDN : strObjectDN = objNameTranslate.Get(ADS_NAME_TYPE_1779)
 
  If Err.Number <> 0 Then strObjectDN = ""
 
  Set objNameTranslate = Nothing
  On Error Goto 0
 
  GetObjectDN = strObjectDN
End Function
 
Function ConvertKbToMb(dblValue)
  If Trim(dblValue) = "" Or IsNull(dblValue) Then
    ConvertKbToMb = ""
  Else
    ConvertKbToMb = Round(dblValue / 1024, 2)
  End If
End Function
 
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objFile : Set objFile = objFSO.OpenTextFile(FILE_NAME, 1, False, 0)
 
Dim objWMI : Set objWMI = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")
 
WScript.Echo "Name" & vbTab & "Size" & vbTab & "Total Items"
 
Do Until objFile.AtEndOfStream
  Dim strUsername : strUsername = Trim(objFile.ReadLine)
  If strUserName <> "" Then
 
    Dim strDN : strDN = GetObjectDN(strUsername, "")
 
    If strDN = "" Then
      WScript.Echo strUsername & vbTab & "Not found in AD"
    Else
      Dim objUser : Set objUser = GetObject("LDAP://" & strDN)
      Dim strMessage : strMessage = objUser.Get("name")
 
      On Error Resume Next
      Dim strLegacyDN : strLegacyDN = "" : strLegacyDN = objUser.Get("legacyExchangeDN")
      On Error Goto 0
 
      If strLegacyDN <> "" Then
 
        Dim colMailboxes : Set colMailboxes = objWMI.ExecQuery("SELECT * FROM Exchange_Mailbox WHERE " & _
          "LegacyDN='" & strLegacyDN & "'", "WQL")
 
        Dim objMailbox
        For Each objMailbox in colMailboxes
          strMessage = strMessage & vbTab & ConvertKbToMb(objMailbox.Size) & "Mb" & _
            vbTab & objMailbox.TotalItems
        Next
      End If
 
      WScript.Echo strMessage
 
      Set objUser = Nothing
    End If
  End If
Loop

Open in new window

0
siber1Author Commented:
Hi Chris,
thanks for the scripts. The last one you posted should work well. One thing, is there any way you can modify it to show a count of the "inbox items" specifically, not the a total count of messages?
this is useful for us to identify mailboxes that exceed the recommended max inbox item count documented by MSFT.

many thanks in advance.

-Mike
0
Chris DentPowerShell DeveloperCommented:

Not easily, we'd have to log onto the mailbox using MAPI / WebDAV and count from there. It's quite unpleasant to work with those. Exchange 2007 can do it natively, but that's not much help here :)

Chris
0
siber1Author Commented:
sure I understand. This is still very useful the scripts you provided.
appreicate your assistance.

-Mike
0
siber1Author Commented:
Chris, i just noticed this post on the script center:
http://www.microsoft.com/technet/scriptcenter/resources/qanda/jan06/hey0116.mspx

is there anyway to incorporate this code into the last script you posted to pull the inbox item count:



Const olFolderInbox = 6
Const olFolderSentMail = 5
 
Set objOutlook = CreateObject("Outlook.Application")
Set objNamespace = objOutlook.GetNamespace("MAPI")
   
Set objFolder = objNamespace.GetDefaultFolder(olFolderInbox)
Set colItems = objFolder.Items
Wscript.Echo "No. of items in Inbox: " & colItems.Count
 
For Each objItem in colItems
    intSize = intSize + objItem.Size
Next
 
Wscript.Echo "Size of Inbox: " & Int(intSize / 1024) & " KB"
 
intSize = 0
 
Set objFolder = objNamespace.GetDefaultFolder(olFolderSentMail)
Set colItems = objFolder.Items
Wscript.Echo "No. of items in Sent Mail folder: " & colItems.Count
 
For Each objItem in colItems
    intSize = intSize + objItem.Size
Next
 
Wscript.Echo "Size of Sent Mail folder: " & Int(intSize / 1024) & " KB"

Open in new window

0
Chris DentPowerShell DeveloperCommented:

Seems to be rather lacking in a place to say which mailbox to connect to unfortunately.

It needs this one really:

http://support.microsoft.com/kb/320071

I've used it before, but not for a long time and never enjoyed it ;)

Chris
0
Chris DentPowerShell DeveloperCommented:

Anyway, I'll have a look, just have to re-acquaint myself WebDAV. It's the easiest option, doesn't require installation of "stuff" on the system running the script.

The downside to is that the account executing the script needs Full Mailbox Access to every mailbox (might test it with Read Permission, just in case).

Chris
0
siber1Author Commented:
thanks very much Chris. look forward to the script!
-Mike
0
siber1Author Commented:
Chris, any progress on this?

thx - Mike
0
Chris DentPowerShell DeveloperCommented:

Not really, having trouble remembering what I did to get WebDAV access working in the first place ;)

Chris
0
Chris DentPowerShell DeveloperCommented:

For the these... Just the Inbox folder, or the Inbox folder and all subfolders?

Chris
0
siber1Author Commented:
really just need the inbox folder message count.

thanks Chris
0
Chris DentPowerShell DeveloperCommented:

This kind of works. Afraid you have to hard-code a fair bit of information to have it run. Can't seem to get it to pass the current user name and password on execution.

If you ever upgrade to Exchange 2007 this functionality is covered with Get-MailboxFolderStatistics which uses MAPI to do it, but MS wrote it so it's better than my stuff ;)

It'll probably need the size value converting up a bit, I think it's in Bytes at the moment, but my test system is small so if you have any means to verify... :)

Chris
Option Explicit
 
Const FILE_NAME = "users.txt"
Const EXCHANGE_SERVER = "legacy-exch-01"
' Used to generate the WEBDAV_PATH. Value comes from Default Recipient Policy.
Const DEFAULT_SMTP_DOMAIN = "yourdomain.com"
' An Exchange Admin
Const ADMIN_USER = "AdminUser"
Const ADMIN_PASSWORD = "SomePassword"
 
Dim WEBDAV_PATH : WEBDAV_PATH = "http://" & EXCHANGE_SERVER & "/ExAdmin/Admin/" & _
  DEFAULT_SMTP_DOMAIN & "/MBX"
 
Function GetObjectDN(strObject, strDomain)
  ' Return Type: String
  '
  ' Returns a Distinguished Name for an Object from it's NT SAM ID.
  ' This will only function for valid object types within an NT Domain structure.
 
  Const ADS_NAME_INITTYPE_GC = 3
  Const ADS_NAME_TYPE_1779 = 1
  Const ADS_NAME_TYPE_NT4 = 3
 
  If strDomain = "" Then
    Dim objNetwork : Set objNetwork = CreateObject("WScript.Network")
    strDomain = objNetwork.UserDomain
    Set objNetwork = Nothing
  End If
 
  On Error Resume Next : Err.Clear
  Dim objNameTranslate : Set objNameTranslate = CreateObject("NameTranslate")
 
  objNameTranslate.Init ADS_NAME_INITTYPE_GC, ""
  objNameTranslate.Set ADS_NAME_TYPE_NT4, strDomain & "\" & strObject
  Dim strObjectDN : strObjectDN = objNameTranslate.Get(ADS_NAME_TYPE_1779)
 
  If Err.Number <> 0 Then strObjectDN = ""
 
  Set objNameTranslate = Nothing
  On Error Goto 0
 
  GetObjectDN = strObjectDN
End Function
 
Function GetFolderSize(strUrl, dblSize, dblMessageCount)
  ' Modified from original: http://support.microsoft.com/kb/320071
 
  Dim oXMLHttp : Set oXMLHttp = CreateObject("Microsoft.xmlhttp")
 
  ' Open DAV connection.
  oXMLHttp.open "SEARCH", strURL, False, ADMIN_USER, ADMIN_PASSWORD
 
  ' Set up query.
  Dim sQuery : 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 """ & strUrl & """') "
  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
 
  ' Load XML.
  Dim oXMLDoc : Set oXMLDoc = oXMLHttp.responseXML
 
  ' Get the XML nodes that contain the individual sizes.
  Dim oXMLSizeNodes : Set oXMLSizeNodes = oXMLDoc.getElementsByTagName("d:x0e080003")
 
  ' Get the XML nodes that contain the individual HREFs.
  Dim oXMLHREFNodes : Set oXMLHREFNodes = oXMLDoc.getElementsByTagName("a:href")
 
  ' Get the XML nodes that contain the individual HasSubs.
  Dim oXMLHasSubsNodes : Set oXMLHasSubsNodes = oXMLDoc.getElementsByTagName("a:hassubs")
 
  ' Loop through the nodes, and then add all of the sizes.
  Dim i
  For i = 0 to oXMLSizeNodes.Length - 1
 
    If InStr(oXMLHREFNodes.Item(i).nodeTypedValue, "Inbox") > 0 Then
 
      dblMessageCount = GetMessageCount(oXMLHREFNodes.Item(i).nodeTypedValue, dblMessageCount)
      dblSize = dblSize + oXMLSizeNodes.Item(i).nodeTypedValue
 
      ' If the folder has subfolders, call your recursive function to 
      ' process subfolders.
      If oXMLHasSubsNodes.Item(i).nodeTypedValue = True Then
 
        dblSize = GetFolderSize(oXMLHREFNodes.Item(i).nodeTypedValue, dblSize, dblMessageCount)(0)
 
      End If
    End If
  Next
 
  GetFolderSize = Array(dblSize, dblMessageCount)
End Function
 
Function GetMessageCount(strURL, dblMessageCount)
 
  Dim objRequest : Set objRequest = CreateObject("Microsoft.XMLHTTP")
  objRequest.Open "SEARCH", strURL, False, ADMIN_USER, ADMIN_PASSWORD
 
  Dim strQuery : strQuery = "<?xml version=""1.0""?>" &_
    "<D:searchrequest xmlns:D = ""DAV:""" &_
    " xmlns:b=""urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"">" &_
    "<D:sql>SELECT ""DAV:displayname"", ""urn:schemas:httpmail:subject"", " &_
    """DAV:creationdate"", ""DAV:getcontentlength"", " &_
    """urn:schemas:httpmail:fromemail""" &_
    " FROM scope('SHALLOW TRAVERSAL OF """ & strURL &_
    """') WHERE ""DAV:ishidden"" = FALSE AND ""DAV:isfolder"" = FALSE " &_
    "</D:sql></D:searchrequest>"
 
  objRequest.SetRequestHeader "Content-Type", "text/xml"
  objRequest.SetRequestHeader "Translate", "f"
  objRequest.Send strQuery
 
  If objRequest.Status = 207 Then
    Dim objXMLDocument : Set objXMLDocument = objRequest.ResponseXML
    Dim objHREFS : Set objHREFs = objXMLDocument.GetElementsByTagName("a:href")
 
    GetMessageCount = dblMessageCount + objHREFS.Length
  End If
End Function
 
'
' Main code
'
 
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objFile : Set objFile = objFSO.OpenTextFile(FILE_NAME, 1, False, 0)
 
WScript.Echo "Name" & vbTab & "Size" & vbTab & "Total Items"
 
Do Until objFile.AtEndOfStream
  Dim strUsername : strUsername = Trim(objFile.ReadLine)
  If strUserName <> "" Then
 
    Dim strDN : strDN = GetObjectDN(strUsername, "")
 
    If strDN = "" Then
      WScript.Echo strUsername & vbTab & "Not found in AD"
    Else
      Dim objUser : Set objUser = GetObject("LDAP://" & strDN)
      Dim strMessage : strMessage = objUser.Get("name")
 
      On Error Resume Next
      Dim strURL : strURL = "" : strURL = WEBDAV_PATH & "/" & objUser.Get("mailNickName")
      On Error Goto 0
 
      If strURL <> "" Then
        Dim arrSize : arrSize = GetFolderSize(strURL, 0, 0)
        strMessage = strMessage & vbTab & arrSize(0) & vbTab & arrSize(1)
      End If
      WScript.Echo strMessage
    End If
  End If
Loop

Open in new window

0
Chris DentPowerShell DeveloperCommented:

This version is a little easier on the head. It just lists the size and item count for the Inbox folder on its own. Previous version dumped Inbox and all subfolders.

Chris
Option Explicit
 
Const FILE_NAME = "users.txt"
Const EXCHANGE_SERVER = "legacy-exch-01"
Const DEFAULT_SMTP_DOMAIN = "tset.com"
Const ADMIN_USER = "adm-dentc"
Const ADMIN_PASSWORD = "Epsilon123"
 
Dim WEBDAV_PATH : WEBDAV_PATH = "http://" & EXCHANGE_SERVER & "/ExAdmin/Admin/" & _
  DEFAULT_SMTP_DOMAIN & "/MBX"
 
Function GetObjectDN(strObject, strDomain)
  ' Return Type: String
  '
  ' Returns a Distinguished Name for an Object from it's NT SAM ID.
  ' This will only function for valid object types within an NT Domain structure.
 
  Const ADS_NAME_INITTYPE_GC = 3
  Const ADS_NAME_TYPE_1779 = 1
  Const ADS_NAME_TYPE_NT4 = 3
 
  If strDomain = "" Then
    Dim objNetwork : Set objNetwork = CreateObject("WScript.Network")
    strDomain = objNetwork.UserDomain
    Set objNetwork = Nothing
  End If
 
  On Error Resume Next : Err.Clear
  Dim objNameTranslate : Set objNameTranslate = CreateObject("NameTranslate")
 
  objNameTranslate.Init ADS_NAME_INITTYPE_GC, ""
  objNameTranslate.Set ADS_NAME_TYPE_NT4, strDomain & "\" & strObject
  Dim strObjectDN : strObjectDN = objNameTranslate.Get(ADS_NAME_TYPE_1779)
 
  If Err.Number <> 0 Then strObjectDN = ""
 
  Set objNameTranslate = Nothing
  On Error Goto 0
 
  GetObjectDN = strObjectDN
End Function
 
Function GetFolderSize(strUrl)
  ' Modified from original: http://support.microsoft.com/kb/320071
 
  Dim oXMLHttp : Set oXMLHttp = CreateObject("Microsoft.xmlhttp")
 
  ' Open DAV connection.
  oXMLHttp.open "SEARCH", strURL, False, ADMIN_USER, ADMIN_PASSWORD
 
  ' Set up query.
  Dim sQuery : 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 """ & strUrl & """') "
  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
 
  ' Load XML.
  Dim oXMLDoc : Set oXMLDoc = oXMLHttp.responseXML
 
  ' Get the XML nodes that contain the individual sizes.
  Dim oXMLSizeNodes : Set oXMLSizeNodes = oXMLDoc.getElementsByTagName("d:x0e080003")
 
  ' Get the XML nodes that contain the individual HREFs.
  Dim oXMLHREFNodes : Set oXMLHREFNodes = oXMLDoc.getElementsByTagName("a:href")
 
  ' Get the XML nodes that contain the individual HasSubs.
  Dim oXMLHasSubsNodes : Set oXMLHasSubsNodes = oXMLDoc.getElementsByTagName("a:hassubs")
 
  ' Loop through the nodes, and then add all of the sizes.
  Dim i
  For i = 0 to oXMLSizeNodes.Length - 1
 
    If InStr(oXMLHREFNodes.Item(i).nodeTypedValue, "Inbox") > 0 Then
 
      Dim dblMessageCount : dblMessageCount = GetMessageCount(oXMLHREFNodes.Item(i).nodeTypedValue)
      Dim dblSize : dblSize = oXMLSizeNodes.Item(i).nodeTypedValue
 
    End If
  Next
 
  GetFolderSize = Array(dblSize, dblMessageCount)
End Function
 
Function GetMessageCount(strURL)
 
  Dim objRequest : Set objRequest = CreateObject("Microsoft.XMLHTTP")
  objRequest.Open "SEARCH", strURL, False, ADMIN_USER, ADMIN_PASSWORD
 
  Dim strQuery : strQuery = "<?xml version=""1.0""?>" &_
    "<D:searchrequest xmlns:D = ""DAV:""" &_
    " xmlns:b=""urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"">" &_
    "<D:sql>SELECT ""DAV:displayname"", ""urn:schemas:httpmail:subject"", " &_
    """DAV:creationdate"", ""DAV:getcontentlength"", " &_
    """urn:schemas:httpmail:fromemail""" &_
    " FROM scope('SHALLOW TRAVERSAL OF """ & strURL &_
    """') WHERE ""DAV:ishidden"" = FALSE AND ""DAV:isfolder"" = FALSE " &_
    "</D:sql></D:searchrequest>"
 
  objRequest.SetRequestHeader "Content-Type", "text/xml"
  objRequest.SetRequestHeader "Translate", "f"
  objRequest.Send strQuery
 
  If objRequest.Status = 207 Then
    Dim objXMLDocument : Set objXMLDocument = objRequest.ResponseXML
    Dim objHREFS : Set objHREFs = objXMLDocument.GetElementsByTagName("a:href")
 
    GetMessageCount = objHREFS.Length
  End If
End Function
 
'
' Main code
'
 
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objFile : Set objFile = objFSO.OpenTextFile(FILE_NAME, 1, False, 0)
 
WScript.Echo "Name" & vbTab & "Size" & vbTab & "Total Items"
 
Do Until objFile.AtEndOfStream
  Dim strUsername : strUsername = Trim(objFile.ReadLine)
  If strUserName <> "" Then
 
    Dim strDN : strDN = GetObjectDN(strUsername, "")
 
    If strDN = "" Then
      WScript.Echo strUsername & vbTab & "Not found in AD"
    Else
      Dim objUser : Set objUser = GetObject("LDAP://" & strDN)
      Dim strMessage : strMessage = objUser.Get("name")
 
      On Error Resume Next
      Dim strURL : strURL = "" : strURL = WEBDAV_PATH & "/" & objUser.Get("mailNickName")
      On Error Goto 0
 
      If strURL <> "" Then
        Dim arrSize : arrSize = GetFolderSize(strURL)
        strMessage = strMessage & vbTab & arrSize(0) & vbTab & arrSize(1)
      End If
      WScript.Echo strMessage
    End If
  End If
Loop

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
siber1Author Commented:
thanks so much Chris. this works fine.
best - Mike
0
he_who_daresCommented:
Chaps is it poss to amend that code so it also shows the sent item count aswell you think?
0
he_who_daresCommented:
Also has anyone managed to pipe this to a txt or csv as i am trying the following and it only displays in a cmd prompt

cscript script.vbs -f zzz.txt

cscript script.vbs /f:zzz.csv


Im referring to the script in the "Accepted Solution"
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
VB Script

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.