Category Archives: Exchange

Event ID 1 MSExchange Autodiscover

Recently I had to install an Exchange 2016 CU16 server as part of an Exchange 2010 migration project. When the server was running as I started moving mailboxes to it, I noticed an increasing number (linear to the number of users it seems) of event ID 1 MSExchange Autodiscover errors in the Application Eventlog of the server:

Event ID 1 MSExchange Autodiscover

Unhandled Exception “Object reference not set to an instance of an object.”
Stack trace: at Microsoft.Exchange.AutoDiscoverV2.FlightSettingRepository.
GetHostNameFromVdir(ADObjectId serverSiteId, String protocol) at Microsoft.Exchange.AutoDiscoverV2. AutoDiscoverV2.ExecuteOnPremEndFlow(AutoDiscoverV2Request request)
at Microsoft.Exchange.AutoDiscoverV2.AutoDiscoverV2.Execute (AutoDiscoverV2Request request, ITenantRepository tenantRepository) at Microsoft.Exchange.AutoDiscoverV2.AutoDiscoverV2HandlerBase.<>c__DisplayClass11_0.b__0() at Microsoft.Exchange.Common.IL.ILUtil.DoTryFilterCatch(Action tryDelegate, Func`2 filterDelegate, Action`1 catchDelegate)

This issue was resolved in Exchange 2016 CU15 en Exchange 2019 CU4, but occasionally pops up in newer versions, and unfortunately on my Exchange 2016 CU16 server.

Although I don’t know the cause of this the workaround is simple. Set the ExternalURL property of the Autodiscover virtual directory, like this:

Get-AutodiscoverVirtualDirectory -Server | Set-AutodiscoverVirtualDirectory -ExternalUrl https://autodiscover.contoso.com/Autodiscover/Autodiscover.xml

This was (is) a known issue at Microsoft and I brought this again to their attention. When something develops, I’ll update this blogpost.

Microsoft Teams and Exchange 2016

Microsoft Teams works best when your mailbox is in Exchange Online, and you have a license for SharePoint Online, and you have OneDrive for Business enabled.

When you have your mailbox in Exchange on-premises your options are limited, you have basic Teams functionality like audio/video and files, but that’s basically it. Not a trace of the calendar or the option to manage meetings in Teams. This is what ‘cloud partners’ have been telling me for a long time: “no, you must migrate your mailbox to Exchange Online” (and we can help you with that I was they were thinking…)

Teams with Exchange on-premises

But, if you have Exchange 2016 CU3 or higher things get better (I’m sorry if you are still running Exchange 2010). To enable the integration of Teams with on-premises Exchange 2016 you need to configure OAuth in your on-premises environment as outlined in my previous blog, and assuming you have Exchange hybrid configured of course.

When you have OAuth configured, Teams can access the on-premises mailbox on behalf of the user that’s logged on in Teams, making it possible to retrieve the user’s calendar. After configuring OAuth and without any additional configuration in Teams the user’s on-premises calendar (here in Exchange 2019) automagically appears:

Teams with Exchange on-premises OAuth

In the Teams client this is a view of your calendar, and using the new meeting option you can create new Teams meetings, invite people, set recurrence, select a channel etc. Invites are sent to other recipients using the regular Exchange process, and when accepted a response is sent (or not) back to your inbox. I never knew this was possible, but this is cool stuff.

Teams with Exchange on-premises new meeting

Integrating the calendar into Teams is a nice addition and it can help users with their daily productivity task. From a compliance perspective things are a bit different. Chats for example are not stored in the user’s mailbox, this is only possible for mailboxes in Exchange Online. The process responsible for copying Teams chat data from the Azure storage (outside of Office 365) simply cannot access the folder in the user’s mailbox.

But, for on-premises calendar integration in your Teams environment this is very nice.

More information

How Exchange and Microsoft Teams interact – https://docs.microsoft.com/en-us/microsoftteams/exchange-teams-interact

Configure OAuth authentication between Exchange and Exchange Online organizations – https://docs.microsoft.com/en-us/exchange/configure-oauth-authentication-between-exchange-and-exchange-online-organizations-exchange-2013-help

 

Configure OAuth authentication in Exchange 2016

As long as I can remember the Hybrid Configuration Wizard finishes successfully, and itgenerates the error about the OAuth portion of the hybrid configuration.

Configure Intra-Organization Connector

HCW8064 – The HCW has completed, but was not able to perform the OAuth portion of your Hybrid configuration. If you need features that rely on OAuth, you can try running the HCW again or manually configure OAuth using these manual steps.

The Learn more option redirects to the Microsoft page Configure OAuth authentication between Exchange and Exchange Online organizations. I used that article for the PowerShell commands in this blogpost.

OAuth is used cross-premises to logon to other services, on behalf of the user. So, if you are logged on to some Microsoft service, this service can use OAuth to access services in Exchange on-premises and vice versa.

Example of these cross-premises services are:

  • Message Records Management (MRM).
  • Exchange in-place eDiscovery.
  • Exchange in-place Archiving.
  • Teams calendaring.

The HCW can configure Azure Active Directory for OAuth authentication, it can create the IntraOrganizationConnectors, but it cannot export and import the (self-signed) certificate on the Exchange server, nor can it (or does it) create the authorization server objects in Active Directory. So, time to test, guided by the Microsoft article and write down my experiences.

Note. This only works for Exchange 2013 and higher, I have been working on this in a mixed Exchange 2016 and Exchange 2019 environment.

Configuring OAuth between Office 365 and Exchange Online involve a number of steps.

Create Authorization server objects in Exchange on-premises

To create the authorization server objects in your on-premises environment enter the following commands in the Exchange Management Shell.

New-AuthServer -Name "WindowsAzureACS" -AuthMetadataUrl "https://accounts.accesscontrol.windows.net/contoso.com/metadata/json/1"
New-AuthServer -Name "evoSTS" -Type AzureAD -AuthMetadataUrl https://login.windows.net/contoso.com/federationmetadata/2007-06/federationmetadata.xml

Your verified domain contoso.com (in the command) should be something like exchangelabs.nl, and not <your tenant name> as outlined in the Microsoft article.

New-AuthServer

Enable the partner application for use with Exchange Online

The partner application was created in the previous step (the first command) and this should be enabled. Do this using the following command in Exchange Management Shell (on-premises):

Get-PartnerApplication | ?{$_.ApplicationIdentifier -eq "00000002-0000-0ff1-ce00-000000000000" -and $_.Realm -eq ""} | Set-PartnerApplication -Enabled $true

Export the Exchange authorization certificate

Authentication cross-premises is using certificates, so the on-premises certificate needs to be exported to Azure Active Directory. In case you were wondering where the CN=Microsoft Exchange Server Auth Certificate certificate was coming from when running the Get-ExchangeCertificate command in Exchange Management Shell, here you go.

Use the following PowerShell commands and store them in a PowerShell script called ExportAuthCert.ps1 or something and run it. This should export the OAuth certificate to a file called OAuthCert.cer.

$ThumbPrint = (Get-AuthConfig).CurrentCertificateThumbprint
If((Test-Path $ENV:SYSTEMDRIVE\OAuthConfig) -eq $false)
{
md $ENV:SYSTEMDRIVE\OAuthConfig
}
CD $ENV:SYSTEMDRIVE\OAuthConfig
$oAuthCert = (dir Cert:\LocalMachine\My) | ?{$_.ThumbPrint -Match $ThumbPrint}
$CertType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert
$CertBytes = $oAuthCert.Export($CertType)
$CertFile = "$env:SYSTEMDRIVE\OAuthConfig\OAuthCert.cer"
[System.IO.File]::WriteAllBytes($CertFile, $CertBytes)

ExportAuthCert

Note. The Export-ExchangeCertificate command doesn’t work in this scenario since the self-signed certificate isn’t exportable.

Import the Exchange authorization certificate into Azure AD

The next step is to import the OAuthCert.cer certificate into Azure AD. Connect to the Microsoft Online service (Connect-MSOLService, if you don’t have this installed you can use the Install-Module MSOnline command) and run the following commands when connected:

$Cred = Get-Credential
Connect-MSOLService -Credential $Cred
$CertFile = "$ENV:SYSTEMDRIVE\OAuthConfig\OAuthCert.cer"
$objFSO = New-Object -ComObject Scripting.FileSystemObject
$CertFile = $objFSO.GetAbsolutePathName($CertFile)
$CER = New-Object System.Security.Cryptography.X509Certificates.X509Certificate
$CER.Import($CertFile)
$binCert = $cer.GetRawCertData()
$CredValue = [System.Convert]::ToBase64String($binCert)
$ServiceName = "00000002-0000-0ff1-ce00-000000000000"
$P = Get-MsolServicePrincipal -ServicePrincipalName $ServiceName
New-MsolServicePrincipalCredential -AppPrincipalId $P.AppPrincipalId -Type asymmetric -Usage Verify -Value $credValue

This will import the self-signed certificate from the Exchange server into Azure AD so it can be used for mutual authentication.

I did not run the commands mentioned above on my Exchange server but on my Azure AD Connect server since the MSOL module was loaded on that server. For importing the certificate file I had to use the following command accessing the certificate file (instead of the $ENV:System variable):

$CertFile = "\\AMS-EXCH01\C$\OAuthConfig\OAuthCert.cer"

Register endpoints in Azure Active Directory

The last step is to register the endpoints of your on-premises Exchange environment into Azure Active Directory. You can use the following commands to register the endpoints:

$ServiceName = "00000002-0000-0ff1-ce00-000000000000";
$x = Get-MsolServicePrincipal -AppPrincipalId $ServiceName;
$x.ServicePrincipalnames.Add("https://webmail.exchangeserver.com/");
$x.ServicePrincipalnames.Add("https://autodiscover.exchangeserver.com/");
Set-MSOLServicePrincipal -AppPrincipalId $ServiceName -ServicePrincipalNames $x.ServicePrincipalNames;

Instead of webmail.exchangeserver.com and Autodiscover.exchangeserver.com you must use your own local FQDNs of the Exchange server (shown below in the verification screenshot).

You can use the the following command to check if this was configured correctly.

Get-MsolServicePrincipal -AppPrincipalId 00000002-0000-0ff1-ce00-000000000000 | select -ExpandProperty ServicePrincipalNames

As shown in the following screenshot:

Register Endpoints

Note. Over the years I have run the HCW several times. Domains have been added, but not (automatically) deleted in Azure Active Directory.

IntraOrganizationConnectors and AvailabilityAddressSpace

The Hybrid Configuration Wizard created the IntraOrganizationConnectors (both in Exchange 2016 as well as Exchange Online) and configured the AvailabilityAddressSpace. There’s no need to create these, but you have to check them using the Get-IntraOrganizationConnector and the Get-AvailabilityAddressSpace commands)

Verify the OAuth configuration

To verify the OAuth configuration you can use the Test-OAuthConnectivity command. You must do this on the on-premises Exchange server and in Exchange Online.

On the on-premises Exchange server use the Exchange Online Uri and a mailbox on-premises:

Test-OAuthConnectivity -Service EWS -TargetUri https://outlook.office365.com/ews/exchange.asmx -Mailbox onprem-user@exchangeserver.com -Verbose | Format-List

In Exchange Online, use the Exchange on-premises Uri with a mailbox in Exchange Online:

Test-OAuthConnectivity -Service EWS -TargetUri https://webmail.exchangeserver.com/metadata/json/1 -Mailbox Online-User@exchangeserver.com -Verbose | Format-List

The output is an extended list, but in the end you should see ResultType: Success and IsValid:True on your console:

Test-OAuthConnectivity

You have now configured the OAuth between Exchange Online and Exchange On-Premises.

 

Sender Domain Validation check in Exchange Online

In my previous blog External Senders with matching display names I explained a Transport Rule that checked for matching display names in order to prevent phishing and possible CFO Fraud.

Another interesting solution with Transport Rules is displaying a warning message when the sender’s domain could not be validated. For example, when a message from a sender who’s SPF record is missing or not valid, it would show something like “The sender of this message could not be validated and may not be the actual sender” as shown in the following screenshot.

In this example the SPF record of the exchangefun.nl domain was missing, hence the validation error.

  • The Transport Rule to achieve this is built on two conditions:
  • The sender is located outside the organization.

The Authentication-Results headers contains one or more of the following entries:

  • dkim=fail
  • spf=TempError
  • spf=PermError
  • spf=SoftFail
  • spf=Fail
  • spf=None

For the email mentioned below, the Authentication-Results header shows the following:

Authentication-Results: spf=none (sender IP is 176.62.196.243)
smtp.mailfrom=exchangefun.nl; wesselius.info; dkim=pass (signature was verified) header.d=Exchangefun.nl;wesselius.info; dmarc=permerror action=none header.from=exchangefun.nl;compauth=pass reason=105

Obviously, it fails on the spf=none entry.

To create a Transport Rule to do this, open the Exchange Online Admin Center and navigate to Rules under Mail Flow and click Add New Rule (the + icon). Use the More Options to add additional conditions to the Transport Rule.

The first condition is The sender is located and select outside the organization. The second condition is A message header includes and enter Authentication-Results for the name of the header and the DKIM and SPF entries mentioned earlier in the text of the message header. It should show something like this:

Click on Add Action and select Prepend a disclaimer. Enter a warning message like:

Warning: The sender of this message could not be validated and may not be the actual sender.

The text can be plain text or HTML formatted as shown in the following screenshot:

When you click Save the Transport Rule is saved in Exchange Online. It could take up to an hour to become effective. And when you receive a message where the domain validation failed a disclaimer is prepended to the email message:

Now you can look in the message header itself to figure out why validation failed. Hopefully this will give a heads-up to users there’s something wrong with the message (but it still can be legitimate message of course).

A special and warm thanks to my fellow MVP Michel de Rooij for his inspiration to write this blog 😉

 

External Senders with matching Display Names

One of my clients is experiencing phishing from where the external senders use a display name of one of the board members. An IT admin looks at the complete email address, but regular users are tempted to only look at the display name and will respond to the message. This way CEO/CFO fraud easily happens.

To avoid this, we can create a Transport Rule in Exchange Online that identifies external email with display names of internal recipients. So, when someone on the internet with a name like my name, a disclaimer is prepended to the message. This way recipients always know it is not an internal message and it will look something like this:

To create a transport rule there are two conditions:

  • Sender is located outside the organization.
  • From message header matches one or more internal display names.

If these conditions are met, a warning message is prepended to the email message.

Open the Exchange Admin Console and navigate to Rules under Mail flow. Create a new rule (use the More Options to add additional conditions. Select the external sender option and select the message headers matches option. Enter the ‘From’ header enter the display names as shown in the following screenshot:

In the Do the following… dropdown box select prepend the disclaimer option and enter a warning message, something like:

This message was sent from outside the company by someone with a display name matching a user in your organization. Please do not click links or open attachments unless you recognize the source of this email and know the content is safe.

You can use plain text or HTML formatting like I did:

When you click save the transport rule is saved, but it can take an hour before it becomes effective. When a new message arrives from someone with a similar display name a warning message is added to the email message.

Hopefully this will alert users that the email is not an internal message but comes from the Internet (but it can still be a valid message of course)