O365Tools.psm1

<#
.Synopsis
This powershell cmdlet sets the powershell execution policy to Remote Signed.
  
.Description
Sets the execution policy.
  
.Example
Set-O365ExecutionPol
#>


Function Set-O365ExecutionPol{
$ExecPolicy = Get-ExecutionPolicy
if ($ExecPolicy -ne "RemoteSigned"){Set-ExecutionPolicy RemoteSigned -Force}
else{
    Write-Host "Execution Policy already set correctly"}
}

<#
.Synopsis
This powershell cmdlet establishes a connection to Office 365. It will prompt the user for credentials twice in order to authenticate the session.
  
.Description
Connect-O365Tools will connect to Office 365 and log into an active session for powershell management of your Office 365 account.
  
.Example
Connect-O365Tools
#>


Function Connect-O365Tools{
$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-Module (Import-PSSession $Session -AllowClobber) -Global
Connect-MsolService
}

<#
.Synopsis
This powershell cmdlet tests whether or not you are connected to Office 365 for powershell management of the system. If you are not connected, it will automatically connect your powershell session to Office 365.
  
.Description
Tests your connection to Office 365 and establishes a connection if it finds you are not connected.
  
.Example
Test-O365Connection
#>


Function Test-O365Connection{
Get-MsolDomain -ErrorAction SilentlyContinue | out-null
$result = $?

    switch ($result)
        {
        False { Write-Host 'Not connected to O365 Account, initiating connection'
                Connect-O365Tools
                }
        True {return}
        }
}

<#
.Synopsis
This powershell cmdlet tests whether or not you are on your local server running Azure Directy Sync.
  
.Description
Tests if you are on your 'DirSync' server.
  
.Example
Test-O365DirSync
#>

Function Test-O365DirSync{
     $dirsync = Get-Service AzureADConnectHealthSyncMonitor -ErrorAction SilentlyContinue
            if ($dirsync -eq $null) {
                Write-Host "Attempting to run a Directory Sync on a system not provisioned with Azure Active Directory Connect - ABORTING OPERATION!" -ForegroundColor Red
                break
                }
                }
<#
.Synopsis
This powershell cmdlet displays a table of Organization Units within your Active Directory.
  
.Description
This is for informational purposes and
  
.Example
Get-O365OUs
#>

Function Get-O365OUs{
    Get-ADOrganizationalUnit -Filter * | FT Name, DistinguishedName -AutoSize
    }

<#
.Synopsis
This powershell cmdlet checks the sync status for Azure AD Connect and outputs a message indicating when the job is complete.
  
.Description
Lets user know when the Azure AD sync has completed
  
.Example
Get-O365SyncStatus
#>



Function Get-O365SyncStatus{
        #Wait 10 seconds for the Sync to start
        Write-Host "Initializing Azure AD $SyncType Sync" -ForegroundColor Green
        Start-Sleep -Seconds 10
        Write-Host "Status" -NoNewline -ForegroundColor Green
        #Display a progress indicator and hold up the rest of the script while the sync completes.
        While(Get-ADSyncConnectorRunStatus){
            Write-Host "." -NoNewline -ForegroundColor Green
            Start-Sleep -Seconds 10
            }

            Write-Host " Forced Azure AD $SyncType Sync has completed." -ForegroundColor Green
}
<#
.Synopsis
This powershell cmdlet allows you to sync Active Directory with your Azure AD Connection server. Password synchronizations can be completed as Delta (only changes are applied), Full (all attributes are checked and applied), or FullPW (an entire full synchronization of your Active Directory). This will not run if Azure AD Connect services are not found on your system and will only run on your 'DirSync' server.
  
.Description
Syncs your Active Directory with Azure AD Connect via powershell cmdlets.
  
.Example
Start-O365DirSync -SyncType Full
 
.Example
Start-O365DirSync -SyncType Delta
 
.Example
Start-O365DirSync -SyncType FullPW
#>


Function Start-O365DirSync{
 [cmdletbinding()]
    Param (
    [Parameter(Position=0,mandatory=$true)] [string]$SyncType
        )
    # End of Parameters
    Process {
            Test-O365Dirsync
    If (Get-ADSyncConnectorRunStatus) {Write-Warning "A sync is already in progress"}
    Else{
        switch ($SyncType)
            {
            Full    {   Start-ADSyncSyncCycle -PolicyType Initial
                        Get-O365SyncStatus
                    }
            Delta   { 
                        Start-ADSyncSyncCycle -PolicyType Delta
                        Get-O365SyncStatus
                    }
            FullPW  { 
                        $adConnector  = Read-Host -Prompt 'Please enter your Full AD Domain Name (i.e. - "fabrikam.com"): '
                        $aadConnector = Read-Host -Prompt 'Please enter your full *.onmicrosoft.com address (i.e. - "aaddocteam.onmicrosoft.com"): '
                        $aadConnector = $aadConnector + " - AAD"
                        Import-Module adsync
                        $c = Get-ADSyncConnector -Name $adConnector
                        $p = New-Object Microsoft.IdentityManagement.PowerShell.ObjectModel.ConfigurationParameter "Microsoft.Synchronize.ForceFullPasswordSync", String, ConnectorGlobal, $null, $null, $null
                        $p.Value = 1
                        $c.GlobalParameters.Remove($p.Name)
                        $c.GlobalParameters.Add($p)
                        $c = Add-ADSyncConnector -Connector $c
                        Set-ADSyncAADPasswordSyncConfiguration -SourceConnector $adConnector -TargetConnector $aadConnector -Enable $false
                        Set-ADSyncAADPasswordSyncConfiguration -SourceConnector $adConnector -TargetConnector $aadConnector -Enable $true
                        Get-O365SyncStatus
                    }
        default {"Invalid parameter entered for '-SyncType'"}
        }
        }
    }#End Process
}
                

<#
.Synopsis
This powershell cmdlet allows you to enable mailbox features such as audilogging and in-place archiving.
  
.Description
Enable mailbox features - as of Version 1.0 you can only enable audit logging and in-place archiving.
  
.Example
Enable-O365Settings -SettingName AuditLogging
 
.Example
Enable-O365Settings -SettingName InPlaceArchive
 
.Example
Enable-O365Settings -SettingName InPlaceArchive -MailAlias "Jon Doe"
#>


Function Enable-O365Settings{
    [cmdletbinding()]
    Param (
    [Parameter(Position=0,mandatory=$true)] [string]$SettingName,
    [Parameter(Position=1)] [string]$MailAlias
       )
    # End of Parameters
    Process {
            Test-O365Connection
            
    switch ($SettingName)
        {
        AuditLogging    {  $UserMailbox = ReadHost -Prompt "Input User Mailbox: " 
                           Get-Mailbox -ResultSize Unlimited -Filter {RecipientTypeDetails -eq "UserMailbox"} | Set-Mailbox -AuditEnabled $true
                           }
        InPlaceArchive  {  $select = Read-Host -Prompt "(A) All Mailboxes ; (S) Single Mailbox "
                            
                            Switch($select)
                                {
                                 A       { (Get-Mailbox) | ForEach {Enable-Mailbox –identity $_.PrimarySMTPAddress –Archive}
                                           }
                                 S       { If(!$MailAlias) { $MailAlias = Read-Host "Enter User Alias: "
                                                            }
                                            Enable-Mailbox "$MailAlias" -Archive
                                           }
                                 default {"Invalid selection"}
                                 }
                        }
        
                    }
        
                } #End Process
    }

<#
.Synopsis
This powershell cmdlet generates reports about your Office 365 Mailboxes and allows you to save them to a location you designate. If the path you designate does not exist, a folder is created. Filenames for reports have a prefix of the numeric date and time along with the type of report you are generating. All reports generated are exported in CSV format and are easily opened using any spreadsheet software or text editor.
  
.Description
Generate reports on your Office 365 Mailboxes
  
.Example
Get-O365Reports -ReportName MailboxSize -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName ArchiveSize -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName MailboxHold -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName LastLogin -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName AciveSync -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName MailboxInfo -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName Forwarding -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName DBGroups -SavePath "C:\Reports"
 
.Example
Get-O365Reports -ReportName DBMembers -SavePath "C:\Reports"
#>


Function Get-O365Reports{
    [cmdletbinding()]
    Param (
    [Parameter(Position=0,mandatory=$true)] [string]$ReportName,
    [Parameter(Position=1,mandatory=$true)] [string]$SavePath
       )
    # End of Parameters
    Process {
            Test-O365Connection
            $datestring = (Get-Date).ToString("s").Replace(":","-")
            $filename = "$SavePath"+"\"+"$datestring"+"_$ReportName.csv"

            IF (-NOT (Test-Path $SavePath -PathType ‘Container’))
                {
                    New-Item $SavePath -ItemType Directory -Force
                }
            
            switch ($ReportName)
                {
                MailboxSize {   Get-Mailbox -ResultSize Unlimited | Get-MailboxStatistics | Select DisplayName,StorageLimitStatus,@{name="TotalItemSize (MB)";expression={[math]::Round(($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}},@{name="TotalDeletedItemSize (MB)";expression={[math]::Round(($_.TotalDeletedItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}},ItemCount,DeletedItemCount | Sort "TotalItemSize (MB)" -Descending | Export-CSV -Path $filename –NoTypeInformation
                                }
        
                ArchiveSize {   Get-Mailbox -Archive -ResultSize Unlimited | Get-MailboxStatistics -Archive | Select DisplayName,StorageLimitStatus,@{name="TotalItemSize (MB)";expression={[math]::Round((($_.TotalItemSize.Value.ToString()).Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}},@{name="TotalDeletedItemSize (MB)";expression={[math]::Round((($_.TotalDeletedItemSize.Value.ToString()).Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}},ItemCount,DeletedItemCount | Sort "TotalItemSize (MB)" -Descending | Export-Csv -Path $filename -NoTypeInformation
                                }
        
                MailboxHold {   Get-Mailbox | ft DisplayName,InPlaceHolds > $filename
                                }

                LastLogin   {   Get-Mailbox | Foreach {Get-MailboxStatistics $_.Identity | Select DisplayName, LastLoggedOnUserAccount, LastLogonTime} | Export-CSV -Path $filename -NoTypeInformation
                                }

                ActiveSync  {   get-MobileDevice |export-csv -Path $filename -NoTypeInformation
                                }
            
                MailboxInfo {   get-mailbox |export-csv -Path $filename -NoTypeInformation 
                                }
                
                Forwarding  {   Get-Mailbox | Where {$_.ForwardingsmtpAddress -ne $null} | Select Name, ForwardingAddress,ForwardingsmtpAddress, DeliverToMailboxAndForward|export-csv $filename -NoTypeInformation
                                }
                
                DBGroups    {   Get-DistributionGroup |Export-Csv $filename
                                }
                
                DBMembers   {   $DBAlias = Read-Host -Prompt 'Distribution Group Alias: '
                                Get-DistributionGroupMember -identity $DBAlias | ft "PrimarySMTPAddress" > $filename
                                }

                default     {"Invalid Report Name"
                                }

                    }
                } #End Process
    }

<#
.Synopsis
This powershell cmdlet allows you to apply settings to all mailboxes in your organization at once. Currently, the only option available is the timezone.
  
.Description
Sets information for ALL mailboxes. Currently the only option you can set is the Timezone within version 1.0
  
.Example
Set-O365Info -SettingName Timezone
#>

Function Set-O365Info{
    [cmdletbinding()]
    Param (
    [Parameter(Position=0,mandatory=$true)] [string]$SettingName
    
       )
    # End of Parameters
    Process {
            Test-O365Connection

            switch ($SettingName)
                {
                Timezone { $Select = ReadHost "Display list of available ID Names? : "
                            if ($select -eq "Y") {[System.TimeZoneInfo]::GetSystemTimeZones() | Format-Table -Property ID, DisplayName}
                            $TZ = Read-Host "Time Zone ID: "
                             get-mailbox | Set-MailboxRegionalConfiguration -TimeZone $TZ
                             }
                }
           }#End Process
}

<#
.Synopsis
This powershell cmdlet streamlines setting up a new user in Active Directory to sync with Office 365. You could use the New-AdUser command to accomplish the same task, but this shortens it significantly and sets up a user with the necessary fields needed for the Azure AD Sync Tool running on your Directory sync server.
  
.Description
Creates a new user on your Domain with the necessary information to sync up with Office 365. Once created, you can either force a Sync or wait for the scheduled directory sync to occur, and then you can activate the user in Office 365.
 
The parameters required in this cmdlet include:
Username - sets the username for the user in Active Directory
DisplayName - sets the Display Name for the user in Active Directory
Email - sets the Primary SMTP Mailing address in Active Directory and syncs with Office 365 for the users mailbox
OU - sets the Organizational Unit in Active Directory to place the new user
PW - sets the password for the user account being created
Fname - sets the users First Name field in AD (not required)
Lname - sets the users Last Name field in AD (not required)
 
Note: If any variables have spaces, remember to wrap them in quotes. Also, for OU Formatting, you can either type out the varaible going backwards from the OU to the domain or you can run Get-O365OUs for a list of the OU's available in your domain.
  
.Example
New-O365SyncdUser -Username jbond -DisplayName "Agent James Bond" -Fname "James" -Lname "Bond" -Email "James.Bond@MYDOMAIN.com" -OU "OU=Agents,OU=MI6,DC=MYDOMAIN,DC=LOCAL" -PW "MyPassword"
 
This example shows the syntax of the command for creating a new user that will sync with Azure AD Connect. In this example, a new user by the name of James Bond is going to be created with an email address of James.Bond@mydomain.com and the account will be placed in Active Directory in the Mydomain.local>MI6>Agents OU.
#>

Function New-O365SyncdUser{
    [cmdletbinding()]
    Param (
    [Parameter(Position=0,mandatory=$true)] [string]$Username,
    [Parameter(Position=1,mandatory=$true)] [string]$DisplayName,
    [Parameter(Position=2)] [string]$FName,
    [Parameter(Position=3)] [string]$LName,
    [Parameter(Position=4,mandatory=$true)] [string]$Email,
    [Parameter(Position=5,mandatory=$true)] [string]$OU,
    [Parameter(Position=6,mandatory=$true)] [string]$PW
       )
    # End of Parameters
    Process {
            $checkOU= [adsi]::Exists("LDAP://$OU")
            if ($checkOU -eq $true){
                New-ADUser -Name "$DisplayName" -SamAccountname "$Username" -UserPrincipalName "$Username" -DisplayName "$DisplayName" -GivenName "$Fname" -Surname "$LName" -OtherAttributes @{'mail'="$Email"} -Path "$OU" -AccountPassword (ConvertTo-SecureString "$pw" -AsPlainText -force) -Enabled $true
                }
            else{
                Write-Host "The (OU) ORGANIZATIONAL UNIT:" -ForegroundColor Red
                Write-Host "'$OU'" -ForegroundColor Red
                Write-Host "DOES NOT EXIST! Make sure the OU has the correct formatting" -ForegroundColor Red
                Write-Host "and that it exists. See below for valid OU's inyour domain: " -ForegroundColor Red
                Write-Host "************************************************************" -ForegroundColor Red
                Get-O365OUs
                Write-Host "************************************************************" -ForegroundColor Red
                Write-Host "Use any of the above 'DistinguishedName' values for an OU. ABORTING OPERATION!" -ForegroundColor Red
                }               
            }
            # End Process
}

<#
.Synopsis
This powershell cmdlet will aid you in the process of converting a 'DirSyncd' users mailbox into a shared mailbox on Office 365. The process carries out the following steps:
1) Moves user to unsynced OU (you must provide an unsynced OU)
2) Forces an Azure AD Full Sync for Office 365 to mark the mailbox as deleted
3) Restores the Synced users mailbox in the cloud
4) Sets the mailbox type to Shared
5) Clears the ImmutableID associated with the newly coverted mailbox to avoid Sync Tasks from re-deleting the mailbox
  
.Description
This function helps automate the process of converting a synced users mailbox to a shared mailbox in Office 365
  
.Example
Convert-O365UsertoShared -Username "jbond"
#>

Function Start-O365ConvertToShared{
    [cmdletbinding()]
    Param (
    [Parameter(Position=0,mandatory=$true)] [string]$Username 
    )
    Process {
            Test-O365Connection
            Test-O365DirSync
            
            #Setting Variables based on the Username input for the required parameters
            $Email = Get-ADUser -Identity $Username -Properties ProxyAddresses | select -ExpandProperty ProxyAddresses | ? {$_ -clike "SMTP:*"}
            $Email = $Email -replace "SMTP:"
            $OU = Get-ADOrganizationalUnit -Filter * | Select -ExpandProperty DistinguishedName |Out-GridView -Title "Select Organizational Unit to move user to:" -PassThru
            
            #Actions taken on your local domain to move the user to an unsynced OU
            Write-Host "Moving user to specified OU: $OU" -ForegroundColor Green
            Get-ADUser $Username| Move-ADObject -TargetPath "$OU"
            Start-O365DirSync -SyncType Full
            
            #Checking after Sync to confirm the mailbox is 'Soft Deleted' in Office 365
            Write-Host "Waiting for Office 365 to register the mailbox cahnges ..." -NoNewline -ForegroundColor Green
            $x = 1
            While($x -ne 12){
                Start-Sleep -Seconds 5
                Write-Host "." -NoNewline -ForegroundColor Green
                $x++ 
                }
            If(Get-Mailbox -SoftDeletedMailbox $email){ Write-Host "User mailbox has been deleted successfully" -ForegroundColor Green}
            Else{
            Write-Host "ERROR - Mailbox not found in query of Office 365 'Soft Deleted' mailboxes. Please check mailbox and try again." -ForegroundColor RED
            return
            } 
            
            #Restoring mailbox as a Cloud-based mailbox
            Restore-MsolUser -UserPrincipalName $Email
            Write-Host "Waiting for Office 365 to register the mailbox changes ..." -NoNewline -ForegroundColor Green
            $x = 1
            While($x -ne 12){
                Start-Sleep -Seconds 5
                Write-Host "." -NoNewline -ForegroundColor Green
                $x++ 
                }

            #Applying settings to convert to a Shared Mailbox
            If(Get-Mailbox $email){
                Set-Mailbox $Email -Type shared
                Set-msoluser -userprincipalname $Email -ImmutableID ""
                }
            Else{
            Write-Host "Mailbox not restored properly - please check logs and try again." -ForegroundColor Red
            return
            }
       }
       #End Process
}
            

#Export Module Functions
    Export-ModuleMember -Function "Start-O365DirSync", "Enable-O365Settings", "Get-O365Reports", "Set-O365Info", "New-O365SyncdUser", "Get-O365OUs", "Test-0365DirSync", "Connect-O365Tools", "Start-O365ConvertToShared", "Set-O365ExecutionPol", "Test-O365Connection"