MVP - Most Valuable Professional

Just can't get enough of IT

This blog is about mostly anything in IT. But the primary focuses are Microsoft technologies like Exchange Server, Microsoft 365, Microsoft Teams, and Cloud Security.
Thomas Stensitzki | MVP
Thomas Stensitzki | MVP

MVP LogoThomas Stensitzki is a leading technology consultant focusing on the Microsoft messaging and collaboration technologies and the owner of Granikos GmbH & Co. KG.

He is an MVP for Office Apps & Services since 2018.

Thomas is an MCT Regional Lead for Germany and delivers Microsoft Learning training courses for Office 365, Microsoft Teams, and Exchange Server.

He holds Master certifications as Microsoft Certified Solutions Master Messaging and as Microsoft Certified Master for Exchange Server 2010. These certifications make him a subject matter expert for any messaging topic related to Microsoft Exchange, Exchange Online, Microsoft 365, and hybrid configurations.

Follow Thomas: LinkedIn, Twitter

His sessions:

MVP Blog:
Personal blog:
Personal website:
Thomas' Tech Talk:

Contact Thomas at


Lastly I've encountered an interesting PowerShell error after upgrading several servers running Exchange Server 2013 CU9 to Exchange Server 2013 CU11.

After a successful upgrade, the Exchange PowerShell script to redistribute the DAG databases failed with an error.

.\RedistributeActiveDatabases.ps1 -DagName DAG01 -BalanceDbsByActivationPreference -Confirm:$false
Cannot process argument transformation on parameter 'Identity'. Cannot convert value "MAILBOXDB01" to type
"Microsoft.Exchange.Configuration.Tasks.DatabaseCopyIdParameter". Error: "Cannot convert hashtable to an object of the
following type: Microsoft.Exchange.Configuration.Tasks.DatabaseCopyIdParameter. Hashtable-to-Object conversion is not
supported in restricted language mode or a Data section."
    + CategoryInfo          : InvalidData: (:) [Get-MailboxDatabaseCopyStatus], ParameterBindin...mationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-MailboxDatabaseCopyStatus
    + PSComputerName        :

The interesting part to note is conversion is not supported in restricted language mode

The supported language mode is configured in the application settings of the PowerShell virtual directory of the Exchange Back End website.

Exchange 2013 PowerShell Virtual Directory Application Settings 

The application settings after Exchange Server 2013 CU11 update:

Exchange PowerShell Virtual Directory PSLanguageMode - RestrictedLanguage

Running PSLanguageMode with value RestrictedLanguage is the default setting. You should change this setting only, if you encounter PowerShell issues.

Double-click PSLanguageMode and change the value to FullLanguage.

Exchange PowerShell Virtual Directory PSLanguageMode - FullLanguage

Currently I have not validation why a clean Exchange 2013 CU11 setup does not show this behaviour. A plain Exchange 2013 CU11 setup executes the script without any issues.



Read More »

The Outlook on the web S/MIME implementation supports a variation of encryption algorithms like

  • RC2 (supported key lengths are 40, 56, 64, and 128)
  • DES (56-bit)  
  • 3DES (168-bit)
  • AES128  
  • AES192  
  • AES256

When you want to configure the OWAEncryptionAlgorithms or OWASigningAlgorithms attributes to support more than one algorithm, you have to follow a certain format. The attribute itself is stored as String and not being validated when using Set-SMimeConfig. Beware of this when you configure S/MIME settings and the S/MIME Plugin is not available in your Outlook on the web client.

TechNet states clearly:

“If the encryption algorithm or minimum key length is not available on a client, Outlook on the web does not allow encryption.”


The string to used when configuring the OWAEncryptionAlgorithms for AES256 and AES128  is

Set-SmimeConfig –OWAEncryptionAlgorithms "6610;660E"

When not using quotation marks, you will receive an error message. But the cmdlet will accept a comma separated list. A comma separated list results in the follow Get-SMimeConfig output

Set-SmimeConfig –OWAEncryptionAlgorithms 6610,660E

OWAEncryptionAlgorithms                          : 660E 6610

This setting results in S/MIME not being available in Outlook on the web.


To successfully apply S/MIME configuration changes, restart the application or restart the Exchange server.

Get-ExchangeServer | ? { $_.AdminDisplayVersion -like '*15.*'} | % { Invoke-Command -ComputerName $_.Name -ScriptBlock {Restart-WebAppPool MSExchangeOWAAppPool} }


Read More »

When you use the Office 365 Portal to move an on-premise mailbox to Office 365 (aka Office 365 Onboarding) you can either move

  • Primary Mailbox and the existing Archive
  • The Archive itself

Screenshot Office 365 Onboarding

There is no option to move only the primary mailbox, if the mailbox already uses a cloud based archive mailbox.

The required option -PrimaryOnly can only be applied when using Remote PowerShell to Exchange Online.

The following lines describe how to move the primary mailbox that does have an enabled cloud archive to Office 365:

# UPN of user to migrate to Exchange Online
$User = ""

# FQDN of configured migration endpoint
$RemoteHost = ""

# EOL target delivery domain aka tenant domain
$TargetDelivery = ""

# Onpremise credentials to access the source mailbox
$OnPremCred = Get-Credential

# New onboarding move request
New-MoveRequest -Identity $User -Remote -RemoteHostName $RemoteHost -RemoteCredential $OnPremCred -TargetDeliveryDomain $TargetDelivery -SuspendWhenReadyToComplete:$false -PrimaryOnly

Your scripts can go from here.



You need assistance with your Exchange Server setup? You have questions about your Exchange Server infrastructure and going hybrid? You are interested in what Exchange Server 2016 has to offer for your environment?

Contact me at
Follow at

Read More »

When you change AutoDiscover settings for users, it can take up to 2 hours until the cached data is invalidated and the new AutoD configuration is sent as a response to new AutoD request.

You have to force a service and a application pool restart to activate your configuration changes immediately:

  • Service: MSExchangeServiceHost
  • Application Pool: MSExchangeAutodiscoverAppPool

These restarts need to be performed on each Exchange 2013/2016 server in your infrastructure serving AutoDiscover requests.

Use the following two PowerShell cmdlets to simplify this task:

Get-ExchangeServer | ? { $_.AdminDisplayVersion -like '*15.*'} | % { Invoke-Command -ComputerName $_.Name -ScriptBlock {Restart-WebAppPool MSExchangeAutodiscoverAppPool } }

Get-ExchangeServer | ? { $_.AdminDisplayVersion -like '*15.*'} | % { Invoke-Command -ComputerName $_.Name -ScriptBlock {Restart-Service MSExchangeServiceHost } }


Read More »
Last updated: 2020-09-05

Exchange Server 2007 Exchange Server 2010 Description

This script will generate a report for Exchange 2007/2010 Public Folder Replication. It returns general information, such as the total number of public folders, total items in all public folders, the total size of all items, the top 20 largest folders, and more. Additionally, it lists each Public Folder and the replication status on each server.

By default, this script will scan the entire Exchange environment in the current domain and all public folders. This can be limited by using the -ComputerName and -FolderPath parameters.

This is an updated version of the Mike Walker ( to support non-ASCII environments.



Generate a public folder generation report for public folder \MYPUBLICFOLDER having replicas on servers MXSRV01, MXSRV02, MXSRV03

Get-PublicFolderReplicationReport.ps1 -ComputerName MXSRV01,MXSRV02,MXSRV03 -FolderPath "\MYPUBLICFOLDER" -Recurse -Subject "Public Folder Environment Report" -AsHTML -To -From -SmtpServer -SendEmail

Example report

Example report


If you want to simplify the report generation, create an additional script: Run-PublicFolderReplicationReport.ps1

    [string]$publicFolderPath = ''

# Variables

# Custom label for email subject
$label = 'Exchange 2007'
$recipients = ''
$sender = ''

# array of public folder servers to query
$publicFolderServers = @('EX2007-01','EX2010-01')

# SMTP server to relay mail
$smtpServer = ''

# Used to trigger a dedicated report for \GrFolder1\Folder1, \GrFolder1\Folder2
$granularRootFolder = @()  # @("\Folder01")
$subPath = ''

# Check for granular folders, Added 2016-01-19
if($granularRootFolder -contains $publicFolderPath) {
    $subPath = $publicFolderPath
    $publicFolderPath = ''

if($publicFolderPath -ne '') {
    Write-Host "Generating Public Folder reports for $($publicFolderPath)"
    # Generate report for a single public folder | Change COMPUTERNAME attribute for servers to analyse
    .\Get-PublicFolderReplicationReport.ps1 -ComputerName $publicFolderServers -FolderPath $publicFolderPath -Recurse -Subject "Public Folder Environment Report [$($publicFolderPath)] [$($label)]" -AsHTML -To $recipients -From $sender -SmtpServer $smtpServer -SendEmail
else {
    if($subPath -ne '') {
        $publicFolderPath = $subPath
    else {
        $publicFolderPath = '\'
    if($granularRootFolder.Count -ne 0) {
        Write-Host 'Following root folders will be excluded when using "\":'
    Write-Host "Generating Public Folder reports for all folders in $($publicFolderPath)"
    $folders = Get-PublicFolder $publicFolderPath -GetChildren 

    # Generate a single report for each folder in root
    $folderCount = ($folders | Measure-Object).Count
    $pfCount = 1
    foreach($pf in $folders) {
        # Check, if folder is in list of granular folders
        if($granularRootFolder -notcontains $pf) {
            if($pf.ParentPath -eq '\') {
                $name = "$($pf.ParentPath)$($pf.Name)"
            else {
                $name = "$($pf.ParentPath)\$($pf.Name)"

            $activity = 'Generating Stats'
            $status = "Fetching $($name)"
            Write-Progress -Activity $activity -Status $status -PercentComplete (($pfCount/$folderCount)*100)
            .\Get-PublicFolderReplicationReport.ps1 -ComputerName $publicFolderServers -FolderPath $name -Recurse -Subject "Public Folder Environment Report [$($name)] [$($label)]" -AsHTML -To $recipients -From $sender -SmtpServer $smtpServer -SendEmail

Use the $granularRootFolder array to add root public folders which require a dedicated report for each sub-folder.


Version History

  • 1.0, Initial community release
  • 1.1, Replica status (green/red) depending on the item count, not the percentage
  • 1.2, Fixed: If 1st server has a lower item count a folder is not being added to the list of folders with incomplete replication
  • 1.3, Changes to number and size formatting, Exchange 2007 now returns MB or GB, as configured
  • 1.4, Handling of KB values with Exchange 2007 added
  • 1.5, Some PowerShell hygiene and fixes
  • 1.6, Count of incomplete replicated public folders stated in the table header (issue #1)




Additional Credits

Additional credits go to Mike Walker (




Additional Note

This Powershell script has been optimized using the ISESteroids™ add-on. Learn more about ISESteroids™ here.



Read More »