Microsoft Ignite 2017 – Key Sessions for Exchange

This year, which was around by 20th TechEd\Ignite, I was working the Commvault booth Mon-Thur and didn’t get to any sessions. As the field expert for most things Microsoft for Commvault (I cover AD, Exchange, SharePoint, Office 365 fully and Azure some), being in the booth to answer questions on what Commvault does for Microsoft solutions, which is a lot (microsoft.com/Commvault), at a Microsoft show was a must. But this also meant I didn’t get to attend any sessions.

So below are some link that lists some key one for Exchange Admins.

  1. By the Exchange Team https://blogs.technet.microsoft.com/exchange
  2. By “Super Tekboy” aka Gareth Gudger https://supertekboy.com/2017
  3. Find all the online sessions here also: https://myignite.microsoft.com/sessions
  4. For Tony Redmond’s reflections on Ignite https://www.petri.com/author/tony-redmond

Know of others such list? Comment and I’ll add them, if they are focused on  Exchange/EXO.

Posted in Technical | Leave a comment

FIXED in iOS 11.0.1: DO NOT Upgrade to iOS 11, if using Apple Mail & Exchange Online or Outlook.com

9/26: iOS 11.0.1 has been released and fixes the issue with ActiveSync with Exchange 2016\Exchange Online. See Apple article HT208136: https://support.apple.com/en-us/HT208136

HTTP/2 will now work on your Exchange 2016, running on Windows Server 2016, and with EXO.

1st heard of here http://www.essential.exchange/2017/09/26/ios-11-0-1-released-eas-on-ios-fixed/, by Michael B. Smith.

Apple released iOS 11 on 9/19/2017 and AGAIN they failed to test the largest email system in the world, Office 365\Exchange Online, with their email client. Apple has had a history of issues with Exchange since iOS 2.0 and with multiple iOS version have broken feature in Apple Mail on initial release.

So, if using an iOS device, do not upgrade to iOS11 yet, if your mailbox is hosted on O365\Exchange Online, Outlook.com, or if your organization is running Exchange 2016 on Windows 2016. The common factor here is that that Office 365\Exchange Online and Outlook.com all use Exchange 2016 running on Windows 2016.

The issue is that the native Apple Mail client in iOS 11 does not support HTTPS/2 TLS protocol, which is used by Exchange 2016. It seems, that Apple Mail can receive messages, but fails to send\reply to them. The Apple Mail App uses Exchange ActiveSync and when it connects to Exchange 2016, Exchange uses HTTPS/2 TLS by default, but Mail App doesn’t negotiate down to HTTP/1.1 and the connection fails.

In Office 365, you should see this alert MC119954:
MC119954

If your organization is running Exchange 2016 on Windows 2016, you can disable HTTP/2 on the server. To do this see this Microsoft article: How to deploy custom cipher suite ordering in Windows Server 2016, which just has this RegKey setting:

To enable and disable HTTP/2, follow these steps:

  1. Start regedit (Registry Editor).
  2. Move to this subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters
  3. Set DWORD type value EnableHttp2Tls to one the following:
    1. Set to 0 to disable HTTP/2
    2. Set to 1 to enable HTTP/2
  4. Restart the computer.

If your mailbox is hosted on Outlook.com or Exchange On-line and you have already updated to iOS11 your only option, currently, is to change email clients. I HIGHLY recommend Microsoft’s Outlook App (download here).

Other articles on this issue:

Posted in Apple, Exchange, Microsoft, O365, Technical | Tagged , , | Leave a comment

FREE Microsoft eBooks! Lots of them!!!

Came across this today and had to share with others: https://blogs.msdn.microsoft.com/mssmallbiz/2017/07/11/largest-free-microsoft-ebook-giveaway-im-giving-away-millions-of-free-microsoft-ebooks-again-including-windows-10-office-365-office-2016-power-bi-azure-windows-8-1-office-2013-sharepo/

12 that cover parts of Office 365
16 that cover or touch on SharePoint
12 for PowerShell

And many others for Office 2013, 2016, and other office products and many on server products. Sadly there are ZERO on Exchange 😦

 

Posted in Microsoft, O365, Outlook, SharePoint, Technical | Leave a comment

Review of Practical PowerShell: Exchange Server 2016

For those that have worked with Exchange for 20 years or are new to Exchange or Exchange Online (Office 365) PowerShell scripting is must have skill. Back in Exchange 2003 and early days you could, and had to do, almost everything from a GUI. Then Exchange 2007 came out and things changed. You still had a GUI, but it had only about ~80% of the administrative features in it, which left ~20% in the new command line scripting interface, PowerShell. Those that had been using VBScript and other languages to carry out bulk task in Exchange were very pleased with PowerShell since it greatly simplified their scripts and work. Administrators for large Exchange implementation were also thrilled to have a much more powerful CLI to carry out bulk tasks. On the other hand, many Exchange admins were not happy about the lack of some feature in the GUI and were reluctant to learn “coding” or scripting to do the rest. Here we are 10 years later and PowerShell is MUST have skill for Exchange, Windows, and many other Microsoft infrastructure administrators. For administrators of Exchange Online\Office 365, this is also a must have skill since there are less feature in the GUI\web admin console (Exchange Admin Center/Exchange Control Panel) for Exchange Online then there are in Exchange 2016, currently. Office 365, or BPOS at the time, was a major driver for PowerShell and why Exchange 2007 was the 1st Microsoft server application to use it. Microsoft needed a way to easily automate task across 10,000s of servers.

The book Practical PowerShell: Exchange Server 2016 was written by Damian Scoles (Blog: https://justaucguy.wordpress.com/) and Dave Stork (Blog: https://dirteam.com/dave/) who are fellow Exchange (or technically Office Servers and Services) MVPs. They ask me in late 2016 to be a technical reviewer of the book, along with Michel De Rooij (Blog: https://eightwone.com/), and I was happy to help since Exchange has been my passion since I installed the beta version of Exchange 4.0 in 1995. There are many different books on PowerShell out there and even on Exchange PowerShell, but one thing with technology and software is that it is contently changing. This book is THE BEST PLACE to get started or to use as a refence for PowerShell for Exchange 2016 or Exchange Online (which uses Exchange 2016). If your organization is still on Exchange 2010 or 2013 this is also an excellent book, but keep in mind that PowerShell cmdlets have changed with each version so not all example will work on previous versions of Exchange.

The book starts out with the basics of PowerShell, covering key features like variables, arrays, loops, functions, working with files, and the various PowerShell tools, like PowerShell ISE. Then it moves to formatting, building your most basic scripts, what’s new and changed in 2016, and using some basic script to connect to Exchange. All aspect of Exchange PowerShell are covered across the book’s eighteen chapters, which are broken out by areas; like Mail Flow, Users, Mobile Devices, Migrations, etc. The structure of the books allows you to pick it up and jump into the chapter that is related to the area you need to learn more about. It contains countless script examples and cmdlets (I check all of them in the 2nd half of the book) that can be the basis for your own scripts and will provides ideas on how to do many things that admins might not have thought of before. Real world examples are used thought the book and it should be on the top of any Exchange admins desk.

On the https://www.practicalpowershell.com/ website you can purchase the PDF and physical copy of the book. I suggest both, I still find having physical copies of technical books beneficial since I like to flip through them looking for things and ideas and then the PDF copy is ideal for search on terms, like cmdlets, and copy and pasting code from.

GET THIS BOOK: https://www.practicalpowershell.com/

Posted in Exchange, Script, Technical | Tagged , , | Leave a comment

Script: Updating Recipients in Exchange Online (Office 365)

A very common request is to update recipients in Exchange Online and commonly many updates are required. Updating a few recipients in EXO can easily be done with the Office 365 Admin Portal or Exchange Admin Console (ECP), but due to human error can lead to mistakes. When more than a few recipients need updates, scripting is needed.

 

The script below will cover five key functions. 1) Connecting to Azure AD/EXO/O365, if not connected already, 2) Getting input from a CSV file, 3) Detecting the recipient type, 4) Updating the properties of an existing recipient, and 5) Creating a Contact when an existing recipient is not found.

1)    Connecting to Azure AD/EXO/O365

Before we can do anything in EXO/O365 we need to start a remote PowerShell session to Office 365. So at the very start of the script it will check to see if there is an existing open session to EXO. If one is not found, a new session will be created.

Before sessions can be created, the Azure AD PowerShell module must be installed on the system running this script. It can be downloaded from: https://go.microsoft.com/fwlink/p/?linkid=236297

The first line below, uses the Get-PSSession cmdlet to get and then filter all session to return a count of those that are “Open” and have the ConfigurationName of “*Microsoft.Exchange*”. If this cmdlet, with the filters, returns no results, then the New-PSSession cmdlet is called. When the New-PSSession cmdlet is used, the credentials of a user, with the required rights, must be supplied. These are requested via a secure pop-up using the Get-Credential cmdlet and saved to the $UserCredential variable.

Using the $Session variable we store the session information, including credentials. This is then used by the Import-PSSession cmdlet to create the session. Finally, the session is connected to using Connect-msolservice.

If (((Get-PSSession | ?{$_.State -Like "*Open*" -And $_.ConfigurationName -Like "*Microsoft.Exchange*"}).Count) -Eq 0) {

$UserCredential= Get-Credential

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

Import-PSSession $Session

Connect-msolservice -credential $UserCredential
}

2)    Getting input from a CSV file

The five lines in the script example below, will read a Recipients.csv file and then process each line using a ForEach loop. In this loop, three fields are displayed: FirstName, LastName, and Email.

In this script, it is assume the CSV as the following fields in it: FirstName, LastName, Role, Email, Phone, MobilePhone, HomePhone, WorkPhone, Comments, Address, City, State, Zip, ID. These, except for ID, can map directly to existing attributes and the ID field will be stored CustomAttribute1 in the full script.

The first line uses the Import-Csv cmdlet to read in the file and then pass it, via the | (pipe), to the ForEach loop.

Import-Csv "Recipients.csv" |
ForEach {
$FullName = $_.FirstName + " " + $_.LastName
Write-Host “Full name: $FullName”
Write-Host "Looking for: $($_.Email)" -ForegroundColor Cyan   }

3)    Detecting if a recipient exists

Now that we have a PS session to O365 and the first line of the CSV ready, we need to see if the recipient existing and then based on its type use the correct cmdlets to update it.

Using the Get-Recipient cmdlet with the Email attribute from the CSV file we can query EXO for a matching recipient. By adding “-ErrorAction SilentlyContinue” we hide the error if one is not found, which makes for a cleaner running script. The $Recipient variable, which is first set to $Null to ensure that the previous value isn’t used, is set by the Get-Recipient cmdlet.

$Recipient = $Null
$Recipient = Get-Recipient $_.Email -ErrorAction SilentlyContinue
If ($Recipient -eq $Null) {
Write-Host "`tRecipient not found, creating" -ForegroundColor Yellow }
Else {
Write-Host `t"Found: $($Recipient.Name)" -ForegroundColor Green }

4)    Updating the properties of an existing recipient

Assuming the recipient exists, we 1st need to find out what type of recipient it is. To do this the script will check the RecipientType property.

There are three RecipientType value, at least supported by this script: MailContact, MailUser, & MailMailbox. A MailContact type is for objects that are mail enable, but do not have a logon and have an external email address. A MailUser is for objects that have been mail enable, with an external email address, but do have a login to O365. Last, MailMailbox is for objects that have an EXO mailbox and O365 login.

For the first two types, the Set-Contact cmdlet is used to set most of the attributes. For MailContact objects, the Set-MailContact cmdlet is used to set the CustomAttribute1 attribute and other Exchange only related attributes. For MailUser objects, Set-MailUser is needed to update the Exchange attributes. For MailMailbox objects, Set-MailMailbox is used to update the Exchange attributes.

Using three IF statements, checking the $Recipient.RecipientType value, the script calls the correct cmdlets to update the attribute. The  -WarningAction 0 parameter is used to hide the yellow warning message when the attribute value doesn’t change, since the value is the same.

If ($Recipient.RecipientType -eq "MailContact") {

Set-Contact $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0
Set-MailContact $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0
}

If ($Recipient.RecipientType -eq "MailUser") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0
Set-MailUser $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0
}

If ($Recipient.RecipientType -eq "MailMailbox") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-MailMailbox $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0
}

5)    Creating a Contact when an existing recipient is not found

The last key part of this script is to create a Contact when a recipient is not found. This is done with the New-MailContact cmdlet, this script only creates Contacts for CSV entries that aren’t found.

Inside a ForEach loop, the current object\entry being processed can be referred to using the $_ object. The cmdlet below sets five attributes to the value in the CSV for the current line being processed.

New-MailContact -Name $FullName -DisplayName $FullName -ExternalEmailAddress $_.Email -FirstName $_.FirstName -LastName $_.LastName

Putting the parts together

There are three major sections of the script, the 1st connects to Office 365, the 2nd is the UpdateRecipient function, and 3rd is the Import-Csv “Recipients.csv” and ForEach loop. The loop in the 3rd part calls the 2nd part for each line in the CSV file.

In the 3rd (Import-Csv “Recipients.csv”) part it queries EXO using the Get-Recipient cmdlet and if one is not found, the New-MailContact cmdlet is used to create a new contact. If the recipient is found or after the New-MailContact cmdlet, the existing or new object and the current value from the CSV file is passed to the UpdateRecipient function.

Below are the key lines from the 3rd section of the script:

Import-Csv "Recipients.csv" |

ForEach {

$Recipient = Get-Recipient $_.Email -ErrorAction SilentlyContinue

If ($Recipient -eq $Null) {

Write-Host "`tRecipient not found, creating" -ForegroundColor Yellow

$FullName = $_.Preferred + " " + $_.LastName

New-MailContact -Name $FullName -DisplayName $FullName -ExternalEmailAddress $_.Email -FirstName $_.FirstName -LastName $_.LastName

$Recipient = Get-Recipient $_.Email

}

Else {

Write-Host `t"Found: $($Recipient.Name)" -ForegroundColor Green

}

UpdateRecipient $Recipient $_

}

 

The 2nd part is the UpdateRecipient function, below is a partial copy of that code.

Function UpdateRecipient ($Recipient, $Properties) {

Write-Host `t"UpdateRecipient: $($Properties.Email)" -ForegroundColor Cyan

$FullName = $Properties.FirstName + " " + $Properties.LastName

 

If ($Recipient.RecipientType -eq "MailContact") {

Set-Contact …

Set-MailContact …

}

If ($Recipient.RecipientType -eq "MailUser") {

Set-User …

Set-MailUser …

}

If ($Recipient.RecipientType -eq "MailMailbox") {

Set-User …

Set-MailMailbox …

}

}

 

Full script


# CSV: FirstName, LastName, Role, Email, Phone, MobilePhone, HomePhone, WorkPhone, Comments, Address, City, State, Zip, ID

 

# CustomAttribute map [EXO = CSV]

# CustomAttribute1 = ID

 

# Connect to Office 365, if not connected

# Requires Azure AD PowerShell Module: https://go.microsoft.com/fwlink/p/?linkid=236297

If (((Get-PSSession | ?{$_.State -Like "*Open*" -And $_.ConfigurationName -Like "*Microsoft.Exchange*"}).Count) -Eq 0) {

$UserCredential= Get-Credential

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

Import-PSSession $Session

connect-msolservice -credential $UserCredential

}

 

Function UpdateRecipient ($Recipient, $Properties) {

Write-Host `t"UpdateRecipient: $($Properties.Email)" -ForegroundColor Cyan

$FullName = $Properties.FirstName + " " + $Properties.LastName

 

If ($Recipient.RecipientType -eq "MailContact") {

Set-Contact $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-Contact $Properties.Email -Phone $Properties.phone -MobilePhone $Properties.mobilephone -HomePhone $Properties.homephone -OtherTelephone $Properties.workphone -WarningAction 0

Set-Contact $Properties.Email -StreetAddress $Properties.address -City $Properties.city -StateOrProvince $Properties.state -PostalCode $Properties.zip -Title $Properties.Title -Notes $Properties.comments -WarningAction 0

Set-MailContact $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0

}

If ($Recipient.RecipientType -eq "MailUser") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-User $Properties.Email -Phone $Properties.phone -MobilePhone $Properties.mobilephone -HomePhone $Properties.homephone -OtherTelephone $Properties.workphone -WarningAction 0

Set-User $Properties.Email -StreetAddress $Properties.address -City $Properties.city -StateOrProvince $Properties.state -PostalCode $Properties.zip -Title $Properties.role -Notes $Properties.comments -WarningAction 0

Set-MailUser $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0

}

If ($Recipient.RecipientType -eq "MailMailbox") {

Set-User $Properties.Email -LastName $Properties.lastname -FirstName $Properties.firstname -DisplayName $FullName -WarningAction 0

Set-User $Properties.Email -Phone $Properties.phone -MobilePhone $Properties.mobilephone -HomePhone $Properties.homephone -OtherTelephone $Properties.workphone -WarningAction 0

Set-User $Properties.Email -StreetAddress $Properties.address -City $Properties.city -StateOrProvince $Properties.state -PostalCode $Properties.zip -Title $Properties.role -Notes $Properties.comments -WarningAction 0

Set-MailMailbox $Properties.Email -CustomAttribute1 $Properties.ID -WarningAction 0

}

}

 

Import-Csv "Recipients.csv" |

ForEach {

$Found = $False

$Recipient = $Null

Write-Host "Looking for: $($_.Email)" -ForegroundColor Cyan

$Recipient = Get-Recipient $_.Email -ErrorAction SilentlyContinue

If ($Recipient -eq $Null) {

Write-Host "`tRecipient not found, creating" -ForegroundColor Yellow

#Create new Contact

$FullName = $_.Preferred + " " + $_.LastName

New-MailContact -Name $FullName -DisplayName $FullName -ExternalEmailAddress $_.Email -FirstName $_.FirstName -LastName $_.LastName

$Recipient = Get-Recipient $_.Email

}

Else {

#Update Recipient

Write-Host `t"Found: $($Recipient.Name)" -ForegroundColor Green

}

UpdateRecipient $Recipient $_

}
Posted in Exchange, O365, Script, Technical | Tagged , , , | Leave a comment

Moderated Messages issues with Exchange Online (EXO) hybrid configurations

I’ve been using Exchange 2016 in a hybrid configuration for a few years now and have a few moderated groups I manage. An issue I ran into with this is that when messages come in for moderation I did not have Accept\Reject buttons coming up in Outlook or in OWA. After some research, I found that some changes were needed both in Exchange 2016 and EXO configs, all of which need to be done with PowerShell.

The issue stems from the approval messages coming in from SystemMailbox{}@.onmicrosoft.com. But the Hybrid configuration wizard only sets up a remote domain entry for .mail.onmicrosoft.com, using the New-RemoteDomain cmdlet. This cmdlet registers and SMTP name space so policies and mail-flow can be controlled for it specifically, via the Set-RemoteDomain cmdlet

You can check your current remote domain list by running: Get-RemoteDomain. This should return a Default\* entry and one for each SMTP domain you are using with EXO. By default these hybrid entries are named “Hybrid Domain – “, you should at least have one called “Hybrid Domain – .mail.onmicrosoft.com” with a DomainName of .mail.onmicrosoft.com.

To fix the issue, so you can Accept\Reject moderated messages you need to do the following on-premises

  1. Create a new remote domain entry for SMTP domain being used to send these messages
New-RemoteDomain -Name "Hybrid Domain - <your tenant>.onmicrosoft.com" -DomainName <your tenant>.onmicrosoft.com
  1. Update the setting for this new RemoteDomain entry to make it a trusted domain
Set-RemoteDomain -Name "Hybrid Domain - <your tenant>.onmicrosoft.com" -IsInternal $true -TargetDeliveryDomain $true -AllowedOOFType InternalLegacy -MeetingForwardNotificationEnabled $true -TrustedMailOutboundEnabled $true -TrustedMailInboundEnabled $true -UseSimpleDisplayName $true -TNEFEnabled $true
  • The value is the short name for DNS domain setup in Office 365 1st, in my case I used izken.onmicrosoft.com

Then you need to do the following to update Exchange Online

  1. Connect to EXO, run the below cmdlet from any PowerShell prompt:
$UserCredential= Get-Credential ; $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $UserCredential -Authentication Basic -AllowRedirection ; Import-PSSession $Session
  1. Create, if they don’t already exist, a RemoteDomain entry for every SMTP domain that may send email to EXO
  • Run Get-AcceptedDomain to check which SMTP domains are setup in EXO if needed

New-RemoteDomain -Name “Hybrid Domain – ” -DomainName

  1. Once your SMTP domains are added, you will need to set them as trusted using the following cmlet
Set-RemoteDomain -Name "Hybrid Domain - <domain name>" -IsInternal $true -TargetDeliveryDomain $true -AllowedOOFType InternalLegacy -MeetingForwardNotificationEnabled $true -TrustedMailOutboundEnabled $true -TrustedMailInboundEnabled $true -UseSimpleDisplayName $true -TNEFEnabled $true

Once the cmdlets are ran above moderated message approval should start working.

In my research, I found this blog post, that covers the same info I did above: http://seanblee.blogspot.com/2014/08/office-365-exchange-online-hybrid.html

Posted in Exchange, Microsoft, O365, Technical | Tagged , | Leave a comment

Exchange Server 2016 “requires .NET Framework 4.5 or later” error

Recently I was trying to address and issue with a corrupted arbitration mailbox. The quick fix for this issue is to delete these mailboxes and the system accounts used by them and run “setup.com /PrepareAD” to recreate them.

When I tried to run: setup /PrepareAD /IAcceptExchangeServerLicenseTerms I was getting this error:

Exchange Server 2016 requires .NET Framework 4.5 or later. Download it from http://go.microsoft.com/fwlink/?LinkId=260991.

I carried out several steps to make sure .NET was installed and working correctly. The system had 4.5.2, 4.6, 4.6.1, & 4.6.2 on it. But Exchange was running 2016 CU3 on Windows 2012 R2, which only supports 4.6.1.

FIX: For the.NET 4.5 error was to upgrade Exchange 2016 to CU4. After upgrading the servers, the SETUP command now runs fine.

.NET 4.6.1 was not supported on Exchange 2013/2016 until CU13/2, article on the lack of support initially. The June 2016 updates officially added support for 4.6.1. The September 2016 updates, CU14/3, did add support for 4.6.2, but ONLY on Windows 2016. The December 2016 updates, CU 15/4, finally add support for 4.6.2 on Windows 2012 R2.

 

Posted in Microsoft, Technical | Tagged , | Leave a comment