Showing posts with label Exchange 2013. Show all posts
Showing posts with label Exchange 2013. Show all posts

25 May 2023

Simply list all Shared Mailboxes from On-premises and in Exchange Online with PowerShell

Hey there, fellow tech enthusiasts!
Today, I have some lines to drop about how to simply list all your shared mailboxes.
In this case I wanted to get all email addresses.

Step 1: Connect to your environment

Connect to you on-premises Exchange environment.

Step 2: Retrieve On-Premises Shared Mailboxes

Let's start by fetching all the remaining shared mailboxes from your on-premises environment. Open up your PowerShell console and execute the following:

$OnPremSharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize unlimited | Select-Object PrimarySmtpAddress

Step 3: Retrieve the remote shared mailboxes

Run the following commands

Get all mailboxes
  $RemoteMailboxes = Get-RemoteMailbox -ResultSize unlimited

Get all remotesharedmailboxes and filter only the smtpaddress
  $RemoteMailboxes | Where-Object { $_.RecipientTypeDetails -eq "RemoteSharedMailbox" } | select PrimarySmtpAddress

Step 5: Consolidate the Results

It's time to bring everything together and create a unified list of shared mailboxes. Run the following commands to consolidate the on-premises and Exchange Online results:

  $AllSharedMailboxes = $OnPremSharedMailboxes + $ExchangeOnlineSharedMailboxes

With this command, you'll combine the arrays of on-premises and Exchange Online shared mailbox addresses into a single array called '$AllSharedMailboxes'. You can make other choices in your filter to generate a different list.

Step 6: Display the Results

  $AllSharedMailboxes

And just like that, your PowerShell console will present you with a complete list of shared mailbox addresses, combining the best of both on-premises en Exchange Online.

21 August 2020

Messages that are sent by using the "Send As" and "Send on behalf" permissions are copied only to the Sent Items folder of the sender

UPDATED 21-08-2020 - Added Exchange Online method


This is something I didn't know existed but keeps popping up as a frequent question in our organization.

An outlook user with access to a shared mailbox, send as or send on behalf of rights sends an email from the shared mailbox, but the sent email doesn't get saved in the shared mailbox sent items folder but in the users sent items folder.

Since Exchange server 2010 SP2 update roll-up 4 it's possible to specify where the sent emails will be saved. This also goes for Exchange server 2013 CU9 and up.

First check the current settings for a shared mailbox:
Get-MailboxSentItemsConfiguration -Identity sharedmailboxname            
            
RunspaceId                  : 2d911aef-3416-42f9-9900-531d0fcdea94            
SendAsItemsCopiedTo         : Sender            
SendOnBehalfOfItemsCopiedTo : Sender            
Identity                    :            
IsValid                     : True
As you can see the "SendasItemsCopiedTo" and "SendOnBehalfOfItemsCopiedTo" is set to "Sender"
There are 2 settings to choose from: "Sender" "SenderAndFrom".

To set it to save in both mailboxes use:
Set-MailboxSentItemsConfiguration -Identity sharedmailboxname -SendAsItemsCopiedTo `
senderandfrom -SendOnBehalfOfItemsCopiedTo SenderAndFrom
Check to be sure:
Get-MailboxSentItemsConfiguration -Identity sharedmailboxname            
            
RunspaceId                  : 2d911aef-3416-42f9-9900-531d0fcdea94            
SendAsItemsCopiedTo         : SenderAndFrom            
SendOnBehalfOfItemsCopiedTo : SenderAndFrom            
Identity                    :            
IsValid                     : True
Set it to all shared mailboxes in a nice one liner for Exchange 2010:
Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails sharedmailbox | Set-MailboxSentItemsConfiguration `
-SendAsItemsCopiedTo SenderandFrom -SendOnBehalfOfItemsCopiedTo SenderAndFrom
Set it to all shared mailboxes in a nice one liner for Exchange 2013:
Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails sharedmailbox | Set-Mailbox `
-MessageCopyForSendOnBehalfEnabled $True -MessageCopyForSentAsEnabled $True
For Exchange Online there are two ways of doing this, in is in the Office 365 Admin portal and the other is in PowerShell.

In the Portal go to Groups - Shared Mailboxes

Then find the Shared mailbox you want to edit and edit "Sent Items"

And here you will see the two toggles to choose you options

With PowerShell:

After loggin in to Exchange Online Check the shared mailbox you want to modify:

Get-EXOMailbox -Identity sharedmailbox@domain.com | FL

These are the attributes that we triggered from the GUI toggle within the Office365 Admin Center earlier:

MessageCopyForSentAsEnabled : True
MessageCopyForSendOnBehalfEnabled : True

Set these attributes for a single mailbox:
Set-EXOMailbox -Identity sharedmailbox@domain.com -MessageCopyForSendOnBehalfEnabled $true -MessageCopyForSentAsEnabled $true

Enable these settings on all your shared mailboxes in your environment:
Get-EXOMailbox -RecipientTypeDetails shared | Where-Object {$_.messagecopyforsentasenabled -eq "" }

If you have to return all shared mailboxes that has the Sent Items Copy enabled:
Get-EXOMailbox -RecipientTypeDetails shared | Where-Object {$_.messagecopyforsentasenabled -eq "true" }

Take the selection of the shared mailboxes that don’t have the Sent Items Copy enabled yet and combine that with the Set-Mailbox command that enables both Sent Items Copy attributes:

Get-EXOMailbox -RecipientTypeDetails shared | Where-Object{$_.messagecopyforsentasenabled -eq ""} | Set-EXOMailbox -MessageCopyForSendOnBehalfEnabled $true -MessageCopyForSentAsEnabled $true


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 October 2019

How to set default retention policy for all existing and new users in Exchange Online - Set default retention policy for On-Premises users

In Exchange Online you can set a retention policy as the default for everyone within the tenant.
In Exchange On-Premises this isn't possible, therefore you have to set them every once in a while.

For Exchange Online:

To view all your retention policies:
Get-RetentionPolicy

The set the one you want as the default:
Set-RetentionPolicy "Company - Default Policy" -IsDefault:$true

For Exchange On-Premises:

To view all your retention policies:
Get-RetentionPolicy

To set the one you want as default for all existing users:
Get-Mailbox -Resultsize Unlimited | Set-Mailbox -RetentionPolicy "Company - Default Policy"

To check what the current retention policy is:
Get-Mailbox -ResultSize Unlimited | Select Retentionpolicy,Name

02 September 2019

Error: MigrationPermanentException: Cannot find a recipient that has mailbox GUID

Error: MigrationPermanentException: Cannot find a recipient that has mailbox GUID

After trying to move a mailbox from Exchange Online to Exchange On-premises the above error occurred.
This happend because the mailbox was created online and not on-premises, and therefore the GUID wasn't synced to AzureAD and vice versa.

Luckily there is a simple fix:

In Exchange Online PowerShell:
Get-Mailbox alias | FL ExchangeGUID

In the On-Premises Exchange PowerShell:
Set-RemoteMailbox Alias -ExchangeGUID 12345678-1234-1234-12345678
Then wait for replication to AzureAD and your mailbox move should go without a hitch.

02 July 2019

EdgeSync failed to decrypt the credential for Edge Transport - Eventid 1033 MSExchange EdgeSync - Renewed certificate lately?

EdgeSync failed to decrypt the credential for Edge Transport server sr-xxxx.domain.lan using the private key of the default Exchange certificate with exception Invalid provider type specified.
. The certificate's thumbprint is XXXXXXXXXXXXXXXXXXXX52F0283F5F8BDDD13058 and its subject is CN=autodiscover.domain.nl, OU=ICT, O=Company., L=City, S=State, C=NL.
Use either Enable-ExchangeCertificate or New-ExchangeCertificate to set the proper Exchange default certificate and re-subscribe the Edge Transport server sr-XXXX.domain.lan again.

Well...here we go again.
At least I'm not bored at work.

Quick recap, this was after renewing our old Exchange certificate that had the SMTP service assigned to it. The old certificate was an old SHA1 type, this is very important to keep in mind as it comes back later in the solution.

In my quest to solve this as quickly as possible I came across some other strange things, which I will list later on.
But first let me sum up all the steps needed to resolve this:

  1. On the Edge server request a new Exchange certificate:
    New-ExchangeCertificate
  2. Generate a new EdgeSubscription file:
    New-EdgeSubscription -FileName C:\Temp\Servername.xml
  3. Copy the EdgeSubscription file to an Exchange 2013 or 2016 or 2019 server (I'm assuming you installed multirole)
  4. Remove the current EdgeSubscription(s):
    Get-EdgeSubscription | select Name
    Remove-EdgeSubscription -Identity YourEdgesubscriptionName
  5. Find the current self signed Exchange Certificate with the servername as Subject. This certificate is created at installation. This certificate needs to get the SMTP service reassigned to it. Copy the thumbprint, we need it in the second command:
    Get-ExchangeCertificate | fl
    Enable-ExchangeCertificate -Thumbprint XXXXXXXXXXXXXXXXXX334EFEA37EFC7E5813 -DoNotRequireSsl -Services:SMTP
  6. Double check your existing subscription has been deleted:
    Get-EdgeSubscription
  7. Create a new Edge Subscription with the file copied in step 3:
    New-EdgeSubscription -FileData ([byte[]]$(Get-Content -Path "C:\Temp\Servername.xml" -Encoding Byte -ReadCount 0)) -Site YourSiteName
  8. Then start your newly created subscription:
    Start-EdgeSynchronization
  9. Test the EdgeSynchronization:
    Test-EdgeSynchronization
  10. The last step is to sync everything:
    Start-EdgeSynchronization -ForceUpdateCookie -ForceFullSync
The problem I had was the certificate that got renewed initialy was a SHA1 certificate.
The one it got replaced with was a SHA256 certificate. When trying to renew the Edge Subscription the following error popped up:
A special Rpc error occurs on server sr-xxxxx Invalid provider type specified
This the SHA1 part I mentioned earlier. The Edge Subscription only works with SHA1 certificates.
Strange and not very secure, eventho it is meant for internal Exchange server traffic only.
Hence the default certificate created at installation of Exchange itself is needed, which is SHA1.

Solved.



28 June 2019

Removing AccessRights - WARNING: An inherited access control entry has been specified and was ignored - WARNING: An inherited access control entry has been provided and was ignored

So this just happed:
Remove-MailboxPermission -Identity SharedMailboxAlias -User Username -AccessRights FullAccess -InheritanceType all
Confirm
Are you sure you want to perform this action?
Removing mailbox permission "SharedMailboxAlias" for user "UserName" with access rights "'FullAccess'".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [?] Help (default is "Y"): y
WARNING: An inherited access control entry has been specified: [Rights: CreateChild, Delete, `
ReadControl, WriteDacl, WriteOwner, ControlType: Allow]  and was ignored on object `
"CN=SharedMailboxAlias,OU=Shared Mailboxes,OU=Mail,DC=Domain,DC=lan".
Checked to see what was keeping me from removing the access rights:
Get-MailboxPermission -Identity SharedMailboxAlias -User UserName

Identity             User                 AccessRights                 IsInherited Deny
========             ====                 ============                 =========== ====
Domain.lan/Mail/S... Domain\UserName      {FullAccess}                 True        True
Domain.lan/Mail/S... Domain\UserName      {FullAccess}, Delete...      True        False
And there it was, the "IsInherited" value True.
So its coming from above...

So I had to go through and remove some legacy permissions from Exchange. This can be added at multiple levels so it’s aways a diagnostic trail to where this was added. Go through each of these and if IsInherited is set to False you’ve found out where it’s being applied from.
Get-MailBoxPermission Domain\UserName

Get-MailboxDatabase | Get-ADPermission -User Domain\UserName

Get-ExchangeServer | Get-ADPermission -User Domain\UserName

Get-OrganizationConfig | Get-ADPermission -User Domain\UserName
Remove the Permissions per level with
Get-MailBoxPermission Domain\UserName | Remove-ADPermission

Get-MailboxDatabase | Get-ADPermission -User Domain\UserName | Remove-ADPermission

Get-ExchangeServer | Get-ADPermission -User Domain\UserName | Remove-ADPermission

Get-OrganizationConfig | Get-ADPermission -User Domain\UserName | Remove-ADPermission
Some of the permissions where also added from AD.

Open up ADSI Edit and Navigate to these :

In “Default Naming Context” OU=Microsoft Exchange Security Groups,DC=Domain,DC=lan
In “Default Naming Context” CN=Microsoft Exchange System Objects
In “Configuration” CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=Domain,DC=lan

Make sure the user is not in any of these.
After the User has been removed from any of these places its inheritance is gone is no longer listed.

22 January 2019

The content cannot be displayed in a frame - Exchange On-Premises - Exchange Online - Exchange Hybrid

After setting up your Hybrid Exchange connection and logging in to the Exchange Control Panel trying to move your first mailbox to Exchange Online you need to login to Office365.

When you click the login button on the popup you receive the following error:
Now this is fairly easy to fix, just add the url https://outlook.office365.com to the trusted sites in Internet Explorer.
But then this:
The option is greyed out.

There are 2 ways to get around this, one through the registry and one through a group policy:
Add the following to a textfile and paste in:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMapKey]
"https://outlook.office365.com"="2"
Save as a .reg and execute.

This can also be stored in the HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMapKey.

The check if the settings are present run in PowerShell:

$(get-item "HKCU:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMapKey").property            
            
$(get-item "HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMapKey").property            

The group policy goes like this:
  • Start -> type gpedit.msc -> hit Enter
  • navigate to Computer Configuration -> Administrative Templates -> Windows Components -> Internet Explorer -> Internet Control Panel -> Security Page
  • in the right-hand panel, double-click on the Site to Zone Assignment List option, then click Show...
  • trusted sites are the ones with 2 in the Value column (1 = Intranet, 3 = Internet, 4 = Restricted)
If that doesn't work (that option is set to "Not Configured" or the list is empty), try the same, except instead of Computer Configuration, start with User Configuration.