March 2016 Quarterly Updates for Exchange Released

Microsoft today released the latest Cumulative Updates for Exchange 2007, 2010, 2013 and 2016.

New for Exchange 2016 only, is the option to download the updates as a single ISO file instead of a self-extracting package.  Copying a single ISO over the network from one server to another is quicker and more efficient than copying the self-extracting package or the thousands of extracted files.

Updates of note this time around:

  • Updated OWA S/MIME Control certificate
  • New distribution package for Exchange 2016
  • Change to mailbox anchoring for remote PowerShell
  • 17 new languages supported for OWA
  • Support for Standalone Hybrid Configuration Wizard in Exchange 2010

Microsoft is working on building in support for .Net 4.6.1 in the next quarter’s Cumulative Updates.  So, avoid installing that version of .Net on ANY Exchange server for the time being.

For more info and download links for the updates, follow the links below:

As a side note, yesterday (March 14th, 2016) marked the 20th anniversary of the first public version of Exchange (v4.0) Released To Manufacturing (RMT’d).

It’s been a long journey from the old MS Mail to Exchange Online/Office 365.  Here’s to the next 20 years!

Happy Birthday Exchange Server!

Convert a mail-enabled public folder to a shared mailbox in Exchange 2007

  1. Create the new Shared mailbox per the instructions here.
    1. Give it the same name as the public folder being converted.
    2. Make sure the users who have access to the public folder are added to the MBX_xxxxxx security group so they have Full Access and Send-As rights to the new mailbox.
  2. Using PowerShell , note the LegacyExchangeDN of the mail-enabled public folder:
    1. Get-MailPublicFolder <pf-smtpaddress> | Select LegacyExchangeDN
    2. (i.e. /O=ORG/OU=ADMIN GROUP/CN=RECIPIENTS/CN=Folder-Name887CE6C3409E34A2848C4BB5E42229C7547F86)
  3. Using PowerShell, note the SMTP addresses assigned to the public folder
    1. (Get-MailPublicFolder <pf-smtpaddress>| Select emailaddresses).emailaddresses | where {$_.prefixstring -eq ‘smtp’}
    2. (SmtpAddress     : Folder-Name@contoso.com

      AddressString   : Folder-Name@contoso.com

      ProxyAddressString : smtp:Folder-Name@contoso.com

      Prefix : SMTP

      IsPrimaryAddress   : False

      PrefixString    : smtp}

  4. Mail-disable the public folder and allow a few minutes for AD to replicate this change.  Mail destined to the original public folder may bounce during this time frame.
  5. Add the LegacyExchangeDN value to the new shared mailbox as an X.500 email address.  This will allow mail originally destined for the public folder to be delivered to the new shared mailbox instead.  This is to support replies to older messages and new messages sent using the Outlook Name cache.
  6. Add the SMTP addresses to the new shared mailbox if they are not already auto-assigned by the email address policy.

Script to create Shared Mailboxes consistently

If you’ve followed the instructions for creating shared mailboxes using PowerShell you know its a little clugey.   However, since the parameters for setting one up is fairly consistent except for the name and who has access to it, I’ve created the following script that can be used to create them.

 
 

 
 

You must have the following components installed in order to run it.


PowerShell


Exchange 2007 Management Console and Shell


Quest ActiveRoles snap-in for Powershell (free download here)


PowerShell must be run in the context of a user account that has rights to create new objects in AD


You must set your PowerShell execution policy to Unrestricted (open PowerShell, type Set-ExecutionPolicy Unrestricted)

 
 

When you run the script from within PowerShell, it will perform the following:

 
 

1.    Check to make sure the Exchange & Quest Snap-ins are present and if not, add them

2.    Query the user for information about the new shared mailbox (name of the mailbox, etc).

3.    Based on the information provided, it will create the new mailbox in one of two OUs (Site1 or Site2)

4.    It will then create a new security group in AD with a MBX_ prefix and grant members of this group Full Access and Send-As rights to the new mailbox

5.    Log all of this in a log file found in the same folder as the script for troubleshooting purposes.

 
 

Once the script completes and creates the mailbox and security group, all you have to do to complete the process is use AD Users & Computers to add user accounts to the new security group to grant them access.

 
 

You’ll need to edit the script to fit your environment (OU paths and Exchange server names, etc)

 
 

The script…

 

 

# ===================================================

#

# This PowerShell script does the following:

# 1. Queries the user for information about a new shared mailbox

# 2. Creates a new shared mailbox based on that information

# 3. Creates an AD security group based on that information

# 4. Grants the new security group full access and send-as rights on the new shared mailbox.

#

# Written by: David Smith

# Last modified: 05/03/2010

# Notes:

#

# ===================================================

### Define functions

function

writetolog([string]$stringtowrite=“*”)

{


$datetime
= (Get-Date).datetime


Write-Host
$stringtowrite


Add-Content
$logfile
$datetime : $stringtowrite

}

 

### Setup the log file

 

[string]$logfilename =
‘create-sharedmailbox.log’

if (Test-Path
$logfilename) {Write-Host
“Log file exists.”;$logfile
=
$logfilename} Else {Write-Host
“Creating log file $logfilename;$logfile
=
New-Item
$logfilename
-Type
file}

writetolog
“===== Beginning new-sharedmailbox.ps1 =====”

 

### Add the Exchange 2007 Snap-ins if they aren’t already and prepare credentials

writetolog
“Checking Exchange 2007 Snapins”

if ((Add-PSSnapin
Microsoft.Exchange.Management.PowerShell.Admin
-ErrorAction
SilentlyContinue) -and (Add-PSSnapin
Microsoft.Exchange.Management.PowerShell.Support
-ErrorAction
SilentlyContinue))

{writetolog
“Added Exchange 2007 Snapins”}

 

Else

 

{writetolog
“Exchange 2007 Snapins present.”}

 

### Add the Quest Active-Roles Snap-ins if they aren’t already and prepare credentials

 

writetolog
“Checking Exchange 2007 Snapins”

 

if (Add-PSSnapin
Quest.ActiveRoles.ADManagement
-ErrorAction
SilentlyContinue)

 

{writetolog
“Added Quest Snapins”}

 

Else

 

{writetolog
“QuestSnapins present.”}

 

### Set the variables

 

[string]$HelpDeskTicket =
Read-Host
-prompt
“Enter HelpDesk #”

[string]$notesstring =
“Created per HelpDesk Ticket #”
+
$HelpDeskTicket

[string]$sharedmbxname =
Read-Host
-Prompt
“Enter New Shared Mailbox Name”

[string]$upn =
$sharedmbxname.Replace(” “,“”) + ‘@contoso.com’

[string]$secgrpname =
‘MBX_’
+
$sharedmbxname.Replace(” “,“”)

[string]$secgrpupn =
$secgrpname
+
‘@contoso.com’

$title
=
“Mailbox Server to host new mailbox:”

$message
=
“Should this new mailbox be placed in Site1 or Site2?”

$Site1
=
New-Object
System.Management.Automation.Host.ChoiceDescription
“&Site1”,
`”The
new
mailbox
will
be
created
in
Site1.”

$Site2 = New-Object System.Management.Automation.Host.ChoiceDescription “&Site2″, `”The new mailbox will be created in Site2.”

$options
=
[System.Management.Automation.Host.ChoiceDescription[]]($Site1, $Site2)

$result
=
$host.ui.PromptForChoice($title, $message, $options,
0)

 

switch

($result) {


0 {[string]$mbxOU =
‘contoso.com/SITES/Site1/Site1-Exchange Objects/Site1-Resource Accounts’


[string]$secgroupOU =
‘contoso.com/SITES/Site1/Site1-Groups/Site1-Security Groups’


[string]$mbxdatabase =
‘site1exchangesite1exchange-sg1site1exchange-db1’}


1 {[string]$mbxOU =
‘contoso.com/SITES/Site2/Site2-Exchange Objects/Site2-Resource Accounts’


[string]$secgroupOU =
‘contoso.com/SITES/Site2/Site2-Groups/Site2-Security Groups’


[string]$mbxdatabase =
‘site2exchangesite2exchange-sg1site2exchange-db1’} }

 

writetolog
“HelpDesk Ticket: $HelpDeskTicket

writetolog
“Shared Mailbox Name: $sharedmbxname

writetolog
“Security Group Name: $secgrpname

writetolog
“Mailbox OU: $mbxOU

writetolog
“Security Group OU: $secgroupou

writetolog
“Mailbox Database: $mbxdatabase

$newSharedMailbox
=
New-Mailbox
-Alias
$sharedmbxname.Replace(” “,“”) -Name
$sharedmbxname
-Database
$mbxdatabase
-OrganizationalUnit
$mbxOU
-Shared
-UserPrincipalName
$upn

Set-Mailbox
$newSharedMailbox
-ManagedFolderMailboxPolicy
‘Mailbox Policy Name’
-Confirm:$false

Set-User
$newSharedMailbox
-Notes
$notesstring

$newSecurityGroup
=
New-QADGroup
-ParentContainer
$secgroupOU
-Name
$secgrpname
-SamAccountName
$secgrpname

Get-Mailbox
$newSharedMailbox
|
Add-MailboxPermission
-User
$secgrpname
-AccessRights
‘FullAccess’

Get-Mailbox
$newSharedMailbox
|
Add-ADPermission
-User
$secgrpname
-ExtendedRights
Send-As

Write-Host
‘Use AD Users & Computers to add the users with access to this shared mailbox to the $secgrpname security group’

Script to add Public Folder replicas all the way down a subtree

I’m in the process of trying to migrate my public folders from Exchange 2003 to Exchange 2007.  As part of the process (since my public folder database is SO HUGE!) I’m moving small subsets of folders at a time instead of performing a “Move All Replicas” task.

To facilitate this I’m adding the new 2007 pub databases to the replica list of a sub-folder first, allowing replication to happen and then removing the 2003 pub databases from the replica list.

The trick is getting the 2 new 2007 pub databases added to the list without necessarily knowing what’s already in the replica list and doing all of this in a script, not a GUI.

Below is the script I wrote to do this.  I simply type the script name at the PowerShell command line and then pass the path of the root folder I want to start with on the command line.  The script starts from that root folder and adds my 2 new 2007 servers to the list all the way down the tree.

[string]$path = $args[0]
Write-Host $path
$server1 = Get-PublicFolderDatabase -Server servername1
$server2 = Get-PublicFolderDatabase -Server servername2

$folders = Get-PublicFolder $path -Recurse
foreach ($rootfolder in $folders) {
 $rootfolder.Replicas +=$server1.Identity
 $rootfolder.Replicas +=$server2.Identity
 $rootfolder | Set-PublicFolder}

Populate the “folder path” field for mail-enabled public folders in the address book

If you’re like me you hate when you get a request from a user to modify something with a mail-enabled public folder because users NEVER tell you the path to that folder in the folder hierarchy.  You can find it via powershell if you want:

Get-MailPublicFolder “smtp@address” | Get-PublicFolder | fl Name, ParentPath

Name    : Folder Name
ParentPath : Parent Folder NameSub folder name

If you look in the address book, each mail-enabled public folder in the list has a “folder path” property that never gets populated.  I wish I knew why Microsoft made this information available but didn’t make it easy to populate the values – you’d think it would just automatically be able to look that information up when it generates the address list – but sadly, NO!

Or you could run a powershell script to set each one of them automatically.  You’ll have to schedule the script to run regularly to make sure the values are up to date though.  You’ll also need the Quest ActiveRoles snapin for powershell. 

Here’s the script I wrote to accomplish this:

$mailpub = Get-MailPublicFolder -ResultSize unlimited
foreach ($folder in $mailpub) {
 $pubfolder = Get-PublicFolder -Identity $folder
 $folderpath = $pubfolder.parentpath + “” + $pubfolder.name
 $qadpub = Get-QADObject -IncludeAllProperties -Type publicfolder -Identity $folder
 Set-QADObject -Identity $qadpub -ObjectAttributes @{folderPathname=$folderpath}}

 
 

Have fun!

Exchange 2007 and Spaces in the Alias field

I’ve not been able to find much documentation about this online yet, but I discovered this issue in my Exchange 2007 Migration Lab: Exchange 2007 doesn’t like spaces in the alias field of mail-enabled objects.

 
 

These spaces will cause any migration of the object into the Exchange 2007 system to fail with the following error:

 
 

WARNING: Object contoso.com/Microsoft Exchange System Objects/Consumer

Support has been corrupted and it is in an inconsistent state. The following

validation errors have occurred:

WARNING: “Consumer Support” is not valid for Alias. Valid values are: Strings

formed with characters from a to z (uppercase or lowercase), digits from 0 to

9, !, #, $, %, &, ‘, *, +, -, /, =, ?, ^, _, `, {, |, } or ~. One or more

periods may be embedded in an alias, but each one of them should be preceded

and followed by at least one of the other characters. Unicode characters from

U+00A1 to U+00FF are also valid in an alias, but they will be mapped to a

best-fit US-ASCII string in the email address which is generated from such an

alias.

 
 

Before you can begin the migration of your AD objects to Exchange 2007, you must update all objects in AD to remove the space.  In my case, I opted for replacing the space with an underscore (i.e. in the above example, “Consumer Support” will become “Consumer_Support”).  This change should only affect the alias property in AD and not the display name.

 
 

I wrote the following procedure involving AD Users & Computers and Powershell to correct the issue in my environment prior to installing the Exchange 2007 Schema updates:

 
 

 
 

  • Create an AD Users & Computers search query to search all exchange-enabled objects.  Include the “Exchange Alias” filed in the column headers
  • Export this list to a tab-delimited file.
  • Open this file in Excel, change the “Exchange Alias” column header to just “Alias”, and re-save as a CSV file
  • Open Powershell
    • $mailobjects = import-csv exportedfile.csv
    • $mailboxes | Where-Object {$_.alias -match ” “} | Export-CSV bad_exchaliases.csv
    • Open in Excel, remove all columns but “Alias”
    • Duplicate the “Alias” column, name it New_Alias
    • In the duplicated column, find/replace all ” ” with “_”
    • Save CSV file
    • $badaliases = import-csv bad_exchaliases.csv
    • $cred = Get-Credential (input credentials with rights to modify all objects)
    • foreach ($object in $badaliases) {Set-QADObject -Identity $object.Alias -ObjectAttributes @{mailnickname=$object.New_Alias} -Credential $cred

Update: Found this page on TechNet: