Automate move the New mailboxes to Cloud

Another day another Spell 🙂

 

We have migrated majority of our users and resource mailboxes to office 365.

All new user mailboxes are now directly enabled on the cloud using Enable-Remotemailbox cmdlet from our identity management system.

  • Question now is, what about shared mailboxes, rooms and equipment mailboxes that are still created OnPrem by our L2 teams ?

As per recommendation for hybrid setup, these should be created OnPrem and than moved to cloud so that appropriate properties are maintained.

Based on below organizational requirement, we have written this solution to run daily.

  • All new resources that are created Onprem should automatically move to cloud.(exchange online)
  • There should also be a provision for not moving the resource online(this is required because of some application dependency)

For second requirement, we have communicated to L2 team that they should update the extensionattribute12 to onpremise if they want that mailbox should stay onprem because of some application dependency.

Download and extract the solution zip from below link.

https://github.com/VikasSukhija/Downloads/blob/master/Automovemailboxestocloud.zip

 

Update the Automovemailboxestocloud.ps1 line number 152 with the address of your exchange onpremise server.(our customer is on 2010)

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri “OnpremExchangeServer/PowerShell/” -Authentication Kerberos    

Now lets update the batch file with all the required parameters.

powershell .\Automovemailboxestocloud.ps1 -RemoteHostName “hybridFQDN” -TargetDeliveryDomain “Company.mail.onmicrosoft.com” -Resourcescaretedpast “-3” -OnpremuserId “domain\serviceaccount” -OnlineuserId “serviceaccount@labtest.com” -smtpserver smtpserver -from DonotReply@labtest.com -erroremail “Reports@labtest.com” -reportemail “teamaddress@labtest.com”

 

 

 

-Resourcescaretedpast –> This parameter checks up to what number of days in the past you want resource mailboxes to be moved.

-OnpremuserId “domain\serviceaccount”  (This account has permissions to exchange onpremise)

-OnlineuserId “serviceaccount@labtest.com” (same account has permissions to exchange online)

Use -erroremail for sending errors to certain mailbox that is monitored.

Use -Reportemail to send the report to the L2 team.

Before moving ahead there is still one step left, encrypt the password of service account, use the encrypt.bat file that is inside the extracted solution.

Now everything is ready , you can run the batch file ones to check the results(run it from command line so that you can see the final results on the screen without closure) and when you think its working, you can schedule it to run daily.

Here is the report that is received ones it runs.

 

If user mailbox is found then its issue with the Provisioning process by IDM system or its a genuine service account sitting on-premise.

Use this solution as is or modify as per your organizational needs.

PowerShell
<#     
    .NOTES 
    =========================================================================== 
    Created with:     ISE 
    Created on:       9/25/2019 1:46 PM 
    Created by:       Vikas Sukhija 
    Organization:      
    Filename:         Automovemailboxestocloud.ps1 
    =========================================================================== 
    .DESCRIPTION 
    This will run daily and move SMB/Resource mailboxes to the cloud 
#> 
param ( 
  [string]$RemoteHostName = $(Read-Host "Enter RemoteHostName - hybrid dns address"), 
  [string]$TargetDeliveryDomain = $(Read-Host "Enter Target Delivery domain"), 
  $Resourcescaretedpast = $(Read-Host "Enter the negative number 1 for last day, -2 for last two days"), 
  [string]$OnlineuserId = $(Read-Host "Enter Online Admin account"), 
  [string]$OnpremuserId = $(Read-Host "Enter Online Onpremise account"), 
  [string]$smtpserver = $(Read-Host "Enter SMTP Server"), 
  [string]$from = $(Read-Host "Enter From Address"), 
  [string]$erroremail = $(Read-Host "Enter Address for Alerts and Errors"), 
  [string]$Reportemail = $(Read-Host "Enter Address for Report") 
) 
function Write-Log 
{ 
  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [array]$Name, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$Ext, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Create')] 
    [string]$folder, 
     
    [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create, 
     
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$Message, 
    [Parameter(Mandatory = $true,ParameterSetName = 'Message')] 
    [String]$path, 
    [Parameter(Mandatory = $false,ParameterSetName = 'Message')] 
    [ValidateSet('Information','Warning','Error')] 
    [string]$Severity = 'Information', 
     
    [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG 
  ) 
  switch ($PsCmdlet.ParameterSetName) { 
    "Create" 
    { 
      $log = @() 
      $date1 = Get-Date -Format d 
      $date1 = $date1.ToString().Replace("/""-") 
      $time = Get-Date -Format t 
     
      $time = $time.ToString().Replace(":""-") 
      $time = $time.ToString().Replace(" """) 
     
      foreach ($n in $Name) 
      {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} 
      return $log 
    } 
    "Message" 
    { 
      $date = Get-Date 
      $concatmessage = "|$date" + "|   |" + $Message +"|  |" + "$Severity|" 
      switch($Severity){ 
        "Information"{Write-Host -Object $concatmessage -ForegroundColor Green} 
        "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow} 
        "Error"{Write-Host -Object $concatmessage -ForegroundColor Red} 
      } 
       
      Add-Content -Path $path -Value $concatmessage 
    } 
  } 
} #Function Write-Log 
function Start-ProgressBar 
{ 
  [CmdletBinding()] 
  param 
  ( 
    [Parameter(Mandatory = $true)] 
    $Title, 
    [Parameter(Mandatory = $true)] 
    [int]$Timer 
  ) 
     
  For ($i = 1; $i -le $Timer$i++) 
  { 
    Start-Sleep -Seconds 1; 
    Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /100 * 100) 
  } 
} 
 
function LaunchEOL 
  { 
    param 
    ( 
      $Credential 
    ) 
         
    $UserCredential = $Credential 
         
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection 
         
    Import-PSSession $Session -Prefix "EOL" -AllowClobber 
  } 
     
  Function RemoveEOL 
  { 
         
    $Session = Get-PSSession | where { $_.ComputerName -like "outlook.office365.com" } 
    Remove-PSSession $Session 
         
  } 
#################Check if logs folder is created#### 
$logpath  = (Get-Location).path + "\logs"  
$testlogpath = Test-Path -Path $logpath 
if($testlogpath -eq $false) 
{ 
  Start-ProgressBar -Title "Creating logs folder" -Timer 10 
  New-Item -Path (Get-Location).path -Name Logs -Type directory 
} 
$Reportpath  = (Get-Location).path + "\Report"  
$testlogpath = Test-Path -Path $Reportpath 
if($testlogpath -eq $false) 
{ 
  Start-ProgressBar -Title "Creating Report folder" -Timer 10 
  New-Item -Path (Get-Location).path -Name Report -Type directory 
} 
####################Load variables and log########## 
$log = Write-Log -Name "AutomateMovetocloud-Log" -folder "logs" -Ext "log" 
$Report1 = Write-Log -Name "AutomateMovetocloud-Report" -folder "Report" -Ext "csv" 
 
Write-log -Message "Start .........Script" -path $log 
try{ 
  $encrypted1 = Get-Content .\password1.txt 
  $pwd = ConvertTo-SecureString -string $encrypted1 
  $Credential1 = New-Object System.Management.Automation.PSCredential -ArgumentList $OnlineuserId$pwd 
  $Credential2 = New-Object System.Management.Automation.PSCredential -ArgumentList $OnpremuserId$pwd 
  Write-log -Message "loading credentials" -path $log 
  } 
  catch{ 
      $_.Exception 
    Write-log -Message "exception has occured loading credentials" -path $log 
    Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error loading credentials Automatemailboxmovetocloud" -Body $($_.Exception.Message) 
    exit; 
  } 
   
try 
  { 
     $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://OnpremExchangeServer/PowerShell/ -Authentication Kerberos 
     import-pssession $session -AllowClobber 
     LaunchEOL -Credential $Credential1 
     Write-log -Message "loading Exchnage onpremise and Exhcnage online shells" -path $log 
  } 
  catch 
  { 
    $_.Exception 
    Write-log -Message "exception has occured loading exchange managemnt shell" -path $log -Severity Error 
    Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error Loading exchange shell Automatemailboxmovetocloud" -Body $($_.Exception.Message) 
    exit; 
  } 
 
#######################Start fetching SMB and resources createdrecently################# 
$pastdays= (get-date).AddDays($Resourcescaretedpast) 
write-log -message "Fetching all mailboxes from the past $pastdays" -path $log 
$allmailboxes = Get-Mailbox -resultsize:unlimited |where {$_.WhenMailboxCreated -gt $pastdays| Select Name,Alias,PrimarySMTPaddress,UserPrincipalName,recipienttypedetails,CustomAttribute12 
write-log -message "Fetched all mailboxes from the past $pastdays" -path $log 
$collection=@() 
if($allmailboxes){ 
  $allmailboxes | foreach-object{ 
    $error.clear() 
    $mcoll = "" | Select Name,Alias,PrimarySMTPaddress,UserPrincipalName,recipienttypedetails,CustomAttribute12, status 
    $name = $_.Name 
    $alias =$_.alias 
    $PrimarySMTPaddress = $_.PrimarySMTPaddress 
    $UserPrincipalName = $_.UserPrincipalName 
    $recipienttypedetails=$_.recipienttypedetails 
    $CustomAttribute12=$_.CustomAttribute12 
    $mcoll.Name = $name 
    $mcoll.Alias = $alias 
    $mcoll.PrimarySMTPaddress = $PrimarySMTPaddress 
    $mcoll.UserPrincipalName = $UserPrincipalName  
    $mcoll.recipienttypedetails = $recipienttypedetails 
    $mcoll.CustomAttribute12 = $CustomAttribute12 
    write-log -message "Processing...............$PrimarySMTPaddress" -path $log 
    if($CustomAttribute12 -eq "OnPremise"){ 
      $mcoll.status = "NotProcessing" 
      write-log -message "NotProcessing.....$PrimarySMTPaddress is $recipienttypedetails" -path $log 
    } 
    else{ 
      if($recipienttypedetails -eq "UserMailbox") 
      { 
        $mcoll.status = "ErrorbyIDMorServiceMailbox" 
        write-log -message "$PrimarySMTPaddress is $recipienttypedetails" -path $log 
     
      }else{ 
        write-log -message "$PrimarySMTPaddress is $recipienttypedetails ... processing" -path $log 
        New-EOLMoveRequest -Identity $PrimarySMTPaddress -Remote -RemoteHostName $RemoteHostName -TargetDeliveryDomain $TargetDeliveryDomain -RemoteCredential $Credential2 -BadItemLimit "100" 
        if($error){ 
          $mcoll.status = "error" 
          write-log -message "error occured processing $PrimarySMTPaddress" -path $log -Severity Warning 
          $error.clear() 
        }else{ 
          $mcoll.status = "RequestSubmitted" 
          write-log -message "Request submitted for $PrimarySMTPaddress" -path $log  
        } 
      }  
      $collection+=$mcoll 
    } 
  } 
  write-log -message "Exporting....................report" -path $log 
  $collection | Export-Csv $Report1 -NoTypeInformation 
  write-log -message "Sending....................report" -path $log 
  Send-MailMessage -SmtpServer $SmtpServer -From $From -To $Reportemail -bcc $erroremail -Subject "Report - AutomateMovetoCloud" -Body "Report - AutomateMovetoCloud" -Attachments $report1 
} 
RemoveEOL 
write-log -message "Removing exchange Online shell" -path $log 
##############################Recycle Logs########################## 
Write-Log -Message "Recycle Logs" -path $log -Severity Information 
$path1 = (Get-Location).path + "\report" 
$path2 = (Get-Location).path + "\logs"  
 
$limit = (Get-Date).AddDays(-60) #for report recycling 
Get-ChildItem -Path $path1 | 
Where-Object {$_.CreationTime -lt $limit| 
Remove-Item -recurse -Force 
 
Get-ChildItem -Path $path2 | 
Where-Object {$_.CreationTime -lt $limit| 
Remove-Item -recurse -Force 
 
Write-Log -Message "Script Finished" -path $log -Severity Information 
Send-MailMessage -SmtpServer $SmtpServer -From $From -To $erroremail -Subject "Transcript Log - AutomateMovetoCloud" -Body "Transcript Log - AutomateMovetoCloud" -Attachments $log 
###############################################################################

Thanks for reading and downloading

Sukhija Vikas (Tech Wizard)

http://TechWizard.cloud

Leave a comment