27 May 2020

How to create a shared mailbox from hybrid Exchange directly in Exchange Online but also visible in on-premises Active directory

How to create a shared mailbox from hybrid Exchange directly in Exchange Online but also visible in on-premises Active directory
Now that's a mouthful, but a question that's asked often.
And that's not strange at all, because after moving most of your mailboxes to Exchange Online, the inevitable new shared mailbox request will pop up.

Only to find out that if created in the old way you need to manually move it Exchange Online.

And if you create shared mailbox in the ECP you will soon find that you problably made the wrong choice and the new mailbox is not visible in your on-premises Active Directory.

There's where this script comes to the recue.
It creates a remote shared mailbox, a distribution group for full access and send-as rights, adds that group to the mailbox, hides the distribution group because we only use it for access rights.
Then login to Exchange Online, disable POP, IMAP, Activesync and OWA, and resets the proxy settings if neccesary.

This can also be used to create usermailboxes, just tweak it to your needs.
It's also on my Github: https://github.com/brenkster/New-RemoteSharedMailbox

param ($Alias,$DisplayName)

#	Show countdown timer
           
Function Start-Countdown
{
    Param(
        [Int32]$Seconds = 600,
        [string]$Message = "Waiting for 10 minutes"
    )
    ForEach ($Count in (1..$Seconds))
    {   Write-Progress -Id 1 -Activity $Message -Status "Waiting for $Seconds seconds, `
$($Seconds - $Count) left" -PercentComplete (($Count / $Seconds) * 100)
        Start-Sleep -Seconds 1
    }
    Write-Progress -Id 1 -Activity $Message -Status "Completed" -PercentComplete 100 -Completed
}



#	Load Exchange Powershell module
#add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010
add-pssnapin Microsoft.Exchange.Management.PowerShell.SnapIn
#	Load Active Directory Powershell module
import-module activedirectory
            
# Setup variables
$DomainController="servername.domain.lan"
$OU='domain.lan/Groups/Mail/Shared Mailboxes'
$OU2='domain.lan/Groups/Mail/Shared Mailbox Groups'
$UPNdomain = "@domain.nl"
$UPNRemoteDomain = "@domain.onmicrosoft.com"



if ($Alias)
{
    if ($Alias.Contains('@')) { $Alias = $Alias.Substring(0,$Alias.IndexOf('@')) }
    $AliasMailbox = Get-Mailbox $Alias -ErrorAction SilentlyContinue
    $AliasMailUser = Get-MailUser $Alias -ErrorAction SilentlyContinue
    if ($AliasMailbox -or $AliasMailUser)
    {
        Write-Host "The Alias specified already exists" -ForegroundColor red
        $Alias = $null
    }
}
while (!$Alias)
{
    $Alias = Read-Host -Prompt "Alias (max 20 caracters)"
    if ($Alias)
    {
        if ($Alias.Contains('@')) { $Alias = $Alias.Substring(0,$Alias.IndexOf('@')) }
        $AliasMailbox = Get-Mailbox $Alias -ErrorAction SilentlyContinue
        $AliasMailUser = Get-MailUser $Alias -ErrorAction SilentlyContinue
        if ($AliasMailbox -or $AliasMailUser)
        {
            Write-Host "The Alias specified already exists" -ForegroundColor red
            $Alias = $null
        }
    }
}

if ($DisplayName)
{
    $DisplayNameMailbox = Get-Mailbox $DisplayName -ErrorAction SilentlyContinue
    $DisplayNameMailUser = Get-MailUser $DisplayName -ErrorAction SilentlyContinue
    if ($DisplayNameMailbox -or $DisplayNameMailUser)
    {
        Write-Host "The Display Name specified already exists" -ForegroundColor red
        $DisplayName = $null
    }
}
while (!$DisplayName)
{
    $DisplayName = Read-Host -Prompt "Display Name (As many caracters as you like)"
    if ($DisplayName)
    {
        $DisplayNameMailbox = Get-Mailbox $DisplayName -ErrorAction SilentlyContinue
        $DisplayNameMailUser = Get-MailUser $DisplayName -ErrorAction SilentlyContinue
        if ($DisplayNameMailbox -or $DisplayNameMailUser)
        {
            Write-Host "The Display Name specified already exists" -ForegroundColor red
            $DisplayName = $null
        }
    }
}

# Setup more variables
$Alias=$Alias.ToLower()
$UPN=$Alias + $UPNDomain
$UPNRemoteRoutingAddress = $Alias + $UPNRemoteDomain

Sleep 10
# Create the SharedMailbox
Write-Host "Creating Shared Mailbox" -ForegroundColor green            
New-RemoteMailbox -RemoteRoutingAddress "$UPNRemoteRoutingAddress" -Shared -UserPrincipalName "$UPN" `
-OnPremisesOrganizationalUnit $OU -Alias $alias -Name $alias -DisplayName $displayname `
-PrimarySmtpAddress $UPN -SamAccountName $alias -DomainController $domaincontroller            
Write-Host "Created Shared Mailbox" -ForegroundColor green            
            
Sleep 10            
# Set the description for the SharedMailbox            
Write-Host "Set Description" -ForegroundColor green            
Set-ADUser $Alias -Description "Shared Mailbox t.b.v. $Displayname"            
Write-Host "Description set" -ForegroundColor green            
            
Sleep 10            
# Create the distributiongroup for security use            
Write-Host "Creating Office365 Distributiongroup" -ForegroundColor green            
New-DistributionGroup  -DisplayName "SM.$alias" -Type Security -Alias "SM.$alias" -Name "SM.$alias" -Organizationalunit $OU2            
Write-Host "Office365 Distributiongroup created" -ForegroundColor green            
            
Sleep 10            
# Hide distributiongroup            
Write-Host "Set Office365 distributiongroup hidden" -ForegroundColor green            
Set-DistributionGroup -Identity "SM.$alias" -HiddenFromAddressListsEnabled:$true            
Write-Host "Office365 distributiongroup set to hidden" -ForegroundColor green            
            
Sleep 30            
# Sync AADConnect and wait for the account to show up online            
Write-Host "Starting Adsynccycle now" -ForegroundColor red            
Invoke-Command -ComputerName servername.domain.lan -Port 5986 -UseSSL -ScriptBlock { Start-ADSyncSyncCycle -PolicyType Delta }            
Write-Host "Adsynccycle has run" -ForegroundColor green            
            
Write-Host "Waiting for AzureAD sync" -ForegroundColor green            
#Start-Countdown -Seconds 600 -Message "Waiting for 10 minutes"            
            
$Time = 600            
$i = 0            
Do {            
    $i++            
    Write-Progress -Activity 'Waiting for 10 minutes' -Status 'Status' -PercentComplete (($i/$Time)*100) -SecondsRemaining ($Time-$i)            
    Start-Sleep 1            
} Until ($i -eq $Time)            
            
# Set the PowerShell session to use the proxy            
netsh winhttp set proxy proxy.domain.lan:8080            
Write-Host "Proxy Set" -ForegroundColor green            
            
# Connect to ExchangeOnline PowerShell            
Connect-ExchangeOnline -ShowProgress $true            
Write-Host "Connected to ExchangeOnline" -ForegroundColor green            
            
# Disable Mailbox features            
Write-Host "Disabeling OWA, POP, IMAP, ActiveSync" -ForegroundColor green            
Set-CASMailbox -Identity $Alias -imapenabled $false -owaenabled $false `
-OWAforDevicesEnabled $false -popEnabled $false -ActiveSyncEnabled $false -PopUseProtocolDefaults $false -ImapUseProtocolDefaults $false            
Write-Host "OWA, POP, IMAP, ActiveSync disabled" -ForegroundColor green            
            
Sleep 10            
# Add the distributiongroup to the sharedmailbox with Full Access            
Write-Host "Setting Mailbox Full Access Permissions" -ForegroundColor green            
Add-MailboxPermission –Identity: $Alias –AccessRights:FullAccess –user:"SM.$Alias"
Write-Host "Full Access Permissions set" -ForegroundColor green

Sleep 10

# Add the distributiongroup to the sharedmailbox with Send-as
Write-Host "Setting Mailbox Send-as Permissions" -ForegroundColor green
Add-ADPermission –Identity "$Alias" –user "SM.$Alias" –ExtendedRights 'Send-as' -DomainController $DomainController            
Write-Host "Send-as Permissions set" -ForegroundColor green            
            
Sleep 10            
            
# Reset proxy to direct access            
netsh winhttp reset proxy            
Write-Host "Proxy Set to default" -ForegroundColor green            
Write-Host "Script Finished" -ForegroundColor green            
Write-Host "Close this window " -ForegroundColor Red            

15 May 2020

PowerShell behind a proxy - Annoying combination

Here is a list of all the methods I found to get PowerShell to work behind an authenticating proxy:

No 1:
$wc = New-Object System.Net.WebClient                        
$wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials                        
$wc.DownloadString('http://microsoft.com')
No 2:
$proxy = New-Object System.Net.WebClient                        
$Proxy.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials                        
$webclient = New-Object System.Net.WebClient
No 3:
$creds = Get-Credential #Prompts for credentials                        
$webclient.Proxy.Credentials = $creds
No 4:
[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials            
[Net.ServicePointManager]::SecurityProtocol = "tls12"
No 5:
[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('http://proxy.domain.lan:8080')                        
[system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials                        
[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true
No 6:
$browser = New-Object System.Net.WebClient            
$browser.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials
No 7:

Check current settings for the PowerShell session:
netsh winhttp show proxy

Output current WinHTTP proxy settings:
Direct access (no proxy server)

Set the proxy server:
netsh winhttp set proxy proxy.domain.lan:8080
Set the proxy server with bypass list:
netsh winhttp set proxy proxy-server="http=proxy.domain.lan;https=proxy.domain.lan:8080" bypass-list="*.domain.lan;10.*"
Check current WinHTTP proxy settings: Proxy Server(s) : proxy.domain.lan:8080 Bypass-List : (none)

Reset to no proxy server settings:
netsh winhttp reset proxy

Output reset WinHTTP proxy settings:
Direct access (no proxy server)