I recently changed the server hardware and copied the %programfiles%\hMailServer\Data\ to the new disk. After checking the filecount against the SQL-database the actual filecount was 20906 against 4655 in the database. Meaning that I had 16251 files taking up space without a reference. That was a waste of space (around 1,5GB).
I dunno how this happened, but I had a faulty RAID controller that made random files writeprotected.
Anyway, here is a Description of the script:
It makes a recursive list of a given directory (usally where you store the *.eml files ) and then it compares to the filenames that are stored in the hmailserver database. If there is a mismatch the file will be renamed to *.deleteme
Who need this?
If you're running a hmailserver and had a couple of lockups or simular I guess you might have some "leftovers" on the disk.
The script (hMailCleaner.vbs):
Please run the script in a command prompt using cscript.exe!
Code: Select all
' ==================================================== ' hMailCleaner by Lars Werner (http://lars.werner.no/) ' ==================================================== ' Usage: cscript hmailcleaner.vbs "data-path" adminpassword [/delete] ' ' How does it work? ' ----------------- ' The script makes a recursive list of a given directory (the place where you store the *.eml files) and ' then it compares to the filenames that are stored in the hmailserver database. ' If there is a mismatch the file will be renamed to *.deleteme ' 'WARNING: If /delete option is given then all the mismatched files will be permanently deleted!!! ' ' Who need this? ' -------------- ' If you're running a hmailserver and had a couple of lockups or simular I guess you might have some "leftovers" on the disk. ' This script marks the files that aren't in the database or even delete them directly! ' Pretty usefull if you have a crappy RAID controller that makes everything writeprotected, like I did ;) ' 'Disclaimer: I use hMailserver in a small scale! This script has only been tested with my server & setup and it might crash or harm your system. So please take backup, and don't come to me crying about it! Option Explicit Dim aFiles() 'Array of all the files in the given path Dim aMailFiles() 'Array of files in the database Dim iCount, iArrayCount, iPercentage, iLastPercentage Dim bDelete 'Really delete? Dim objFSO, objFolder, colFiles, objFile '=========================== '== SUBS & FUNCTIONS '= Store each file from a given directory into an array Function ArrayOfFiles(Folder) 'Returns an object of objFolder (used in recursive mode) Dim SubFolder For Each Subfolder in Folder.SubFolders Set objFolder = objFSO.GetFolder(Subfolder.Path) Set colFiles = objFolder.Files Redim preserve aFiles(UBound(aFiles) + colFiles.Count) 'Resize the array with the new files we got For Each objFile in colFiles if StrComp(Right(objFile.Name, 9), ".deleteme") <> 0 then aFiles(iCount) = objFolder.Path & "\" & objFile.Name end if iCount = iCount + 1 Next ArrayOfFiles Subfolder 'Recursive call Next End Function '=========================== '= Store each db "file" into an array Sub FillMailArray(sAdminPw) Dim oApp Set oApp = CreateObject("hMailServer.Application") ' Authenticate the client. Call oApp.Authenticate ("Administrator", sAdminPw) Dim iDomains, iAccounts, iMessages iArrayCount = 0 ReDim aMailFiles(iArrayCount) for iDomains = 0 to oApp.Domains.Count - 1 Dim oDomain Set oDomain = oApp.Domains.Item(iDomains) WScript.Echo "Domain: " & oDomain.Name for iAccounts = 0 to oDomain.Accounts.Count - 1 Dim oAccount set oAccount = oDomain.Accounts.Item(iAccounts) WScript.Echo " -> " & oAccount.Address WScript.Echo " > Messages: " & oAccount.Messages.Count Redim preserve aMailFiles(UBound(aMailFiles) + oAccount.Messages.Count) for iMessages = 0 to oAccount.Messages.Count - 1 Dim oMessage set oMessage = oAccount.Messages.Item(iMessages) aMailFiles(iArrayCount) = oMessage.Filename iArrayCount = iArrayCount + 1 set oMessage = nothing Next 'End iMessages set oAccount = nothing Next 'End iAccounts set oDomain = nothing Next 'End iDomains set oApp = nothing End Sub '=========================== '== MAIN bDelete = false 'Check if we're using wscript (quit) or cscript (ok) if InStr(lcase(WScript.Fullname), "wscript") > 0 then WScript.Echo "Please do not run this program from windows! Use the command prompt and cscript.exe instead" WScript.Quit end if 'Check how many arguments we have if WScript.Arguments.Count >=2 then Set objFSO = CreateObject("Scripting.FileSystemObject") iCount = 0 'Overall counter to know where we are in the file-array Set objFolder = objFSO.GetFolder(Wscript.Arguments(0)) Set colFiles = objFolder.Files Redim aFiles(colFiles.Count) For Each objFile in colFiles 'Ignore already "deleted" messages if StrComp(Right(objFile.Name, 9), ".deleteme") <> 0 then aFiles(iCount) = objFolder.Path & "\" & objFile.Name end if iCount = iCount + 1 Next 'Just wait message for the user WScript.Echo "Please wait, creating filelist for: " & Wscript.Arguments(0) 'Now get an recursive list of files ArrayOfFiles objFSO.GetFolder(Wscript.Arguments(0)) 'Now create an array of files from the database FillMailArray(Wscript.Arguments(1)) 'Print out the info before we start renaming WScript.Echo WScript.Echo " Number of physical files on disk: " & UBound(aFiles) WScript.Echo "Number of files in hmail database: " & UBound(aMailFiles) WScript.Echo 'Check if aMailFiles is bigger than aFiles and give a warning! if UBound(aFiles) < UBound(aMailFiles) then WScript.Echo "WARNING: hMaildatabase contains more files than there actually is on the hard drive, this will hMailServer to give ""failed to open"" messages in IMAP" WScript.Echo end if 'Check if we're gonna delete & Write warning if we're gonna delete the file if WScript.Arguments.Count = 3 then if InStr(lcase(WScript.Arguments(2)), "/delete") then bDelete = true WScript.Echo "WARNING: Mismatched files will be permanently deleted! (To abort press CTRL-C, 3 sec delay)" WScript.Echo WScript.Sleep 3000 else WScript.Echo "WARNING: Unknown third argument, files will be renamed!" WScript.Echo end if end if 'Now loop through the files & compare with the database files iLastPercentage = 0 'Stores the last procentage so it does not update so much WScript.Echo "Please wait while the files are compared..." for iCount = 0 to UBound(aFiles) - 1 'Check if we can find the filename in the database Dim bFound, sComp bFound = false 'We only do the check when there is an actual file! if Len(aFiles(iCount)) <> 0 then 'Get the filename we are gonna to compare with (remove the directory) sComp = right(lcase(aFiles(iCount)), len(aFiles(iCount)) - len(Wscript.Arguments(0))) 'We only compare the info behind selected dir :) if Left(sComp,1) = "\" then sComp = Right(sComp, len(sComp)-1) 'Remove the \ if it exists... 'Now check with the databaselist for iArrayCount = 0 to UBound(aMailFiles) 'Check if the entry actually is an entry if(Len(aMailFiles(iArrayCount))) <> 0 then if StrComp(sComp, lcase(Right(aMailFiles(iArrayCount), Len(sComp))), 0) = 0 then aMailFiles(iArrayCount) = "" bFound = true exit for end if end if Next 'If we haven't found the file we are going to rename/delete it if bFound = false then if bDelete = false then call objFSO.MoveFile(aFiles(iCount), aFiles(iCount) & ".deleteme") WScript.Echo "Renamed: " & aFiles(iCount) else call objFSO.DeleteFile(aFiles(iCount)) WScript.Echo "Deleted: " & aFiles(iCount) end if end if end if 'Len(aFiles(iCount) <> 0 'Here we write the progress (5% at the time) iPercentage = FormatNumber((iCount * 100) / UBound(aFiles), 0) if iPercentage - iLastPercentage = 5 then WScript.Echo "Progress: " & iPercentage & "%" iLastPercentage = iPercentage end if Next WScript.Echo WScript.Echo "Finished!" 'Cleanup of objects Set colFiles = nothing Set objFolder = nothing set objFSO = nothing else WScript.Echo "====================================================" WScript.Echo "hMailCleaner by Lars Werner (http://lars.werner.no/)" WScript.Echo "====================================================" WScript.Echo WScript.Echo "Usage: cscript hmailcleaner.vbs ""data-path"" adminpassword [/delete]" WScript.Echo WScript.Echo "Example: cscript hmailcleaner.vbs ""C:\Program Files\hMailServer\Data"" AdminPw" WScript.Echo "With logfile: cscript hmailcleaner.vbs ""C:\Program Files\hMailServer\Data"" AdminPw >log.txt" WScript.Echo "(The log.txt will be placed the current directory that you're running the script from, no output will be shown)" WScript.Echo WScript.Echo "How does it work?" WScript.Echo "-----------------" WScript.Echo "The script makes a recursive list of a given directory (the place where you store the *.eml files) and then it compares to the filenames that are stored in the hmailserver database." WScript.Echo "If there is a mismatch the file will be renamed to *.deleteme (default behaviour)" WScript.Echo WScript.Echo "WARNING: If /delete option is given then all the mismatched files will be permanently deleted!!!" end if
Warning: I use hMailserver in a small scale! This script has only been tested with my server & setup and it might crash or harm your system. So please take backup, and don't come to me crying about it!