MZN.Office365.psm1

#### FUNCTIONS ####
<#
.Synopsis
   Starts an AD sync to Azure AD on the remote server
.DESCRIPTION
   When a sync to Azure AD is required in a script, then this function can be used to remotely start the sync
   to Azure AD. Specify the policy type (delta or intial) and the module path (if the directory is not default)
.EXAMPLE
   PS C:\Scripts> Start-ADSync -ComputerName Server01
 
    PSComputerName RunspaceId Result
    -------------- ---------- ------
    Server01 d5490783-7f1f-46bb-aa97-fa8d4cabdd32 Success
     
    Successfully started the AD Sync Cycle on target Server01
 
#>

Function Start-ADSync{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  ConfirmImpact='Medium'
                  )]
    Param
    (
        #Specify the AAD Connect Server
        [Parameter(Mandatory=$true, 
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true
                   )]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [Alias("ADConnectServer","DirSyncServer","ADSyncServer")]
        [string] 
        $ComputerName,

        #Specifiy the AAD Connect Module Path on the AAD Connect Server
        [Parameter(ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true
                   )]
        [Alias("Module","Path")]
        [string] 
        $modulePath = "C:\Program Files\Microsoft Azure AD Sync\Bin\ADSync\ADSync.psd1",

        #Specifiy the policy type that needs to sync
        [Parameter()]
        [Alias("Type")]
        [ValidateSet('Delta','Initial')]
        [string] 
        $policyType = "Delta",

        #Switch to turn on Error logging
        [Switch]$ErrorLog,
        [String]$LogFile = '.\Force-ADSync.log'
    )

    Process
    {
        #starts transcript to errorlog when error log is specified
        if($Errorlog){
            Start-Transcript -Path $LogFile -Append
        }

        if ($pscmdlet.ShouldProcess($ComputerName, "Making a connection to the AD Connect Server"))
        {
            #trying to make a connection to the AD Connect Server
            Try{
                $s = New-PSSession -ComputerName $ComputerName -EA Stop
                Write-Verbose "Successfully connected to the AD Connect server $Computername"
            }
            Catch{
                Write-Warning "Unable to Connect to the AD Connect Server!"
                Write-Verbose $error[0]
                If ($ErrorLog){
                        Stop-Transcript
                    }

                break
            }
        }
        
        
        if ($pscmdlet.ShouldProcess($ComputerName, "Importing the AD Connect Module"))
        {
            #Setting the script block in a variable
            $scriptBlock = {
                param( [String] $modulePath )
                Import-Module $modulePath
            }
            
            #Importing the AD Connect Module
            Try{
                Invoke-Command -Session $s -ScriptBlock $scriptBlock -ArgumentList $(,$modulePath) -ErrorAction inquire
                Write-Verbose "Successfully imported AD Connect Module from location $modulePath"
            } 
            Catch{
                Write-Warning "Unable to import AD Connect Module!"
                Write-Verbose $error[0]              
                Remove-PSSession $s -ErrorAction SilentlyContinue
                If ($ErrorLog){
                        Stop-Transcript
                }
                break                
            }
        }

        if ($pscmdlet.ShouldProcess($ComputerName, "Performing an AD Sync Cycle"))
        {    
            #Setting the script block in a variable
            $scriptBlock = {
                param( [String] $policyType )
                Start-ADSyncSyncCycle -PolicyType $policyType
            }

            #starting the AD Sync Cycle on the remote server
            try{
                Invoke-Command -Session $s -ScriptBlock $scriptBlock -ArgumentList $(,$policyType) -ErrorAction Stop 
                Write-Host "Successfully started the AD Sync Cycle on target $ComputerName" -ForegroundColor Green
            }
            catch{
                Write-Warning "Unable to start the AD Sync Cylce!"
                Write-Verbose $error[0]      
            }
            Finally{
                #removing the session and stopping the transcript
                Remove-PSSession $s -ErrorAction SilentlyContinue
                If ($ErrorLog){
                        Stop-Transcript
                }     
            }
        }
    }
    End
    {
    }
}

<#
.Synopsis
   Connects to Office 365
.DESCRIPTION
   Connects to all instances of Office 365 for the tenant
.EXAMPLE
   PS C:\Users> Connect-O365
 
.EXAMPLE
    PS C:\Users> Connect-O365 -Proxy:$true
#>

Function Connect-O365{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  ConfirmImpact='Medium'
                  )]
    Param
    (
        #Specifiy if a proxy is required. Default the IE Proxy settings are used
        [Parameter()]
        [switch] 
        $Proxy = $false
    )
    
    process
    {
        #Imports the installed Azure Active Directory module.
        Import-Module MSOnline

        #Capture administrative credential for future connections.
        $credential = get-credential  

        #Set organization variable
        $org = $credential.UserName.Split("@")[1]
        $spoAdminURI = "https://" + $org.Split(".")[0] +"-admin.sharepoint.com"   

        #Set proxy settings
        if($proxy -eq $true){
            $proxySettings = New-PSSessionOption -ProxyAccessType IEConfig

            #Establishes Online Services connection to Office 365 Management Layer.
            Connect-MsolService -Credential $credential

            #login to Azure
            Login-AzureRmAccount -Credential $credential
            
            #Imports SharePoint Online session commands into your local Windows PowerShell session.
            Import-Module Microsoft.Online.Sharepoint.PowerShell
            Connect-SPOService -url $spoAdminURI -Credential $credential

            #Creates an Exchange Online session using defined credential.
            $ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $credential -Authentication "Basic" -AllowRedirection -SessionOption $proxySettings
            Import-Module (Import-PSSession $ExchangeSession -AllowClobber) -Global

            #Connection to Skype Online
            Import-Module SkypeOnlineConnector
            $sfboSession = New-CsOnlineSession -Credential $credential -SessionOption $proxySettings
            Import-Module (Import-PSSession $sfboSession -AllowClobber) -Global

            #Connect to Azure AD
            Connect-AzureAD -Credential $credential
        }
        else{

            #Establishes Online Services connection to Office 365 Management Layer.
            Connect-MsolService -Credential $credential

            #login to Azure
            Login-AzureRmAccount -Credential $credential


            #Imports SharePoint Online session commands into your local Windows PowerShell session.
            Import-Module Microsoft.Online.Sharepoint.PowerShell
            Connect-SPOService -url $spoAdminURI -Credential $credential

            #Creates an Exchange Online session using defined credential.
            $ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $credential -Authentication "Basic" -AllowRedirection
            Import-Module (Import-PSSession $ExchangeSession -AllowClobber) -Global

            #Connection to Skype Online
            Import-Module SkypeOnlineConnector
            $sfboSession = New-CsOnlineSession -Credential $credential 
            Import-Module (Import-PSSession $sfboSession -AllowClobber) -Global

            #Connect to Azure AD
            Connect-AzureAD -Credential $credential
            
        }
        
       
    }

}

<#
.Synopsis
   Checks if the users location is configured and if not configures the location for NL and sets the required licences.
.DESCRIPTION
   Checks if the users location is configured and if not configures the location for NL and sets the required licences.
.EXAMPLE
   PS C:\WINDOWS\system32> Set-O365License -userPrincipalName test@contoso.com -licenseType EMS
     
    User test@contoso.com is licensed for Enterprise Mobility and Security!
 
.EXAMPLE
    PS C:\WINDOWS\system32> $user = import-csv c:\temp\test.csv
 
    PS C:\WINDOWS\system32> $user | foreach{Set-O365License -userPrincipalName $_.userPrincipalName -location NL -licenseType EMS,O365E3}
#>

Function Set-O365License{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  ConfirmImpact='Low')]
    Param
    (
        #Provide the UPN of the user
        [Parameter(Mandatory=$true, 
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [Alias("UPN","User","emailAddress")] 
        $userPrincipalName,

        #Provide the required location
        [Parameter(ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [ValidateSet('NL','DE')]
        $location = "NL",

        #Provide the required licenses
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [ValidateSet('O365E3','EMS')]
        [Alias("license")] 
        [string[]]
        $licenseType,

        #Switch to turn on Error logging
        [Switch]$ErrorLog,
        [String]$LogFile = '.\Set-Office365License.log'
    )

    Process
    {
        #start error logging if -errorlog parameter was set
        if($ErrorLog){
            Start-Transcript -Path $LogFile -Append
        }

        if ($pscmdlet.ShouldProcess("Office365", "Checking if user $userPrincipalName is present in Office365"))
        {
            try
            {
                $User = Get-MsolUser -UserPrincipalName $userPrincipalName -ErrorAction stop
                $UsageLocation = $user.UsageLocation
                $License = $user.Licenses
                Write-Verbose "User found in Office 365."
            }
            catch
            {
                Write-Warning "Unable to find the user in Office 365!"
                Write-Verbose $error[0]              
                If ($ErrorLog){
                        Stop-Transcript
                }
                break                
            }
        
        }
        
        if ($pscmdlet.ShouldProcess("Office 365", "Checking if the location is set for user $userPrincipalName"))
        {
            if(!($UsageLocation)){

                Write-Verbose "Usage location is not set for user $userPrincipalName. Setting location to $location."

                try
                {
                    #set usage location to $location
                    $user | Set-MsolUser -UsageLocation $location -ErrorAction stop
                    write-verbose "Usage location set for $userPrincipalName to $location successfully."
                }
                catch
                {
                    Write-Warning "Unable set the usage location for $userPrincipalName to $location!"
                    Write-Verbose $error[0]              
                  
                }    
            }
            elseif($location -ne $UsageLocation)
            {
                Write-Verbose "Current usage location for the user $userPrincipalName is $UsageLocation. Changing the usage location to $location."

                try
                {
                    #set usage location to $location
                    $user | Set-MsolUser -UsageLocation $location -ErrorAction stop
                    write-verbose "Usage location set for $userPrincipalName to $location successfully."
                }
                catch
                {
                    Write-Warning "Unable set the usage location for $userPrincipalName to $location!"
                    Write-Verbose $error[0]              
                }    
            }
            else{
                write-verbose "Current usage location for the user is $usageLocation. No action required."
            }
                        

        }  

        if ($pscmdlet.ShouldProcess("Office 365", "Checking if the required licenses are available for the user $userPrincipalName"))
        {
            $accountSKUs = Get-MsolAccountSku

            #checking for the licenses and setting these when not assigned
            switch($licenseType){
                    O365E3
                    {
                        if($License.accountsku.skupartnumber -match "ENTERPRISEPACK"){
                            #User already has an Enterprise License
                            write-host "$userPrincipalName already has an O365 E3 License" -ForegroundColor Green
                        }
                        else
                        {
                            #Enabling O365 E3 License
                            write-verbose "Enabling O365 Enterprise license for User $userPrincipalName"

                            try{
                                $user | Set-MsolUserLicense -AddLicenses ($accountSKUs|where{$_.AccountSkuId -match "ENTERPRISEPACK"}).accountSkuID -ea stop
                                write-host "User $userPrincipalName is licensed for O365 Enterprise E3!" -ForegroundColor Green
                            }
                            catch{
                                Write-Warning "Unable to set the Office 365 E3 License for the user $userPrincipalName!"
                                Write-Verbose $error[0]
                            }
                        }

                    }
                              
                    EMS
                    {
                        #Checking and setting EMS License
                        if($License.accountsku.skupartnumber -match "EMS"){
                            #User already has an Enterprise License
                            write-host "$userPrincipalName already has an EMS License" -ForegroundColor Green
                        }
                        else
                        {
                            #Enabling O365 E3 License
                            write-verbose "Enabling EMS license for user $userPrincipalName"

                            try{
                                $user | Set-MsolUserLicense -AddLicenses ($accountSKUs|where{$_.AccountSkuId -match "EMS"}).accountSkuID -ea stop
                                write-host "User $userPrincipalName is licensed for Enterprise Mobility and Security!" -ForegroundColor Green
                            }
                            catch{
                                Write-Warning "Unable to set the EMS License for the user $userPrincipalName!"
                                Write-Verbose $error[0]
                            }
                        }
                    }
            }
            
        }

    }
    
    End
    {
        if($ErrorLog){
            Stop-Transcript
        }

    }
}

<#
.Synopsis
   Starts mail migration to Office 365
.DESCRIPTION
   Starts mail migration to Office 365
#>

Function Start-MailMigration{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  ConfirmImpact='Low')]
    Param
    (
        #Provide the UPN of the user
        [Parameter(Mandatory=$true, 
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [ValidateNotNullOrEmpty()]
        [Alias("UPN","User","emailAddress")] 
        $UserPrincipalName,

        #Provide the hostname of the onpremise exchange server
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [Alias('RemoteHost','LocalServer')]
        $RemoteHostName,

        #Provide the hostname of the onpremise exchange server
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        $DeliveryDomain,

        #Provide the on-premise credentials
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.PSCredential]
        $OnPremCreds,

        #Switch to turn on Error logging
        [Switch]$ErrorLog,
        [String]$LogFile = '.\Migrate-Mail.log'

    )

    Begin
    {
    }
    Process
    {
        #start error logging if -errorlog parameter was set
        if($ErrorLog){
            Start-Transcript -Path $LogFile -Append
        }

        #execute migration to Office 365
        if ($pscmdlet.ShouldProcess($UserPrincipalName, "Starting mailbox migration to Office 365."))
        {
            try
            {
                #start move request to Office 365 for the completed mailbox
                New-MoveRequest -Identity $UserPrincipalName -Remote -RemoteHostName $RemoteHostName -BatchName "O365" -TargetDeliveryDomain $DeliveryDomain -RemoteCredential $OnPremCreds -BadItemLimit 1000 -ErrorAction stop -SuspendWhenReadyToComplete
                Write-Host "Started upload to Office 365 for user $UserPrincipalName"
                Write-Host "To check the progress use the following command while connect to Office 365: get-moverequest"
                Write-Host "To complete the move request user the following command while connect to Office 365: get-moverequest $UserPrincipalName | resume-moverequest"
            }
            catch
            {
                Write-Warning "Unable start the mail migration for user $UserPrincipalName!"
                Write-Verbose $error[0]              
                               
            }
            
        }
    }
    End
    {
        If ($ErrorLog){
            Stop-Transcript
        }
    }
}

<#
.Synopsis
   Set the rights on the agenda or calendar of the user Default to Reviewer and a secretary group to Editor
.DESCRIPTION
   This CMDLET sets the mailbox permissions of the agenda (NL) or the calendar (NL) of the mailbox of the user to the default permissions.
   The user Default will be set to Reviewer
   The provided group will be set to Editor
.EXAMPLE
   Set-MailboxDefaultPermission -UserName test@contoso.com -GroupName Secretariaat
.EXAMPLE
   $users | %{Set-MailboxDefaultPermission -UserName $_.UserPrincipalName -GroupName $groupname} | out-file $report -Append
.NOTES
   Author: Michael Zimmerman
   Date: 19/02/2018
#>

Function Set-MailboxDefaultPermission{
    [CmdletBinding(SupportsShouldProcess=$true, 
                  ConfirmImpact='Medium')]
    Param
    (
        # Provide the name of the user which mailbox permissions will be altered
        [Parameter(Mandatory=$true, 
                   ValueFromPipelineByPropertyName=$true, 
                   Position=0)]
        [ValidateNotNullOrEmpty()]
        [Alias("user")] 
        $UserName,

        # Provide the group name which will be set to editor
       [Parameter(Mandatory=$true, 
                   ValueFromPipelineByPropertyName=$true, 
                   Position=1)]
        [ValidateNotNullOrEmpty()]
        [Alias("group")] 
        $GroupName
    )


    Process
    {
        #get the mailbox
        try
        {
            Write-Verbose "Getting the mailbox of the user $username"
            $mailbox = get-mailbox $UserName -EA Stop
        }
        catch
        {
           Write-Error $Error[0]
           return
        }
        
        #check if the dutch or english calendar is used
        if($AgendaPermissions = get-MailboxFolderPermission ($mailbox.Alias + ":\Calendar") -ErrorAction silentlycontinue){
            $AgendaFolder = ($mailbox.Alias + ":\Calendar")
            Write-Verbose "The user $username has an English calendar. Continuing..."       
        }
        elseif($AgendaPermissions = Get-MailboxFolderPermission ($mailbox.Alias + ":\agenda") -ErrorAction silentlycontinue){
            $AgendaFolder = ($mailbox.Alias + ":\agenda")
            Write-Verbose "The user $username has a Dutch calendar. Continuing..."       
        }
        else{
            Write-Warning "Could not get the calendar information of the user $UserName."
            return
        }

        #check if the correct permissions are already set for the default user and if not set the correct permissions
        if($AgendaPermissions | where{$_.user -match "Default" -and $_.AccessRights -match "Reviewer"})
        {
            Write-verbose "The calendar permissions for mailbox $username to user Default are already set to reviewer."
        }
        else
        {
            if ($pscmdlet.ShouldProcess("mailbox $UserName", "Setting the mailbox permission of the user Default"))
            {
                try
                {
                    set-MailboxFolderPermission $AgendaFolder -user Default -AccessRights Reviewer -EA stop | out-null
                    Write-verbose "successfully added the reviewer access rights to the user Default on the mailbox $username."
                }
                catch
                {
                    Write-error "Unable to add the reviewer access rights to the user Default on the mailbox $username."
                }
            }
        }
        
        #check if the correct permissions are already set for the default user and if not set the correct permissions
        if($AgendaPermissions | where{$_.user -Match $GroupName -and $_.AccessRights -match "Editor"})
        {
            Write-verbose "The calendar permissions for mailbox $username to the group $groupname are already set to reviewer."
        }
        else
        {
            if ($pscmdlet.ShouldProcess("mailbox $UserName", "Setting the mailbox permission of the group $GroupName"))
            {
                try
                {
                    add-MailboxFolderPermission $AgendaFolder -user $GroupName -AccessRights Editor | Out-Null
                    Write-verbose "successfully added the Editor access rights to the group $GroupName on the mailboxcalendar of $username."
                }
                catch
                {
                    Write-error "Unable to add the Editor access rights to the group $groupname on mailboxcalendar of $username."
                }
            }
        }

        $CurrentPermissionsDefault = Get-MailboxFolderPermission $AgendaFolder |  where{$_.user -match "Default"} | select user,accessrights 
        $CurrentPermissionsGroup = Get-MailboxFolderPermission $AgendaFolder |  where{$_.user -match $GroupName} | select user,accessrights 

        $hash = @{
        
            UserName = $UserName
            "User Default Access Rights" = $CurrentPermissionsDefault.AccessRights
            "Group $GroupName Access Rights" = $CurrentPermissionsGroup.AccessRights

        }
        
        $Object = New-Object PSObject -Property $hash
        
        return $Object
    }
}