Environment requirements: Powershell 5.0, plus domain computer
- Install EWS API to default location
https://www.microsoft.com/en-us/download/details.aspx?id=42951 - For permission configuration, add the ApplicationImpersonation role in the Exchange management center of Office365 and the Exchange management center and administrator role, and add the executive account as a member
- Delete message script breakdown
3.1 connect EWS API with execution accountImport-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" #Import API module $username = "Executive account email" $password = "Execute account password" $exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2016_CU7) $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2016_CU7 $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion) $service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials -ArgumentList $userName, $password
3.2 specify the account number of the deleted email
$deleteusersamid = "xxxx" #Deleted email account samid $userinfo = get-aduser $deleteusersamid -Properties EmailAddress,targetAddress $targetAddress =$userinfo.targetAddress if($targetAddress){ #Delete office 365 email $uri=[system.URI] "https://outlook.office365.com/EWS/Exchange.asmx" }else{ #Delete Exchange mailbox messages $uri=[system.URI] "https://email.localexchange.com/ews/exchange.asmx" } $upn = $userinfo.EmailAddress $service.url = $uri $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SMTPAddress,$upn)
3.3 specify delete mail conditions
#New search logical collection $sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And); #Specify start time $filter1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $starttime) $sfCollection.add($filter1) #Specify end time $filter2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $endtime) $sfCollection.add($filter2) #Specify the subject of the email. The subject is fuzzy matching. It is OK to take a section of the subject. The content should not contain special matching $filter3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject,$subject) $sfCollection.add($filter3) #Specify delivery address $filter4 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Sender, $Sender) $sfCollection.add($filter4) #Specify the content of the text. The text is fuzzy matching. It is OK to take a paragraph of the text. The content should not contain special match $filter5 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Body,$Body) $sfCollection.add($filter5) #Specify the maximum number of messages to read at a time $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000) #Specify the maximum number of folders to read at a time $FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(100)
3.4 in inbox, sent mail, deleted mail search mail
#Search inbox for messages, no subfolders $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::inbox,$sfCollection,$view) #Search for messages in sent messages $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SentItems,$sfCollection,$view) #Search for messages in deleted messages $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::DeletedItems,$sfCollection,$view)
3.5 search for messages in subfolders of inbox
#Get all folders in inbox $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox) $FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(100) $FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep $findFolderResults = $inbox.FindFolders($FolderList) $sortfindFolderResults = $findFolderResults | where{$_.FolderClass -eq "IPF.Note"} #Search for messages in each subfolder foreach($subfoler in $sortfindFolderResults){ $displayname = $subfoler.displayname $echocontent = "Querying $upn folder $displayname Messages in" Write-Host $echocontent -ForegroundColor gray $id = $subfoler.id $folder_ms= "" $folder_ms= [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$id) $mails = "" $mails= $service.FindItems($id,$sfCollection,$view) if($mails){ $findResults += $mails } }
3.6 delete all the searched messages. The optional values of deletion type are as follows:
MoveToDeletedItems: messages moved to deleted folders
Softdelete: soft delete, which can be recovered in the recovery of deleted messages
harddelete: hard delete, permanent delete, unable to recover
foreach($item in $findResults){ $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::softdelete) }
4. Delete mail function
function EWSDeleteEmail { <# .SYNOPSIS //Delete the specified message content EWSDeleteEmail -recepient extest7 -sender user@domain.cn -starttime "2018.12.24 10:48" -endtime "2018.12.24 10:51" -subject "234" -Confirm:$false #> [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory=$true)] $sender, [Parameter(Mandatory=$true)] $subject, [Parameter(Mandatory=$true)] [System.datetime]$starttime , [Parameter(Mandatory=$true)] [System.datetime]$endtime , [Parameter(Mandatory=$false)] $recepient ) if($PSCmdlet.ShouldProcess($param)) { if($recepient -or ($file -match ".csv")){ if($endtime -gt $starttime){ if($subject){ if($sender -match "\@"){ $result = @() Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" $username = "user@domain.com" $password = "Password" $exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2016_CU7) $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2016_CU7 $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion) $service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials -ArgumentList $userName, $password $filter1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $starttime) $filter2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $endtime) $filter3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject,$subject) $filter4 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Sender, $Sender) $sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And); $sfCollection.add($filter1) $sfCollection.add($filter2) $sfCollection.add($filter3) $sfCollection.add($filter4) if($recepient){ $recsamid = ($recepient -split "\@")[0] $userinfo = "" $userinfo = get-aduser $recsamid -Properties EmailAddress,targetAddress $useremail = "" $useremail = $userinfo.EmailAddress if($useremail){ $targetAddress = "" $targetAddress =$userinfo.targetAddress if($targetAddress){ $uri=[system.URI] "https://outlook.office365.com/EWS/Exchange.asmx" }else{ $uri=[system.URI] "https://email.domain.com/ews/exchange.asmx" } $upn = $userinfo.EmailAddress $service.url = $uri $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SMTPAddress,$upn) $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox) $FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(100) $FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep $findFolderResults = $inbox.FindFolders($FolderList) $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000) $findResults = @() $mails = "" $echocontent = "Querying $upn Messages in inbox" Write-Host $echocontent -ForegroundColor gray $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::inbox,$sfCollection,$view) $mails | Add-Member -MemberType NoteProperty -Name foldername -Value "inbox" if($mails){ $findResults += $mails } $mails = "" $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SentItems,$sfCollection,$view) $mails | Add-Member -MemberType NoteProperty -Name foldername -Value "SentItems" if($mails){ $findResults += $mails } $mails = "" $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::DeletedItems,$sfCollection,$view) $mails | Add-Member -MemberType NoteProperty -Name foldername -Value "DeletedItems" if($mails){ $findResults += $mails } if(!$findResults){ $sortfindFolderResults = $findFolderResults | where{$_.FolderClass -eq "IPF.Note"} foreach($subfoler in $sortfindFolderResults){ $displayname = $subfoler.displayname $echocontent = "Querying $upn folder $displayname Messages in" Write-Host $echocontent -ForegroundColor gray $id = $subfoler.id $folder_ms= "" $folder_ms= [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$id) $mails = "" $mails= $service.FindItems($id,$sfCollection,$view) if($mails){ $mails | Add-Member -MemberType NoteProperty -Name foldername -Value $displayname $findResults += $mails } } } if($findResults){ $num = ($findResults | measure).count $outinfo = $findResults | select DateTimeReceived,Sender,Subject,Size,foldername $outinfotxt = $outinfo | fl | Out-String $echocontent = @" //Query criteria: //To: $upn //From: $Sender //Subject: $subject //Time period: $starttime-$endtime //Number of search results: $num //Details: $outinfotext "@ Write-Host $echocontent -ForegroundColor gray foreach($item in $findResults){ $Error.Clear() $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::softdelete) if($Error){ $Errortxt = $Error | Out-String $item | Add-Member -MemberType NoteProperty -Name action -Value "failed" $item | Add-Member -MemberType NoteProperty -Name errorinfo -Value $Errortxt }else{ $item | Add-Member -MemberType NoteProperty -Name action -Value "succeed" } $item | Add-Member -MemberType NoteProperty -Name searchuser -Value $recsamid $newitem = $item | select searchuser,DateTimeReceived,Sender,Subject,Size,foldername,action,errorinfo $result += $newitem } }else{ $userobject = New-Object psobject -Property @{ searchuser = $recsamid DateTimeReceived = "" Sender= $Sender Subject= $subject Size= "" foldername= "" action= "" errorinfo= "Search result is 0" } $result += $userobject } }else{ $userobject = New-Object psobject -Property @{ searchuser = $recsamid DateTimeReceived = "" Sender= $Sender Subject= $subject Size= "" foldername= "" action= "" errorinfo= "Not Exsit Recipent" } $result += $userobject } } return $result }else{ Write-Host "Please enter the sender's full address" -ForegroundColor Red } }else{ Write-Host "Please enter the subject keywords" -ForegroundColor Red } }else{ Write-Host "starttime Should be less than endtime" -ForegroundColor Red } }else{ Write-Host "Please provide recipient information" -ForegroundColor Red } } }
5. How to use the delete mail function
Short term test: open Powershell and copy the above code to run in Powershell.
Use the following command to delete a message:
EWSDeleteEmail -sender sender@domain.com -subject "testsubject" -starttime "2020.4.24 9:50" -endtime "2020.4.24 9:55" -recepient recipient@domain.com
Long term use: it is recommended to save the function to Powershell personal Profile
#Check whether there is a Profile $profile #Create a Profile (it is found in the previous step that the existing Profile skips this step) New-Item –Path $Profile –Type File –Force #Open Profile, add function copy to the last notepad $Profile
Then every time you open Powershell, you can use the EWSDeleteEmail function directly.
EWSDeleteEmail -sender sender@domain.com -subject "testsubject" -starttime "2020.4.24 9:50" -endtime "2020.4.24 9:55" -recepient recipient@domain.com
6. How to delete mail in batch
6.1. The list user.csv to be deleted is in the following format
email user1@domain.com user2@domain.com user3@domain.com
6.2. Batch run delete mail and save the results to the result.csv file
$userlist = Import-Csv user.csv foreach($user in $userlist){ $recepient = $user.email $info = EWSDeleteEmail -sender sender@domain.com -subject "Test" -starttime "2020.4.24 9:50" -endtime "2020.4.24 9:55" -recepient $recepient $info | Export-Csv result.csv -Encoding UTF8 -Append }
7. Extended usage
If you need to query whether a user has received a message or whether the message has been read, you can cancel the part of the deleted message in the function and return the search result $findResults. Then you can see the message related information, such as whether it has been read, etc
7.1 read specified mail content function
function ReadSpecificEmail { <# .SYNOPSIS //Read the specified mailbox message ReadSpecificEmail -recepient extest7 -sender user@domain.cn -starttime "2018.12.24 10:48" -endtime "2018.12.24 10:51" -subject "234" -Confirm:$false #> [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory=$true)] $sender, [Parameter(Mandatory=$true)] $subject, [Parameter(Mandatory=$true)] [System.datetime]$starttime , [Parameter(Mandatory=$true)] [System.datetime]$endtime , [Parameter(Mandatory=$false)] $recepient ) if($PSCmdlet.ShouldProcess($param)) { if($recepient -or ($file -match ".csv")){ if($endtime -gt $starttime){ if($subject){ if($sender -match "\@"){ $result = @() Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" $username = "user@domain.com" $password = "Password" $exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2016_CU7) $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2016_CU7 $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion) $service.Credentials = New-Object Microsoft.Exchange.WebServices.Data.WebCredentials -ArgumentList $userName, $password $filter1 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsGreaterThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $starttime) $filter2 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, $endtime) $filter3 = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+ContainsSubstring([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject,$subject) $filter4 = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Sender, $Sender) $sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And); $sfCollection.add($filter1) $sfCollection.add($filter2) $sfCollection.add($filter3) $sfCollection.add($filter4) if($recepient){ $recsamid = ($recepient -split "\@")[0] $userinfo = "" $userinfo = get-aduser $recsamid -Properties EmailAddress,targetAddress $useremail = "" $useremail = $userinfo.EmailAddress if($useremail){ $targetAddress = "" $targetAddress =$userinfo.targetAddress if($targetAddress){ $uri=[system.URI] "https://outlook.office365.com/EWS/Exchange.asmx" }else{ $uri=[system.URI] "https://email.domain.com/ews/exchange.asmx" } $upn = $userinfo.EmailAddress $service.url = $uri $service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SMTPAddress,$upn) $inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox) $FolderList = new-object Microsoft.Exchange.WebServices.Data.FolderView(100) $FolderList.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep $findFolderResults = $inbox.FindFolders($FolderList) $view = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000) $findResults = @() $mails = "" $echocontent = "Querying $upn Messages in inbox" Write-Host $echocontent -ForegroundColor gray $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::inbox,$sfCollection,$view) $mails | Add-Member -MemberType NoteProperty -Name foldername -Value "inbox" if($mails){ $findResults += $mails } $mails = "" $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SentItems,$sfCollection,$view) $mails | Add-Member -MemberType NoteProperty -Name foldername -Value "SentItems" if($mails){ $findResults += $mails } $mails = "" $mails = $service.FindItems([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::DeletedItems,$sfCollection,$view) $mails | Add-Member -MemberType NoteProperty -Name foldername -Value "DeletedItems" if($mails){ $findResults += $mails } if(!$findResults){ $sortfindFolderResults = $findFolderResults | where{$_.FolderClass -eq "IPF.Note"} foreach($subfoler in $sortfindFolderResults){ $displayname = $subfoler.displayname $echocontent = "Querying $upn folder $displayname Messages in" Write-Host $echocontent -ForegroundColor gray $id = $subfoler.id $folder_ms= "" $folder_ms= [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$id) $mails = "" $mails= $service.FindItems($id,$sfCollection,$view) if($mails){ $mails | Add-Member -MemberType NoteProperty -Name foldername -Value $displayname $findResults += $mails } } } if($findResults){ $num = ($findResults | measure).count $outinfo = $findResults | select DateTimeReceived,Sender,Subject,Size,foldername $outinfotxt = $outinfo | fl | Out-String $echocontent = @" //Query criteria: //To: $upn //From: $Sender //Subject: $subject //Time period: $starttime-$endtime //Number of search results: $num //Details: $outinfotext "@ Write-Host $echocontent -ForegroundColor gray $result = $findResults }else{ $userobject = New-Object psobject -Property @{ searchuser = $recsamid DateTimeReceived = "" Sender= $Sender Subject= $subject Size= "" foldername= "" action= "" errorinfo= "Search result is 0" } $result += $userobject } }else{ $userobject = New-Object psobject -Property @{ searchuser = $recsamid DateTimeReceived = "" Sender= $Sender Subject= $subject Size= "" foldername= "" action= "" errorinfo= "Not Exsit Recipent" } $result += $userobject } } return $result }else{ Write-Host "Please enter the sender's full address" -ForegroundColor Red } }else{ Write-Host "Please enter the subject keywords" -ForegroundColor Red } }else{ Write-Host "starttime Should be less than endtime" -ForegroundColor Red } }else{ Write-Host "Please provide recipient information" -ForegroundColor Red } } }