Advertisement
dceola

delete-email

Feb 14th, 2018
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <#
  2. .SYNOPSIS
  3.     This script will prompt the user for sender and subject line for a Spam or Phishing email and remove it from all mailboxes in the organization
  4. .DESCRIPTION
  5.     This script requires you to have Exchange 2010 Management Shell installed to your computer before it will work.
  6. .EXAMPLE
  7.     delete-email.ps1 -Sender <email address> -Subject <text> -O365user <user@domain.com> -O365pass <password> -ExchUser <domain\user> -ExchPass <password> -MoveMsg <boolean flag, set true if present>
  8. .REQUIRES -Version 3.0
  9. .REQUIRES -PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
  10. .REQUIRES -Run this command as admin before running this script for the first time on a system: New-EventLog -LogName Application -Source "Email Deletion"
  11. #>
  12. param(
  13.     [Parameter(Mandatory=$false)][string]$Sender = "",
  14.     [Parameter(Mandatory=$false)][string]$Subject = "",
  15.     [parameter(Mandatory=$false)][string]$O365User,
  16.     [Parameter(Mandatory=$false)][string]$O365Pass,
  17.     [Parameter(Mandatory=$false)][string]$ExchUser,
  18.     [Parameter(Mandatory=$false)][string]$ExchPass
  19. )
  20. #################################################################################
  21. #
  22. #  Gather Input & check provided parameters for validity
  23. #
  24. #################################################################################
  25.  
  26.     Write-Verbose "This script will ask you for sender email address and email subject line of an email to remove from all maiboxes."
  27.     $SubjectRequired = $false
  28.  
  29.     # Ask user for the sender email address and verify via regex that it is a valid email address. Re-prompt user for valid address until user gets it right.
  30.     Do {
  31.         if((-not $sender) -or ($match -ne $true)) {
  32.             $Sender = Read-Host -Prompt "Please input the senders email address"
  33.         }
  34.  
  35.         if( $Sender -match "^[a-zA-Z0-9._%+-=]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$") {
  36.             $match = $true
  37.         }
  38.        else{
  39.             Write-Host "You did not enter a properly formatted email address. Please try again" -ForegroundColor Red
  40.         }
  41.     }while($match -ne $true)
  42.     $match = "" #clear the $match variable for reuse
  43.  
  44.     #Check if sender address provided is an internal address, if so - require a subject line.
  45.     if( $sender -match "long list of our email domains") {
  46.         $SubjectRequired = $true
  47.     }
  48.        
  49.     # Prompt user for subject line of email to search for, prompt user repeatedly until they enter a subject, if it's required.
  50.     Do {
  51.         if([string]::IsNullOrWhiteSpace($Subject)) {
  52.             $Subject = Read-Host -Prompt "Please input the email subject line"
  53.         }
  54.         if( [string]::IsNullOrWhiteSpace($Subject) -and $SubjectRequired ) {
  55.                 write-host "You must enter a subject line when dealing with a Carilion Internal sender." -ForegroundColor Red              
  56.         }
  57.     } while ($SubjectRequired -and [string]::IsNullOrWhiteSpace($Subject) )
  58.  
  59. #Build a string to send to Event Log, and send an Application Event log entry
  60. $logtext = "Script ran by: $env:userdomain\$env:username`r`nSender address: $Sender`r`nSubject line: $Subject"
  61. Write-EventLog -LogName Application -Source "Email Deletion" -EntryType Information -EventId 65535 -Message $logtext
  62.  
  63.  
  64. #################################################################################
  65. #
  66. #  Begin Office 365 Connectivity & cleanup
  67. #
  68. #################################################################################
  69.  
  70.     # Prompt user for O365 login credentials
  71.     if((-not $O365User) -or (-not $O365Pass)) {
  72.         $O365Credential = Get-Credential -Message "Please enter your Office365 credentials <user@domain.org> format."
  73.     }
  74.  
  75.     try{
  76.         write-verbose "Loading Office 365 Powershell Connection ..."
  77.         $O365Sess = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $O365Credential -Authentication Basic -AllowRedirection -ErrorAction Stop
  78.         Import-PSSession $O365Sess -AllowClobber -DisableNameChecking -ErrorAction Stop
  79.         write-verbose "Office 365 Security and Compliance center Powershell connection loaded."
  80.     }
  81.     catch{
  82.         write-host "Loading Office 365 Powershell Connection failed.  Please connect your internet connectivity, credentials provided or O365 portal status." -ForegroundColor Red
  83.         exit
  84.     }
  85.  
  86.     # Create O365 Content Search to locate the message. Uses the current date and the spam sender's address as a name for the
  87.     $date = Get-Date -displayhint datetime
  88.     $compsearchname = "$date - $Sender"
  89.     $user = $env:USERNAME
  90.     write-verbose "Creating Content search in O365 based on provided information."
  91.     write-verbose "Spam sender email address: $Sender"
  92.     write-verbose "Spam email subject line: $Subject"
  93.     #Runs one search command if there is a subject line present, another if there is no subject line present.
  94.     if(-not $Subject) {
  95.         New-ComplianceSearch -Name $compsearchname -Description "Searching for Spam/Phishing message from $Sender. Search created by $user" -ExchangeLocation all -ContentMatchQuery "from: `"$Sender`""
  96.     }
  97.     else {
  98.         New-ComplianceSearch -Name $compsearchname -Description "Searching for Spam/Phishing message from $Sender. Search created by $user" -ExchangeLocation all -ContentMatchQuery "subject:`"$Subject`" AND from: `"$Sender`""
  99.     }
  100.  
  101.     Start-ComplianceSearch -Identity $compsearchname
  102.     write-verbose "Content search created & started."
  103.     Get-PSSession | Remove-PSSession #Removes O365 session so there is no confusion between commands from on-prem Exchange and O365 Exchange.
  104.  
  105. #################################################################################
  106. #
  107. #  Import Exchange 2010 snap ins & begin On Prem cleanup
  108. #
  109. #################################################################################
  110.  
  111.     write-verbose "Importing Exchange 2010 PowerShell SnapIn"
  112.     # Attempt importing Exchange 2010 snap ins. Fail and exit script if not found.
  113.     if((-not $ExchUser) -or (-not $ExchPass)) {
  114.         $ExchCred = Get-Credential -Message "Please enter your On-Prem Exchange Admin credentials.  <domain\username> format."
  115.     }
  116.     try{
  117.         Write-Verbose "Loading Exchange 2010 Powershell Snapins ..."
  118.         $ExchSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exch-prd-htcas1/powershell/ -Authentication Kerberos -Credential $ExchCred
  119.         Import-PSSession $ExchSession
  120.         }
  121.     catch{
  122.         Write-Host "Incorrect password or you do not have Exchange 2010 Management Shell installed.  Please install before running this script" -ForegroundColor Red
  123.         exit
  124.         }
  125.  
  126.     # Get on-prem mailbox servers.  Regex assumes they are all named "DAG--" with the last character being A or B, and third to last being any number.
  127.     # The DAG server naming is likely unique to my org, they all end like DAG1A, DAG1B, etc.
  128.     # We only have to do regex here because my orgs DAGs all have 3 members named A, B and C.  The C items are only there for backup reasons and do not contain live mailboxes
  129.     $MailboxServers = @()
  130.     $MailboxServers = get-mailboxserver | where { $_.Name -match "DAG\w[AB]"}
  131.    
  132.     # Get on-prem CAS servers.
  133.     # My org has 8 mailbox servers and 8 CAS servers.  To spread workload, we connect powershell session to each CAS and run deletion script against one mailbox server per CAS.
  134.     $HTCASServers = @()
  135.     $HTCASServers = Get-ClientAccessServer
  136.  
  137.     write-verbose "We will now loop through the following Exchange Mailbox servers to remove the message from all on-prem mailboxes. This may take some time"
  138.     write-verbose "$MailboxServers"
  139.     $count = 0     #counter to incrememt which CAS server to connect to. This portion of script relies on org having an equal number of MBX and CAS servers
  140.  
  141.     foreach ($mbxsrv in $MailboxServers){
  142.         $HTCAS = $HTCASServers[$count] # Select array item to pass to start-job block
  143.         # Start-Job block allows parallel running of the cleanup task, which is essential as it reduces the time to process greatly.
  144.         Start-Job -Name $mbxsrv -scriptblock {
  145.             param (
  146.                 [Parameter()][string]$mbxsrv,
  147.                 [Parameter()][string]$Sender,
  148.                 [Parameter()][string]$Subject,
  149.                 [Parameter()][System.Management.Automation.PSCredential]$ExchCred,
  150.                 [Parameter()][String]$HTCAS
  151.             )
  152.  
  153.             try {
  154.                 # Connects the background PS job to a CAS server.  
  155.                 $ExchSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://$HTCAS/powershell/" -Authentication Kerberos -Credential $ExchCred -ErrorAction Stop
  156.                 Import-PSSession $ExchSession -ErrorAction Stop
  157.             }
  158.             catch {
  159.                 write-host "Failed to connect to local exchange environment."
  160.                 exit
  161.             }
  162.             # Run a search logging the results, then a search deleting the results. Still trying to combine into one search.
  163.             # Seperate commands depending on if the Subject line is present or not.
  164.             if(-not $Subject) {
  165.                 Get-Mailbox -Server "$mbxsrv" -ResultSize Unlimited | Search-Mailbox -SearchQuery From:"$Sender" -targetmailbox contentfilter -targetfolder searchlog -loglevel full -logonly
  166.                 Get-Mailbox -Server "$mbxsrv" -ResultSize Unlimited | Search-Mailbox -SearchQuery From:"$Sender" -DeleteContent -force
  167.             }
  168.             else {
  169.                 Get-Mailbox -Server "$mbxsrv" -ResultSize Unlimited | Search-Mailbox -SearchQuery From:"$Sender",Subject:"$Subject" -targetmailbox contentfilter -targetfolder searchlog -loglevel full -logonly
  170.                 Get-Mailbox -Server "$mbxsrv" -ResultSize Unlimited | Search-Mailbox -SearchQuery From:"$Sender",Subject:"$Subject" -DeleteContent -force
  171.             }
  172.         } -ArgumentList $mbxsrv, $Sender, $Subject, $ExchCred, $HTCAS #args to send into the start-job scriptblock.
  173.  
  174.         $count += 1 # increments to select the next CAS server
  175.     }
  176.     get-job | wait-job # get created jobs, wait for completion, remove them.
  177.     write-verbose "Spam message successfully removed from all on-prem mailboxes."
  178.     Get-PSSession | Remove-PSSession  #Removes local exchange session so there is no confusion between commands from on-prem Exchange and O365 Exchange.
  179.  
  180. #################################################################################
  181. #
  182. #  Check O365 Search & finalize cleanup
  183. #
  184. #################################################################################
  185.  
  186.     # Re-connect to O365 powershell
  187.     write-verbose "Checking status of O365 Content Search."
  188.     $O365Sess = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $O365Credential -Authentication Basic -AllowRedirection -ErrorAction Stop
  189.     Import-PSSession $O365Sess -AllowClobber -DisableNameChecking -ErrorAction Stop
  190.  
  191.  
  192.     # Check compliance search status.  Pause for 30s and check again if not Completed
  193.     $search = Get-ComplianceSearch -Identity $compsearchname
  194.     while($search.Status -ne "Completed") {
  195.         write-host "O365 Content Search not yet completed.  Waiting 30s" -ForegroundColor Red
  196.         Start-Sleep -Seconds 30
  197.         $search = Get-ComplianceSearch -Identity $compsearchname
  198.     }
  199.     write-verbose "Content search is complete."
  200.     $found = (get-compliancesearch -identity $compsearchname).Items # get count of found items
  201.     write-verbose "$found items found in O365"
  202.     if($found -gt 0) { # if >0 found items, delete them all.
  203.         write-verbose "Removing spam message from O365 mailboxes."
  204.         New-ComplianceSearchAction -SearchName $compsearchname -Purge -Force #force flag seems to not be recognized; still prompts for deletion confirmation.
  205.         Write-host "Removed $found matching emails in O365 mailboxes."
  206.     }
  207.  
  208. write-host "Spam message removed from all mailboxes, on-premesis and O365." -ForegroundColor Green
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement