How to selectively purge mailboxes using a script (Exchange 2003) - Another go…
I originally posted this article on Thursday 18th October, where it was up for about 20 minutes before I pulled it.
The reason for me pulling the article is that original script that I provided did some very odd things to my test Exchange server (which I only noticed about 15 minutes after I posted) so after some de-bugging I can now present the new script (which is now working fine) and the original article – but, at the end I would like to explain exactly what went wrong – as I believe that it might be useful for others that intend to purge mailboxes via VBSCRIPT.
Some of you may know that I like a challenge, and indeed I also like suggestions being made for articles on this blog. Today I sat down to finish writing an article on Spam (that has been in progress for the better part of a week now) when I decided to have a look at my GMAIL account.
The first message in the mailbox was from a reader of my blog (Ariel) asking if a script could be written to selectively purge disconnected mailboxes from the information store on an Exchange server.
Essentially Ariel wanted to have a list of names in a text file, these names would correspond to disconnected mailboxes on an Exchange server, but the purge script would look at this file and ignore those specific names during processing (I have included the mail below).
Hi,
Just happened to check on your site related to exchange and just wondren if you have some script that could purged deleted mailboxes using a text file as reference.
its process is like, when it runs, it looks for all deleted items on exchange and check if the mailboxes is art of the listing in a text file, and if does, it deletes/purge it, if not, it leaves the mailbox alone.
hope to hear from you soon.
regards,
Ariel
I can only think that Ariel wishes to keep on top of purged mailboxes, but also wishes to maintain a few for company reasons, but none the less it was a challenge that I could not resist – so out came by copy of Notepad++ and I fired up my Exchange test lab.
After a couple of Hours test I came up the following script (click below for download)
Within the Zip are two files which are as follows:
-
PurgeMailboxes.vbs – this file contains the code which processes the purging of mailboxes from the store
-
NotPurge.csv – the file contains the list of mailboxes that might be disconnected – but should not be purged
Installation:
-
Download the zip file to your Exchange server and extract them to a directory (for example c:\MB)
-
Open the PurgeMailboxes.vbs file and find the following line:
-
strPathToCSV =”S:\MB” – change this to the path where the NotPurge.csv file is located (so if you extracted the files to the c:\mb folder this value will become strPathToCSV =”C:\MB” then save your changes
-
-
Open the NotPurge.csv file and UNDER the MailboxDISName header type in the list of mailboxes that you wish for the program to ignore – each mailbox should be on a new line – AND – must be the Display Name of the mailbox as it appears in the Exchange System Manager.
-
Run the program from the command line (or schedule it) using the following command line:
-
cscript.exe PurgeMailboxes.vbs
-
Known Issues:
- Display names that contain special commas “,” or apostrophes “’” the script will ignore.
- The Script MUST be run on the Exchange server where the purged mailboxes reside.
What went wrong with the first version of the script:
The first version of the script that I published (which thankfully nobody downloaded) cycled through each mailbox in the store and would attempt to purge them (the idea being that if the mailbox was disconnected and not in the CSV file it would purge).
However after running the script in my test lab I started to get the following errors in the Application Event Log:


I also noticed that all Store bound and SMTP bound traffic had stopped working in the test server. I looked up the Log ID’s and the answers that I seemed to be getting suggested that the Databases from two Exchange servers had been swapped around and this would cause this error (have a look here: http://technet.microsoft.com/en-us/library/aa997314.aspx for full information).
Obviously I knew that this had not been the case, however the article did add to my suspicions that my script had perhaps done something to the SystemMailbox{GUID} and the SMTP {GUID} in the store I was working – it was at this point I took the article down until I could work out what had happened.
For further information on the System Mailboxes Evan Dodds wrote a very good article on them here: http://blogs.technet.com/evand/archive/2004/12/17/323636.aspx
I decided to have a closer look at the Exchange_Mailbox class which is defined within WMI on Exchange servers and my script makes heavy use of – the following are properties defined as part of the class (from Microsoft http://msdn2.microsoft.com/en-us/library/aa143732.aspx):
| LegacyDN Property | [key, read] string LegacyDN; |
| The LegacyDN property indicates the legacyDN of the mailbox and matches the legacyExchangeDN attribute of the user object in Microsoft Active Directory®. | |
|
[key, read] string MailboxGUID; |
|
|
The MailboxGUID property indicates the globally unique identifier (GUID) that links the mailbox to a user in Active Directory. |
|
| [key, read] string ServerName; | |
| The ServerName property indicates the name of the server where the mailbox resides | |
| StorageGroupName Property |
[key,read] string StorageGroupName; |
|
The StorageGroupName property indicates the name of the storage group that contains the mailbox. |
|
| [key, read] string StoreName; | |
|
The StoreName property indicates the name of the message database (MDB) that contains the mailbox. |
|
|
[read] uint32 AssocContentCount; |
|
|
The AssocContentCount property indicates the total number of messages associated with the mailbox folders. |
|
|
[read] datetime DateDiscoveredAbsentInDS; |
|
|
The DateDiscoveredAbsentInDS property indicates when the store detected that the mailbox no longer had a corresponding user entry in Active Directory. Mailboxes without Active Directory user entries are known as disconnected mailboxes. |
|
|
[read,Units("Bytes")] uint64 DeletedMessageSizeExtended; |
|
|
The DeletedMessageSizeExtended property indicates the cumulative size of all deleted messages that are still being retained according to retention policy settings. |
|
| [read] string LastLoggedOnUserAccount; | |
|
The LastLoggedOnUserAccount property indicates the account name last used to log on to the mailbox. |
|
| [read] datetime LastLogoffTime; | |
|
The LastLogoffTime property indicates the time that the last user logged off. |
|
|
[read] datetime LastLogonTime; |
|
|
The LastLogonTime property indicates the time that the last user logged on. |
|
| [read] string MailboxDisplayName; | |
|
The MailboxDisplayName property indicates the display name of the mailbox and matches the displayName attribute in Active Directory. |
|
|
[read, Units("Bytes")] uint64 Size; |
|
|
The Size property indicates the cumulative size of all of the messages in the mailbox, in bytes. |
|
|
[read, Values{"Below Limit", "Issue Warning","Prohibit Send", "No Checking","Mailbox Disabled"}, |
|
|
The StorageLimitInfo property contains the storage limit settings on the mailbox. |
|
| [read] uint32 TotalItems; | |
| The TotalItems property indicates the total number of messages in the mailbox. |
The reason why I wanted to have a closer look at the Class definition is because I had a theory, which was – I believed that although the SystemMailbox (and the SMTP Mailbox) appear as normal mailboxes in the Information Store, they are in fact disconnected – but the clean up agent, nor the store view shows this fact, however I needed to confirm this fact (the idea being if they are actually disconnected and my script works by trying to purge all disconnected mailboxes – then they will get deleted).
The property that I was interested in was the “DateDiscoveredAbsentInDS” – essentially if either of these mailboxes had a value in the property defined then they were consider “disconnected” and then fair game for my script (which is bad news).
I found that at certain times (not always) the above Property would have a value (although I am willing to accept that it was perhaps my test rig) – however this did mean that if the system mailboxes could technically be disconnected under certain circumstances – I needed to ensure that my script would not touch them.
So I added in the following logic into my script:
SA = “System”
SM = “SMTP”
posSA=InStr(objExchange_Mailbox.MailBoxDisplayName,SA)
posSM=InStr(objExchange_Mailbox.MailBoxDisplayName,SM)
If NOT (posSA 0) XOR (posSM 0) Then
If strCSVName strName Then
On error Resume Next
Wscript.Echo “Processing: ” & strName
objExchange_Mailbox.Purge
End if
Else
Wscript.Echo “The following has been determined as a SYSTEM MB: ” & strName
End if
posSa = 0
posSN = 0
The above code defines the keywords “System” and “SMTP” (which will always appear at position 0 in the Mailbox Display Name) and then uses the InStr() function in VBSCRIPT to determine if the name of the Mailbox that is being processed contains either keyword – if it does then the Purge method of the Exchange_Mailbox class will NOT be invoked.
I have throughly tested this version of the script and I am confident that it works safely – however I recommend (as I always do with all my scripts – run them in your test environment FIRST).
I have included this above information because although I made a mistake (which could of had serious consequences for others) I believe that it is important to share this information. If you Google “Exchange Purge Mailboxes” you will get a number of results – most of which explain how you can purge single mailboxes – however these scripts can be modified to operate on the entire store – which is where my pitfall comes in – if you wish to run something like this on your entire store, make sure that you excluded your SystemMailboxes AND ensure that you test before hand in a test rig.
Add this page to your favorite Social Bookmarking websites
Last Updated (Wednesday, 30 December 2009 17:08)





