Tag Archives: PowerShell

Multiple mailbox users match identity “Mailbox1”

So I’m working on a nice Public Folder migration from Exchange 2016 to Exchange Online. Last week all preparations were performed and this morning I was planning to start the migrationbatch. Fourteen Public Folder mailboxes in Exchange 2016 to eighteen Public Folder mailboxes in Exchange Online. What could possibly go wrong….

Creating the new endpoint for the migrationbatch failed with an error saying “Multiple mailbox users match identity “PFMailbox1″. Specify a unique value” as shown in the following screenshot:

Or in plain text:

PS C:\PFScripts> $PfEndpoint = New-MigrationEndpoint -PublicFolder -Name PublicFolderEndpoint -RemoteServer $Source_RemoteServer -Credentials $Source_Credential
Multiple mailbox users match identity "Mailbox1". Specify a unique value.
    + CategoryInfo          : NotSpecified: (:) [New-MigrationEndpoint], MigrationPermanentException
    + FullyQualifiedErrorId : [Server=AM0PR09MB2402,RequestId=bccebc4f-d231-41d3-b8fe-a676311b3575,TimeStamp=22-8-2022 09:33:52] [FailureCategory=Cmdlet-MigrationPermanentException] 80069390,Microsoft.Exchange.Management.Migration. MigrationService.Endpoint.NewMigrationEndpoint
    + PSComputerName        : outlook.office365.com
PS C:\PFScripts>

This is strange since there’s no mailbox user named “Mailbox1”, there’s only one Public Folder mailbox named “Mailbox1” and that is holding the Public Folder hierarchy. But, last week I have been preparing the Public Folder migration, and one step was to create a Public Folder mailbox, just to see if it would work. I deleted the Public Folder mailbox, but it is a soft deleted state, and this conflicts with the creation of the Public Folder migration endpoint.

To find the Public Folder mailboxes including the soft deleted mailboxes, execute the following command against Exchange Online:

PS C:\PFScripts> Get-Recipient  -IncludeSoftDeletedRecipients -RecipientTypeDetails publicfoldermailbox | fl Name, OrganizationalUnit, DistinguishedName, ExchangeGuid

It will return a list of Public Folder mailboxes, including the ones in a soft deleted state. Clearly visible in the following screenshot is the soft deleted Public Folder mailbox:

Use the following command against Exchange Online to remove the soft deleted Public Folder mailbox:

[PS] C:\> Remove-Mailbox -PublicFolder "<ExchangeGuid>" -PermanentlyDelete

Wait some time for replication to happen in EXODS and try again to create the Public Folder migration endpoint. This time it succeeded.

Retrieve mailbox statistics in PowerShell for a large number of users

I’m currently working on a project where we are going to move 24,000 mailboxes from Exchange 2016 to Exchange Online. For planning purposes we would like to know the basic statistics, like the LastLogonTime and the number of items (both regular and deleted).

To retrieve this for my mailbox, you can use something like this:

[PS] C:\ >Get-Mailbox -Identity wesseliusj | Get-MailboxStatistics | Select DisplayName,LastLogonTime,ItemCount,TotalItemSize,DeletedItemsCount,TotalDeletedItemSize

DisplayName          : Wesselius, J
LastLogonTime        : 28-4-2022 11:24:46
ItemCount            : 1065
TotalItemSize        : 63.95 MB (67,060,296 bytes)
DeletedItemsCount    :
TotalDeletedItemSize : 5.421 MB (5,684,477 bytes)

The TotalItemSize and TotalDeletedItemSize are returned as text and not numeric. Since I want to export everything into a CSV file and import into Excel for further processing, it must be converted to a numeric value. This is called a calculated property and this is possible using the following option:

@{Name="TotalItemSizeMB";Expression={$_.TotalItemSize.Value.ToBytes()}}

ToBytes() can also be ToKB(), ToMB() or ToGB() depending on your situation.

The previous command and output will now be something like this:

[PS] C:\>Get-Mailbox -Identity wesseliusj | Get-MailboxStatistics | Select DisplayName,LastLogonTime,ItemCount,@{Name="TotalItemSizeMB";Expression={$_.TotalItemSize.Value.ToBytes()}},DeletedItemsCount,@{Name="TotalDeletedItemSizeMB";Expression={$_.TotalDeletedItemSize.Value.ToBytes()}}


DisplayName            : Wesselius, J
LastLogonTime          : 28-4-2022 11:24:46
ItemCount              : 1065
TotalItemSizeMB        : 67060293
DeletedItemsCount      :
TotalDeletedItemSizeMB : 5684477

Now use the Export-Csv command and we are good to go (you would hope 😊):

[PS] C:\>get-mailbox -ResultSize unlimited | Get-MailboxStatistics | Select DisplayName,LastLogonTime,ItemCount,@{Name="TotalItemSizeMB";Expression={$_.TotalItemSize.Value.ToBytes()}},DeletedItemsCount,@{Name="TotalDeletedItemSizeMB";Expression={$_.TotalDeletedItemSize.Value.ToBytes()}} | export-csv -Path statistics.csv -nti

Sending data to a remote command failed with the following error message: [ClientAccessServer=EXCH2016,BackEndServer=exch2016.labs.local,RequestId=c0430cd6-6f4d-48a5-8434-d59ebcd91887,TimeStamp=28-4-2022 10:03:54] [FailureCategory=W
SMan-Others] The total data received from the remote client exceeded the allowed maximum. The allowed maximum is 524288000. For more information, see the about_Remote_Troubleshooting Help topic.
    + CategoryInfo          : OperationStopped: (exch2016.labs.local:String) [], PSRemotingTransportException
    + FullyQualifiedErrorId : JobFailure
    + PSComputerName        : exch2016.labs.local

[PS] C:\>

Unfortunately, the Get-Mailbox command retrieves all 24,000 mailboxes in one run and then tries to use this as input for the Get-MailboxStatistics command. While this works for just a few mailboxes, it runs out of memory for a large set of mailboxes.

The solutions here (or one of the solutions) is to import all mailboxes into a variable, and loop through all mailboxes in this variable combined with the Get-MailboxStatistics command:

[PS] C:\> $Mailboxes = Get-Mailbox -Resultsize Unlimited
[PS] C:\> ForEach ($Mailbox in $Mailboxes) {Get-MailboxStatistics $Mailbox | Select  DisplayName,LastLogonTime,ItemCount,@{Name="TotalItemSizeMB";Expression={$_.TotalItemSize.Value.ToBytes()}},DeletedItemsCount,@{Name="TotalDeletedItemSizeMB";Expression={$_.TotalDeletedItemSize.Value.ToBytes()}} | export-csv -Path statistics.csv -nti}

One last question I got is to add a UPN or alias of the user to the CSV file. UPN and alias are not in the object that’s returned by Get-MailboxStatistics, but are returned by the Get-Mailbox command. To get these properties in the output, again a calculated property must be used, similar to the size properties that were used earlier.

To retrieve the UPN, use something similar to the following:

@{Name = "UPN"; Expression={$Mailbox.UserPrincipalName}}

This will take the UserPrincipalName property of the first command (Get-Mailbox) and parse it into the output. The entire command will be:

[PS] C:\>ForEach ($Mailbox in $Mailboxes) {Get-MailboxStatistics $Mailbox | Select  DisplayName, @{Name = "UPN"; Expression={$Mailbox.UserPrincipalName}},LastLogonTime,ItemCount,@{Name="TotalItemSizeMB";Expression={$_.TotalItemSize.Value.To
Bytes()}},DeletedItemsCount,@{Name="TotalDeletedItemSizeMB";Expression={$_.TotalDeletedItemSize.Value.ToBytes()}}}

DisplayName            : Wesselius, J
UPN                    : j.wesselius@Exchangelabs.nl
LastLogonTime          : 29-4-2022 14:22:03
ItemCount              : 1098
TotalItemSizeMB        : 68714749
DeletedItemsCount      :
TotalDeletedItemSizeMB : 5822787

[PS] C:\>

This will create a proper CSV file with all the information I need, ready to import into Excel 😊

More information regarding working with large number of users (in Office 365) please check the following article: Running PowerShell cmdlets for large numbers of users in Office 365 – Microsoft Tech Community

Send from Alias in Exchange Online

A bit later than planned, but I was attending a training last week, but a long-awaited feature in Exchange is sending mail from another email address that is stamped on a user, a so called alias. In a typical environment, a mailbox has a primary SMTP address and this address is used to send an receive email. This can be something like j.wesselius@exchangelabs.nl. Besides this primary SMTP address there can be more SMTP addresses that can be used to receive mail, for example Mr.Exchange@exchangelabs.nl or MasterOfDisaster@exchangelabs.nl. In Exchange on-premises and Exchange Online, these Aliasses are only used to receive email, not to send email. Up until now that is (for Exchange Online, no idea if they want to enable this for Exchange on-premises).

Microsoft has started to roll out the Send From Alias in Exchange Online starting in January 2022 (it was already announced back in April 2021) and it is available in Outlook on the Web and Outlook for iOS and Outlook for Android. Outlook for the PC will follow, according to Microsoft in Q2, 2022.

To enable the Send from Alias in Exchange Online, execute the following command in Exchange Online PowerShell:

[PS] C:\> Set-OrganizationConfig -SendFromAliasEnabled $True

It takes some time before effective, in my case it worked the next day.

All SMTP proxy addresses on a mailbox are available for this. When you logon as a user and go to settings | Mail | Compose and Reply you can check which aliases you want to use. + Addresses are also shown and so are the mail.onmicrosoft.com addresses. Don’t know who thought this was useful, in my opinion you don’t want to use these (internal) addresses at all:

Now when you write a new email in Outlook on the Web and select the From option, you can select the email address that you checked in the previous step.

The proxy addresses that are selected in the first step (the OWA settings) will automatically available in Outlook for Android and Outlook for iOS.

When you send an email using one of these aliases as a from address, it will automatically be visible in the recipient mailbox, in this example in Gmail:

I don’t expect much use of this feature until Outlook for the desktop will offer it, but it’s a nice add-on (finally).

New Exchange Online PowerShell v2

When using PowerShell with Exchange Online you can use the ‘good old traditional’ way to connect to Exchange Online:

$ExCred = Get-Credential 
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $ExCred -Authentication Basic -AllowRedirection
Import-PSSession $Session

This is not a recommended way to connect to Exchange Online using your tenant admin account, it uses basic authentication (will be decommissioned in 2021) and MFA (number one prerequisite for tenant admin security!) is not possible.

The second option is the Exchange Online Remote PowerShell Module which you can download from the Exchange Online Admin Center (use Internet Explorer for this download!) as shown in the following screenshot:

Exchange Online PowerShell Module

This is a separate PowerShell module you can start and use the Connect-EXOPSSession command to connect to Exchange Online. This PowerShell module users Modern Authentication and supports Multi-Factor Authentication.

The latest (and newest) option is the Exchange Online PowerShell V2 module. This module works far more efficient with large datasets than the previous PowerShell modules for Exchange Online. It also supports Modern Authentication and Multi-Factor Authentication.

To install the Exchange Online PowerShell V2 module you first have to install the PowerShellGet module using the Install-Module PowershellGet command:

Install-Module PowershellGet

Followed by the Install-Module -Name ExchangeOnlineManagement command:

Install-Module ExchangeOnlineManagement

When installed you can use the Connect-ExchangeOnline command to connect to Exchange Online. When MFA for your admin account is configured it will automatically use it:

Connect-ExchangeOnline

The differences between V1 and V2 are clearly visible in the commands. All V2 commands contain EXO, like:

  • Get-Mailbox vs Get-EXOMailbox
  • Get-Recipient vs Get-EXORecipient
  • Get-MailboxStatistics vs Get-EXOMailboxStatistics
  • Get-CASMailbox vs Get-EXOCASMailbox

This means that all scripts you have written for use with Exchange Online need to be changed to reflect the V2 commands.

For a complete overview you can use the Get-Command *EXO* to retrieve all PowerShell commands that contain EXO (still very limited 🙂 ):

Get-Command EXO

The Exchange Online PowerShell V2 module is still in preview, the current version is 0.3582.0 which you can check using the Get-Module ExchangeOnlineManagement command:

Get-Module ExchangeOnlineManagement

The Exchange Online PowerShell v2 module is a work in progress, but it the future of PowerShell in Exchange Online, so you should keep an eye on this development.

More Information

Use the Exchange Online PowerShell V2 module – https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/exchange-online-powershell-v2/exchange-online-powershell-v2?view=exchange-ps

Install-Module MSOnline fails with unable to download from URI

When installing the MSOnline module using the Install-Module MSOnline command in PowerShell it fails with a cryptic error like:

WARNING: Unable to download from URI ‘https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409&#8217; to ”.
WARNING: Unable to download the list of available providers. Check your internet connection.
PackageManagement\Install-PackageProvider : No match was found for the specified search criteria for the provider ‘NuGet’. The package provider requires ‘PackageManagement’ and ‘Provider’ tags. Please check if the specified package has the tags.

And

WARNING: Unable to download from URI ‘https://go.microsoft.com/fwlink/?LinkID=627338&clcid=0x409&#8217; to ”.
WARNING: Unable to download the list of available providers. Check your internet connection.
PackageManagement\Get-PackageProvider : Unable to find package provider ‘NuGet’. It may not be imported yet. Try ‘Get-PackageProvider -ListAvailable’.
Install-Module : NuGet provider is required to interact with NuGet-based repositories. Please ensure that ‘2.8.5.201’ or newer version of NuGet provider is installed.

As shown in the following screenshot:

Install-PackageProvider

It turns out that this is a TLS issue, PowerShell does not use TLS 1.2 by default, while Microsoft requires TLS 1.2 from clients. To set TLS 1.2 usage for PowerShell, you can use the following command:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

Now if you try again, it will install the MSOnline module:

Install-Module MSOnline

This is a per session setting, if you want to enable it for all sessions, add the previous command to the Microsoft.PowerShell_profile.ps1 and Microsoft.PowerShellISE_profile.ps1 profiles (use Notepad $Profile for this.

More information

Azure ActiveDirectory (MSOnline) – https://docs.microsoft.com/en-us/powershell/azure/active-directory/install-msonlinev1?view=azureadps-1.0