Copy Links and Backlinks Between Users and Shared Mailboxes (automapping)

Posted on 1 CommentPosted in cross-forest, Exchange Server, mailbox, migration, msExchDelegateListBL, msExchDelegateListLink, shared mailbox

Automap for shared mailboxes does not work across forests when moving mailboxes.

When the user is granted permission to a shared mailbox, the default behaviour of automapping means that the shared mailbox has msExchDelegateListLink set to the DN of the user, and the backlink (hidden in AD by default) on the user is populated with the DN of the shared mailbox. Whenever the link attribute is updated, the backlink is automatically updated as well. For more on back links see https://neroblanco.co.uk/2015/07/links-and-backlinks-in-active-directory-for-exchange/

That is, is UserMailbox is granted full access to SharedMailbox you will see the following in Active Directory (Advanced View) > Attribute Editor > msExchDelegateListLink = “CN=UserMailbox,OU=etc” (on the SharedMailbox). And for the UserMailbox in Active Directory (Advanced View) > Attribute Editor > msExchDelegateListBL = “CN=SharedMailbox,OU=etc”.

When you migrate mailboxes across forests you make use of Prepare-MoveRequest.ps1 to copy all the attributes. The msExchDelegateListLink is not part of this attribute set and the msExchDelegateListBL is auto populated so we can ignore it for now – if msExchDelegateListLink was copied and updated to the new forest name, then msExchDelegateListBL would be filled in automatically.

So how do we copy the msExchDelegateListLink value for each user and then write it to the mail user object in the target forest before the mailbox is migrated (or if you have already done your migration and found this property missing and so automapping of shared mailboxes having failed (though the permissions have been copied fine), how can you grab the data from the old source forest and apply it to the mailboxes in the target?

Using PowerShell and the ActiveDirectory module is how.

First you need to export a list of all the automapped shared mailboxes each user has (this is the msExchDelegateListBL values for the user mailboxes you have migrated). There are two cmdlets to run here, the first does the entire source directory and the second filters the output to an OU and its child OU’s (so you can export a subset of data) using SearchBase. Only one of these two cmdlets is needed.

This code is PowerShell and needs to be run from any domain joined computer.

Import-Module ActiveDirectory
Get-ADUser -Properties msExchDelegateListBL,msExchDelegateListLink -LDAPFilter "(msExchDelegateListBL=*)" | Select name,DistinguishedName,@{Name='SharedMailbox';Expression={$_.msExchDelegateListBL -Join ";"}} | Export-csv automap-userlist.csv -NoTypeInformation -NoClobber -Encoding UTF8
Get-ADUser -Properties msExchDelegateListBL,msExchDelegateListLink -LDAPFilter "(msExchDelegateListBL=*)" -SearchBase 'OU=Sales,DC=domain,DC=local' | Select name,DistinguishedName,@{Name='SharedMailbox';Expression={$_.msExchDelegateListBL -Join ";"}} | Export-CSV automap-userlist.csv -NoTypeInformation -NoClobber -Encoding UTF8

These cmdlets return a CSV file listing each mailbox that has an automapping to a shared mailbox and what that shared mailbox is.

The CSV file then needs copying to the target AD forest, and as the target forest is very unlikely to contain the same OU structure and domain names, the DN of each object in the CSV file needs updating. This can be done with Find/Replace in Excel or Notepad quite easily.

For example, in a CSV I might see:

“name”,”Distinguishedname”,”SharedMailbox”

“First User”,”CN=First User,OU=Sales,DC=domain,DC=local”,”CN=SharedMailbox,CN=Users,DC=domain,DC=local CN=AnotherSharedMailbox,OU=Shared Mailboxes,OU=Exchange,DC=domain,DC=local”

“Second User”,”CN=Second User,CN=Users,DC=domain,DC=local”,”CN=Sales,OU=Shared Mailboxes,OU=Exchange,DC=domain,DC=local”

In this I have the DN of the mailbox and the DN of the shared mailbox in the source forest. Use Find and Replace to change all the source DN’s (or the OU/DC bits) to suit the location of the matching object in the target forest. For example, my above “second user” was as shown, but after updating the DN might be “CN=Second User,OU=Migrated,DC=target,DC=forest”. So in that case I find/replace “CN=Users,DC=domain,DC=local” for “OU=Migrated,DC=target,DC=forest”.

For my examples that follow on from here, I have saved the edited CSV file as automap-userlist-target-dn-updated.csv

Once I have the CSV file updated for the values in the target forest, I need to split each row where a user has more than one shared mailbox listed into multiple rows. This is simple with PowerShell:

Import-Csv -Path automap-userlist-target-dn-updated.csv |
% {$row = $_; $_.SharedMailbox.split(";")} |
% {$row.SharedMailbox=$_; $row} |
Export-Csv automap-userlist-target-dn-updated-split.csv -NoClobber -NoTypeInformation -Encoding UTF8

Now that I have a row in the CSV for each Shared Mailbox to User Mailbox mapping, I can set the msExchDelegateListLink value on each shared mailbox for the DN of the user that has access to it. This will update the msExchDelegateListBL on the user object automatically.

Import-Module ActiveDirectory
Import-CSV "automap-userlist-target-dn-updated-split.csv" | % {
Write-Host Add $_.DistinguishedName to $_.SharedMailbox
Get-ADUser -identity $_.SharedMailbox | Set-ADUser -Add @{msExchDelegateListlink=$_.DistinguishedName} 
}

In terms of errors in the above, if you get “get-aduser : Directory object not found” then the DN value for the Shared Mailbox is wrong, and if you see “set-aduser : The name reference is invalid” then the DN value for the user who has access to the shared mailbox is wrong (the DistinguishedName column in the CSV). The script can be run multiple times, so you are safe to fix the CSV file and import the entire list again. It will only add a given DN once in total per shared mailbox.

If your target (or source) forest has more than one domain, run the script from a server in the correct domain or use “-Server DC-name” in both the Get-ADUser and the Set-ADUser cmdlets.

Outbound Email Via Exchange Online Protection When Using Hybrid Exchange Online

Posted on 1 CommentPosted in dmarc, EOP, exchange, exchange online, Exchange Online Protection, Exchange Server, hybrid, mailbox, spf

In a long term hybrid scenario, where you have Exchange Online and Exchange Server configured and mailboxes on both, internet bound email from your on-premises servers can route in two general ways.

The first is outbound via whatever you had in place before you moved to Office 365. You might have configured Exchange Online to also route via this as well.

The second is to route Exchange Server outbound emails via Exchange Online Protection. Your Exchange Online configuration does not need to be adjusted for this to work, as the default route for all domains to the internet (or the * address space as it is known) is via EOP as long as you create no alternative outbound connector for *.

This blog post looks at configuring Exchange Server so that your on-premises mailboxes also route out via Exchange Online Protection, and does it without changing the connectors made by the hybrid wizard. If you change the hybrid wizard connectors and then run the wizard again, it will reset things to how it wants them to be, which will remove your configuration changes.

This configuration setup results in a single new send connector created on-premises in Exchange Server (or one connector per site is you route emails from more than one Active Directory site). This new connector is not the Outbound to Office 365 connector that the hybrid wizard creates and so changes here do not break hybrid and changes to the hybrid wizard do not impact outbound mail flow.

This blog post also assumes you already have a working route outbound for all internet emails and you are swapping over to outbound via EOP, so these steps work though ensuring that is correct and will work before changing the route for *.

Examine the hybrid send connector to Office 365

[PS] C:\ExchangeScripts\pfToO365>Get-SendConnector out* | fl

AddressSpaces:                  {smtp:domainuk.mail.onmicrosoft.com;1}
AuthenticationCredential :
CloudServicesMailEnabled :      True
Comment : ConnectedDomains :    {}
ConnectionInactivityTimeOut :   00:10:00
DNSRoutingEnabled :             True
DomainSecureEnabled :           False
Enabled :                       True
ErrorPolicies :                 Default
ForceHELO :                     False
Fqdn :                          mail.domain.uk
FrontendProxyEnabled : 	        False
HomeMTA :                       Microsoft MTA
HomeMtaServerId :               SERVER01
Identity :                      Outbound to Office 365
IgnoreSTARTTLS :                False
IsScopedConnector :             False
IsSmtpConnector :               True
MaxMessageSize :                35 MB (36,700,160 bytes)
Name :                          Outbound to Office 365
Port :                          25
ProtocolLoggingLevel :          None
RequireOorg :                   False
RequireTLS :                    True
SmartHostAuthMechanism :        None
SmartHosts :                    {}
SmartHostsString :
SmtpMaxMessagesPerConnection :  20
SourceIPAddress :               0.0.0.0
SourceRoutingGroup :            Exchange Routing Group (DWBGZMFD01QNBJR)
SourceTransportServers :        {SERVER02, SERVER01}
TlsAuthLevel :                  DomainValidation
TlsCertificateName :            <I>CN=GlobalSign Organization Validation CA - SHA256 - G2, O=GlobalSign 
                                nv-sa, C=BE;<S>CN=*.domain.uk, O=Acme Limited, L=London, S=London, C=GB
TlsDomain :                     mail.protection.outlook.com
UseExternalDNSServersEnabled :  False

The above PowerShell from the on-premises Exchange Management Shell shows you the hybrid send connector. As you can see this is set to route emails only for your hybrid address space (domainuk.mail.onmicrosoft.com in this example)

The other important attributes for EOP mail flow here are AddressSpaces, CloudServicesMailEnabled, DNSRoutingEnabled, Fqdn, RequireTLS, SmartHosts, and TLSAuthLevel. Setting these correctly on a new send connector will allow you to route other domains to EOP and then onward to the internet.

Create a new send connector

This blog is based upon information found in https://technet.microsoft.com/en-us/library/dn751020(v=exchg.150).aspx but it differs from the scenario described there within. In this scenario, as you have already run the hybrid wizard, the connector to the cloud from on-premises and from the cloud to your servers already exists. Therefore all we need to do is create an additional send connector on-premises to route all the other domains to EOP and the internet.

New-SendConnector -Name <DescriptiveName> -AddressSpaces testdomain1.com,testdomain2.com -CloudServicesMailEnabled $true -Fqdn <CertificateHostNameValue> -RequireTLS $true -DNSRoutingEnabled $false -SmartHosts <YourDomain_MX_Value> -TlsAuthLevel  CertificateValidation -Usage Internet

In the above, the connector is originally created being able to route for two test domains (written as testdomainx.com above, comma separated in the list with no spaces). This ensures that you do not break your existing mail flow but allows you to test that the connector works and then later change the connector to support * address space. The “YourDomain_MX_Prefix” is the same value as you would use in your MX to route emails to Exchange Online (tenant-prefix-com.mail.protection.outlook.com for example).

Testing the connector

In the above new send connector, testdomain1.com is a domain hosted in a different Office 365 tenant. Testdomain2.com is a domain who’s email is not hosted in Office 365 at all. You need both test scenarios, as routing to domains inside Office 365 is more likely to work if the connector is not configured properly.

So from a mailbox on-premises, send an email to a recipient at both testdomain1.com and testdomain2.com. Do not set the connector up to use gmail or Outlook.com, as that will impact other senders within your organization. Use domains that no one else is likely to want to email.

Ensure that you do not get any NDR’s and check the recipient mailboxes to ensure delivery. Note that you are possibly likely to need to update your SPF record for the sending domain to additionally include the following:

  • include:spf.protection.outlook.com
  • ipv4:w.x.y.z (where w.x.y.z is the external IP address(es) of your on-premises Exchange transport servers)

Updating the connector

Once your mail flow tests work, and you can check the route by pasting the received message headers into http://exrca.com you should see that email routes into your Office 365 tenant, then leave EOP (the word “outbound” will be in one of the FQDNs – this server is on the external edge of EOP), then routed inbound to your email provider (or back into your recipient tenant).

Once mail flow works, you can either add more recipient domains to increase the scope of the test – for example add a domain that you email occasionally, such as the partner helping you with this work and a few other domains. Once all your testing is ready change this connector to have * as the address space and not list specific domains.

As your other connector for * is still up and running you will find that 50% of your email will use the new connector and 50% the old. Then you can disable the old connector to go 100% email outbound through EOP (you need an EOP licence per sender to do this, or if you have an Exchange Online licence for each user you are already covered).

Finally when you have been routing on-premises email through EOP for a few weeks with the old connector disabled, you can delete the old connector and tidy up the configuration rather than leaving disabled connectors around.

Duplicate Exchange Online and Exchange Server Mailboxes

Posted on 4 CommentsPosted in duplicate, EOP, exchange, exchange online, Exchange Online Protection, Exchange Server, mailbox, MX, Office 365

With a hybrid Exchange Online deployment, where you have Exchange Server on-premises and Exchange Online configured in the cloud, and utilising AADConnect to synchronize the directory, you should never find that a synced user object is configured as both a mailbox in the cloud and a mailbox on-premises.

When Active Directory is synced to Azure Active Directory, the ExchangeGUID attribute for the on-premises user is synced to the cloud (assuming that you have not do a limited attribute sync and not synced the Exchange attributes – as that is required for Exchange Online hybrid). The Exchange Online directory takes a sync of information relating to Exchange from Azure Active Directory (Azure AD), which is known as forward sync. This ensures that the ExchangeGUID attribute from the on-premises mailbox is synced into your Exchange Online directory.

When a user is given an Exchange Online licence, it becomes the job of Exchange Online to provision a mailbox for this user. When Exchange Online needs to provision a new mailbox, it will not do so where the ExchangeGUID attribute already exists. The existence of this attribute tells the provisioning process that the mailbox already exists on-premises and will be migrated here later and so not to create a conflicting mailbox. A cloud user who does not have an ExchangeGUID attribute synced from on-premises will get a mailbox created by the Exchange Online provisioning process upon a licence being assigned, and on-premises users that do not have a mailbox on-premises (who also have no ExchangeGUID attribute) will also find that granting them an Exchange Online licence will trigger the creation of a mailbox for them.

This is all well and good, and the above is what happens in most cases. But there is an edge case where an on-premises user with a mailbox (and therefore has the ExchangeGUID attribute populated) will also get a mailbox in Exchange Online. This happens where the organization manually created cloud mailboxes before enabling AADConnect to sync the directories, and these cloud users match the on-premises user by UserPrincipalName and they are given an Exchange Online licence.

In this above case, because they are cloud users with an Exchange Online licence they get a mailbox. Deleting the cloud user and then enabling sync will cause the original mailbox to be restored to the user account as the UserPrincipalName matches.

For example, the below shows a user being created in the cloud called “twomailboxes@domain.com”:

image

The user is granted a full Office 365 E3 licence, so this means the user has an Exchange Online mailbox. There is no AADConnect sync in place, but the UPN matches a user on-premises who has a mailbox.

In Exchange Online PowerShell, once the mailbox is provisioned we can see the following:

image

PS> get-mailbox twomailboxes | fl name,userprincipalname,exchangeguid



Name              : twomailboxes
UserPrincipalName : twomailboxes@domain.com
ExchangeGuid      : d893372b-bfe0-4833-9905-eb497bb81de4

Repeating the same on-premises will show a separate user (remember, no AD sync in place at this time) with the same UPN and a different ExchangeGUID.

image

[PS] >get-mailbox twomailboxes | fl name,userprincipalname,exchangeguid



Name              : Two Mailboxes
UserPrincipalName : twomailboxes@cwh.org.uk
ExchangeGuid      : 625d70aa-82ed-47a2-afa2-d3c091d149aa

Note that the on-premises object ExchangeGUID is not the same as the cloud ExchangeGUID. This is because there are two seperate mailboxes.

Get-User in the cloud will also report something useful. It will show the “PreviousRecipientTypeDetails” value, which is not modifiable by the administrator, in this case shows there was not a previous mailbox for the user but this can show that a previous mailbox did exist. For completion we also show the licence state:

image

PS > get-user twomailboxes | fl name,recipienttype,previousrecipienttypedetails,*sku*



Name                         : twomailboxes
RecipientType                : UserMailbox
PreviousRecipientTypeDetails : None
SKUAssigned                  : True

Now in preparation for the sync of the Active Directory to Azure Active Directory, the user accounts in the cloud are either left in place (and so sync will do a soft-match for those users) or they are deleted and the on-premises user account syncs to the cloud. In the first case, the clash on the sync will result in the cloud mailbox being merged into the settings from the on-premises mailbox. In the second case, there is no user account to merge into, but there is a mailbox to restore against this user. And even though the newly synced user has an ExchangeGUID attribute on-premises that is synced to the cloud, and they have a valid licence, Exchange Online reattaches the old mailbox associated with a different GUID.

The impact of this is minor to massive. In the scenario where MX points to on-premises and you have not yet moved any mailboxes to the cloud, this cloud mailbox will only get email from other cloud mailboxes in your tenant (there are none in this scenario) or internal alerts in Office 365 (and these are reducing over time, as they start to follow correct routing). It can be a major issue though if you use MX to Exchange Online Protection. As there is now a mailbox in the cloud for a user on-premises, inbound internet sourced email for your on-premises user will get delivered to the cloud mailbox and not appear on-premises. Where the invalid mailbox has no email, recovery is not required. Finally, where there is a duplicate mailbox, move requests for those users for onboarding to Exchange Online will fail:

image

This reads “a subscription for the migration user <email> couldn’t be loaded”. This occurs where the user was not licenced and so there was not a duplicate mailbox in the cloud, but the user was later licenced before the migration completed.

Where the invalid duplicate mailbox exists in the cloud and is getting valid emails delivered to it, the recovery work described below additionally will involve exporting email from this invalid mailbox and then removing the mailbox as part of the fix. Extraction of email from the duplicate mailbox needs to happen before the licence is removed.

To remove the cloud mailbox and to stop it being recreated, you need to ensure that the synced user does not have an Exchange Online licence. You can grant them other licences in Office 365, but not Exchange Online. I have noticed that if you do licencing via Azure AD group based licencing rules then this will also fail (these are still in preview at time of writing) and that you need to ensure that the user is assigned the licence directly in the Office 365 portal and that they do not get the Exchange Online licence. After licence reconciliation in the cloud occurs (a few minutes typically) the duplicate mailbox is removed (though I have seen this take a few hours). The Get-User cmdlet above will show the RecipientType being a MailUser and not Mailbox.

You are now in a position where your duplicate cloud mailbox is gone (which is why if that mailbox had been a target to valid emails before now, you would need to have extracted the data via discovery and search processes first).

Running the above Get-User and Get-Mailbox (and now Get-MailUser) cmdlets in the cloud will show you that the ExchangeGUID on the cloud object now matches the on-premises object and the duplication is gone. You can now migrate that mailbox to the cloud successfully.

We can take a look at what we see in remote PowerShell here:

Recall from above that there were two different ExchangeGUIDs, one in the cloud and one on-premises. These in my example where:

Cloud duplicate ExchangeGuid      : d893372b-bfe0-4833-9905-eb497bb81de4

On-premises mailbox ExchangeGuid  : 625d70aa-82ed-47a2-afa2-d3c091d149aa

Get-User before licences removed in the cloud, showing a mailbox and that it was previously a mailbox as well:

image

PS > get-user twomailboxes | fl name,recipienttype,previousrecipienttypedetails,*sku*



Name                         : Two Mailboxes
RecipientType                : UserMailbox
PreviousRecipientTypeDetails : UserMailbox
SKUAssigned                  : True

Get-Mailbox in the cloud showing the GUID was different from on-premises:

image

PS > get-mailbox twomailboxes | fl name,userprincipalname,exchangeguid



Name              : Two Mailboxes
UserPrincipalName :
twomailboxes@domain.com

ExchangeGuid      : d893372b-bfe0-4833-9905-eb497bb81de4

Once the licence is removed in Office 365 for Exchange Online and licence reconciliation completes (SKUAssigned is False) you will see that Get-User shows it is not a mailbox anymore:

image

PS > get-user twomailboxes | fl name,recipienttype,previousrecipienttypedetails,*sku*



Name                         : Two Mailboxes
RecipientType                : MailUser
PreviousRecipientTypeDetails : UserMailbox
SKUAssigned                  : False

And finally Get-MailUser (not Get-Mailbox now) shows the ExchangeGUID matches the on-premises, synced, ExchangeGUID value:

image

PS > get-mailuser twomailboxes | fl name,userprincipalname,exchangeguid



Name              : Two Mailboxes
UserPrincipalName : twomailboxes@domain.com
ExchangeGuid      : 625d70aa-82ed-47a2-afa2-d3c091d149aa

Note that giving these users back their Exchange Online licence will revert all of the above and restore their old mailbox. As these users cannot have an Exchange Online licence assigned in the cloud, for risk of their old mailbox returning you need to ensure that within 30 days of their on-premises mailbox being migrated to the cloud you do give then an Exchange Online mailbox. Giving them a licence after migration of their on-premises mailbox to the cloud will ensure their single, migrated, mailbox remains in Exchange Online. But giving their user a licence before migration will restore their old cloud mailbox.

For users that never had a matching UPN in the cloud and a cloud mailbox, you can licence them before you migrate their mailbox as they will work correctly within the provisioning system in Exchange Online.