New Series – Exchange Maintenance Scripts
IMAP/POP3
IMAP and POP are not the most popular (or secure) protocols to be used by an Exchange Server, however they are certainly still in use and as an engineer who supported a lot of different client bases, I still see these protocols in use. For this script however, is more of a particular scenario where disk space becomes an issue when logging is enabled. Let’s say that in a particular Exchange Organization, logging is enabled for a lot of different options – IIS, IMAP, POP and so on. In the case of IMAP/POP, the log files are generated every day, on an hourly basis and IT would like to keep a set number of days’ worth of logs for troubleshooting client or application connection issues. The logs do not need to exist after this sliding window has expired.
For the sake of arguments, we will use a sliding window of 7 days. Any of these logs that are over a certain age will be removed to keep disk space used by logs to a minimum. The advantage of this PowerShell script is that we can adjust that window if need change by lowering the days to 3 or maybe raising the value to 14 days. Let’ bread down the script step by step.
Connecting to an Exchange Server
In this script we will assume that a jump or admin box is being used, which means that the Exchange PowerShell module may not be installed. As such, we will run this with regular Windows PowerShell and connect to a remote Exchange Server of our choice.
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchange.domain.com/PowerShell/ -Authentication Kerberos Import-PSSession $Session -DisableNameChecking
Keep in mind that ‘exchange.domain.com’ is simply the FQDN (Fully Qualified Domain Name) of the Exchange Server with which we will run our cmdlets from.
For a fun side project, you could pull a list of Exchange Servers in AD and connect to one of these servers. Add on top of this an enhancement where if the connection cannot be made, to try to next one of these servers and so on. This would provide some level of High Availability (HA) for your script).
List of Exchange Servers
As this script will need to analyze each Exchange Server, we’ll need to pull that list. To make the list cleaner we will select just the name and then sort that list. All of this can be done with one line:
$ExchangeServers = ( Get-ExchangeServer ).Name | Sort Name
Checking Each Server
As most environments have more than one server, using a Loop to check each server in order is the next logical step and since we are examining IMAP and POP we will use two loops. First Foreach Loop for IMAP:
Foreach ($ExchangeServer in $ExchangeServers) {
Retrieve IMAP log settings:
$LogsLocation = (Get-ImapSettings -Server $ExchangeServer ).LogFilelocation
Normalize location to a UNC path (to be queried remotely and not locally …):
$Dir = $LogsLocation.Split(':') $Location = '\\'+$ExchangeServer+'\'+$Dir[0]+'$'+$Dir[1]
Next, we set some variables to reset some variables so each loop (for each server) is the same:
$Filesremoved = 0 $Count = 0 $LastWrite = 'N/A'
In this next code section we’ll query the location for files making sure to encapsulate the query in a Try {}Catch {} code section for error handling in case the directory is not available. If files are found, a $Count variable is populated with a file count and the last write time of the files is also queried and store in the $LastWrite variable:
Try { $Count = (Get-ChildItem $Location -ErrorAction stop).Count If ($Count -gt 0) { $LastWrite = (Get-ChildItem $Location | Sort LastWriteTime | Select -Last 1).LastWriteTime } } Catch { $Count = 0 $LastWrite = 'N/A' }
After we’ve retried that information, if the $Count variable is greater than 0, we can geta list of files, current date and set the $PreviousDays variable to 7 for our sliding window size:
If ($Count -gt 0) { $Today = Get-Date $PreviousDays = ($Today).AddDays(-7) $Names = (Get-ChildItem $Location | Where {$_.LastWriteTime -gt $PreviousDays}).Name $Files = (Get-ChildItem $Location).Name
With the list of files, we will now loop through them as these are files that are over 7 days old. Each file will be deleted and counted as it is deleted.
Foreach ($File in $Files) { If ($Names -NotContains $File) { $FileToRemove = $Location+'\'+$File Remove-Item $FileToRemove $Filesremoved++ } } } }
POP3 Log Truncation
Now that we have a code block that works, we can repurpose this for POP3 and only change the ‘Get-ImapSettings’ cmdlet to reflect POP3 logs – Get-POPSettings. Complete code block below:
# POP Section: Foreach ($ExchangeServer in $ExchangeServers) { $LogsLocation = (Get-POPSettings -Server $ExchangeServe ).LogFilelocation $Dir = $LogsLocation.Split(':') $Location = '\\'+$ExchangeServe+'\'+$Dir[0]+'$'+$Dir[1] $Filesremoved = 0 $Count = 0 $LastWrite = 'N/A' Try { $Count = (Get-ChildItem $Location -ErrorAction stop).Count If ($Count -gt 0) { $LastWrite = (Get-ChildItem $Location | Sort LastWriteTime | Select -Last 1).LastWriteTime } } Catch { $Count = 0 $LastWrite = 'N/A' } If ($Count -gt 0) { $Today = Get-Date $PreviousDays = ($Today).AddDays(-7) $Names = (Get-ChildItem $Location | Where {$_.LastWriteTime -gt $PreviousDays}).Name $Files = (Get-ChildItem $Location).Name Foreach ($File in $Files) { If ($Names -NotContains $File) { $FileToRemove = $Location+'\'+$File Remove-Item $FileToRemove $Filesremoved++ } } } }
Closing PowerShell Sessions
As I like to clean-up after I am done, we can remove old PowerShell sessions to keep this clean as well:
Get-PSSession | Remove-PSSession
Additional Enhancements
Some organizations would like to have this type of work logged in case there are issues after removing logs. These same changes can also be rolled up into an email notification to IT Support personnel who are in charge of the messaging servers. Think about how you would want this structured and create your own SMTP reports.
Conclusion
Disk space on modern servers may seem quaint as most servers are virtualized these days,. However, Exchange Server do have a greater chance of not being due to hardware requirements. That being said, keeping disk space usage low can be a priority for those with either limited resources or busy servers. This script is just one of many logs that can be managed with an automated script. Later in this series we will also cover IIS logs and configuration for our Exchange Servers.
TIP: If IMAP/POP logging has been disabled and your log files are not truncating, then simply reboot the server as this should take care of any lingering configuration changes that may not have saved properly.
Additionally, this script could be used for any program that generates a large amount of logs that could take up too much disk space, such as IIS. DO NOT use this for Exchange database logs.