Quantcast
Channel: Exchange Server Development forum
Viewing all articles
Browse latest Browse all 7132

Powershell: Empty Folder Cleanup of Multiple Accounts

$
0
0

My apologies if this is not the correct subforum.   I work in a heavily automated environment that uses Exchange in its document processing tasks.  Emails get sent to folders, then read from them and further processed, then archived.  This results in hundreds of empty archive folders, which I would like to clean up on a schedule.  I have found a functional script that uses EWS and works well for a single mailbox/account:

##Version 2 added url encoding
## Get the Mailbox to Access from the 1st command line argument. Enter the SMTP address of the mailbox
$MailboxName = "SMTPAddress"

## Load Managed API dll
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"
Add-Type -AssemblyName System.Web

## Set Exchange Version. Use one of the following:
## Exchange2007_SP1, Exchange2010, Exchange2010_SP1, Exchange2010_SP2, Exchange2013, Exchange2013_SP1
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1

## Create Exchange Service Object
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)

## Set Credentials to use two options are available Option1 to use explicit credentials or Option 2 use the Default (logged On) credentials

## Credentials Option 1 using UPN for the Windows Account
$psCred = Get-Credential
$creds = New-Object System.Net.NetworkCredential($psCred.UserName.ToString(),$psCred.GetNetworkCredential().password.ToString())
$service.Credentials = $creds

## Credentials Option 2
#service.UseDefaultCredentials = $true

## Choose to ignore any SSL Warning issues caused by Self Signed Certificates

## Code From http://poshcode.org/624
## Create a compilation environment
$Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
$Compiler=$Provider.CreateCompiler()
$Params=New-Object System.CodeDom.Compiler.CompilerParameters
$Params.GenerateExecutable=$False
$Params.GenerateInMemory=$True
$Params.IncludeDebugInformation=$False
$Params.ReferencedAssemblies.Add("System.DLL") | Out-Null

$TASource=@'
  namespace Local.ToolkitExtensions.Net.CertificatePolicy{
    public class TrustAll : System.Net.ICertificatePolicy {
      public TrustAll() {
      }
      public bool CheckValidationResult(System.Net.ServicePoint sp,
        System.Security.Cryptography.X509Certificates.X509Certificate cert,
        System.Net.WebRequest req, int problem) {
        return true;
      }
    }
  }
'@
$TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
$TAAssembly=$TAResults.CompiledAssembly

## We now create an instance of the TrustAll and attach it to the ServicePointManager
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll

## End code from http://poshcode.org/624

## Set the URL of the CAS (Client Access Server) to use two options are available to use Autodiscover to find the CAS URL or Hardcode the CAS to use

## CAS URL Option 1 Autodiscover
$service.AutodiscoverUrl($MailboxName,{$true})
"Using CAS Server : " + $Service.url

## CAS URL Option 2 Hardcoded
#$uri=[system.URI] "https://casservername/ews/exchange.asmx"
#$service.Url = $uri

## Optional section for Exchange Impersonation
#$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)

## Show Trace. Can be used for troubleshooting errors
#$service.traceenabled = $true

function ConvertId{
	param (
	        $OwaId = "$( throw 'OWAId is a mandatory Parameter' )"
		  )
	process{
	    $aiItem = New-Object Microsoft.Exchange.WebServices.Data.AlternateId
	    $aiItem.Mailbox = $MailboxName
	    $aiItem.UniqueId = $OwaId
	    $aiItem.Format = [Microsoft.Exchange.WebServices.Data.IdFormat]::OwaId
	    $convertedId = $service.ConvertId($aiItem, [Microsoft.Exchange.WebServices.Data.IdFormat]::EwsId)
		return $convertedId.UniqueId
	}
}

## Get Empty Folders from EMS
get-mailboxfolderstatistics -identity cnrecon | Where-Object{$_.FolderType -eq "User Created" -band $_.ItemsInFolderAndSubFolders -eq 0} | ForEach-Object{
	# Bind to the Inbox Folder"Deleting Folder " + $_.FolderPath
	try{

		$urlEncodedId = [System.Web.HttpUtility]::UrlEncode($_.FolderId.ToString())
		$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId((Convertid $urlEncodedId))
		#$folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId((Convertid $_.FolderId))
		$ewsFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
		if($ewsFolder.TotalCount -eq 0){
			$ewsFolder.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::SoftDelete)
			"Folder Deleted"
		}
	}
	catch{
		$_.Exception.Message
	}
}

With a little tweaking this works great for each mailbox I run it against by defining the $MailboxName as the SMTP address of the desired box I want to clean.  It's worth noting that for some reason the $MailboxName alias isn't working in the part where it looks up in Autodiscover...I have to manually put the address in there as well.

My question is, can this be modified to work against multiple email boxes?  I have several score boxes with hundreds of empty archived folders each.  Running an individual script for each box seems inefficient.  I tried supplanting a text file with addresses for $MailboxName, but that doesn't work in the Autodiscover part further down.

Thank you for any help you can offer, I'm not very experienced with Powershell or scripting in general, so this feels like I'm diving in a little deep.



Viewing all articles
Browse latest Browse all 7132

Trending Articles