Link to home
Start Free TrialLog in
Avatar of juragan
juragan

asked on

AD attribute for user's mailbox size?

Hi,

Does anyone know the AD attribute for current user's mailbox size?

I want to export user's AD attributes as well as Exchange related attribute. I can find the AD attributes for user's soft and hard quota, but can not find AD attribute for the current user's mailbox size.  I want to export these informations using a tool such as exporter pro. If I export the mailbox size list into csv using ESM, then it would required lot of work to combine it with the other report I made.


Avatar of Sembee
Sembee
Flag of United Kingdom of Great Britain and Northern Ireland image

I don't believe the current mailbox size is stored in the domain as it is a variable amount. Exchange reads the quota that is stored in the domain, but doesn't report the size back.

Simon.
Avatar of Jejin Joseph
Well if your intention is to extract the mailbox size for reporting, this script might help you get that information. http://support.microsoft.com/kb/320071

I haven't a clue what Exporter Pro is... But...

Which version of Exchange?

Exchange 2003 has a WMI component that will report the size of all mailboxes on the server. I can show you code for that if you wish.

Chris
Avatar of juragan
juragan

ASKER

It is a software from SystemTools.com.
I am using Exchange 2003 Enterprise.  Would appreciate if you can show me the code.



Here we go, it's quite long but will create a Tab Delimited Text File (called MailboxSizes.txt) containing all Exchange Users (and a few accidental extra's normally), their mailbox sizes, whether they use the default Store Limits or not (and if they don't what has been set), and the mailbox store they're in.

It also echo's that output so please run the script with CScript of you'll get a hell of a lot of popup boxes. i.e.:

C:\> cscript <ScriptName.vbs>

Finally it creates a summary of how much space is taken up if you were to split stores into alphabetical order as we do (AlphabeticalTotal.txt).

The only thing you need to change is the EXCHANGE_SERVER constant at the beginning (save this as .vbs and make sure you read the opening comment):



' Retrieves information relating to Mailbox Sizes. Must be run as Exchange Administrator and must be run from a
' machine with the Exchange System Tools installed. Only compatible with Exchange 2003.
'
' Author: Chris Dent
' Last Modified: 10/10/2006

Option Explicit

' Global Constants

Const EXCHANGE_SERVER = "<ExhangeServerName>"

' Global Variables

Dim objResults

'
' Functions
'

Function FormatGUID(arrGUID)
      Dim strGUID, strTemp
      Dim i

      For i = LBound(arrGUID) To UBound(arrGUID)
            strTemp = strTemp & Hex(AscB(MidB(arrGUID, i + 1, 1)) \ 16) &_
                  Hex(AscB(MidB(arrGUID, i + 1, 1)) Mod 16)
      Next

      ' Reversed Pairs

      i = 0
      strGUID = "{"
      Do Until i = 8
            strGUID = strGUID & Mid(strTemp, 7 - i, 1)
            strGUID = strGUID & Mid(strTemp, 8 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 12
            strGUID = strGUID & Mid(strTemp, 19 - i, 1)
            strGUID = strGUID & Mid(strTemp, 20 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 16
            strGUID = strGUID & Mid(strTemp, 15 - i + 12, 1)
            strGUID = strGUID & Mid(strTemp, 16 - i + 12, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"

      ' Normal Pairs

      For i = 17 to 20
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "-"
      For i = 21 to 32
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "}"
      FormatGUID = strGUID
End Function

'
' Subroutines
'

Sub GetADData
      Const ADS_SCOPE_SUBTREE = 2

      Dim objConnection, objCommand, objRootDSE, objRecordSet
      Dim strDisplayName, strUseLimits, strLimit, strSize, strStore, strMailboxGUID
      Dim booUseLimits

      Set objConnection = CreateObject("ADODB.Connection")
      objConnection.Provider = "ADsDSOObject"
      objConnection.Open "Active Directory Provider"
      
      Set objCommand = CreateObject("ADODB.Command")
      objCommand.ActiveConnection = objConnection

      Set objRootDSE = GetObject("LDAP://RootDSE")

      objCommand.CommandText = "SELECT displayName, mDBUseDefaults, " &_
                  "mDBStorageQuota, msExchMailboxGUID FROM 'LDAP://" &_
                  objRootDSE.Get("defaultNamingContext") & "' WHERE " &_
                  "objectCategory='CN=Person,CN=Schema," & objRootDSE.Get("configurationNamingContext") & "'"

      Set objRootDSE = Nothing
      
      objCommand.Properties("Page Size") = 1000
      objCommand.Properties("Timeout") = 600
      objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
      objCommand.Properties("Cache Results") = False
      
      Set objRecordSet = objCommand.Execute
      
      While Not objRecordSet.EOF
            If Not IsNull(objRecordSet.Fields("msExchMailboxGUID")) Then
                  strMailboxGUID = FormatGUID(objRecordSet.Fields("msExchMailboxGUID"))
                  
                  If Not objResults.Exists(strMailboxGUID) Then
                        booUseLimits = objRecordSet.Fields("mDBUseDefaults")
                        If booUseLimits = True Then
                              strUseLimits = "True"
                        Else
                              strUseLimits = "False"
                        End If

                        strDisplayName = objRecordSet.Fields("displayName")
                        strLimit = objRecordSet.Fields("mDBStorageQuota")
            
                        objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                                    strSize, strStore)
                  End If
            End If
            objRecordSet.MoveNext
      Wend
      
      objConnection.Close
      
      Set objRecordSet = Nothing
      Set objCommand = Nothing
      Set objConnection = Nothing
End Sub

Sub GetMailboxes
      Const WBEM_RETURN_IMMEDIATELY = &h10
      Const WBEM_FORWARD_ONLY = &h20

      Dim objWMIService, objMailbox
      Dim colMailboxes
      Dim strMailboxGUID, strDisplayName, strLimit, strUseLimits, strSize, strStore

      Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")
      Set colMailboxes = objWMIService.ExecQuery("SELECT * FROM Exchange_Mailbox", "WQL",_
                  WBEM_RETURN_IMMEDIATELY + WBEM_FORWARD_ONLY)

      For Each objMailbox In colMailboxes
            If objMailbox.ServerName = EXCHANGE_SERVER Then
                  If InStr(objMailbox.MailboxDisplayName, "SystemMailbox") = 0 And _
                              InStr(objMailbox.MailboxDisplayName, "UKEXBE01") = 0 Then

                        strMailboxGUID = objMailbox.MailboxGUID

                        If objResults.Exists(strMailboxGUID) Then
                              strDisplayName = objResults(strMailboxGUID)(0)
                              strLimit = objResults(strMailboxGUID)(1)
                              strUseLimits  = objResults(strMailboxGUID)(2)
                              strSize = objMailbox.Size
                              strStore = objMailbox.StoreName
                        
                              objResults.Remove strMailboxGUID
                              objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                                          strSize, strStore)
                        End If
                  End If
            End If
      Next
      
      Set colMailboxes = Nothing
      Set objWMIService = Nothing
End Sub

Sub WriteResults
      Dim objFileSystem, objFile
      Dim strEcho, strLine, strMailboxGUID, strDisplayName, strLimit, strUseLimits, strSize, strStore
      Dim i, intTotal

      Set objFileSystem = CreateObject("Scripting.FileSystemObject")
      Set objFile = objFileSystem.OpenTextFile("MailboxSizes.txt", 2, True, 0)
      
      strLine = "Display Name" & VbTab & "Limit on Account" & VbTab &_
            "Use Limits Enabled" & VbTab & "Size on Server" & VbTab & "Storage Group"
      objFile.WriteLine strLine
      
      For Each strMailboxGUID in objResults
            strDisplayName = objResults(strMailboxGUID)(0)
            strLimit = objResults(strMailboxGUID)(1)
            strUseLimits = objResults(strMailboxGUID)(2)
            strSize = objResults(strMailboxGUID)(3)
            strStore = objResults(strMailboxGUID)(4)
      
            strEcho = strDisplayName & ": " 
            If strUseLimits = False Then
                  strEcho = strEcho & "Limit: " & strLimit & " - "
            End If
            strEcho = strEcho & "Size: " & strSize & " - Store: " & strStore
            WScript.Echo strEcho
      
            strLine = strDisplayName & VbTab & strLimit & VbTab & strUseLimits &_
                  VbTab & strSize & VbTab & strStore
                  
            objFile.WriteLine strLine
      Next
      
      Set objFile = Nothing
      
      Set objFile = objFileSystem.OpenTextFile("AlphabeticalTotal.txt", 2, True, 0)
      For i = 65 to 90
            intTotal = 0
            For Each strMailboxGUID in objResults
                  If Left(objResults(strMailboxGUID)(0), 1) = Chr(i) Then
                        If IsNumeric(objResults(strMailboxGUID)(3)) Then
                              intTotal = intTotal + CDbl(objResults(strMailboxGUID)(3))
                        End If
                  End If
            Next
            objFile.WriteLine Chr(i) & VbTab & intTotal
      Next
End Sub

'
' Main Code
'

Set objResults = CreateObject("Scripting.Dictionary")

GetADData
GetMailboxes
WriteResults

Set objResults = Nothing

One more note. All sizes are in Kb as this is how Exchange holds them; I don't convert those anywhere in the script.

Chris
Nice script.

Two things...

1. Is UKEXBE01 supposed to be in there?
2. The variable doesn't seem to be right just above it. If I change the Exchange_Server to the server's real name, then remove the " and & then the script runs fine - although doesn't drop dump the mailbox size.

Simon.

1. Nope, that would be mine, I forgot to remove it and change it for EXCHANGE_SERVER.

2. Where are you removing those from?

There are only really two important places that use the constant:

Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")

And:

If objMailbox.ServerName = EXCHANGE_SERVER Then

For that the EXCHANGE

The rest are pretty meaningless in the scheme of things.

Anyway, that bit must run correctly or it won't pick up the mailbox sizes at all. The mailboxes themselves are matched to the User Accout via the MailboxGUID (which is hopefully clear anyway).

Chris
It was this one that I was changing:

    Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")

Originally it would generate a cannot find server error.

I can run the script, it picks up the mailboxes, but it doesn't show the size.

Simon.

Hey Simon,

There are a couple of things I didn't think of at the time. Mainly because the constant was a last minute addition (it was only for figuring out how we needed to organise our mailbox stores when we move everything over).

First of all:

    Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")

When it concatenates the strings including the Constant it must end up with a valid connection string; from the error you're getting the network name is not able to resolve. Can you try replacing that line with:

    Set objWMIService = GetObject("winmgmts:\\SomeExchangeHostName\root\MicrosoftExchangeV2")

Where SomeExchangeHostName is (naturally) the name of your own Exchange Server. Whatever happens it must be able to resolve the hostname.

Then it would perhaps be good to remove one of the If Statements in the loop below for the time-being as it's case sensitive and could easily break the query after the connection is established (which I should have accounted for in the first place).

This is the block of code:

     For Each objMailbox In colMailboxes
          If objMailbox.ServerName = EXCHANGE_SERVER Then
               If InStr(objMailbox.MailboxDisplayName, "SystemMailbox") = 0 And _
                         InStr(objMailbox.MailboxDisplayName, "UKEXBE01") = 0 Then

                    strMailboxGUID = objMailbox.MailboxGUID

                    If objResults.Exists(strMailboxGUID) Then
                         strDisplayName = objResults(strMailboxGUID)(0)
                         strLimit = objResults(strMailboxGUID)(1)
                         strUseLimits  = objResults(strMailboxGUID)(2)
                         strSize = objMailbox.Size
                         strStore = objMailbox.StoreName
                   
                         objResults.Remove strMailboxGUID
                         objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                                   strSize, strStore)
                    End If
               End If
          End If
     Next

And it should be replaced with:

     For Each objMailbox In colMailboxes
          If InStr(objMailbox.MailboxDisplayName, "SystemMailbox") = 0 Then

               strMailboxGUID = objMailbox.MailboxGUID

               If objResults.Exists(strMailboxGUID) Then
                    strDisplayName = objResults(strMailboxGUID)(0)
                    strLimit = objResults(strMailboxGUID)(1)
                    strUseLimits  = objResults(strMailboxGUID)(2)
                    strSize = objMailbox.Size
                    strStore = objMailbox.StoreName
                   
                    objResults.Remove strMailboxGUID
                    objResults.Add strMailboxGUID, Array(strDisplayName, strLimit, strUseLimits,_
                              strSize, strStore)
               End If
          End If
     Next

That also removes one of the filters for generally meaningless mailboxes - it'll be easy enough to strip those out with Excel anyway.

I'll repost the script with these edits in a moment so it's not quite so much messing around.

Chris
I made the change you outlined already and it partially worked - hence my second comment in my post above.

You left UKEXBE01 in again...

I will wait for you to post the complete code and then I will test it again. I have a couple of sites to work on it for now.

Do you have a web site to share this with the wider community?

Simon.

> Do you have a web site to share this with the wider community?

I have the space, I just haven't really got around to documenting all of this sufficiently to add it on there. I'll make a bit of an effort to get it all sorted out at some point.

In the meantime:

I left it in intentionally that time; I figure it's too late to pretend it's not there.

This is the complete code again with some fixes additions (mainly mDBOverQuotaLimit). It won't worry too much about the Name of the server this time as long as it can resolve it to an IP somewhere and actually complete the WMI connection (that's all it's used for). If you're running it from the Exchange Server itself then it can just be ".".

It's still restricted to Exchange 2003 of course, and if it's running from an alternate PC it must be the System Tools for that version (just for the WMI components). As before it must be run as an Exchange Administrator.


' Retrieves information relating to Mailbox Sizes. Must be run as Exchange Administrator and must be run from a
' machine with the Exchange System Tools installed. Only compatible with Exchange 2003.
'
' Author: Chris Dent
' Last Modified: 10/10/2006

Option Explicit

' Global Constants

Const EXCHANGE_SERVER = "ServerName"

' Global Variables

Dim objResults

'
' Functions
'

Function FormatGUID(arrGUID)
      Dim strGUID, strTemp
      Dim i

      For i = LBound(arrGUID) To UBound(arrGUID)
            strTemp = strTemp & Hex(AscB(MidB(arrGUID, i + 1, 1)) \ 16) &_
                  Hex(AscB(MidB(arrGUID, i + 1, 1)) Mod 16)
      Next

      ' Reversed Pairs

      i = 0
      strGUID = "{"
      Do Until i = 8
            strGUID = strGUID & Mid(strTemp, 7 - i, 1)
            strGUID = strGUID & Mid(strTemp, 8 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 12
            strGUID = strGUID & Mid(strTemp, 19 - i, 1)
            strGUID = strGUID & Mid(strTemp, 20 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"
      Do Until i = 16
            strGUID = strGUID & Mid(strTemp, 27 - i, 1)
            strGUID = strGUID & Mid(strTemp, 28 - i, 1)
            i = i + 2
      Loop
      strGUID = strGUID & "-"

      ' Normal Pairs

      For i = 17 to 20
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "-"
      For i = 21 to 32
            strGUID = strGUID & Mid(strTemp, i, 1)
      Next
      strGUID = strGUID & "}"
      FormatGUID = strGUID
End Function

'
' Subroutines
'

Sub GetADData
      Const ADS_SCOPE_SUBTREE = 2

      Dim objConnection, objCommand, objRootDSE, objRecordSet
      Dim strDisplayName, strUseLimits, strSize, strStore, strMailboxGUID
      Dim strWarnLimit, strQuotaLimit
      Dim booUseLimits

      Set objConnection = CreateObject("ADODB.Connection")
      objConnection.Provider = "ADsDSOObject"
      objConnection.Open "Active Directory Provider"
      
      Set objCommand = CreateObject("ADODB.Command")
      objCommand.ActiveConnection = objConnection

      Set objRootDSE = GetObject("LDAP://RootDSE")

      objCommand.CommandText = "SELECT displayName, mDBUseDefaults, " &_
                  "mDBStorageQuota, mDBOverQuotaLimit, msExchMailboxGUID FROM 'LDAP://" &_
                  objRootDSE.Get("defaultNamingContext") & "' WHERE " &_
                  "objectCategory='CN=Person,CN=Schema," & objRootDSE.Get("configurationNamingContext") & "'"

      Set objRootDSE = Nothing
      
      objCommand.Properties("Page Size") = 1000
      objCommand.Properties("Timeout") = 600
      objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
      objCommand.Properties("Cache Results") = False
      
      Set objRecordSet = objCommand.Execute
      
      While Not objRecordSet.EOF
            If Not IsNull(objRecordSet.Fields("msExchMailboxGUID")) Then
                  strMailboxGUID = FormatGUID(objRecordSet.Fields("msExchMailboxGUID"))
                  
                  If Not objResults.Exists(strMailboxGUID) Then
                        booUseLimits = objRecordSet.Fields("mDBUseDefaults")
                        If booUseLimits = True Then
                              strUseLimits = "True"
                        Else
                              strUseLimits = "False"
                        End If

                        strDisplayName = objRecordSet.Fields("displayName")
                        
                        If InStr(1, strDisplayName, "SystemMailbox", VbTextCompare) = 0 Then
                              strWarnLimit = objRecordSet.Fields("mDBStorageQuota")
                              strQuotaLimit = objRecordSet.Fields("mDBOverQuotaLimit")
            
                              objResults.Add strMailboxGUID, Array(strDisplayName, strUseLimits,_
                                          strWarnLimit, strQuotaLimit, strSize, strStore)
                        End If
                  End If
            End If
            objRecordSet.MoveNext
      Wend
      
      objConnection.Close
      
      Set objRecordSet = Nothing
      Set objCommand = Nothing
      Set objConnection = Nothing
End Sub

Sub GetMailboxes
      Const WBEM_RETURN_IMMEDIATELY = &h10
      Const WBEM_FORWARD_ONLY = &h20

      Dim objWMIService, objMailbox
      Dim colMailboxes
      Dim strMailboxGUID, strDisplayName, strUseLimits, strSize, strStore
      Dim strWarnLimit, strQuotaLimit

      Set objWMIService = GetObject("winmgmts:\\" & EXCHANGE_SERVER & "\root\MicrosoftExchangeV2")
      Set colMailboxes = objWMIService.ExecQuery("SELECT * FROM Exchange_Mailbox", "WQL",_
                  WBEM_RETURN_IMMEDIATELY + WBEM_FORWARD_ONLY)

      For Each objMailbox In colMailboxes
            If InStr(1, objMailbox.MailboxDisplayName, "SystemMailbox", VbTextCompare) = 0 Then

                  strMailboxGUID = objMailbox.MailboxGUID

                  If objResults.Exists(strMailboxGUID) Then
                        strDisplayName = objResults(strMailboxGUID)(0)
                        strUseLimits  = objResults(strMailboxGUID)(1)
                        strWarnLimit = objResults(strMailboxGUID)(2)
                        strQuotaLimit = objResults(strMailboxGUID)(3)
                        strSize = objMailbox.Size
                        strStore = objMailbox.StoreName
                        
                        objResults.Remove strMailboxGUID
                        objResults.Add strMailboxGUID, Array(strDisplayName, strUseLimits,_
                                    strWarnLimit, strQuotaLimit, strSize, strStore)
                  End If
            End If
      Next
      
      Set colMailboxes = Nothing
      Set objWMIService = Nothing
End Sub

Sub WriteResults
      Dim objFileSystem, objFile
      Dim strEcho, strLine, strMailboxGUID, strDisplayName, strUseLimits, strSize, strStore
      Dim strWarnLimit, strQuotaLimit
      Dim i, intTotal

      Set objFileSystem = CreateObject("Scripting.FileSystemObject")
      Set objFile = objFileSystem.OpenTextFile("MailboxSizes.txt", 2, True, 0)
      
      strLine = "Display Name" & VbTab & "Use Limits Enabled" & VbTab & "Warning Limit" &_
            VbTab & "Quota Limit" & VbTab & "Size on Server" & VbTab & "Storage Group"
      objFile.WriteLine strLine
      
      For Each strMailboxGUID in objResults
            strDisplayName = objResults(strMailboxGUID)(0)
            strUseLimits = objResults(strMailboxGUID)(1)
            strWarnLimit = objResults(strMailboxGUID)(2)
            strQuotaLimit = objResults(strMailboxGUID)(3)
            strSize = objResults(strMailboxGUID)(4)
            strStore = objResults(strMailboxGUID)(5)
      
            strEcho = strDisplayName & ": "
            If strUseLimits = "False" Then
                  strEcho = strEcho & "Warning Limit: " & strWarnLimit & " | Quota Limit: " &_
                        strQuotaLimit & " - "
            End If
      
            strEcho = strEcho & "Size: " & strSize & " - Store: " & strStore
            WScript.Echo strEcho
            
            strLine = strDisplayName & VbTab & strUseLimits & VbTab & strWarnLimit &_
                        VbTab & strQuotaLimit & VbTab & strSize & VbTab & strStore
                  
            objFile.WriteLine strLine
      Next
      
      Set objFile = Nothing
      
      Set objFile = objFileSystem.OpenTextFile("AlphabeticalTotal.txt", 2, True, 0)
      For i = 65 to 90
            intTotal = 0
            For Each strMailboxGUID in objResults
                  If Left(objResults(strMailboxGUID)(0), 1) = Chr(i) Then
                        If IsNumeric(objResults(strMailboxGUID)(4)) Then
                              intTotal = intTotal + CDbl(objResults(strMailboxGUID)(4))
                        End If
                  End If
            Next
            objFile.WriteLine Chr(i) & VbTab & intTotal
      Next
End Sub

'
' Main Code
'

Set objResults = CreateObject("Scripting.Dictionary")

GetADData
GetMailboxes
WriteResults

Set objResults = Nothing

Voilà. Works beautifully. Hopefully juragan will notice as well.

Simon.

Excellent :)

Chris
Avatar of juragan

ASKER

Thanks for the script, Chris.

I have 4 Exchange servers in my network, and I ran the script with 'Server_1' for the Server Name variable.

The script dumped the listing on the Command Prompt box, as well as created two .txt files.  I opened the file mailboxsizes.txt and noticed that it contains ALL mailboxes from ALL servers, however only users from SERVER have the fields 'Size on Server' and 'Storage Group' filled in.

Did I miss anything?

Nope you didn't. It only lists mailboxes for the server it's directly running against. Hold on a moment and I'll add some bits in tol get around that.

Chris
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I used this solution and it worked great!  Thanks.

It's quite old and has been updated a fair bit since. I'm happier with my update / rewrite here:

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

It reports in rather more detail without much of the complexity I have above. The only significant part I dropped was writing the report to the screen, writing to a file is just much neater.

Chris
Chris,

Awesome PowerShell script linked through your link above!