#region Connect to all the things
#Test O365 Connection
If($Null -eq $O365Cred){
$O365Cred = $Host.ui.PromptForCredential("","Enter your OFFICE 365 admin creds","ENTER YOUR ACCOUNT NAME HERE","")
}
Try{Get-O365Mailbox aguerot -ErrorAction Stop > $Null}
Catch{
$O365Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $O365Cred -Authentication Basic -AllowRedirection
Import-PSSession $O365Session –Prefix o365
}
Try{Get-MsolUser -UserPrincipalName ENTER TEST USER HERE -ErrorAction Stop > $Null}
Catch{Connect-MsolService -Credential $O365Cred}
Try{Get-ComplianceSearch > $Null}
Catch{
#Get login credentials
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid -Credential $O365Cred -Authentication Basic -AllowRedirection
Import-PSSession $Session -AllowClobber -DisableNameChecking
}
#endregion
#Get User Info
$User = Read-host "Enter user name"
$Logfile = "PATH TO LOG FILE\$User.txt"
Function LogWrite
{
Param ([string]$logstring)
Write-Host $LogString
Add-content $Logfile -value $logstring
}
$Date = Get-Date -Format "MM/dd/yyyy"
LogWrite $Date
LogWrite " "
LogWrite "Username: $User"
#Begin Compliance Search
$UPN = Get-ADUser $User | ForEach-Object{$_.UserPrincipalName}
$SearchName = $User + "_Termed"
New-ComplianceSearch -Name $SearchName -ExchangeLocation $UPN
Start-ComplianceSearch $SearchName
Logwrite " "
LogWrite "Compliance search $SearchName started"
Do{
$complianceSearch = Get-ComplianceSearch $SearchName | ForEach-Object{$_.Status}
Write-Host "Compliance Search in Progress"
Start-Sleep -s 30
}
While ($complianceSearch -ne 'Completed')
$Size = Get-ComplianceSearch $SearchName | ForEach-Object{$_.Size}
$Size = $Size / 1048576 | Out-String
$Size = $Size.SubString(0,6)
# Create Compliance Search in exportable format
New-ComplianceSearchAction -SearchName $SearchName -EnableDedupe $true -Export -Format FxStream -ArchiveFormat PerUserPST > $Null
#Wait for Export to complete
$ExportName = $SearchName + "_Export"
Start-Sleep -s 20
do{
$SearchAction = Get-ComplianceSearchAction -Identity $ExportName | Select-Object Status,JobProgress
$Status = $SearchAction.Status
$ExportProgress = $SearchAction.JobProgress
Write-Host "Export in progress, $ExportProgress complete"
If($Status -ne "Completed"){
Start-Sleep -s 60
}
}
while ($Status -ne 'Completed')
LogWrite "Compliance search completed"
$exportlocation = "C:\pst" #enter the path to your export here !NO TRAILING BACKSLASH!
$exportexe = "\UnifiedExportTool\microsoft.office.client.discovery.unifiedexporttool.exe" #path to your microsoft.office.client.discovery.unifiedexporttool.exe file. Usually found somewhere in ForEach-ObjectLOCALAPPDATAForEach-Object\Apps\2.0\
# Gather the URL and Token from the export in order to start the download
#We only need the ContainerURL and SAS Token but I parsed some other fields as well while working with AzCopy
#The Container URL and Token in the following template has been altered to protect the innocent:
$exporttemplate = @'
Container url: {ContainerURL*:https://xicnediscnam.blob.core.windows.net/da3fecb0-4ed4-447e-0315-08d5adad8a5a}; SAS token: {SASToken:?sv=2014-02-14&sr=c&si=eDiscoveryBlobPolicy9ForEach-Object7C0&sig=RACMSyH6Cf0k4EP2wZSoAa0QrhKaV38Oa9ciHv5Y8MkForEach-Object3D}; Scenario: General; Scope: BothIndexedAndUnindexedItems; Scope details: AllUnindexed; Max unindexed size: 0; File type exclusions for unindexed: <null>; Total sources: 2; Exchange item format: Msg; Exchange archive format: IndividualMessage; SharePoint archive format: SingleZip; Include SharePoint versions: True; Enable dedupe: EnableDedupe:True; Reference action: "<null>"; Region: ; Started sources: StartedSources:3; Succeeded sources: SucceededSources:1; Failed sources: 0; Total estimated bytes: 12,791,334,934; Total estimated items: 143,729; Total transferred bytes: {TotalTransferredBytes:7,706,378,435}; Total transferred items: {TotalTransferredItems:71,412}; Progress: {Progress:49.69 ForEach-Object}; Completed time: ; Duration: 00:50:43.9321895; Export status: {ExportStatus:DistributionCompleted}
Container url: {ContainerURL*:https://zgrbediscnam.blob.core.windows.net/5c21f7c7-42a2-4e24-9e69-08d5acf316f5}; SAS token: {SASToken:?sv=2014-02-14&sr=c&si=eDiscoveryBlobPolicy9ForEach-Object7C0&sig=F6ycaX5eWcRBCS1Z5nfoTKJWTrHkAciqbYRP5ForEach-Object2FhsUOoForEach-Object3D}; Scenario: General; Scope: BothIndexedAndUnindexedItems; Scope details: AllUnindexed; Max unindexed size: 0; File type exclusions for unindexed: <null>; Total sources: 1; Exchange item format: FxStream; Exchange archive format: PerUserPst; SharePoint archive format: IndividualMessage; Include SharePoint versions: True; Enable dedupe: True; Reference action: "<null>"; Region: ; Started sources: 2; Succeeded sources: 2; Failed sources: 0; Total estimated bytes: 69,952,559,461; Total estimated items: 107,707; Total transferred bytes: {TotalTransferredBytes:70,847,990,489}; Total transferred items: {TotalTransferredItems:100,808}; Progress: {Progress:93.59 ForEach-Object}; Completed time: 4/27/2018 11:45:46 PM; Duration: 04:31:21.1593737; Export status: {ExportStatus:Completed}
'@
$exportdetails = Get-ComplianceSearchAction -Identity $exportname -IncludeCredential -Details | Select-Object -ExpandProperty Results | ConvertFrom-String -TemplateContent $exporttemplate
$exportdetails
$exportcontainerurl = $exportdetails.ContainerURL
$exportsastoken = $exportdetails.SASToken
# Download the exported files from Office 365
Write-Host "Compliance Search Size:" $Size
LogWrite "Initiating download"
LogWrite "Saving export to: $exportlocation"
$arguments = "-name ""$searchname""","-source ""$exportcontainerurl""","-key ""$exportsastoken""","-dest ""$exportlocation""","-trace true"
Start-Process -FilePath "$exportexe" -ArgumentList $arguments
#Do while microsoft.office.client.discovery.unifiedexporttool.exe running
$started = $false
Do {
$status = Get-Process microsoft.office.client.discovery.unifiedexporttool -ErrorAction SilentlyContinue
If (!($status)) {
Write-Host 'Waiting for process to start' ; Start-Sleep -Seconds 5
}
Else {
Write-Host 'Process has started' ; $started = $true
}
}
Until ( $started )
Do{
$Finished = $False
Write-host "Sleeping 300 seconds"
Start-Sleep -s 300
$DownloadSize = Get-Childitem "C:\pst" -recurse -include *.pst | ForEach-Object{$_.Length}
$DownloadSize = $DownloadSize / 1048576 | Out-String
$DownloadSize = $DownloadSize.SubString(0,6)
Write-Host " "
Write-Host "Compliance Search Size:" $Size
Write-Host "Downloaded Size:" $DownloadSize
Write-Host " "
<## Commenting this out to test performance
$ProcessesFound = Get-Process | ? {$_.Name -like "*unifiedexporttool*"}
Write-Host "Process still running"
If ($ProcessesFound) {
$Progress = get-ComplianceSearchAction -Identity $exportname -IncludeCredential -Details | Select-Object -ExpandProperty Results | ConvertFrom-String -TemplateContent $exporttemplate | ForEach-Object{$_.Progress}
Write-Host "Export still downloading, progress is $Progress, waiting 300 seconds"
Start-Sleep -s 300
}
#>
If($DownloadSize -ge $Size){
$status = Get-Process microsoft.office.client.discovery.unifiedexporttool -ErrorAction SilentlyContinue
If (!($status)) {
Write-Host "Download has finished"
$Finished = $True
}
}
}Until ($Finished -eq $True)
$DownloadSize = Get-Childitem "C:\pst" -recurse -include *.pst | ForEach-Object{$_.Length}
$DownloadSize = $DownloadSize / 1048576 | Out-String
$DownloadSize = $DownloadSize.SubString(0,6)
Write-Host " "
Write-Host "Compliance Search Size:" $Size
Write-Host "Downloaded Size:" $DownloadSize
Write-Host " "
#Read-Host "Pausing script until you verify download. Seriously. If the download isn't done this gets really bad. You sure you're ready? Press enter to continue"
LogWrite "PST exported & downloaded"
#Remove compliance search & export
$ExportName = $SearchName + "_Export"
Remove-ComplianceSearchAction -Identity $ExportName -Confirm:$False
Remove-ComplianceSearch $SearchName -Confirm:$False
If($?){Write-Host "Compliance search & export removed"}
#Get & Remove O365 licenses
$UPN2 = Get-ADUser -Identity $User | ForEach-Object{$_.UserPrincipalName}
$MSOLUser = Get-MsolUser -UserPrincipalName $UPN2 -ErrorAction SilentlyContinue
#$IsLicensed = $MSOLUser.IsLicensed
$Licenses = $MSOLUser.Licenses[0].AccountSkuId
Set-MsolUserLicense -UserPrincipalName $UPN2 -RemoveLicenses $Licenses
If($?){Write-Host "$User $Licenses removed"}
#Move to Disabled Accts OU
Get-AdUser $User | Move-AdObject -TargetPath "" #Moves to an OU that doesnt sync to O365
LogWrite "$User account has been moved to Disabled Accts OU"
#Run DirSync on Azure AD Connect sync server
Invoke-Command -Computername "" -ScriptBlock {C:\DirSync-ForceDelta.ps1} #Runs an Azure AD Connect Directory sync on a remote server
#Move PST for upload
Get-Childitem "C:\pst" -recurse -include *.pst | Move-Item -Destination "C:\pst"
#Upload mailbox to Azure
Write-Host "Uploading to Azure"
Start-Process "Disable User Process\LaunchCmd-Custom.cmd" #Customized Azure Storage AZ copy upload script
#Confirm upload to finished
write-host " "
$confirmation = Read-Host "Did Azure upload complete successfully? You need to enter y here"
if ($confirmation -eq 'y'){
#Delete pst
Remove-Item "C:\pst\*" -Recurse -Confirm:$False
If($?){Write-host " "
Write-Host "PST Deleted"}
}