Exchange Webservice API Tweaking

We have a symantec server that notifies us when we get attacks on our endpoints. We also have an onsite Nessus server that scans everyday and triggers those alarms, so I’ve written the below script that will go through a shared mailbox where the alerts reside and find the actual bad ones.

It works fine, but I was trying to find a way to search through all folders/items instead of hard coding the numbers such as:

#connects to appropriate folder
$folder = $inbox.findfolders(100) | where-object {$_.displayname -eq "Symantec"} | Foreach {$_.findfolders(10)} | Where-Object {$_.displayname -eq "Attacked Computers"} #<--...#inbox.findfolders(go through all folders and then where-object..)

#finds first 100 items in that folder
$mail = $folder.FindItems(100) #<--$mail = $folders.finditems(all items)

I’m not sure how to do this/if it’s possible, but I thought I would ask on here.

Below is the complete script.

#runs every 2 hours in task scheduler and checks the inbox>symantec>Attacked Computers folder for actual attacks, ie not our nessus server

#creds saved in xml, encryption based on user profile
$creds = import-clixml c:\scripts\creds.xml

$s = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
$s.Credentials = New-Object Net.NetworkCredential($creds.username, $creds.password)
$s.Url = new-object Uri("https://mail.domain.com/ews/exchange.asmx")

#connects to support inbox
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($s,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)

#connects to appropriate folder
$folder = $inbox.findfolders(100) | where-object {$_.displayname -eq "Symantec"} | Foreach {$_.findfolders(10)} | Where-Object {$_.displayname -eq "Attacked Computers"}

#finds first 100 items in that folder
$mail = $folder.FindItems(100) 

#only tests objects 2 hours and newer
$testmail = $mail | where-object {$_.DateTimeReceived -ge (get-date).AddHours(-2)} 
$testmail | % {$_.Load()} 

#Filters out to only the email subjects required
$SEPmail = $testmail | ? {$_.conversationtopic -like "*Security Alert by Number of Attacked Computers*"}

$sepmail | foreach {
	#Filters out device/tamper emails that also reside in same folder
	if($_.body -notmatch "Disabled Device" -and $_.body -notmatch "Tamper Protection")
	{
		#if it does NOT match Nessus IP, then legit attack occured
		if($_.body -notmatch "10.12.25.105")
		{
			write-host "ATTACK! $($_.datetimereceived)" -foregroundcolor "red"
			
			#contains all of emails body
			$html = $_.body
			
			$smtpServer = "10.255.255.125"
			$msg = new-object Net.Mail.MailMessage
			$smtp = new-object Net.Mail.SmtpClient($smtpServer)
			$msg.From = "SEPattack@domain.com"
			$msg.To.Add(@("ITguys@domain.com"))
			$msg.Subject = "WE BEEN ATTACKED!"
			$msg.Body = $html
			$msg.isbodyhtml = $true
			$smtp.Send($msg)
			
			
		}
	}
}

Instead of manually coding the max result for the FindFolders method, you could create a FolderView object that has the max page result (max number of items returned) as a property. There is also a property to indicate traversal depth. Take a look at the MSDN reference for the FolderView class here: https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.folderview_properties(v=exchg.80).aspx

I think this would start you in the right direction. Also, you could make the max results a parameter that could be set to a default of 100, but changed to any value at runtime.