Quantcast
Channel: Tim McMichael
Viewing all 161 articles
Browse latest View live

Office 365: Start-ManagedFolderAssistant in Office 365

$
0
0

In Office 365 administrators can invoke the managed folder assistant by using the start-ManagedFolderAssistance command.

 

PS C:\> Start-ManagedFolderAssistant tmcmichael@domain.com

 

This week I had a customer present with an issue where the invocation of the managed folder assistance was failing with a generic RPC error.

 

“The call to Mailbox Assistance Service on server: ‘NAME’ failed.  Error from RPC is –2147220989”

 

When this error is encountered subsequent retries of the same command can be successful.

 

The error can sometimes occur as portions of mailboxes are being initialized within the service.  For example - if a secondary archive is being provisioned off a main archive.

 

As a potential workaround to this issue the primary mailbox GUID can be specified in the start-ManagedFolderAssistant command. 

 

get-mailboxLocation –user tmcmichael@domain.com | fl mailboxGuid,mailboxLocationType

 

MailboxGuid         : aace1f4e-5181-4855-a0c7-466f1fe2f1d1

MailboxLocationType : Primary

MailboxGuid         : c2098d94-d55b-4a06-9b52-d485c54e9a19

MailboxLocationType : MainArchive

 

This command will dump the mailbox types and GUID of all mailboxes associated with a user.

 

From the list we can locate the primary mailbox and the mailbox GUID.  Using this mailbox GUID we can invoke the managed folder assistance.

 

PS C:\> Start-ManagedFolderAssistant aace1f4e-5181-4855-a0c7-466f1fe2f1d1

 

When utilizing the GUID we can minimize the change that any initialization process does not cause the command to fail.


Office 365: SPAM detection and reverse DNS lookups.

$
0
0

In Office 365 support we occasionally receive requests to review non-deliverable reports.  In some instances the non-deliverable reports are generated by remote mail systems antispam technologies – specific reverse DNS looksups.

 

What is a reverse DNS lookup.  Let’s take a look.

 

An email is addressed from an Office 365 mailbox to a remote mail system.  Our outbound gateways connect to the remote mail system to begin the SMTP transmission.  Here is a sample header:

 

Hop↓
Submitting host
Receiving host
Time
Delay
Type⇒

1
BY2PR0501MB1848.namprd05.prod.outlook.com ([10.163.155.153])
BY2PR0501MB1848.namprd05.prod.outlook.com ([10.163.155.153])
2/7/2018, 2:02:41 PM

mapi

2
BY2PR0501MB1848.namprd05.prod.outlook.com (10.163.155.153)
BY2PR0501MB1816.namprd05.prod.outlook.com (10.163.155.146)
2/7/2018, 2:02:41 PM

0 seconds

Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256)

3
NAM01-SN1-obe.outbound.protection.outlook.com (104.47.32.55)
DM3NAM06FT011.mail.protection.outlook.com (10.152.109.1)
2/7/2018, 2:02:43 PM

2 seconds

Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256)

 

In this case NAM01-SN1-obe.outbound.protection.outlook.com is the server initiating the connection to the receiving gateway.  This server identifies itself in that transmission as NAM01-SN1-obe.outbound.protection.outlook.com and the public IP address associated – in this instance 104.47.32.55.

 

When a reverse DNS lookup is performed – the IP address of the connection is utilized to return the hostname assigned by the ISP hosting the reverse dns namespace.   Here is an example from nslookup:

 

C:\>nslookup
Default Server:  UnKnown
Address:  192.168.1.254

> server 8.8.8.8
Default Server:  google-public-dns-a.google.com
Address:  8.8.8.8

> set type=ptr
> 104.47.32.55
Server:  google-public-dns-a.google.com
Address:  8.8.8.8

Non-authoritative answer:
55.32.47.104.in-addr.arpa       name = mail-sn1nam01on0055.outbound.protection.outlook.com

 

In this case the reverse DNS lookup for IP address 104.47.32.55 is mail-sn1nam01on0055.outbound.protection.outlook.com.

 

At one time in the antispam world a protection that was often utilized was to compare the connecting host name to the reverse DNS name.  If the names matched the host was considered valid.  In the case of Office 365 the reverse dns record may not match the name of the host initiating the connection.  As you can see here NAM01-SN1-obe.outbound.protection.outlook.com is not equal to mail-sn1nam01on0055.outbound.protection.outlook.com.  There is no requirement within the mail flow RFCs that the connecting host name or the name provided within the connections EHLO request must match a reverse DNS lookup of the connecting IP address. 

 

In the case of the NDRS presented from the customer the NDR is due to antispam on the receiving servers blocking connections from servers that do not pass a successful reverse DNS check. 

 

Unfortunately from the Office 365 standpoint there is little that can be done.  Reverse DNS looks ups are largely unreliable in todays transport environments to feed antispam decisions and have arguably been replaced by more reliable technologies like SPF and DKIM.  Administrators experiencing these types of NDRs should engage with the third party blocking the messages and request whitelisting for their domains.

 

You can find some more specific and detailed information regarding server naming conventions and Office 365 here –> https://blogs.msdn.microsoft.com/tzink/2016/07/15/the-outbound-ip-and-helo-format-for-office-365/

Office 365: Adding a cloud only distribution group as a member of a distribution group on premises…

$
0
0

Today I spoke with a customer that had a unique situation – at least for me.  They have started to create distribution lists that reside in Office 365.  They still had distribution lists that were synchronized from on premises.  The customer wanted to add the cloud only distribution list as a member of the distribution list synchronized from on premises. 


Natively this functionality is not possible since cloud only distribution lists are not synchronized from the cloud to on premises.  (One could arguable use Office 365 Groups and group back sync – but that could get complicated).  To fulfill this request I believe we can utilize a mailbox and forwarding.  Let’s take a look.


On premises we have a DL called OnPremisesDL.


[PS] C:\Windows\system32>Get-DistributionGroup OnPremisesDL


Name         DisplayName  GroupType PrimarySmtpAddress

----         -----------  --------- ------------------

OnPremisesDL OnPremisesDL Universal
OnPremisesDL@domain.org



In the cloud we have a DL called CloudDL.


PS C:\Users\timmcmic> Get-DistributionGroup CloudDL


Name    DisplayName GroupType PrimarySmtpAddress

----    ----------- --------- ------------------

CloudDL CloudDL     Universal
CloudDL@domain.onmicrosoft.com


My initial thoughts were to utilize a shared mailbox for this purpose.  Our new-remoteMailbox does not have the ability to provision a shared mailbox remotely – and the mailbox must exist as an object both in the cloud and on premises.  To accomplish this we will create the shared mailbox on premises and migrate it to Office 365.


[PS] C:\Windows\system32>New-Mailbox -Shared -Name CloudDL-Forward


Name                      Alias                ServerName       ProhibitSendQuota

----                      -----                ----------       -----------------

CloudDL-Forward           CloudDL-Forward      azure-mbx        Unlimited


With the mailbox created it can be migrated to Office 365 which will preserve the shared status and convert it to a remote shared mailbox.


image


image


Post migrating the mailbox to Office 365 we can set the appropriate properties to allow forwarding.  My first recommendation is to hide the mailbox from the distribution list.   This command is executed on premises.


[PS] C:\Windows\system32>Set-RemoteMailbox CloudDL-Forward -HiddenFromAddressListsEnabled:$TRUE

[PS] C:\Windows\system32>


My second recommendation is to enable forwarding using the forwarding SMTP address property and prevent delivery to the shared mailbox.  The forwarding address utilized should match the cloud distribution lists primary SMTP address.  This command is executed in Office 365. 


[PS] C:\Windows\system32>Set-Mailbox CloudDL-Forward -ForwardingSMTPAddress CloudDL@domain.onmicrosoft.com -DeliverToMailboxAndForward:$FALSE

[PS] C:\Windows\system32>


Hiding the mailbox from the address list will prevent users from accidentally selecting it in a name search or when browsing the address list.  The forwarding SMTP address parameter will allow transport to send all messages to the cloud DL preserving the from address as the original sender.  The deliver to mailbox and forward parameter set to false will prevent the delivery of the message to the shared mailbox.  This essentially serves as a forwarder that exists as both an object on premises and within the cloud.


In order for the messages to route to the on premises distribution list and then deliver to the cloud distribution list our mailbox must be a member of the on premises distribution list.


[PS] C:\Windows\system32>Add-DistributionGroupMember -Identity OnPremisesDL -Member CloudDL-Forward

[PS] C:\Windows\system32>


When this has completely synchronized to the on premises environment a test can be performed.  Using an outlook profile we will email the onpremisesDL@domain.com.  The email should arrive in the mailbox of user@domain.com since user@domain.com is a member of CloudDL@domain.onmicrosoft.com


image


The test email was successfully received to the mailbox that is a member of CloudDL.  Note the to address is the on premises distribution list.

Office 365: Licensing mail users results in mailbox objects.

$
0
0

In Office 365 we allow administrators to create mail user objects.  A mail user object is a security principal in the local active directory that also has an external email address assigned.  The user will appear in the global address list as a recipient and when selected the messages sent to the external email address assigned to the user.

 

In recent weeks I have worked with customers that have begun the process of implementing automated license assignment or implementing group based licensing.  In the process of doing so their mail user objects were included within the licensing scope applied.  When the Exchange Online license was applied – the mail user objects were converted to mailbox objects causing interruptions in mail flow.

 

Here is an example of a mail user created on premises.

 

[PS] C:\>Get-MailUser TestAssigned

Name                                     RecipientType
----                                     -------------
Test Assigned                            MailUser

 

When Azure AD Connect has replicated the object it will be represented in Exchange Online as a mail user object.

 

PS C:\> Get-MailUser TestAssigned

Name                                     RecipientType
----                                     -------------
Test Assigned                            MailUser

 

When the mail user account is initially provisioned the account is not licensed.

 

PS C:\> Get-MsolUser -UserPrincipalName testassigned@domain.com

UserPrincipalName            DisplayName   isLicensed
-----------------            -----------   ----------
TestAssigned@domain.com      Test Assigned False

 

Using the Office 365 Portal an Exchange Online license can be assigned to the mail user account.

 

PS C:\> Get-MsolUser -UserPrincipalName testassigned@domain.com

UserPrincipalName            DisplayName   isLicensed
-----------------            -----------   ----------
TestAssigned@domain.com      Test Assigned True

 

Post license assigned the object is converted to a mailbox object within Exchange Online.

 

PS C:\> Get-Mailbox testassigned

Name                      Alias                ServerName       ProhibitSendQuota
----                      -----                ----------       -----------------
Test Assigned             TestAssigned         cy1pr0601mb1626  49.5 GB (53,150,220,288 bytes
)

 

The external email address property of the mail user is not preserved – all email will now be delivered to the mailbox that was provisioned.

 

This is considered by design.  In Exchange Online the only objects that will not provision a mailbox when a license is assigned is an on premises mailbox.  This is denoted in Exchange Online by a user object that is replicated with an Exchange Guid.  (Note:  There is one exception to this – information can be found here:  https://blogs.technet.microsoft.com/timmcmic/2017/09/10/office-365-users-have-both-a-cloud-and-on-premises-mailbox/)

 

To correct the condition the license can be removed through the Office 365 Portal (or though any means that can remove the Exchange Online sku).

 

PS C:\> Get-MsolUser -UserPrincipalName testassigned@domain.com

UserPrincipalName            DisplayName   isLicensed
-----------------            -----------   ----------
TestAssigned@domain.com      Test Assigned False

 

This will result in the object converting back to a mail user object and the external email address being applicable again.

 

PS C:\> Get-MailUser testassigned

Name                                     RecipientType
----                                     -------------
Test Assigned                            MailUser

 

In order to preserve mail user functionality Exchange Plans should not be assigned when licenses are assigned to these recipient objects.

Office 365: Internal forwarding and remote domains…

$
0
0

In Office 365 I often encourage customers to control user forwarding through the user of remote domains.  You can find two of my blog posts on this topic here:

 

https://blogs.technet.microsoft.com/timmcmic/2015/06/08/exchange-and-office-365-mail-forwarding-2/

https://blogs.technet.microsoft.com/timmcmic/2015/04/19/office-365-determine-accounts-that-have-forwarding-enabled/

 

In a default installation a remote domain is defined in the service only for the * domain. 

 

PS C:\> Get-RemoteDomain

Name                           DomainName                                   AllowedOOFType
----                           ----------                                   --------------
Default                        *                                            External

 

The auto forwarding property can be adjusted to FALSE which prevents autoforwarding from succeeding even if configured by the end user.

 

PS C:\> Get-RemoteDomain | Select-Object AutoForwardEnabled

AutoForwardEnabled
------------------
             False

 

I recently had a customer present with an issue where forwarding was not working.  In this particular instance forwarding was not working when a mailbox in the service created a rule or was using forwarding SMTP address to a user that was not yet migrated.  The recipients mailbox was located on premises in the same organization.  Let us take a look at an example…

 

In Office 365 I have changed the forwarding SMTP address to be a proxy address of an object that has not yet been migrated.  The forwarding smtp address property is treated in the same manner as an inbox rule setting a forwarding or redirect address.  (For a details explanation of the different forwarding methods see my previously mentions posts).

 

Set-Mailbox Contact -ForwardingSmtpAddress journal@contoso.com

 

When the forwarding address as been set all emails directed to this mailbox should also be redirected to the forwarding address.

 

To test the forwarding using an external mailbox outside the organization I addressed an email to the mailbox where forwarding was enabled.  Using message tracing I traced the message and noted that the status now shows as FAILED.

 

PS C:\> Get-MessageTrace -RecipientAddress journal@contoso.com -SenderAddress timmcmic@microsoft.com

Received            Sender Address         Recipient Address       Subject Status
--------            --------------         -----------------       ------- ------
4/9/2018 2:41:08 PM timmcmic@microsoft.com journal@contoso.com     Test    Failed

 

Using get-messageTraceDetail we can review the full path of the message including any drops.

 

PS C:\> $trace=Get-MessageTrace -RecipientAddress journal@contoso.com -SenderAddress timmcmic@microsoft.com | Get-MessageTraceDetail
PS C:\> $trace

Date                   Event                Detail
----                   -----                ------
4/9/2018 2:41:11 PM    Journal              Message was journaled. Journal report was sent to journal@contoso.co...
4/9/2018 2:41:11 PM    Drop                 Reason: [{LED=250 2.1.5 RESOLVER.MSGTYPE.AF; handled AutoForward address...
4/9/2018 2:41:11 PM    Drop                 Reason: [{LED=250 2.1.5 RESOLVER.MSGTYPE.AF; handled AutoForward address...
4/9/2018 2:41:11 PM    Spam Diagnostics

 

In this instance we can see two drop events have occurred.  We can review the specific details of one of the drop events.

 

PS C:\> $trace[1].detail
Reason: [{LED=250 2.1.5 RESOLVER.MSGTYPE.AF; handled AutoForward addressed to external recipient};{MSG=};{FQDN=};{IP=};{LRT=}]

 

This is interesting – the message trace details seem to indicate that the message was dropped to an external recipient.  Why?

 

In this case the message is leaving the office 365 organization and therefore is considered external even though the message is destined to the on premises organization.  Due to transport seeing the forwarding recipient as external – and the remote domain * being the only domain defined and having auto forwarding disabled – the message is turfed.

 

How can we fix this?

 

We can fix this by defining a remote domain for the internal namespace.

 

PS C:\> New-RemoteDomain -DomainName contoso.com -Name "Contoso Remote Domain"

Name                           DomainName                                   AllowedOOFType
----                           ----------                                   --------------
Contoso Remote Domain          contoso.com                                  External

 

PS C:\> Get-RemoteDomain "Contoso Remote Domain" | fl autoForwardEnabled


AutoForwardEnabled : True

 

The entire process can be retested after allowing time for replication.  In this instance we will observe that the forwarded message is now delivered.

 

PS C:\> Get-MessageTrace -RecipientAddress journal@contoso.com -SenderAddress timmcmic@microsoft.com  | where{$_.status -like "Delivered"}

Received            Sender Address         Recipient Address       Subject Status
--------            --------------         -----------------       ------- ------
4/9/2018 3:06:30 PM timmcmic@microsoft.com journal@contoso.com     Test    Delivered

 

 

PS C:\> $trace=Get-MessageTrace -RecipientAddress journal@contoso.org -SenderAddress timmcmic@microsoft.com  | where{$_.status -like "Delivered"} | get-messageTraceDetail
PS C:\> $trace

Date                   Event                Detail
----                   -----                ------
4/9/2018 3:06:33 PM    Journal              Message was journaled. Journal report was sent to journal@contoso.co...
4/9/2018 3:06:33 PM    Journal              Message was journaled. Journal report was sent to journal@contoso.co...
4/9/2018 3:06:33 PM    Journal              Message was journaled. Journal report was sent to journal@contoso.co...
4/9/2018 3:06:34 PM    Send external        Message sent to mail.contoso.com at IPAddress using TLS1.2 w...
4/9/2018 3:06:33 PM    Spam Diagnostics

 

The new remote domain settings are being applied as expected.

Office 365: Detecting and preventing duplicate mailboxes between On-Premises and Exchange Online

$
0
0

In Office 365 when licenses are assigned to a user a mailbox should not be provisioned if the user has a mailbox on premises.  Our provisioning logic looks to see if there is a replicated Exchange GUID to make a determination on the type of object that should be provisioned.  The one exception of this is if the account has a previousRecipientDisplayTypeDetails of UserMailbox.  In all cases if this recipient type is a UserMailbox a mailbox will be provisioned.  This can lead to duplicate mailboxes between Office 365 and on premises Exchange.


I detail some of these situations in the following blog posts:


https://blogs.technet.microsoft.com/timmcmic/2017/09/10/office-365-users-have-both-a-cloud-and-on-premises-mailbox/

https://blogs.technet.microsoft.com/timmcmic/2018/04/09/office-365-licensing-mail-users-results-in-mailbox-objects/



To being identifying users that might have the probability of having a duplicate mailbox created we must first pull all mail users that have a populated Exchange GUID.  If a mail user has an Exchange GUID – it should match the on premise mailbox. 


$mailUsers=Get-MailUser -ResultSize unlimited | where {$_.exchangeGUID -notlike "*00000*"}

$mailUsers


Name                                     RecipientType

----                                     -------------

Journal Mailbox                          MailUser

TestCloud0                               MailUser

TestCloud1                               MailUser

TestCloud2                               MailUser

TestCloud3                               MailUser

TestCloud4                               MailUser


The second step is to trim the list down further to those mail users that have a previousRecipientDisplayTypeDetails of UserMailbox. 


$users=$mailUsers | % {get-user $_.alias | where {$_.PreviousRecipientTypeDetails -eq "UserMailbox"}}

$users


Name       RecipientType

----       -------------

TestCloud0 MailUser

TestCloud1 MailUser

TestCloud2 MailUser

TestCloud3 MailUser

TestCloud4 MailUser


The array of users created above should reflect all mail users where the Exchange GUID is populated and the previous recipient type details are UserMailbox.


We now support resetting the users previousRecipientTypeDetails through the set-user command.  IMPORTANT NOTE:  When resetting these values if there is any data in the cloud mailbox that you wish to have recovered DO NOT proceed with these instructions.  Continuing to follow these instructions will result in the inability to recover data.  Using a loop we are able to move through the array of users and clear the previous recipient type details. 


To reset the previousRecipientTypeDetails…


$users | % {Set-User -Identity $_.samAccountName -PermanentlyClearPreviousMailboxInfo -Confirm:$FALSE -Verbose}





VERBOSE: Delete all existing information about user "TestC505571820778136"?. This operation will clear existing values

from Previous home MDB and Previous Mailbox GUID of the user. After deletion, reconnecting to the previous mailbox that
  existed in the cloud will not be possible and any content it had will be unrecoverable PERMANENTLY. Do you want to

continue?

VERBOSE: Delete all existing information about user "Test56390-1214024844"?. This operation will clear existing values

from Previous home MDB and Previous Mailbox GUID of the user. After deletion, reconnecting to the previous mailbox that
  existed in the cloud will not be possible and any content it had will be unrecoverable PERMANENTLY. Do you want to

continue?

VERBOSE: Delete all existing information about user "TestCl56390595684140"?. This operation will clear existing values

from Previous home MDB and Previous Mailbox GUID of the user. After deletion, reconnecting to the previous mailbox that
  existed in the cloud will not be possible and any content it had will be unrecoverable PERMANENTLY. Do you want to

continue?

VERBOSE: Delete all existing information about user "TestCl50043487409662"?. This operation will clear existing values

from Previous home MDB and Previous Mailbox GUID of the user. After deletion, reconnecting to the previous mailbox that
  existed in the cloud will not be possible and any content it had will be unrecoverable PERMANENTLY. Do you want to

continue?

VERBOSE: Delete all existing information about user "Test58465-1005051264"?. This operation will clear existing values

from Previous home MDB and Previous Mailbox GUID of the user. After deletion, reconnecting to the previous mailbox that
  existed in the cloud will not be possible and any content it had will be unrecoverable PERMANENTLY. Do you want to

continue?


Using powershell to validate that our changes were successful by restarting the discover process outlined above.


$mailUsers=Get-MailUser -ResultSize unlimited | where {$_.exchangeGUID -notlike "*00000*"}

$users=$mailUsers | % {get-user $_.alias | where {$_.PreviousRecipientTypeDetails -eq "UserMailbox"}}

$users

$users.count

0


With the users array count being zero there are no mail users left with a previous recipient display type of user mailbox.  With this value cleared – should a license be assigned to the user a mailbox will not be generated in Exchange Online.

Office 365: Trusting application emails sent through internal relay…

$
0
0

In todays connected environments there are several applications that send email through designated internal relay servers.  The messages may originate from application servers that generate notifications, scans from multifunction printers, or other network connected devices.  An excellent target for internal relay servers are the hybrid servers implemented for Office 365 integration or any Exchange 2010 or newer server. 


In some installations a connector is created that allows for anonymous access.  This is definitely the case when the Exchange server receives email from the internet.


image


In many cases the internet or anonymous connector is what is utilized for internal relay applications.  This works for accepting and sending email within the environment – but there are several limitations.  Any email that is received through only the anonymous permission is considered not authenticated.  Here are some implications:


  • Sender addresses are not resolved to email addresses in the global address list.
  • Email to distribution lists requiring authentication will not be processed.
  • Message limits of the on premises organization are applied to the messages relayed.


In this example telnet was utilized to submit a message through the anonymous connector.  The message header indicates the message was received as anonymous.


21
X-MS-Exchange-Organization-AuthAs
Anonymous


In order for internal applications to reliably deliver email it may be necessary to trust these messages.  The messages must come from an authenticated source.  To allow this to occur a receive connector can be created the implements the following:


  • IP restrictions to the sending applications or devices.
  • Authentication using “Externally Secured”.


image


image


Exchange by default will always utilize the most restrictive connector.  When the device connects and the IP address is within scope of the connector the externally secured permissions will be applied.  When the connector with externally secured is selected this results in the authentication settings for the email being set as INTERNAL.  


In this example telnet was utilized to submit a message through the externally secured connector.  The message header indicates the message was received as internal.


19
X-MS-Exchange-Organization-AuthAs
Internal


For more information on the connector security settings please review the following article –> https://technet.microsoft.com/en-us/library/mt668454(v=exchg.160).aspx

Office 365: Resetting a migrated users Azure Active Directory account….

$
0
0

In certain support circumstances it may become necessary to hard delete an Azure Active Directory account.  When the user has a mailbox that has been migrated to Exchange Online additional steps may be required to restore mailbox access.


It is important to note that hard deleting an account should not be a common place operation.  There can potentially be significant impacts to the other services that are linked to an account – for example Sharepoint Online site ownerships / permissions and One Drive for Business files. 


When a mailbox is migrated to Exchange Online the on premises mailbox GUID is preserved in Office 365.  If the original Azure Active Directory account is hard deleted – the Exchange Online mailbox will be set to an inactive status.  The Azure Active Directory account will be provisioned as a remote mailbox but continues to have the Exchange GUID of the mailbox on premises.  If a license is assigned to the new account – a mailbox is not provisioned due to the presence of the on premises Exchange GUID.  The assumption is that the mailbox needs to be migrated again.


Let’s take a look at an example.


In this example there is an on premises mailbox.  This can be validated with get-recipient and noting the recipientType is UserMailbox.


[PS] C:\>Get-Recipient BlogTest



Name      RecipientType

----      -------------

Blog Test UserMailbox


The ExchangeGUID is stamped on the mailbox when created on premises and is utilized to create the link between the Active Directory object and the mailbox object within the database.


[PS] C:\>Get-Mailbox BlogTest | Select-Object exchangeGuid



ExchangeGuid

------------

3155cca2-d022-4cbe-8f93-e3ecfc98894d


In Office 365 an on premises mailbox is represented as a mail user object.  This can be validated with get-recipient and noting the recipientType is MailUser.


PS C:\> Get-Recipient BlogTest



Name      RecipientType

----      -------------

Blog Test MailUser


The same exchangeGUID found on premises is stamped on the mail user object in Office 365.


PS C:\> Get-Recipient BlogTest | Select-Object exchangeGUID



ExchangeGuid

------------

3155cca2-d022-4cbe-8f93-e3ecfc98894d


When the mailbox is successfully migrated to Office 365 a conversion of the object on premises occurs to a remote mailbox type.


[PS] C:\>Get-RemoteMailbox BlogTest



Name         RecipientTypeDetails                    RemoteRecipientType

----         --------------------                    -------------------

Blog Test    RemoteUserMailbox                       Migrated


The recipient in Office 365 is now a user mailbox object.


PS C:\> Get-Recipient BlogTest



Name      RecipientType

----      -------------

Blog Test UserMailbox


The GUIDs continue to remain the same.


[PS] C:\>Get-RemoteMailbox BlogTest | Select-Object exchangeGUID



ExchangeGuid

------------

3155cca2-d022-4cbe-8f93-e3ecfc98894d


PS C:\> Get-Mailbox BlogTest | Select-Object exchangeGUID



ExchangeGuid

------------

3155cca2-d022-4cbe-8f93-e3ecfc98894d


This represents the standard account creation and migration process.


At this time through a support engagement it is determined that the associated Azure Active Directory account needs to be hard deleted.  This is accomplished through the remove-msolUser command.


PS C:\> Remove-MsolUser -UserPrincipalName blogtest@domain.org



Confirm

Continue with this operation?

[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): y



PS C:\> Remove-MsolUser -UserPrincipalName blogtest@domain.org -RemoveFromRecycleBin



Confirm

Continue with this operation?

[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): y


When the Azure Active Directory account is removed the associated Exchange Online mailbox is also removed.


PS C:\> Get-Mailbox BlogTest

The operation couldn't be performed because object 'BlogTest' couldn't be found on

'CO1PR06A002DC01.NAMPR06A002.prod.outlook.com'.
     + CategoryInfo          : NotSpecified: (:) [Get-Mailbox], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=DM6PR06MB4026,RequestId=0bfe62ac-6691-43d8-99e6-5ae8358796b5,TimeStamp=4/29/2018
     3:37:40 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException] CEDE4B18,Microsoft.Exchange.Management.RecipientTasks.GetMailbox
     + PSComputerName        : ps.outlook.com



When the next Azure Active Directory Connect cycle runs the same account will be provisioned as a new object in Azure Active Directory.


PS C:\> Get-MsolUser -UserPrincipalName blogtest@domain.org



UserPrincipalName        DisplayName isLicensed

-----------------        ----------- ----------

blogtest@domain.org      Blog Test   False


The provisioning of the new account is detected by Exchange Online and a mail user object is provisioned.


PS C:\> Get-Recipient BlogTest



Name     RecipientType

----     -------------

BlogTest MailUser


In this instance the object is a remote mailbox / migrated user.  It would be expected that a mailbox object would appear in Exchange Online – but the object is a mail user. 


When reviewing the properties of the Azure Active Directory object validation errors exist and an error is noted on the account in the portal.


PS C:\> Get-MsolUser -UserPrincipalName blogtest@domain.org | Select-Object validationStatus



ValidationStatus

----------------
            Error


image


Why does the validation error exist?  When a mailbox has been migrated to Office 365 the ExchangeGUID continues to remain on the object on premises.  This was visible in the previous commands we executed.  Although the recipient type is remote mailbox – the presence of an ExchangeGUID on premises prevents a mailbox from being provisioned.  The service assumes there is still a mailbox to be migrated.


If this is the case – how do we get the blank mailbox that we were looking for to provision?  The exchangeGUID can be removed on premises.  This can be accomplished by using ADSIEdit and locating the account to be modified.


image


image


At the next Azure Active Directory Connect synchronization cycle the exchangeGUID will be cleared from the object in Office 365.  When the object is completed synchronization the Exchange Online object remains a mail user but the exchangeGUID is now null.


PS C:\> Get-Recipient BlogTest | fl recipientType,skuassigned,exchangeGUID





RecipientType : MailUser

SKUAssigned   :

ExchangeGuid  : 00000000-0000-0000-0000-000000000000


At this time a license can be assigned to the user.


PS C:\> Get-MsolUser -UserPrincipalName blogtest@domain.org | Select-Object isLicensed,Licenses



IsLicensed Licenses

---------- --------
       True {Organization:STANDARDWOFFPACK}


When the license assignment successfully provisions to Exchange Online the mail user is converted to a user mailbox – a new mailbox has been provisioned.


PS C:\> Get-Recipient BlogTest | fl recipientType,skuassigned,exchangeGUID





RecipientType : UserMailbox

SKUAssigned   : True

ExchangeGuid  : ec78d8ce-fee9-40e7-b8a6-d0628a22c527


The original mailbox can now be merged into the new mailbox to preserve any data delivered to the original mailbox.






Office 365: Mail disable an on premises security group…

$
0
0

Administrators may enable security groups on premises as distribution groups. 


[PS] C:\>Get-DistributionGroup BlogSecurityGroup


Name              DisplayName       GroupType                  PrimarySmtpAddress

----              -----------       ---------                  ------------------

BlogSecurityGroup BlogSecurityGroup Universal, SecurityEnabled
BlogSecurityGroup@domain.org


Azure Active Directory Connect will provision these groups and they will appear as mail enabled objects in Exchange Online.


PS C:\> Get-DistributionGroup BlogSecurityGroup


Name              DisplayName       GroupType                  PrimarySmtpAddress

----              -----------       ---------                  ------------------

BlogSecurityGroup BlogSecurityGroup Universal, SecurityEnabled
BlogSecurityGroup@domain.org


There may be requirements to remove the mail enabled attributes of the group.  This is done on premises through disable-distributiongroup.


[PS] C:\>Disable-DistributionGroup BlogSecurityGroup


Confirm

Are you sure you want to perform this action?

Disabling distribution group "BlogSecurityGroup" will remove the Exchange properties from the Windows group object.


When the distribution group has been disabled it still appears in Exchange Online as a mail enabled group.  In this instance with a proxy address that defaults to the default onmicrosoft.com domain.


PS C:\> Get-DistributionGroup BlogSecurityGroup


Name              DisplayName       GroupType                  PrimarySmtpAddress

----              -----------       ---------                  ------------------

BlogSecurityGroup BlogSecurityGroup Universal, SecurityEnabled BlogSecurityGroup@domain.onmicrosoft.com


If the group must be completely removed from Exchange Online – the associated MSOL object must be removed.


PS C:\> Get-MsolGroup -SearchString BlogSecurityGroup


ObjectId                               DisplayName                GroupType                  Description

--------                               -----------                ---------                  -----------

c2d0b7df-f0d5-4f0a-9470-edfa56e4910e   BlogSecurityGroup          MailEnabledSecurity




PS C:\> Get-MsolGroup -SearchString BlogSecurityGroup | Remove-MsolGroup


Confirm

Continue with this operation?

[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): y


Exchange Online will receive notification that the group has been removed and fully clean up the associated distribution group object.


PS C:\> Get-DistributionGroup BlogSecurityGroup

The operation couldn't be performed because object 'BlogSecurityGroup' couldn't be found on

'CO1PR06A002DC01.NAMPR06A002.prod.outlook.com'.
     + CategoryInfo          : NotSpecified: (:) [Get-DistributionGroup], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=DM6PR06MB4026,RequestId=62703e0c-3437-49b9-9b84-be6253159d2e,TimeStamp=4/29/2018
     6:18:49 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException] FC078746,Microsoft.Exchange.Management.RecipientTasks.GetDistributionGroup
     + PSComputerName        : ps.outlook.com


If the group still exists on premises Azure AD Connect will recreate it as a security enabled group during the next synchronization cycle.

Office 365: Unable to locate an Azure Active Directory user for an Exchange Online Mailbox

$
0
0

In order for an Exchange Online mailbox to exist in Office 365 it must be attached to an Azure Active Directory object.  In Exchange Online we record the object ID for the Azure Active Directory account as the external directory object id of the mailbox.


PS C:\> Get-Mailbox tmcmichael | fl name,externalDirectoryObjectID




Name                      : Timothy McMichael

ExternalDirectoryObjectId : 61425db0-7812-49dd-b6aa-1a732bdec569


Using the external directory object ID we can locate the Azure Active Directory account that the mailbox is linked to.


PS C:\> Get-MsolUser -ObjectId 61425db0-7812-49dd-b6aa-1a732bdec569


UserPrincipalName          DisplayName       isLicensed

-----------------          -----------       ----------

tmcmichael@domain.org      Timothy McMichael True


I recently had a customer that presented with the inability to locate the Azure Active Directory Object for an associated mailbox. 


Using get-mailbox the mailbox object was successfully located:


PS C:\> Get-Mailbox contact | fl name,externalDirectoryObjectID




Name                      : Contact Mailbox

ExternalDirectoryObjectId : 3959607e-8c53-4413-9d39-1af548b00819


When using get-msolUser the Azure Active Directory account could not be successfully located.


PS C:\> Get-MsolUser -ObjectId 3959607e-8c53-4413-9d39-1af548b00819

Get-MsolUser : User Not Found.  User: 3959607e-8c53-4413-9d39-1af548b00819.

At line:1 char:1

+ Get-MsolUser -ObjectId 3959607e-8c53-4413-9d39-1af548b00818

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : OperationStopped: (:) [Get-MsolUser], MicrosoftOnlineException
     + FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.UserNotFoundException,Microsoft.Online.Administration.Automation.GetUser


If the mailbox object was a valid object – why can an Azure Active Directory account not be located.


In this particular instance we discovered that the mailbox was set as the JournalingReportNDRTo.


PS C:\> Get-TransportConfig | fl JournalingReportNdrTo




JournalingReportNdrTo : contact@domain.com


When a mailbox is specified as the journalingReportNDRTo recipient the mailbox cannot be deprovisioned.  In this particular instance we suspect that the Azure Active Directory Account was removed and subsequently purged.  When the object is purged from Azure Active Directory the associated Exchange Online Mailbox should enter a soft deleted state.  In this instance the mailbox was not soft deleted because of an external dependency.

Office 365: The mystery of mobile phone…

$
0
0

In the last few weeks I have worked several escalations from customers inquiring about inconsistencies with the mobile phone attribute.  In almost all cases inconsistencies were noticed in the Exchange Online contact card where mobile phone listed did not match on premises.


When directory synchronization is enabled on an Office 365 tenant a set of attributes are locked with a source of authority flag establishing on premises as the SOA.  The implications here are that changes to these attributes should only be accepted through the Azure Active Directory Synchronization software.  Administrators and end users can see this behavior when attempting to change – for example – first name.


PS C:\> Set-MsolUser -UserPrincipalName tim.mcmichael@domain.com -FirstName Test

Set-MsolUser : Unable to update parameter. Parameter name: FIRSTNAME.

At line:1 char:1

+ Set-MsolUser -UserPrincipalName tim.mcmichael@domain.com -FirstName  ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : OperationStopped: (:) [Set-MsolUser], MicrosoftOnlineException
     + FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.PropertyNotSettableException,Microsoft.Online.Administration.Automation.SetUser


As with other attributes mobile phone is initially setup with the expectation that it will be provided through the Azure Active Directory Synchronization software.  Let us review a sample user:


The remote mailbox object is provisioned on-premises and a mobile number set.


[PS] C:\>Get-User testmobile | fl *mobile*




MobilePhone : 8035551212


The recipient is successfully replicated to Azure Active Directory and the mobile number from on premises is retained.


PS C:\> Get-MsolUser -UserPrincipalName testmobile@fortmillems.org | fl *mobile*




AlternateMobilePhones : {}

MobilePhone           : 8035551212


At anytime the mobile number may change on premises to a different value.


[PS] C:\>Set-User testmobile -MobilePhone 9991112222

[PS] C:\>Get-User testmobile | fl *mobile*




MobilePhone : 9991112222


The recipient is again successfully replicated to Azure Active Directory and the mobile number from on premises is again retained.


PS C:\> Get-MsolUser -UserPrincipalName testmobile@domain.com | fl *mobile*




AlternateMobilePhones : {}

MobilePhone           : 9991112222


In Office 365 there are several self service options for attributes.  For example users can enroll themselves in Multi-Factor Authentication or potentially manage some of their personal attributes.  One of these attribute is mobile phone.  This allows the end user to set their own mobile phone number.  In addition administrators have access to user attribute both via the portal and powershell where mobile phone can also be adjusted. 


PS C:\> Get-MsolUser -UserPrincipalName testmobile@domain.com | fl *mobile*




AlternateMobilePhones : {}

MobilePhone           : 1234567890


So wait – mobile phone was previously accepted from on premises when directory synchronization was enabled but is now also taking updates from Azure Active Directory directly?  That’s correct – mobile phone is a unique attribute.  When directory synchronization is enabled mobile phone will continue to be populated from on premises through the sync process.  Although this occurs – the mobile phone can be updated through any number of cloud interfaces.   What happens now if the mobile number changes on premises.


[PS] C:\>Set-User testmobile -MobilePhone 0987654321

[PS] C:\>Get-User testmobile | fl *mobile*




MobilePhone : 0987654321


Synchronization is now allowed to complete and reviewing the attributes of mobile number in Azure Active Directory we note the attribute HAS NOT updated.


PS C:\> Get-MsolUser -UserPrincipalName testmobile@domain.com | fl *mobile*




AlternateMobilePhones : {}

MobilePhone           : 1234567890


This is by design.  When the mobile phone number was adjusted in Azure Active Directory the source of authority was changed from on premises to Azure Active Directory.  When Azure Active Directory Sync pushes any changes of the mobile attribute from on premises to Office 365 – Azure Active Directory ignores the change. 


So what about Exchange Online – what will display in the users contact card.  Exchange Online takes all of the information as provided by Azure Active Directory.  Regardless where the source of authority lies – the value stamped on the object in Azure Active Directory will be the value of the attribute on the mail enabled object in Exchange Online and what will subsequently appear in the global address list.  Here is a sample get-user from Exchange Online:


PS C:\> Get-User testMobile | fl *mobile*




MobilePhone : 1234567890


If you have mobile phone attributes that you need populated from on premises to Office 365 and are encountering this issue a support case can be utilized to discuss options with product support services.

Office 365: Exchange Migrations and the data migrated information…

$
0
0

In Office 365 migration batches are the preferred method of establishing mailbox migrations to Office 365.  When a migration batch is established the users included in the batch are represented as migration users within the service. 


Within the context of each migration user is where we track the migration process.  One of the data points contained within the migration process is the DATA MIGRATED tab.  When enumerating the users within a migration batch, and selecting a migration user, this information is visible within the portal.


USER@domain.com

Status: Synced

USER@domain.com Skipped item details

Data migrated: 1.4 GB ‎(1,503,707,494 bytes)‎
Migration rate: 0 B ‎(0 bytes)‎
Error:
Report: USER@domain.com Download the report for this user

Last successful sync date: 7/2/2018 6:12:47 PM

Status:

Queued duration: 00:00:09.5015268
In-progress duration: 6.04:36:17.0329441
Synced duration: 36.10:02:28.6166962
Stalled duration: 02:12:43.4040899


One of the common questions and comments that I receive is that the DATA MIGRATED field may often reflect sizes that are slightly more to drastically more than the mailbox being migrated.  This on occasion leads to confusion about the migration process and the data that was migrated.  Here’s an example.


I recently migrated a mailbox from an on premises Exchange 2010 installation.  With Exchange 2010 being the source we can already expect that the data migrated to the service to be more than the reported mailbox size due to the inconsistencies in the methods Exchange 2010 reports mailbox sizes.  At the time that the mailbox migration completed the following was reported within the migration portal.


user@domain.com

Status: Completed

user@domain.com Skipped item details

Data migrated: 2.485 GB ‎(2,668,722,884 bytes)‎
Migration rate: 0 B ‎(0 bytes)‎
Error:
Report: user@domain.com
Download the report for this user

Last successful sync date: 7/3/2018 3:14:56 PM

Status:

Queued duration: 00:00:08.5213717
In-progress duration: 01:01:30.1987283
Synced duration: 00:00:00
Stalled duration: 01:21:09.3851867


In this example the data migrated field shows 2.485 GB migrated.  If we review the migration statistics associated with the mailbox we can get an idea of the reported mailbox size to be migrated. 


PS C:\> Get-MigrationUserStatistics user@domain.com -IncludeReport | Export-Clixml -Path c:\temp\migration.xml


PS C:\> $stats=Import-Clixml -Path C:\temp\migration.xml


PS C:\> $stats.EstimatedTotalTransferSize

1.501 GB (1,612,092,317 bytes)


In this particular instance the estimated mailbox transfer size was 1.5 GB.  If we look at the data migrated verses the estimated data transfer size the difference is almost 1 GB difference.  Even accounting for reporting inconsistencies from Exchange 2010 mailbox size estimates 1 GB is a significant difference.  Why has this happened?


The data migrated field is a summary counter of all data transmissions between Office 365 and the on premises Exchange environment.  It is NOT a reflection of the data migrated verses the estimated mailbox size.  In this particular instance the mailbox move process was interrupted several times.  The interruptions may be the result of throttling, connection problems, or other migration interruptions. 


7/3/2018 2:22:35 PM [CO2PR07MB2711] The job has been paused temporarily due to unfavorable server health, with request throttling state: 'StalledDueToTarget_DiskLatency'. It will automatically resume after '7/3/2018 2:23:35 PM'.

7/3/2018 2:28:38 PM [CO2PR07MB2711] The Microsoft Exchange Mailbox Replication service 'CO2PR07MB2711.namprd07.prod.outlook.com' (15.20.930.16 ServerCaps:FFFFFF, ProxyCaps:0FFFC7FD6DFDBF5FFFFFCB07FFFF, MailboxCaps:, legacyCaps:FFFFFF) is examining the request.

7/3/2018 2:28:38 PM [CO2PR07MB2711] Content from the Shard mailbox (Mailbox Guid: 6021ac05-d3f5-4bf4-ad03-f749aa02a1e4, Database: 545e461d-55da-4037-9c3e-d57a539e5e43) will be merged into the target mailbox.

7/3/2018 2:28:38 PM [CO2PR07MB2711] Connected to target mailbox 'live.domain.com\f28fad8a-546d-4965-8bcd-94806d53967d (Primary)', database 'NAMPR07DG170-db053', Mailbox server 'CO2PR07MB2711.namprd07.prod.outlook.com' Version 15.20 (Build 930.0).

7/3/2018 2:28:45 PM [CO2PR07MB2711] Connected to source mailbox 'live.domain.com\f28fad8a-546d-4965-8bcd-94806d53967d (Primary)', database 'DAG-Administration', Mailbox server 'MICHAEL.domain.com' Version 14.3 (Build 382.0), proxy server 'PROXY.domain.com' 15.1.1531.3 ServerCaps:, ProxyCaps:, MailboxCaps:, legacyCaps:0FFD6FFFBF5FFFFFCB07FFFF.

7/3/2018 2:28:47 PM [CO2PR07MB2711] Request processing continued, stage LoadingMessages.


7/3/2018 2:28:47 PM [CO2PR07MB2711] Stage: LoadingMessages. Percent complete: 20.

7/3/2018 2:41:04 PM [CO2PR07MB2711] Stage: CopyingMessages. Percent complete: 85.

7/3/2018 2:41:04 PM [CO2PR07MB2711] Copy progress: 17097/21426 messages, 1.299 GB (1,394,743,256 bytes)/1.501 GB (1,611,958,891 bytes), 30/67 folders completed.

7/3/2018 2:41:04 PM [CO2PR07MB2711] The job has been paused temporarily due to unfavorable server health, with request throttling state: 'StalledDueToTarget_DiskLatency'. It will automatically resume after '7/3/2018 2:42:04 PM'.


7/3/2018 2:49:49 PM [CO2PR07MB2711] The Microsoft Exchange Mailbox Replication service 'CO2PR07MB2711.namprd07.prod.outlook.com' (15.20.930.16 ServerCaps:FFFFFF, ProxyCaps:0FFFC7FD6DFDBF5FFFFFCB07FFFF, MailboxCaps:, legacyCaps:FFFFFF) is examining the request.

7/3/2018 2:49:55 PM [CO2PR07MB2711] Content from the Shard mailbox (Mailbox Guid: 6021ac05-d3f5-4bf4-ad03-f749aa02a1e4, Database: 545e461d-55da-4037-9c3e-d57a539e5e43) will be merged into the target mailbox.

7/3/2018 2:49:55 PM [CO2PR07MB2711] Connected to target mailbox 'live.domain.com\f28fad8a-546d-4965-8bcd-94806d53967d (Primary)', database 'NAMPR07DG170-db053', Mailbox server 'CO2PR07MB2711.namprd07.prod.outlook.com' Version 15.20 (Build 930.0).

7/3/2018 2:50:02 PM [CO2PR07MB2711] Connected to source mailbox 'live.domain.com\f28fad8a-546d-4965-8bcd-94806d53967d (Primary)', database 'DAG-Administration', Mailbox server 'MICHAEL.domain.com' Version 14.3 (Build 382.0), proxy server 'PROXY.domain.com' 15.1.1531.3 ServerCaps:, ProxyCaps:, MailboxCaps:, legacyCaps:0FFD6FFFBF5FFFFFCB07FFFF.

7/3/2018 2:50:04 PM [CO2PR07MB2711] Request processing continued, stage LoadingMessages.


7/3/2018 2:50:04 PM [CO2PR07MB2711] Stage: LoadingMessages. Percent complete: 20.

7/3/2018 3:00:05 PM [CO2PR07MB2711] Stage: CopyingMessages. Percent complete: 89.


In this example the move request was stalled several times.  Each time after the stall the migration request is picked back up – and message loading occurs.  This would be an example of additional data added to the transfer set that was not mailbox level items that would have been accounted for in the mailbox size. 


If I was curious about the status of the migration and understanding the full migration status – how can I ensure the data was moved.  When a move enters the finalization phase the source mailbox and target mailbox are locked.  We have a mailbox folder verification process that is executed.  The mailbox folder verification process iterates through each folder in the source mailbox and compares it to the target mailbox.  Item counts and sizes are compared in real time.  If there are any discrepancies identified the move will be placed into a failed state.  The mailbox verification is logged into the migration log file and can be viewed by the administrator.


PS C:\> Get-MigrationUserStatistics user@domain.com -IncludeReport | Export-Clixml -Path c:\temp\migration.xml


PS C:\> $stats=Import-Clixml -Path C:\temp\migration.xml


PS C:\> $stats.Report.MailboxVerification

Source                                         : 10188 [1.152 GB (1,237,342,091 bytes)]

SourceFAI                                      : 27 [1.203 MB (1,261,537 bytes)]

Target                                         : 10188 [1.464 GB (1,571,440,111 bytes)]

TargetFAI                                      : 27 [1.227 MB (1,286,579 bytes)]

Corrupt                                        : 0 [0 B (0 bytes)]

Large                                          : 0 [0 B (0 bytes)]

Skipped                                        : 0 [0 B (0 bytes)]

FolderSourcePath                               : /Top of Information Store/Inbox

FolderTargetPath                               : /Top of Information Store/Inbox

FolderSourceID                                 : {0, 0, 0, 0...}

FolderTargetID                                 : {0, 0, 0, 0...}

ParentSourceID                                 : {0, 0, 0, 0...}

ParentTargetID                                 : {0, 0, 0, 0...}

WKFType                                        : Inbox

WKFTypeInt                                     : 10

FolderIsMissing                                : False

FolderIsMisplaced                              : False

MismatchedFlagsCount                           : 0

MissingItemsInTargetBucket                     : 0 [0 B (0 bytes)]

MismatchedFlagsSample                          : {}

DuplicatedItemsInTargetBucket                  : 0 [0 B (0 bytes)]

MissingInSourceExtraItemsInTargetBucket        : 0 [0 B (0 bytes)]

MismatchedSyncFolderIdExtraItemsInTargetBucket : 0 [0 B (0 bytes)]

NonMRSSyncedExtraItemsInTargetBucket           : 0 [0 B (0 bytes)]

FolderExclusionExtraItemsInTargetBucket        : 0 [0 B (0 bytes)]

MailboxGuid                                    : f28fad8a-546d-4965-8bcd-94806d53967d

UnknownElements                                :

UnknownAttributes                              :

XmlSchemaType                                  :



Source                                         : 5129 [247.9 MB (259,986,587 bytes)]

SourceFAI                                      : 3 [5.91 KB (6,052 bytes)]

Target                                         : 5129 [500 MB (524,288,275 bytes)]

TargetFAI                                      : 3 [8.085 KB (8,279 bytes)]

Corrupt                                        : 0 [0 B (0 bytes)]

Large                                          : 0 [0 B (0 bytes)]

Skipped                                        : 0 [0 B (0 bytes)]

FolderSourcePath                               : /Top of Information Store/Deleted Items

FolderTargetPath                               : /Top of Information Store/Deleted Items

FolderSourceID                                 : {0, 0, 0, 0...}

FolderTargetID                                 : {0, 0, 0, 0...}

ParentSourceID                                 : {0, 0, 0, 0...}

ParentTargetID                                 : {0, 0, 0, 0...}

WKFType                                        : DeletedItems

WKFTypeInt                                     : 14

FolderIsMissing                                : False

FolderIsMisplaced                              : False

MismatchedFlagsCount                           : 0

MissingItemsInTargetBucket                     : 0 [0 B (0 bytes)]

MismatchedFlagsSample                          : {}

DuplicatedItemsInTargetBucket                  : 0 [0 B (0 bytes)]

MissingInSourceExtraItemsInTargetBucket        : 0 [0 B (0 bytes)]

MismatchedSyncFolderIdExtraItemsInTargetBucket : 0 [0 B (0 bytes)]

NonMRSSyncedExtraItemsInTargetBucket           : 0 [0 B (0 bytes)]

FolderExclusionExtraItemsInTargetBucket        : 0 [0 B (0 bytes)]

MailboxGuid                                    : f28fad8a-546d-4965-8bcd-94806d53967d

UnknownElements                                :

UnknownAttributes                              :

XmlSchemaType                                  :


In summary – the DATA MIGRATED field cannot be used as a measure of migration success or failure.  Only in cases where the move is started and almost immediately finalized with no errors, stalls, or interruptions will the value be near or close to the mailbox size being migrated.

Office 365: Correcting users who have had a mailbox in the cloud and on-premises…

$
0
0

In some previous blog posts I have outlined conditions where users may have inadvertently had a mailbox both on premises and in the cloud at the same time.  The following links outline these scenarios and how to attempt to proactively identity users that may fall in this condition.


https://blogs.technet.microsoft.com/timmcmic/2018/04/10/office-365-detecting-and-preventing-duplicate-mailboxes-between-on-premises-and-exchange-online/

https://blogs.technet.microsoft.com/timmcmic/2017/09/10/office-365-users-have-both-a-cloud-and-on-premises-mailbox/

https://blogs.technet.microsoft.com/timmcmic/2018/04/09/office-365-licensing-mail-users-results-in-mailbox-objects/


With an understanding of the scenarios that lead to this and how to proactively identity users administrators can quickly identify the conditions that lead to this occurring and work to prevent it for other accounts moving forward.  How do we handle an account though that has encountered this condition?


There are two methods to handle accounts that have had mailboxes both on premises and in the cloud.  I will outline the options below for administrators to consider – as each has benefits and drawbacks.


OPTION #0:  Delete the existing Azure Active Directory Account


The Exchange Online mailbox object is linked to an Azure Active Directory account.  When the azure active directory account is removed and subsequently purged from the recycle bin the Exchange Online mailbox is placed in a soft deleted state.  During the next Azure Active Directory Connect synchronization cycle the user will be resynchronized to Azure Active Directory as new and will carry forward the Exchange attribute from on premises.  This should result in a mail user created in Exchange Online and not a mailbox object.  The mailbox object can now be migrated from on premises and the associated soft deleted mailbox merged into the original to retain data.


There are several benefits to this approach:


  • Deleting and purging an account from Azure Active Directory is generally a simple process.
  • The mailbox can be immediately migrated from on-premises once the mail user object is provisioned.
  • Exchange Online supports the administrator merging mailbox contents.  The soft deleted mailbox belonging to the user can be merged into the migrated mailbox allowing for no messages to be lost.


There are several potential drawbacks to this approach:


  • This is a complete Azure Active Directory account reset.
  • All permissions granted to this account within the service – for example Sharepoint site ownership / OneDrive / and any other services will be lost.
  • Any membership in cloud only distribution lists – for example Office 365 groups – will be lost.
  • There may be a brief interruption in mail flow to this account while the deletion and recreation of the Exchange Online object occurs.


In Exchange Online we can verify the presence of a mailbox that matches an on premises account.


Exchange Online:


PS C:\> Get-Mailbox testduplicate


Name                      Alias           Database                       ProhibitSendQuota    ExternalDirectoryObjectId

----                      -----           --------                       -----------------    -------------------------

testduplicate             testduplicate   NAMPR06DG282-db128             49.5 GB (53,150,2... e3eaf6c1-f012-42e9-a54...


On-Premises Exchange:


[PS] C:\>Get-Mailbox testduplicate


Name                      Alias                ServerName       ProhibitSendQuota

----                      -----                ----------       -----------------

Test Duplicate            testduplicate        azure-mbx        Unlimited


In the portal we can verify that the account is synchronized from the on-premises active directory.


image


The synchronized user has now been verified to have both a mailbox in the cloud and on-premises.


To begin the recovery the administrator should capture the Exchange Online mailbox information – specifically the Exchange GUID of the mailbox.  This GUID will be utilized in the recovery of the soft deleted mailbox.


PS C:\> Get-Mailbox testduplicate | select-object ExchangeGUID


ExchangeGuid

------------

fa38094d-cbfd-46b7-82f6-8a3022e39a66


Using Azure Active Directory powershell the account can be removed and purged from the recycle bin.


PS C:\> Remove-MsolUser -UserPrincipalName testduplicate@domain.com -Force

PS C:\> Remove-MsolUser -UserPrincipalName testduplicate@domain.com -Force –RemoveFromRecycleBin


The deletion can be verified using powershell.  The user cannot be found in either the active users list or the recycle bin – this indicates a successful deletion.


PS C:\> Get-MsolUser -UserPrincipalName testduplicate@domain.com

Get-MsolUser : User Not Found.  User: testduplicate@domain.com.

At line:1 char:1

+ Get-MsolUser -UserPrincipalName testduplicate@domain.com

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : OperationStopped: (:) [Get-MsolUser], MicrosoftOnlineException
     + FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.UserNotFoundException,Microsoft.Online.Administration.Automation.GetUser


PS C:\> Get-MsolUser -UserPrincipalName testduplicate@domain.com -ReturnDeletedUsers

Get-MsolUser : User Not Found.  User:
testduplicate@domain.com.

At line:1 char:1

+ Get-MsolUser -UserPrincipalName testduplicate@domain.com -Return ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : OperationStopped: (:) [Get-MsolUser], MicrosoftOnlineException
     + FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.UserNotFoundException,Microsoft.Online.Administration.Automation.GetUser


In Exchange Online we can confirm that the mailbox object is no longer present.


PS C:\> Get-Mailbox testduplicate

The operation couldn't be performed because object 'testduplicate' couldn't be found on

'CO1PR06A002DC02.NAMPR06A002.prod.outlook.com'.
     + CategoryInfo          : NotSpecified: (:) [Get-Mailbox], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=DM6PR06MB4026,RequestId=76d78567-e257-4608-a175-2dc3cd8658c2,TimeStamp=7/15/2018
     3:51:45 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException] 260B3828,Microsoft.Exchange.Management.Rec
   ipientTasks.GetMailbox
     + PSComputerName        : ps.outlook.com


The duplicate online mailbox should now be in a soft deleted state.


PS C:\> Get-Mailbox testduplicate -SoftDeletedMailbox


Name                      Alias           Database                       ProhibitSendQuota    ExternalDirectoryObjectId

----                      -----           --------                       -----------------    -------------------------

Test Duplicate            testduplicate   NAMPR06DG282-db128             49.5 GB (53,150,2...


At this time the online portion of the accounts have been cleaned up.  Azure Active Directory Connect synchronization can be performed and the object should be reprovisioned from the on-premises directory.


PS C:\> Get-MsolUser -UserPrincipalName testduplicate@domain.com


UserPrincipalName             DisplayName    isLicensed

-----------------             -----------    ----------

testduplicate@domain.com      Test Duplicate False


The object should now be successfully provisioned as a mail user within Exchange Online.  This is the expected recipient type for an on premises mailbox.


PS C:\> Get-MailUser testduplicate


Name                                     RecipientType

----                                     -------------

Test Duplicate                           MailUser


At this time the on-premises mailbox can be migrated to Office 365.  This is an optional step – but would be required in order to perform the merge of any data contained within the service at this time.


image


When the migration has completed successfully the object will become a mailbox object within Exchange Online.


PS C:\> Get-Mailbox testduplicate


Name                      Alias           Database                       ProhibitSendQuota    ExternalDirectoryObjectId

----                      -----           --------                       -----------------    -------------------------

Test Duplicate            testduplicate   NAMPR06DG143-db051             99 GB (106,300,44... 7ba2fffc-e3ce-4d65-b350-d0a3763e5ffa


To complete our recovery the mailbox restoration can be processed.  To begin we need the Exchange GUID of the migrated mailbox.


PS C:\> Get-Mailbox testduplicate | Select-Object exchangeGUID


ExchangeGuid

------------

e683f1ee-4c85-4b99-b4bc-7511572a361d


The Exchange GUID for the soft deleted mailbox was previously recorded.  Using this information we can begin the merge process.


New-MailboxRestoreRequest -SourceMailbox fa38094d-cbfd-46b7-82f6-8a3022e39a66 -TargetMailbox e683f1ee-4c85-4b99-b4bc-7511572a361d –AllowLegacyDNMismatch


Name           TargetMailbox Status

----           ------------- ------

MailboxRestore testduplicate Queued


The merge can be monitored with get-mailboxRestoreRequest. 


PS C:\Users\timmcmic> Get-MailboxRestoreRequest


Name           TargetMailbox Status

----           ------------- ------

MailboxRestore testduplicate InProgress


PS C:\Users\timmcmic> Get-MailboxRestoreRequest

Name           TargetMailbox Status
----           ------------- ------
MailboxRestore testduplicate Completed


At this time this option has completed.



OPTION #1:  Remove the Exchange Online License


The Exchange Online mailbox object is linked to an Azure Active Directory account.  When the Exchange Online license is removed from the object the associated mailbox will be made unavailable.  This should result in a mail user created in Exchange Online and not a mailbox object.  The mailbox object can now be migrated from on premises and the associated soft deleted mailbox merged into the original to retain data.


There are several benefits to this approach:


  • The existing Azure Active Directory account is preserved.
  • All permissions assigned to the object are preserved across Sharepoint and OneDrive etc.  (This assumes ONLY the Exchange Online license is removed…)


There are several potential drawbacks to this approach:


  • The Exchange Online mailbox is not recoverable.  Any data contained will be lost.
  • There may be a brief interruption in mail flow to this account while the deletion and recreation of the Exchange Online object occurs.


To begin the mailbox can be confirmed in Exchange Online and On-Premises.


Exchange Online:


PS C:\> Get-Mailbox testlicense


Name                      Alias           Database                       ProhibitSendQuota    ExternalDirectoryObjectId

----                      -----           --------                       -----------------    -------------------------

TestLicense               TestLicense     NAMPR06DG103-db019             49.5 GB (53,150,2... c686dfd9-aa4a-4b54-8680-cc0d4c9b0a62


On-Premise Exchange:


[PS] C:\>Get-Mailbox testlicense


Name                      Alias                ServerName       ProhibitSendQuota

----                      -----                ----------       -----------------

Test License              testlicense          azure-mbx        Unlimited


In the portal we can confirm that the account is synchronized from the on-premises Active Directory.


image


The synchronized user has now been verified to have both a mailbox in the cloud and on-premises.


The Exchange Online license can now be removed through the portal.


image


When the license removal has synchronized into Exchange Online the mailbox will be converted to a mail user.


PS C:\> Get-MailUser testLicense


Name                                     RecipientType

----                                     -------------

Test License                             MailUser


When the conversion to a mail user has occurred the mailbox can be migrated from on premises.  If the license is re-assigned the object will convert back to a mailbox.  Assigning an Exchange Online license should be withheld until the mailbox is migrated (or the previous recipient type is changed – reference the previously attached blogs) allowing it to be safe to apply a license.

Office 365: Unable to modify group membership in the Office 365 portal…

$
0
0

In Office 365 cloud only groups can have their membership managed through the Office 365 portal or through the Azure Active Directory powershell commands.  As with on premises Active Directory multiple group types can be created and managed.  You can also create direct user membership in groups as well as nested group membership.  I recently had an interesting experience with a customer attempting to manage nested group membership.


There is a top level group in our example called TopLevelGroup.  The group contained two members – an individual user account and another nested group.


PS C:\> Get-MsolGroupMember -GroupObjectId a988084b-8642-4406-b25d-8687b8c509e7


GroupMemberType EmailAddress               DisplayName

--------------- ------------               -----------

User            tmcmichael@domain.com      Timothy McMichael

Group                                      SubGroup0


image


The group membership is consistent in both powershell and the portal.


There is a sub group in our example called SubGroup0.  The groups contains a single member – an individual user account.


PS C:\> Get-MsolGroupMember -GroupObjectId 8966d905-c966-4d2e-89ea-a151f1534252


GroupMemberType EmailAddress               DisplayName

--------------- ------------               -----------

User            tmcmichael@domain.com      Timothy McMichael


image


The group membership is consistent in both powershell and the portal.


Through the course of administration the individual user account was accidentally removed from the top level group. 


PS C:\> Get-MsolGroupMember -GroupObjectId a988084b-8642-4406-b25d-8687b8c509e7


GroupMemberType EmailAddress DisplayName

--------------- ------------ -----------

Group                        SubGroup0


When the accidental deletion was discovered the administrator attempted to add the user back to the top level group.  To perform this operation the administrator selected the group within the portal – selected the edit members option – and the add members operation button.  This presented the administrator with the list of users to add to the group.  Using the search operation the user was located.  When the user was found it was noted that the user already had a checkbox next to them and the save button was greyed out.  The user could not be added through the portal interface.


image


You can also attempt to modify the groups that an individual is a member of through the individual user properties.  The user is located under active users and is selected for properties.  Under Group Membership select the edit option then the add memberships button.  This brings up the group search option.  When searching for the group the same behavior is noted.  The group already has the checkbox selected as if the user is a member. 


image


Why is this occurring?  The portal is actually displaying the group membership based on expanding all subgroup members.  In this case the individual user account continues to be a member of the subgroup.  Since it is a member of the subgroup the portal expands it as a member of the top level group.  If this is the case – how do I get the user to be a direct member of the top level group if that is the desire?  In order to perform this operation powershell must be utilized.  Here is an example…


Get the object ID of the individual user.


PS C:\> get-msoluser -UserPrincipalName tmcmichael@domain.com | select-object objectID


ObjectId

--------

61425db0-7812-49dd-b6aa-1a732bdec569



Get the object ID of the top level group.



PS C:\> Get-MsolGroup -SearchString TopLevelGroup | select-object objectID


ObjectId

--------

a988084b-8642-4406-b25d-8687b8c509e7



Add the user to the top level group.



PS C:\> Add-MsolGroupMember -GroupObjectId a988084b-8642-4406-b25d-8687b8c509e7 -GroupMemberType User -GroupMemberObjectId 61425db0-7812-49dd-b6aa-1a732bdec569


Validate the group membership is correct.


PS C:\> Get-MsolGroupMember -GroupObjectId a988084b-8642-4406-b25d-8687b8c509e7


GroupMemberType EmailAddress               DisplayName

--------------- ------------               -----------

User            tmcmichael@domain.com      Timothy McMichael

Group                                      SubGroup0


Using these steps the user can be restored back as a member to the top level group.

Office 365: A different approach to handling Office 365 group mail flow…

$
0
0

In Exchange Online an Office 365 Group ( Unified Group / Modern Group ) allows for a new level of team collaboration.  Office 365 Groups are created directly in Exchange Online and Azure Active Directory.  This makes them cloud only objects.  The membership and attributes of these objects are maintained directly in Office 365.


There are legitimate scenarios where on premises applications must be able to send email to the Office 365 groups.  By default an Office 365 Group does not write back to on premises Active Directory and therefore is not a valid recipient for Exchange on-premises.  To compensate for this Azure Active Directory Connect has a group writeback feature.  The group writeback feature allows Office 365 groups to be represented in the on-premises Active Directory.  The group membership cannot be managed using the on-premises Active Directory – any changes are overwritten by Azure Active Directory Connect. 


When a group is written back to the on-premises active directory they are not mail enabled by default.  Administrators must execute the update-recipient command in order to have the objects represented in the on-premises global address list and for full transport functionality.  In some cases this can be an interesting task.  There is another option to establish mail flow and have the object appear in the on-premises global address list.


Utilizing a mail contact…


The process starts by provisioning the Office 365 Group in either Exchange Online or in Azure Active Directory.  When the group is provisioned the mail enabled attributes are created – of particular interest to us are the email addresses stamped on the group.


The group must be updated with an email address that includes domain.mail.onmicrosoft.com.


PS C:\> Set-UnifiedGroup Officers -emailaddresses:@{add=officers@domain.mail.onmicrosoft.com}


With the new email address present we can gather the attributes that we will use in future commands into a variable.


PS C:\> $group=Get-UnifiedGroup -Identity Officers



PS C:\> $group.EmailAddresses

smtp:officers@fortmillrescuesquad.mail.onmicrosoft.com

SMTP:Officers@fortmillems.org

smtp:Officers@fortmillrescue.com

SPO:SPO_8bd244fb-60f3-4710-a1ef-40bc7ef584ff@SPO_eefdeca8-5850-4ca5-a160-0716f2d8496e

smtp:Officers@FortMillRescueSquad.onmicrosoft.com



PS C:\> $group.DisplayName

Officers


PS C:\> $group.name

Officers_7ccca570b9


PS C:\> $group.alias

Officers


As with most mail enabled objects in Office 365 this group has a primary email address at the vanity domain @domain.org and a secondary email address at the tenant domain @domain.mail.onmicrosoft.com.  I have also noted the other attributes that we will utilize later. 


The next step is to locate or create an Organizational Unit in the on-premises Active Directory to store the on-premises objects we will associated with these groups.  An important configuration step here is that the OU must NOT be included in objects that are replicated by Azure Active Directory Connect to Azure Active Directory.  This is performed through the Azure Active Directory Connect configuration wizard. 


image


The last step of the process is to provision mail enabled contacts within the non-sync OU.  The mail enabled contacts will:


  • Have a primary email address matching the primary email address of the mail enabled group in Office 365.
  • Have an external email address matching the tenant specific email address.
  • Any number of secondary addresses as necessary.
  • Note – the primary and secondary email addresses may be defined automatically by the on-premises recipient policies and match the Office 365 Group depending on the configuration of the on-premises recipient policies.


In this example I will utilize powershell to create the mail enabled contact and the values previously gathered above.


[PS] C:\>New-MailContact -DisplayName "Officers" -Name "Officers_7ccca570b9" -ExternalEmailAddress "officers@domain.mail.onmicrosoft.com" -Alias "Officers" -PrimarySmtpAddress "officers@domain.org" -OrganizationalUnit "domain.local/TopLevelOU/Contacts/Office365-NoSync"


Name                      Alias                                          RecipientType

----                      -----                                          -------------

Officers_7ccca570b9       Officers                                       MailContact


The contact creation can be verified with get-mailcontact and reviewing the individual attributes set.


[PS] C:\>$contact=get-mailContact Officers_7ccca570b9


[PS] C:\>$contact.displayName

Officers



[PS] C:\>$contact.name

Officers_7ccca570b9



[PS] C:\>$contact.ExternalEmailAddress




SmtpAddress        : officers@domain.mail.onmicrosoft.com

AddressString      : officers@domain.mail.onmicrosoft.com

ProxyAddressString : SMTP:officers@domain.mail.onmicrosoft.com

Prefix             : SMTP

IsPrimaryAddress   : True

PrefixString       : SMTP





[PS] C:\>$contact.Alias

Officers



[PS] C:\>$contact.PrimarySmtpAddress




Length         : 25

Local          : officers

Domain         : domain.org

Address        : officers@domain.org

IsUTF8         : False

IsValidAddress : True




[PS] C:\>$contact.OrganizationalUnit

domain.local/TopLevelOU/Groups/Office365-NoSync


The mail contact will appear in the on premises global address list.


image


When the contact is selected as a mail target the email will be received at address@domain.org and will forward to address@domain.onmicrosoft.com.  Here is an example from the on-premises message tracking logs.


[PS] C:\>Get-MessageTrackingLog -MessageId c652db0a537848d4bf43c6d435bbb79e@domain.org


Timestamp              EventId          Source        Sender                Recipients            MessageSubject

---------              -------          ------        ------                ----------            --------------

8/21/2018 8:23:03 PM   HAREDIRECTFAIL   SMTP          Administrator@OOOO... {officers@OOOOOOOO... Test New Contact

8/21/2018 8:23:03 PM   RECEIVE          SMTP          Administrator@OOOO... {officers@OOOOOOOO... Test New Contact

8/21/2018 8:23:17 PM   RESOLVE          ROUTING       Administrator@OOOO... {officers@OOOOOOOO... Test New Contact

8/21/2018 8:23:22 PM   AGENTINFO        AGENT         Administrator@OOOO... {officers@OOOOOOOO... Test New Contact

8/21/2018 8:23:25 PM   TRANSFER         ROUTING       Administrator@OOOO... {officers@OOOOOOOO... Test New Contact

8/21/2018 8:23:29 PM   SENDEXTERNAL     SMTP          Administrator@OOOO... {officers@OOOOOOOO... Test New Contact

8/21/2018 8:22:58 PM   RECEIVE          STOREDRIVER   Administrator@OOOO... {officers@OOOOOOOO... Test New Contact

8/21/2018 8:23:06 PM   SUBMIT           STOREDRIVER   Administrator@OOOO... {officers@OOOOOOOO... Test New Contact



The Exchange Online message tracking logs show the inbound transmission to Office 365.


PS C:\> Get-MessageTrace -RecipientAddress officers@domain.mail.onmicrosoft.com


Received             Sender Address                Recipient Address                                 Subject

--------             --------------                -----------------                                 -------

8/21/2018 8:23:28 PM Administrator@domain.org      officers@domain.mail.onmicrosoft.com              Test New Contact


When the full message headers are pulled from the message delivered to the group we can additionally validate that the authentication source is internal.  The messages are trusted.


26
X-MS-Exchange-Organization-AuthAs
Internal


When using this process the contact on-premises shows as a mail enabled contact.  It will not show as a distribution group – which may impact some peoples abilities to locate within the global address list – for example someone who selects all lists in the address book drop down.  If you prefer – you could utilize a distribution list with a single member to achieve the same results. 


Utilizing a distribution group…


The same pre-requisites must be followed.  We need to add the additional email address to the unified group, capture the values for the group, and have a prepared organizational unit not synchronized.  The process only deviates in how we create the relationship between the on-premises groups and the Office 365 Groups.


The steps of this process include provisioning a distribution group and a mail enabled contacts within the non-sync OU.


The distribution list will:


  • Have a primary email address matching the primary email address of the mail enabled group in Office 365.
  • Contain a mail enable contact with an external email address matching the domain.mail.onmicrosoft.com address of the Office 365 Group.
  • Any number of secondary addresses as necessary.
  • Note – the primary and secondary email addresses may be defined automatically by the on-premises recipient policies and match the Office 365 Group depending on the configuration of the on-premises recipient policies.


The mail enabled contact will:


  • Have an external email address matching the domain.mail.onmicrosoft.com address of the Office 365 Group.
  • Be a recipient hidden from the global address list.


In this example I will utilize powershell to create the mail enabled group and the values previously gathered above.


[PS] C:\>New-DistributionGroup -DisplayName "Officers" -Name "Officers_7cca570b9" -Alias "Officers" -PrimarySmtpAddress
"officers@domain.org" -OrganizationalUnit "domain.local/TopLevelOU/Groups/Office365-NoSync"




Name               DisplayName GroupType PrimarySmtpAddress

----               ----------- --------- ------------------

Officers_7cca570b9 Officers    Universal
officers@domain.org


Using powershell the mail enabled contact will be created.  To avoid any attribute collisions “–contact” was added to the end of each parameter.


[PS] C:\>New-MailContact -DisplayName "Officers-Contact" -Name "Officers_7ccca570b9-Contact" -ExternalEmailAddress "officers@domain.mail.onmicrosoft.com" -Alias "Officers-Contact" -PrimarySmtpAddress "officers-contact@domain.org" –OrganizatisonalUnit "domain.local/TopLevelOU/Contacts/Office365-NoSync"


Name                      Alias                                          RecipientType

----                      -----                                          -------------

Officers_7ccca570b9-Conta Officers-Contact                               MailContact

ct


The mail contact can then be hidden from the address list preventing users from locating it rather than the group created.


[PS] C:\>Set-MailContact Officers_7cca570b9-contact -HiddenFromAddressListsEnabled:$TRUE


With the mail contact provisioned it can be added to the distribution group as a member. 


[PS] C:\>Add-DistributionGroupMember -Identity Officers_7cca570b9 -Member Officers_7cca570b9-contact



[PS] C:\>Get-DistributionGroupMember -Identity Officers_7cca570b9


Name                       RecipientType

----                       -------------

Officers_7cca570b9-contact MailContact


Here is an example of the message tracking log on-premises.  The distribution list expansion and redirect to the external recipient can be reviewed.


[PS] C:\>Get-MessageTrackingLog -MessageId "4d19cf9cae67475cb4b41e011f28031d@domain.org"


Timestamp              EventId          Source        Sender                Recipients            MessageSubject

---------              -------          ------        ------                ----------            --------------

8/22/2018 2:08:05 PM   HAREDIRECTFAIL   SMTP          Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:05 PM   RECEIVE          SMTP          Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:05 PM   EXPAND           ROUTING       Administrator@OOOO... {officers-contact@... Distribution Grou...

8/22/2018 2:08:05 PM   RESOLVE          ROUTING       Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:06 PM   AGENTINFO        AGENT         Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:06 PM   TRANSFER         ROUTING       Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:06 PM   DROP             ROUTING       Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:06 PM   TRANSFER         ROUTING       Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:07 PM   SENDEXTERNAL     SMTP          Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:05 PM   RECEIVE          STOREDRIVER   Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...

8/22/2018 2:08:05 PM   SUBMIT           STOREDRIVER   Administrator@OOOO... {officers@OOOOOOOO... Distribution Grou...


A message trace in Office 365 confirms receipt of the message to the Office 365 Group.


PS C:\> Get-MessageTrace -RecipientAddress officers@fortmillrescuesquad.mail.onmicrosoft.com


Received             Sender Address                Recipient Address                                 Subject

--------             --------------                -----------------                                 -------

8/22/2018 2:08:06 PM Administrator@domain.org      officers@domain.mail.onmicrosoft.com              Distribution Gr...


When the full message headers are pulled from the message delivered to the group we can additionally validate that the authentication source is internal.  The messages are trusted.


26
X-MS-Exchange-Organization-AuthAs
Internal


Utilizing this method the on premises object appears as a mail enabled distribution group with a single member.  It will appear in the global address list as a group object and you can apply many of the same group properties – such as moderation and authentication – should it be required.


Senders and authentication…


The steps provided above yield email that arrives in Office 365 Groups as internal.  This considers the message to be trusted and authenticated.  In the testing performed above an on-premises mailbox was utilized as the source of the messages.  In many cases administrators are considering this plan or group writeback to allow the on premises organization to receive internet email as the primary MX and route to the Office 365 Groups <or> to allow internal applications to relay to Office 365 Groups.


When messages do not originate in the context of an authenticated user the connector status is utilized to determine the security of a message.  When the MX record points to an on premises server – it should be directed to a connector that has anonymous rights only.  This connector will not elevate messages received to an internal status.  In this test I utilized telnet to send an email through a connector where only the anonymous rights are present.  The header shows an authentication status of Anonymous.


24
X-MS-Exchange-Organization-AuthAs
Anonymous


When trusted internal applications require the ability to send securely to Office 365 Groups a connector can be leveraged that utilizes the externally secured permissions.  I have written a document here that some may find helpful.  https://blogs.technet.microsoft.com/timmcmic/2018/04/22/office-365-trusting-application-emails-sent-through-internal-relay/  In this test I utilized an MFP to send an email through a connector where the externally secured rights were applied and restrictions were in placed based on source IP address.  The header shows an authentication status of Internal.


25
X-MS-Exchange-Organization-AuthAs
Internal


This information can be useful in understanding how rights are applied to distribution groups and the security of inbound mail flow.


Office 365: Stale Information in the Offline Address Book and Individual Contact Cards

$
0
0

In Office 365 an Exchange related object can be replicated from the on premises Active Directory to Azure Active Directory and then forward synchronized into the Exchange Online Active Directory.  In most cases the objects synchronized into the Exchange Online Active Directory represent mail enabled objects.  User accounts are unique in that they are replicated into Exchange Online regardless of their mail enabled status.  The user accounts residing in the Exchange Online Active Directory can be seen with the get-user command.


Let us take a look at an example.  An on premises a remote mailbox object is created –> Direct Report. When running get-user against the on-premises account a MAILUSER is returned.  This is expected for a remote mailbox.


[PS] C:\>Get-User DirectReport


Name          RecipientType

----          -------------

Direct Report MailUser


An on premises account is created –> Team Manager.  Team Manager is not a mail enabled object.  When running get-user against the on-premises account a USER object is returned.  This is expected for a user object that is not mail enabled.


[PS] C:\>Get-User TeamManager


Name         RecipientType

----         -------------

Team Manager User


In this particular instance DIRECTREPORT has been assigned the MANAGER TEAM MANAGER.


[PS] C:\>Get-User DirectReport | fl name,manager




Name    : Direct Report

Manager : domain.local/Users/Team Manager


Using get-user in Office 365 for the remote mailbox we can see that it is listed as a USERMAILBOX.  This is expected for a remote mailbox object.


PS C:\> Get-User DIRECTREPORT


Name          RecipientType

----          -------------

Direct Report UserMailbox


The TEAMMANAGER account remains as a USER object in Exchange Online.


PS C:\> get-user "Team Manager"


Name         RecipientType

----         -------------

Team Manager User


As previously highlighted the objects represented in Exchange Online Active Directory also have a representation in Azure Active Directory.  The link between the objects can be seen on the user objects ExternalDirectoryObjectID. 


PS C:\> Get-User "Team Manager" | fl externalDirectoryObjectID




ExternalDirectoryObjectId : b3343293-8837-492b-88e6-08c4c4ec5099


Using the external directory object ID the get-MSOLUser command can be utilized to find a corresponding object. 


PS C:\> Get-MsolUser -ObjectId b3343293-8837-492b-88e6-08c4c4ec5099


UserPrincipalName           DisplayName  isLicensed

-----------------           -----------  ----------

teammanager@domain.org      Team Manager False


The end conclusion is that a valid user object in Exchange Online Active Directory is also represented by a valid object in Azure Active Directory (and potentially on-premises Active Directory if sourced on premises).


The Offline Address Book and individual contact cards displaying information like manager and direct reports.  These types of settings are not limited to recipients – but also include user objects as in this scenario.  Pulling the contact card for a manager shows the direct reports and pulling a direct report shows the manager.  This information is based from the user settings exposed through get-user.


I recently worked on an escalation where some users individual contact cards were not correct.  Some users were showing direct reports that no longer existed in the company and the same with manager attributes.  How did we determine the users were not available?


To begin the investigation we started by narrowing down where the direct report could be seen within the clients.    In this case a manager was reporting that a direct report that left the company was still showing on the users contact card.  The direct report – Bill James (bjames@domain.com) was confirmed be on the contact card in Outlook Web Access, Outlook Online Mode, and Outlook Cached Mode.  What this tells us is that this is not an issue with the build of the Offline Address Book – as online mode clients always display information directly from the directory.


Azure AD Connect is utilized in the environment to synchronize objects from the on premises Active Directory to Azure Active Directory.  Since the source of objects was on premises we verified that the account could not be found. 


[PS] C:\>get-user bjames@domain.com

The operation couldn't be performed because object 'bjames@domain.com' couldn't be found on 'Azure-Dc.fmrs.local'.
     + CategoryInfo          : NotSpecified: (:) [Get-User], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=AZURE-MBX,RequestId=25a34a91-9c7f-46df-a40e-399809d5e318,TimeStamp=9/10/2018 3:4
    4:58 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException] 6BDE9D0,Microsoft.Exchange.Management.Recipien
   tTasks.GetUser
     + PSComputerName        : azure-mbx.domain.local


This output validated that the object was not found in the on-premises Active Directory.


The next phase of the investigation was to determine if the object resided in Azure Active Directory.  Is it possible that a delete from on-premises was not processed into the directory that is the source of information for other workloads.


PS C:\> Get-MsolUser -SearchString bjames

PS C:\>


In this particular instance nothing was returned.  For good measure we also looked at deleted objects.


PS C:\> Get-MsolUser -SearchString bjames -ReturnDeletedUsers

PS C:\>


This confims that the user account is not present in Azure Active Directory.


The last step of the investigation is to review the Exchange Online Active Directory. 


PS C:\> get-user "Bill James"

Name         RecipientType
----         -------------
Bill James   User


In this particular instance a user object is found in Exchange Online.  When reviewing the recipient type we can see that the recipient is of class USER.  If the recipient does not exist on premises and does not exist in Azure Active Directory then why does it exist in Exchange Online Active Directory.  Does the object have an external directory object ID? 


PS C:\> Get-User "Bill James" | fl externalDirectoryObjectID


ExternalDirectoryObjectId : b1583093-3345-324a-7ae6-09b45e6a1b33


In this example the user does have an external directory object ID.  This means we should be able to locate the object in Azure Active Directory.


PS C:\> Get-MsolUser -ObjectId b1583093-3345-324a-7ae6-09b45e6a1b33

Get-MsolUser : User Not Found.  User: b1583093-3345-324a-7ae6-09b45e6a1b33.

At line:1 char:1

+ Get-MsolUser -ObjectId b1583093-3345-324a-7ae6-09b45e6a1b33

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : OperationStopped: (:) [Get-MsolUser], MicrosoftOnlineException
     + FullyQualifiedErrorId : Microsoft.Online.Administration.Automation.UserNotFoundException,Microsoft.Online.Admini
    stration.Automation.GetUser


The user object still cannot be found in Azure Active Directory.


In this particular example the Exchange Online Active Directory account was orphaned.  The account was removed from Azure Active Directory but the account still exists in the Exchange Online Active Directory which results in the associated contact card displays.


How does one resolve this particular issue.  To resolve this issue a support case needs to be opened with Office 365 support.  There can be several reasons that an account is orphaned that does not pertain to missing a deletion notification – and support can work with customers to identify these causes or escalate to our product engineering groups.


If you’re interested in identifying potentially orphaned accounts in bulk – we can utilize the following procedure.


  • Gather all objects of TYPE user and export the userprincipalName and externalDirectoryObjectID (if not NULL).
    • $users=invoke-command {Get-User -ResultSize unlimited | where {$_.externalDirectoryObjectID -ne $NULL} | select-object userPrincipalName,ExternalDirectoryObjectID}
    • $users | export-CSV –path c:\Temp\UsersWithExternalDirectoryObjectID.csv
  • Scan all user objects for errors locating an external directory object ID in Azure Active Directory.
    • $users | % { $error.clear() ; get-msolUser –objectID $_.externalDirectoryObjectID ; if ( $error –ne $NULL ) { $row = new-object psobject ; $row | add-member –memberType NoteProperty –value $_.externalDirectoryObjectID –name “Name”  $data += $row }}
    • $data | export-csv –path c:\temp\PotentiallyOrphanedUsers.csv
  • Scan all objects not found in Azure Active Directory to determine deleted status.  If deleted user is not orphaned.  If not found user if orphaned.
    • $users | import-csv c:\temp\PotentiallyOrphanedUsers.csv.
    • $users | % { $error.clear() ; get-msolUser –objectID $_.externalDirectoryObjectID –returnDeletedUsers; if ( $error –ne $NULL ) { $row = new-object psobject ; $row | add-member –memberType NoteProperty –value $_.externalDirectoryObjectID –name “Name”  $data += $row }}
    • $data | export-csv –path c:\temp\OrphanedUsers.csv


This data can be provided to Office 365 support to assist in reconciliation and remediation.

Office 365: Challenges with Distribution Groups for Migrated Mailboxes and a Script Based Solution

$
0
0

===========================================================================================

Group Migration Script v1.0 –> https://github.com/timmcmic/DLConversion/blob/master/src/DLConversion.ps1

===========================================================================================


Distribution groups are an excellent way to organize multiple recipients under a single address.  Like Exchange Server on-premises, Office 365 supports mail-enabled distribution groups, security groups, and dynamic distribution groups.  When Active Directory and Exchange are used on-premises, distribution groups are typically created in the on-premises Active Directory and Azure Active Directory Connect is used to maintain and replicate the distribution groups to Office 365.


Generally, there are two types of administration models that use distribution groups (which can co-exist or be used exclusively):


1. The first model uses centralized administration for all configuration and membership changes. When a member needs to be added or removed, the help desk or an admin typically processes the request.  When co-existing with Office 365 this type of administration model is very effective.  With all changes originating on premises – Azure AD Connect can easily replicated them into the Azure AD where Office 365 workloads can process them.


2. The second model delegates some or all to the user that owns the distribution group. In this model, Outlook is used for management of the distribution group.  In a hybrid configuration, this model often creates management challenges. Outlook processes the membership changes by modifying membership on the domain controller provided to the user’s mailbox by Active Directory. After the membership change is made, Azure AD Connect pushes the requested changes to Azure AD where Office 365 workloads can process them. Office 365 mailboxes receive their list of domain controllers from Exchange Online, which prevents distribution group synchronized from on-premises from being modified in Office 365. Therefore, anyone whose mailbox has been migrated to Office 365 can no longer managed distribution groups. The same is also true for administrators that attempt to manage the distribution group in Office 365.


When asked how to allow migrated mailboxes to manage distribution groups that are owned by the mailboxes the answer is to migrate the distribution groups to Office 365. For some, this involves manually deleting and recreating the distribution groups. Others have also found scripts to do this, but they don’t always address all the attributes associated with a distribution group and instead focus on simple attributes like proxy addresses, membership, name, etc.


In this post, I’ll show you a script that addresses these concerns and allows you to migrate distribution groups to Office 365 with full fidelity. Before we get into the script, let’s look at some of the challenges encountered when attempting to migrate distribution groups.



Group Membership


Distribution groups created on-premises are managed using AD tools or Exchange management tools. When managing distribution groups with Exchange tools, membership rules are enforced (for example, a member can be added only if the object is mail-enabled). This can include mail contacts, mail users, and mailboxes. Groups and users, both mail-enabled and not, can be added using Exchange tools.  AD tools are more forgiving, though; the administrator can add any valid AD object to the group membership (for example, a contact that is not mail-enabled could be added to the distribution group, although this would have no effect on mail flow).


Exchange Online has a set of rules for objects that are replicated from Azure AD to Exchange Online Active Directory.  If an object is not mail-enabled, it is not represented in Exchange Online AD. This includes any groups that are members of an on-premises distribution group but not mail-enabled.  An exception to this rule is user accounts. User account objects are replicated to Exchange Online even if they are not mail-enabled.


When migrating distribution groups, all objects that are not mail-enabled or users must be filtered out. Here is an example of a distribution group that contains a mix of members.


PS C:\> Get-DistributionGroupMember -Identity Migrate

Name              RecipientType
----              -------------
Domain Users      Group
Journal Mailbox   UserMailbox
Brian Murphy      MailContact
Timothy McMichael MailUser
Migrate1          MailUniversalSecurityGroup
Migrate2          MailUniversalDistributionGroup
Team Manager      User
Dynamic           DynamicDistributionGroup
Test Contact      Contact



Users and Groups


For users and groups to be members of a distribution group they must exist in Office 365.  There are common scenarios where Organizational Units are intentionally excluded from replication to Azure Active Directory.  Before migrating any distribution groups you must ensure that the members exist in Office 365.  If they don’t, attempts to create the distribution group through automation will fail.  Since it is possible for groups to have other group as members, any type of migration of a group to Office 365 will require removal of the on-premises group. If the groups that are members are not migrated first, their membership in that group would be lost.



Multivalued Attributes


Distribution groups have several multi-valued attributes that require consideration before migrated.  The attributes managedBy, moderatedBy, acceptMessagesOnlyFromSendersOrMembers, grantSendOnBehalfTo, rejectMessagesFromSendersOrMembers, and bypassModerationFromSendersOrMembers, for example, store their member references as distinguished names of objects.  Here is a sample output:


PS C:\> $a=Get-DistributionGroup migrate
PS C:\> $a.managedBy
domain.local/Organization/Users/Officers/Timothy McMichael
domain.local/Organization/Users/Officers/Bill Smith
PS C:\> $a.moderatedBy
domain.local/Organization/Users/Officers/Timothy McMichael
PS C:\> $a.AcceptMessagesOnlyFromSendersOrMembers domain.local/Organization/Users/Officers/Bill Smith
domain.local/ConvertedDL/Migrate1
PS C:\> $a.BypassModerationFromSendersOrMembers
domain.local/ConvertedDL/Migrate1
PS C:\> $a.RejectMessagesFromSendersOrMembers
domain.local/ConvertedDL/Migrate2
PS C:\> $a.GrantSendOnBehalfTo
domain.local/Organization/Users/Officers/Timothy McMichael


If these attributes were extracted as arrays and then used with Office 365, the references would not work because the DNs of the objects stored in Office 365 needs to reference the DN of the object in Exchange Online. 


The managedBy attribute is a shared attribute with Active Directory, and it can be set to a non-mail-enabled user.  In Exchange Online, only a valid recipient object can be entered in the managedBy field.  Thus, before you can convert the distribution group, you must ensure that all members of the managedBy field are Exchange Online recipients.


The remaining multi-valued attributes can only be set via Exchange cmdlets, which ensures that the objects are mail-enabled user objects.



Proxy / Email Addresses


The email addresses field is a multi-valued attribute.  If the proxy addresses are not in use on another object in Exchange Online, they can be moved to the new distribution group.  Note, that it is important to preserve the Reply To functionality.  Migrated distribution groups don’t really change – they have the same name, same proxy addresses, and same members.  But the nickname cache in Outlook uses the distinguished name of the group (which points to on-premises).  If a user were to address an email to the migrated group by selecting the group from nickname cache, the message would NDR.



Other Attributes


Other attributes of a distribution group are mostly text based, allowing them to be exported and imported as text. There are also several Boolean values that can be translated to the equivalent on the new distribution group, including custom attributes.



Group Migration Script


The group migration script described in this post considers all the factors presented above. Executing the script starts by preparing some pre-requisites.



Prerequisites


The first pre-requisite is to establish an Organizational Unit (OU) within Active Directory that is not synchronized to Azure Active Directory. This OU will be where the group objects will be moved during the conversion process. The conversion process in v1 of the script retains the original distribution group.  The distinguished name of this group will need to be recorded as it will be a script variable.


The second pre-requisite involves creating a secure credentials XML file that can be used by the script. The administrator must note the file names and the path where they are stored. These are variables within the script that must be updated, or the administrator can match the files contained in the script.  Create one file for on-premises credentials and one file for cloud credentials. If using XML files is not your preferred method of handling credentials, you can modify the script to prompt for credentials or consider storing credentials using other methods supported by PowerShell.


$cred = get-credential

$cred | export-cliXML –path c:\Scripts\credentials.xml


One caveat to using these files is that they are signed to the user and machine on which they were created.  Therefore, all admins using the script have to create their own sets of files.


The third pre-requisite is to ensure that the PSLOGGING module from the PowerShell Gallery is installed. This module is necessary to create files that record operations along with clean-up and logging when an error has occurred.


install-module PSLOGGING


The fourth pre-requisite is to configure Basic authentication on a local PowerShell directory.  By default, Basic authentication is not enabled in on-premises, which limits the ability to create a “remote” PowerShell session to on-premises Exchange server. Administrators often work around this by identifying one server where Basic authentication is enabled or by enabling Basic authentication on all PowerShell virtual directories behind a load-balanced name.  Whether a single server or multiple servers are used, it is a requirement to establish an SSL session to the name provided, which means there must be a public certificate installed on the specified endpoint.


Get-PowerShellVirtualDirectory –server <SERVERNAME> | Set-PowerShellVirtualDirectory –basicAuthentication:$TRUE


The last pre-requisite is to review the variables contained within the script for any necessary modifications. Variables that are recommended for the admin to adjust are noted with ###ADMIN### in front of their definition. These variables include PowerShell URLs, paths, and file names.



Script Mechanics


With the pre-requisites covered, let’s dive into the mechanics of how the script works and review the individual functions.


The process starts by gathering the credentials XML files and preparing them for use in subsequent functions. The success or failure of these operations is largely dependent on ensuring the credentials stored in the files are accurate and that the associated variables with the files have been updated successfully.


The script then proceeds to create the necessary PowerShell sessions for operations to be performed.  There are three PowerShell sessions created:


1. The first session is to an on-premises server where commands will operate against on-premises recipient objects.

2. The second session is to Office 365 where Office 365 recipient commands will be executed.

3. The third session is to the Azure AD Connect server, which will be used to invoke synchronization as recipient objects are modified.


To activate the on-premises and Office 365 PowerShell sessions, they must be imported.  When importing remote PowerShell sessions, you can often have the same cmdlets returned in each session.  In this case, there is definite overlap between Exchange and Exchange Online.  To avoid any confusion when importing the Office 365 PowerShell session we append the cmdlets with O365.  This effectively takes a cmdlet like Get-Recipient and makes it Get-O365Recipient. PowerShell is smart enough to detect the correct cmdlet and invoke it within the appropriate session.


After the underlying PowerShell sessions are started, the script exports all properties of the on-premises distribution group and all properties of the Office 365 distribution group to variables for later use.  The Office 365 distribution group should match the on-premises group as the source of authority for the Office 365 group is on-premises.


After the data has been extracted, the script performs a safety check against the distribution group, which reviews the directory synchronization flag of the distribution group in Office 365. If this flag is set to FALSE, it indicates that the distribution group is cloud-only.  If this scenario occurs, the script is automatically ended. The script can only be so smart, and it uses the SMTP address of the on-premises distribution group to locate the replicated copy in Office 365. Because it’s possible for a group in Office 365 and on-premises to share the same address even though they are not directory synchronized, the script must stop because if it continued, the Office 365 group would be removed and replaced with the on-premises group which could have unintended consequences.


After the safety check is complete, the script records and exports the information for the on-premises and Office 365 groups to XML files defined by the administrator. XML output allows us to retain full fidelity of the multivalued attributes in case something goes wrong, or we need to manually correct a failure condition.


The last portion of data collection (membership) and backup then proceeds. Membership is obtained and written to a variable that will be used in later operations. It is also exported to XML file to ensure that we have a copy of the information prior to starting any of the conversion activities.


With all the pertinent information stored within variables and backup XML files, the next step is processing this information. In the previous section, I outlined some of the challenges in working with this data.  There can be non-mail-enabled objects that need to be accounted for – these will not have primary SMTP addresses. There are mail-enabled objects that need to be accounted for but may be stored as distinguished names on certain attributes. Knowing that we need to account for all these differences forces us to develop a method to translate those individual users and recipients to objects that can be located in Exchange Online. To that end, we know that we can locate recipients via their primary SMTP address or a user account through the user principal name. So, the script iterates through all the multi-valued attributes and attempts to normalize the data into references that can be found in Exchange Online. If the object is a recipient class, we record the primarySMTPAddress of the object.  If the object is a non-mail-enabled user, we record the userPrincipalName of the object.  For each multi-valued attribute this culminates in an individual array of references that will allow us to find the objects in Exchange Online.


When the arrays of normalized data have been built we need to validate that the objects can be found in Exchange Online. The script looks for objects in Exchange Online using Get-Recipient and Get-User cmdlets in the Office 365 PowerShell. If the object is found, the recipient or user is valid and is synchronized by Azure AD Connect.  If an object is not found, the process stops and allows the administrator to correct any issues. Groups can also be members of distribution groups, so the script reviews all groups that are members and determines if they have been migrated to Office 365. Assuming all users are found, and all member groups have been migrated, it is safe to proceed with the migration.


The first step in finalizing the migration is to move the distribution group to the OU that does not synchronize. As the script proceeds, Azure AD Connect will see this as a group deletion and eventually remove it from Office 365.  The removal from Azure AD will propagate to Exchange Online Active Directory, resulting in the distribution group becoming deleted.


To ensure that all domain controllers show that the group was moved to the OU, repadmin is used to force replication across all domain controllers in the domain.  If your domain is very large, consider changing this function to a list of domain controllers or to a single domain controller.  You can also comment out the function and just increase the wait time to allow for normal replication to occur.


With domain replication underway/completed, next is to remove the distribution group from Azure AD. This process uses a remote PowerShell session to perform a delta synchronization.  A delta synchronization may already be in progress, so the script is designed to retry every 1 minute until it can assure that at least one delta sync was triggered by the script.  A delta sync can take several minutes to run depending on the size of the environment, and it only removes the group from Azure AD. The forward synchronization process will detect the groups removal from Azure AD and synchronize the change to Exchange Online.  Because there really is no way to monitor progress once the delta synchronization is issued, the script begins issuing calls to Azure AD for the group. If the call is successful, the group still exists, and the script waits 1 minute between attempts, looping until the group is not found (basically, an error occurs locating the group, which confirms the group is no longer in Office 365).


Once the group has been removed the script can now create the new replacement group using the base settings.  Next, all the non-multivalued attributes of the distribution group are set, including email addresses, custom attribute, extension attributes, and other Boolean variables that control mail flow, delivery, etc.  Next, multi-valued attributes are set by using the normalized arrays that were built previously. After all attributes have been addressed, the new distribution group in Office 365 now mirrors the original distribution group on-premises.


The final step is to gather all the settings of the new distribution group and export them to XML, which serves as a record of the operation. At the end of the script, all created PowerShell sessions are removed in preparation for the next migration.



Frequently Asked Questions


Q:  How can I prevent PowerShell sessions from timing out?

A:  There is really no method to prevent the PowerShell settings from timing out.  During testing, we determined that the operation that ran the longest was building the array of normalized SMTP addresses for the distribution group membership.  When the PowerShell session to Office 365 was left open during this process it would often be closed before we were ready to proceed with other portions.  It was also determined that when processing long arrays (for example, adding all the distribution group membership), the session may time out.  To overcome this, we routinely reset the session to Office 365 after portions of the script that took more time to process data.


Q:  Can the script be run in bulk?

A:  It is possible to feed the script a list of proxy addresses for distribution groups to migrate by calling the script multiple times.  The process through would repeat in terms of domain controller replication, Azure AD Connect synchronization, etc.  The original design of the script approached this from the perspective of servicing one-off requests for migration and not necessarily bulk migrations or conversions.


Q:  Is the script efficient?

A:  Efficiency is always relative…is it more efficient then trying to do all of this by hand and manage all the attributes? Certainly. The script must rely on several processes that do not necessarily have any guaranteed timelines.  For example, we can’t predict how long a delta sync or forward sync will take.  Thus, it’s not possible to give you a 100% accurate estimate of how long it takes to migrate a distribution group.  There is also a great deal of logging that occurs during the script which adds some overhead, but given the nature and importance of distribution groups, having the additional information is important.


Q:  What is the largest distribution group size that was tested?

A:  The script was validated using a distribution group with 10,000 members and had a minimum of 10 members in each of the multi-valued attributes.


Q:  How long did it take to migrate a group with 10,000 members?

A:  A little more than 3 hours:

Days              : 0
Hours             : 3
Minutes           : 6
Seconds           : 57
Milliseconds      : 768
Ticks             : 112177687252
TotalDays         : 0.129835286171296
TotalHours        : 3.11604686811111
TotalMinutes      : 186.962812086667
TotalSeconds      : 11217.7687252
TotalMilliseconds : 11217768.7252


Q:  What happens to mail flow during the migration process?

A:  It depends.  The distribution group is maintained on-premises during this entire process.  If messages enter the on-premises environment first and are addressed to the distribution group, you can expect that expansion will occur and message delivery will happen. The group in Office 365 is in flux during the entire migration process.  If the group is missing and a message is received, it may NDR.  If the group has been created but member addition is in-progress, then only some of the members may receive it.  I recommend that you provide warnings to distribution group owners that mail flow will be affected during the transition.


Q:  If the distribution group is a mail-enabled security group, and that group has been assigned permissions to Office 365 workloads, what happens during the conversion?

A:  Permissions would be lost.  The script only works because the group is deleted – and this would be processed by other workloads as a group deletion.


Q:  Do I have to keep the on-premises distribution group post-migration?

A:  It depends.  If messages are processed through the on-premises environment, there needs to be a corresponding mail-enabled object.  We are looking into automating the conversion of the group to a mail contact in a future version of the script to allow for mail flow to continue.


Q:  Dynamic distribution groups are not replicated by Azure Active Directory Connect.  How does the script handle dynamic distribution groups?

A:  Administrators must manually create dynamic distribution groups in Office 365.  The script intentionally does not treat dynamic distribution groups differently then a normal recipient.  In this case we detect a member and record the primary SMTP address.  When we run the recipient test against Office 365 by primary SMTP address – the recipient is returned and the script can proceed.  If the recipient is not found the script will fail.


Sample Invocations


===============================================================================

Attempting to convert the distribution group Migrate without ignoring invalid managers or invalid members.  The group to be converted IS NOT located in Office 365.  An error is generated and the script stops.


PS C:\Scripts> .\ConvertDL.ps1 -dlToConvert Migrate -ignoreInvalidDLMember:$FALSE -ignoreInvalidManagedByMember:$FALSE




     Directory: C:\Scripts





Mode                LastWriteTime         Length Name

----                -------------         ------ ----

-a----        9/18/2018   7:17 PM              0 DLConversion.log

***************************************************************************************************

Started processing at [09/18/2018 19:17:22].

***************************************************************************************************



Running script version [1.0].



***************************************************************************************************



This function imports the on premises secured credentials file....

The on premises credentials file was imported successfully.



This function imports the Office 365 secured credentials file....

The Office 365 credentials file was imported successfully.



This function creates the powershell session to on premises Exchange....

The powershell session to on premises Exchange was created successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function creates the powershell session to AAD Connect....

The powershell session to AAD Connect was created successfully.



This function imports the powershell session to on premises Exchange....

WARNING: The names of some imported commands from the module 'tmp_y0ib5tyw.pmz' include unapproved verbs that might make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_y0ib5tyw.pmz

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_y0ib5tyw.pmz\tmp_y0ib5tyw.pmz.psm1

Description       : Implicit remoting for
https://webmail.domain.com/powershell

Guid              : 1dfe9d4c-8ca2-4de2-aa8c-8e0281af907c

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_y0ib5tyw.pmz

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-ADPermission, Add-ADPermission], [Add-AvailabilityAddressSpace,
                     Add-AvailabilityAddressSpace], [Add-ContentFilterPhrase, Add-ContentFilterPhrase],
                     [Add-DatabaseAvailabilityGroupServer, Add-DatabaseAvailabilityGroupServer]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to on premises Exchange was imported successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_rt1gncnz.op4' include unapproved verbs that might make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_rt1gncnz.op4

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_rt1gncnz.op4\tmp_rt1gncnz.op4.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : f829f0b4-a669-4e18-a789-4afa9e4e9bd0

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_rt1gncnz.op4

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



This function collects the on premises distribution list configuration....

The on premises distribution list information was collected successfully.



This function collects the Office 365 distribution list configuration....

The operation couldn't be performed because object 'Migrate' couldn't be found on

'CO1PR06A002DC02.NAMPR06A002.prod.outlook.com'.
     + CategoryInfo          : NotSpecified: (:) [Get-DistributionGroup], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=MWHPR06MB2446,RequestId=bef7d47e-8d2d-4c75-a6d4-40264dee7723,TimeStamp=9/18/2018

7:17:47 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException]

F71693B4,Microsoft.Exchange.Management.RecipientTasks.GetDistributionGroup
     + PSComputerName        : outlook.office365.com

The operation couldn't be performed because object 'Migrate' couldn't be found on

'CO1PR06A002DC02.NAMPR06A002.prod.outlook.com'.
     + CategoryInfo          : NotSpecified: (:) [Get-DistributionGroup], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=MWHPR06MB2446,RequestId=bef7d47e-8d2d-4c75-a6d4-40264dee7723,TimeStamp=9/18/2018
     7:17:47 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException] F71693B4,Microsoft.Exchange.Management.Rec
   ipientTasks.GetDistributionGroup
     + PSComputerName        : outlook.office365.com



ERROR: The Office 365 distribution list information could not be collected - exiting.

ERROR: The operation couldn't be performed because object 'Migrate' couldn't be found on 'CO1PR06A002DC02.NAMPR06A002.prod.outlook.com'.


This function cleans up all powershell sessions....

All powershell sessions have been cleaned up successfully.





***************************************************************************************************

Finished processing at [09/18/2018 19:17:47].

***************************************************************************************************


===============================================================================


===============================================================================

Attempting to convert the distribution group Migrate without ignoring invalid managers or invalid members.  The group contains another distribution or security group that is not mail enabled.  An error is generated and the script stops.


PS C:\Scripts> .\ConvertDL.ps1 -dlToConvert Migrate -ignoreInvalidDLMember:$FALSE -ignoreInvalidManagedByMember:$FALSE




     Directory: C:\Scripts





Mode                LastWriteTime         Length Name

----                -------------         ------ ----

-a----        9/19/2018   2:11 PM              0 DLConversion.log

***************************************************************************************************

Started processing at [09/19/2018 14:11:07].

***************************************************************************************************



Running script version [1.0].



***************************************************************************************************



This function imports the on premises secured credentials file....

The on premises credentials file was imported successfully.



This function imports the Office 365 secured credentials file....

The Office 365 credentials file was imported successfully.



This function creates the powershell session to on premises Exchange....

The powershell session to on premises Exchange was created successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function creates the powershell session to AAD Connect....

The powershell session to AAD Connect was created successfully.



This function imports the powershell session to on premises Exchange....

WARNING: The names of some imported commands from the module 'tmp_rmsylwqo.1zq' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_rmsylwqo.1zq

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_rmsylwqo.1zq\tmp_rmsylwqo.1zq.psm1

Description       : Implicit remoting for
https://webmail.domain.com/powershell

Guid              : bb38fffd-b692-41c6-bb7f-ac49fe3a006b

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_rmsylwqo.1zq

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-ADPermission, Add-ADPermission], [Add-AvailabilityAddressSpace,
                     Add-AvailabilityAddressSpace], [Add-ContentFilterPhrase, Add-ContentFilterPhrase],
                     [Add-DatabaseAvailabilityGroupServer, Add-DatabaseAvailabilityGroupServer]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to on premises Exchange was imported successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_4korcvyz.ikr' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_4korcvyz.ikr

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_4korcvyz.ikr\tmp_4korcvyz.ikr.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 1a019be1-7a24-410f-b38e-37dbcc282021

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_4korcvyz.ikr

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



This function collects the on premises distribution list configuration....

The on premises distribution list information was collected successfully.



This function collects the Office 365 distribution list configuration....

The Office 365 distribution list information was collected successfully.



This function validates a cloud DLs saftey to migrate....

The DL is safe to proeced for conversion - source of authority is on-premises.



This function writes the on prmeises distribution list configuration to XML....

The on premises distribution list information was written to XML successfully.



This function writes the Office 365 distribution list configuration to XML....

The Office 365 distribution list information was written to XML successfully.



This function collections the on premises DL membership....

The DL membership was collected successfully.



This function writes the on prmeises distribution list membership configuration to XML....

The on premises distribution list membership information was written to XML successfully.



This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



Begin processing a DL membership array.

This function builds an array of DL members or multivalued attributes....

ERROR: Domain Users

ERROR: A non-mail enabled or Office 365 object was found in the group.

ERROR: Script invoked without skipping invalid DL Member.

ERROR: The object must be removed or mail enabled.

ERROR: EXITING.


This function cleans up all powershell sessions....

All powershell sessions have been cleaned up successfully.





***************************************************************************************************

Finished processing at [09/19/2018 14:11:55].

***************************************************************************************************


===============================================================================


===============================================================================

Attempting to convert the distribution group Migrate without ignoring invalid managers or invalid members.  The group contains another mail enabled distribution group that has not been migrated to Office 365.  The script automatically stops as all sub groups need to be migrated prior to top level groups.  The script was also run with –ignoreInvalidDLMembers TRUE – all non-mail enabled members or members not represented in Office 365 ar automatically ignored.


PS C:\Scripts> .\ConvertDL.ps1 -dlToConvert Migrate -ignoreInvalidDLMember:$TRUE -ignoreInvalidManagedByMember:$FALSE




     Directory: C:\Scripts





Mode                LastWriteTime         Length Name

----                -------------         ------ ----

-a----        9/19/2018   2:22 PM              0 DLConversion.log

***************************************************************************************************

Started processing at [09/19/2018 14:22:24].

***************************************************************************************************



Running script version [1.0].



***************************************************************************************************



This function imports the on premises secured credentials file....

The on premises credentials file was imported successfully.



This function imports the Office 365 secured credentials file....

The Office 365 credentials file was imported successfully.



This function creates the powershell session to on premises Exchange....

The powershell session to on premises Exchange was created successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function creates the powershell session to AAD Connect....

The powershell session to AAD Connect was created successfully.



This function imports the powershell session to on premises Exchange....

WARNING: The names of some imported commands from the module 'tmp_b11x0ew3.20l' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_b11x0ew3.20l

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_b11x0ew3.20l\tmp_b11x0ew3.20l.psm1

Description       : Implicit remoting for
https://webmail.domain.com/powershell

Guid              : 3c49dbae-b2af-428e-9be4-94ffc63126a4

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_b11x0ew3.20l

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-ADPermission, Add-ADPermission], [Add-AvailabilityAddressSpace,
                     Add-AvailabilityAddressSpace], [Add-ContentFilterPhrase, Add-ContentFilterPhrase],
                     [Add-DatabaseAvailabilityGroupServer, Add-DatabaseAvailabilityGroupServer]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to on premises Exchange was imported successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_ti245wqn.qju' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_ti245wqn.qju

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_ti245wqn.qju\tmp_ti245wqn.qju.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 4c2cf1a7-0042-4595-9025-98728851b5ed

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_ti245wqn.qju

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



This function collects the on premises distribution list configuration....

The on premises distribution list information was collected successfully.



This function collects the Office 365 distribution list configuration....

The Office 365 distribution list information was collected successfully.



This function validates a cloud DLs saftey to migrate....

The DL is safe to proeced for conversion - source of authority is on-premises.



This function writes the on prmeises distribution list configuration to XML....

The on premises distribution list information was written to XML successfully.



This function writes the Office 365 distribution list configuration to XML....

The Office 365 distribution list information was written to XML successfully.



This function collections the on premises DL membership....

The DL membership was collected successfully.



This function writes the on prmeises distribution list membership configuration to XML....

The on premises distribution list membership information was written to XML successfully.



This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



Begin processing a DL membership array.

This function builds an array of DL members or multivalued attributes....

Processing mail enabled DL member:

Journal Mailbox

Processing mail enabled DL member:

Brian Murphy

Processing mail enabled DL member:

Timothy McMichael

Processing mail enabled DL member:

Migrate1

Processing mail enabled DL member:

Migrate2

Processing non-mailenabled DL member:

Team Manager

Processing mail enabled DL member:

Dynamic

The following object was intentionally skipped - object type not replicated to Exchange Online

Test Contact


Processing mail enabled DL member:

NotReplicated

The following SMTP address was added to the array:

journal@domain.org

The following SMTP address was added to the array:

brian@domain.com

The following SMTP address was added to the array:

tmcmichael@domain.org

The following SMTP address was added to the array:

Migrate1@domain.org

The following SMTP address was added to the array:

Migrate2@domain.org

The following SMTP address was added to the array:

teammanager@domain.org

The following SMTP address was added to the array:

Dynamic@domain.org

The following SMTP address was added to the array:

notreplicate@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_2cmzyxkm.gbx' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_2cmzyxkm.gbx

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_2cmzyxkm.gbx\tmp_2cmzyxkm.gbx.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 455ba332-1b14-49d2-891d-1701e6fdea84

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_2cmzyxkm.gbx

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

journal@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

brian@domain.com

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

tmcmichael@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate1@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate1@domain.org

False

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate2@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate2@domain.org

True

ERROR: A distribution list was found as a sub-member or on a multi-valued attribute.

ERROR: The distribution list has not been migrated to Office 365 (DirSync Flag is TRUE)

ERROR: All sub lists or lists with permissions must be migrated before proceeding.

This function cleans up all powershell sessions....

All powershell sessions have been cleaned up successfully.




***************************************************************************************************

Finished processing at [09/19/2018 14:23:08].

***************************************************************************************************


===============================================================================


===============================================================================

Attempting to convert the distribution group Migrate without ignoring invalid managers or invalid members.  The group contains a mailbox recipient that is not represented in Office 365.  Although the ignoreInvalidDLMember is set to $TRUE – since the object should be a valid object present in Office 365 the script stops.  (In this case the user is in an OU that is not synchronized to Office 365).


PS C:\Scripts> .\ConvertDL.ps1 -dlToConvert Migrate -ignoreInvalidDLMember:$TRUE -ignoreInvalidManagedByMember:$FALSE




     Directory: C:\Scripts





Mode                LastWriteTime         Length Name

----                -------------         ------ ----

-a----        9/19/2018   2:27 PM              0 DLConversion.log

***************************************************************************************************

Started processing at [09/19/2018 14:27:17].

***************************************************************************************************



Running script version [1.0].



***************************************************************************************************



This function imports the on premises secured credentials file....

The on premises credentials file was imported successfully.



This function imports the Office 365 secured credentials file....

The Office 365 credentials file was imported successfully.



This function creates the powershell session to on premises Exchange....

The powershell session to on premises Exchange was created successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function creates the powershell session to AAD Connect....

The powershell session to AAD Connect was created successfully.



This function imports the powershell session to on premises Exchange....

WARNING: The names of some imported commands from the module 'tmp_tvpecjxl.5ga' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_tvpecjxl.5ga

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_tvpecjxl.5ga\tmp_tvpecjxl.5ga.psm1

Description       : Implicit remoting for
https://webmail.domain.com/powershell

Guid              : 0985f143-cf95-4102-87d9-030408dd4bc8

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_tvpecjxl.5ga

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-ADPermission, Add-ADPermission], [Add-AvailabilityAddressSpace,
                     Add-AvailabilityAddressSpace], [Add-ContentFilterPhrase, Add-ContentFilterPhrase],
                     [Add-DatabaseAvailabilityGroupServer, Add-DatabaseAvailabilityGroupServer]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to on premises Exchange was imported successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_i4ivhhbw.2tu' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_i4ivhhbw.2tu

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_i4ivhhbw.2tu\tmp_i4ivhhbw.2tu.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 86d813da-91e6-4e12-a369-577d696f60f4

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_i4ivhhbw.2tu

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



This function collects the on premises distribution list configuration....

The on premises distribution list information was collected successfully.



This function collects the Office 365 distribution list configuration....

The Office 365 distribution list information was collected successfully.



This function validates a cloud DLs saftey to migrate....

The DL is safe to proeced for conversion - source of authority is on-premises.



This function writes the on prmeises distribution list configuration to XML....

The on premises distribution list information was written to XML successfully.



This function writes the Office 365 distribution list configuration to XML....

The Office 365 distribution list information was written to XML successfully.



This function collections the on premises DL membership....

The DL membership was collected successfully.



This function writes the on prmeises distribution list membership configuration to XML....

The on premises distribution list membership information was written to XML successfully.



This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



Begin processing a DL membership array.

This function builds an array of DL members or multivalued attributes....

Processing mail enabled DL member:

Journal Mailbox

Processing mail enabled DL member:

Brian Murphy

Processing mail enabled DL member:

Timothy McMichael

Processing mail enabled DL member:

Migrate1

Processing non-mailenabled DL member:

Team Manager

Processing mail enabled DL member:

Dynamic

The following object was intentionally skipped - object type not replicated to Exchange Online

Test Contact

Processing mail enabled DL member:

NotReplicated

The following SMTP address was added to the array:

journal@domain.org

The following SMTP address was added to the array:

brian@domain.com

The following SMTP address was added to the array:

tmcmichael@domain.org

The following SMTP address was added to the array:

Migrate1@domain.org

The following SMTP address was added to the array:

teammanager@domain.org

The following SMTP address was added to the array:

Dynamic@domain.org

The following SMTP address was added to the array:

notreplicate@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_rysbip4g.faj' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_rysbip4g.faj

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_rysbip4g.faj\tmp_rysbip4g.faj.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 95f11f7e-d775-4d52-8cb5-b4ba67dd7e35

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_rysbip4g.faj

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

journal@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

brian@domain.com

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

tmcmichael@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate1@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate1@domain.org

False

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

teammanager@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Dynamic@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

notreplicate@domain.org


The operation couldn't be performed because object 'notreplicate@domain.org' couldn't be found on

'CO1PR06A002DC02.NAMPR06A002.prod.outlook.com'.
     + CategoryInfo          : NotSpecified: (:) [Get-Recipient], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=MWHPR06MB2446,RequestId=f6a99890-192d-4630-b244-337d6c706c97,TimeStamp=9/19/2018
     2:28:03 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException] 5A65645E,Microsoft.Exchange.Management.Rec
   ipientTasks.GetRecipient
     + PSComputerName        : outlook.office365.com



ERROR: The recipients were not found in Office 365 - exiting.

ERROR: The operation couldn't be performed because object 'notreplicate@domain.org' couldn't be found on 'CO1PR06A002DC02.NAMPR06A002.prod.outlook.com'.


This function cleans up all powershell sessions....

All powershell sessions have been cleaned up successfully.





***************************************************************************************************

Finished processing at [09/19/2018 14:28:04].

***************************************************************************************************


===============================================================================


===============================================================================

Attempting to convert the distribution group Migrate without ignoring invalid managers or invalid members.  The managed by attribute was set through Active Directory Users and Computers and a non-mail enabled object was selected.  IgnoreInvalidManagedByMember is set to $FALSE – therefore the script ends because managed by cannot be established.  The managedBy recipient would need to be removed or ignoreInvalidManagedByMember set to $TRUE.


PS C:\Scripts> .\ConvertDL.ps1 -dlToConvert Migrate -ignoreInvalidDLMember:$TRUE -ignoreInvalidManagedByMember:$FALSE




     Directory: C:\Scripts





Mode                LastWriteTime         Length Name

----                -------------         ------ ----

-a----        9/19/2018   2:35 PM              0 DLConversion.log

***************************************************************************************************

Started processing at [09/19/2018 14:35:02].

***************************************************************************************************



Running script version [1.0].



***************************************************************************************************



This function imports the on premises secured credentials file....

The on premises credentials file was imported successfully.



This function imports the Office 365 secured credentials file....

The Office 365 credentials file was imported successfully.



This function creates the powershell session to on premises Exchange....

The powershell session to on premises Exchange was created successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function creates the powershell session to AAD Connect....

The powershell session to AAD Connect was created successfully.



This function imports the powershell session to on premises Exchange....

WARNING: The names of some imported commands from the module 'tmp_u2zod0xm.0jy' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_u2zod0xm.0jy

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_u2zod0xm.0jy\tmp_u2zod0xm.0jy.psm1

Description       : Implicit remoting for
https://webmail.domain.com/powershell

Guid              : 2a209690-a2fd-4d0e-89e9-e52df5c5573e

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_u2zod0xm.0jy

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-ADPermission, Add-ADPermission], [Add-AvailabilityAddressSpace,
                     Add-AvailabilityAddressSpace], [Add-ContentFilterPhrase, Add-ContentFilterPhrase],
                     [Add-DatabaseAvailabilityGroupServer, Add-DatabaseAvailabilityGroupServer]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to on premises Exchange was imported successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_i53fb2xz.uuu' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_i53fb2xz.uuu

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_i53fb2xz.uuu\tmp_i53fb2xz.uuu.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 20a82db7-7a4b-4034-95bc-6934f15f4c7b

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_i53fb2xz.uuu

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



This function collects the on premises distribution list configuration....

The on premises distribution list information was collected successfully.



This function collects the Office 365 distribution list configuration....

The Office 365 distribution list information was collected successfully.



This function validates a cloud DLs saftey to migrate....

The DL is safe to proeced for conversion - source of authority is on-premises.



This function writes the on prmeises distribution list configuration to XML....

The on premises distribution list information was written to XML successfully.



This function writes the Office 365 distribution list configuration to XML....

The Office 365 distribution list information was written to XML successfully.



This function collections the on premises DL membership....

The DL membership was collected successfully.



This function writes the on prmeises distribution list membership configuration to XML....

The on premises distribution list membership information was written to XML successfully.



This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



Begin processing a DL membership array.

This function builds an array of DL members or multivalued attributes....

Processing mail enabled DL member:

Journal Mailbox

Processing mail enabled DL member:

Brian Murphy

Processing mail enabled DL member:

Timothy McMichael

Processing mail enabled DL member:

Migrate1

Processing non-mailenabled DL member:

Team Manager

Processing mail enabled DL member:

Dynamic

The following object was intentionally skipped - object type not replicated to Exchange Online

Test Contact

The following SMTP address was added to the array:

journal@domain.org

The following SMTP address was added to the array:

brian@domain.com

The following SMTP address was added to the array:

tmcmichael@domain.org

The following SMTP address was added to the array:

Migrate1@domain.org

The following SMTP address was added to the array:

teammanager@domain.org

The following SMTP address was added to the array:

Dynamic@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_l1gyiiem.qhr' include unapproved verbs that might

make them less discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the

Verbose parameter. For a list of approved verbs, type Get-Verb.



Name              : tmp_l1gyiiem.qhr

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_l1gyiiem.qhr\tmp_l1gyiiem.qhr.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : ffbd7762-080a-48fa-88c0-d7cf5089d656

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_l1gyiiem.qhr

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace],
                     [Add-o365DistributionGroupMember, Add-o365DistributionGroupMember],
                     [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission], [Add-o365MailboxLocation,
                     Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

journal@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

brian@domain.com

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

tmcmichael@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate1@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate1@domain.org

False

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

teammanager@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Dynamic@domain.org

The recipients were found in Office 365.



Begin processing a ManagedBy array.

This function builds an array of DL members or multivalued attributes....

ERROR: domain.local/Users/Test Manager

ERROR: A non-mail enabled or Office 365 object was found in ManagedBy.

ERROR: Script invoked without skipping invalid DL Member.

ERROR: The object must be removed or mail enabled.

ERROR: EXITING.


This function cleans up all powershell sessions....

All powershell sessions have been cleaned up successfully.





***************************************************************************************************

Finished processing at [09/19/2018 14:35:45].

***************************************************************************************************


===============================================================================


===============================================================================

Attempting to convert the distribution group Migrate without ignoring invalid managers or invalid members.  The invoke includes both ignore values – allowing us to skip


PS C:\Scripts> .\ConvertDL.ps1 -dlToConvert Migrate -ignoreInvalidDLMember:$TRUE -ignoreInvalidManagedByMember:$TRUE




     Directory: C:\Scripts





Mode                LastWriteTime         Length Name

----                -------------         ------ ----

-a----        9/19/2018   2:54 PM              0 DLConversion.log

***************************************************************************************************

Started processing at [09/19/2018 14:54:59].

***************************************************************************************************



Running script version [1.0].



***************************************************************************************************



This function imports the on premises secured credentials file....

The on premises credentials file was imported successfully.



This function imports the Office 365 secured credentials file....

The Office 365 credentials file was imported successfully.



This function creates the powershell session to on premises Exchange....

The powershell session to on premises Exchange was created successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function creates the powershell session to AAD Connect....

The powershell session to AAD Connect was created successfully.



This function imports the powershell session to on premises Exchange....

WARNING: The names of some imported commands from the module 'tmp_nkc0cq2u.nri' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_nkc0cq2u.nri

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_nkc0cq2u.nri\tmp_nkc0cq2u.nri.psm1

Description       : Implicit remoting for
https://webmail.domain.com/powershell

Guid              : 63c5f70a-44fa-47ed-95ef-749afa5a5d44

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_nkc0cq2u.nri

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-ADPermission, Add-ADPermission], [Add-AvailabilityAddressSpace, Add-AvailabilityAddressSpace],
                     [Add-ContentFilterPhrase, Add-ContentFilterPhrase], [Add-DatabaseAvailabilityGroupServer,
                     Add-DatabaseAvailabilityGroupServer]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to on premises Exchange was imported successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_qxckji5q.2cy' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_qxckji5q.2cy

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_qxckji5q.2cy\tmp_qxckji5q.2cy.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 4428cefd-6fa1-4ed9-9e49-baae4c962b8d

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_qxckji5q.2cy

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



This function collects the on premises distribution list configuration....

The on premises distribution list information was collected successfully.



This function collects the Office 365 distribution list configuration....

The Office 365 distribution list information was collected successfully.



This function validates a cloud DLs saftey to migrate....

The DL is safe to proeced for conversion - source of authority is on-premises.



This function writes the on prmeises distribution list configuration to XML....

The on premises distribution list information was written to XML successfully.



This function writes the Office 365 distribution list configuration to XML....

The Office 365 distribution list information was written to XML successfully.



This function collections the on premises DL membership....

The DL membership was collected successfully.



This function writes the on prmeises distribution list membership configuration to XML....

The on premises distribution list membership information was written to XML successfully.



This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



Begin processing a DL membership array.

This function builds an array of DL members or multivalued attributes....

Processing mail enabled DL member:

Journal Mailbox

Processing mail enabled DL member:

Brian Murphy

Processing mail enabled DL member:

Timothy McMichael

Processing mail enabled DL member:

Migrate1

Processing non-mailenabled DL member:

Team Manager

Processing mail enabled DL member:

Dynamic

The following object was intentionally skipped - object type not replicated to Exchange Online

Test Contact


The following SMTP address was added to the array:

journal@domain.org

The following SMTP address was added to the array:

brian@domain.com

The following SMTP address was added to the array:

tmcmichael@domain.org

The following SMTP address was added to the array:

Migrate1@domain.org

The following SMTP address was added to the array:

teammanager@domain.org

The following SMTP address was added to the array:

Dynamic@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_1qvzwqrs.bux' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_1qvzwqrs.bux

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_1qvzwqrs.bux\tmp_1qvzwqrs.bux.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 87c6283a-a172-48b8-b31c-d5b966941fd5

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_1qvzwqrs.bux

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

journal@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

brian@domain.com

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

tmcmichael@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate1@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate1@domain.org

False

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

teammanager@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Dynamic@domain.org

The recipients were found in Office 365.



Begin processing a ManagedBy array.

This function builds an array of DL members or multivalued attributes....

The following object was intentionally skipped - object type not replicated to Exchange Online

domain.local/Users/Test Manager


Processing Managed By member:

The following SMTP address was added to the array:

bmoran@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_swg5mjit.e3j' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_swg5mjit.e3j

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_swg5mjit.e3j\tmp_swg5mjit.e3j.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : e769a4d9-fe17-4170-8634-ae2cecc1654c

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_swg5mjit.e3j

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

bmoran@domain.org

The recipients were found in Office 365.



Begin processing a ModeratedBy array.

This function builds an array of DL members or multivalued attributes....

Processing ModeratedBy, GrantSendOnBehalfTo, AcceptMessagesOnlyFromSendersorMembers, RejectMessagesFromSendersOrMembers, or BypassModerationFromSendersOrMembers member:

The following SMTP address was added to the array:

tmcmichael@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_qt1dzaih.egn' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_qt1dzaih.egn

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_qt1dzaih.egn\tmp_qt1dzaih.egn.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 086dd663-c6d8-45b9-9836-7745e03dd255

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_qt1dzaih.egn

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

tmcmichael@domain.org

The recipients were found in Office 365.



Begin processing a GrantSendOnBehalfTo array

This function builds an array of DL members or multivalued attributes....

Processing ModeratedBy, GrantSendOnBehalfTo, AcceptMessagesOnlyFromSendersorMembers, RejectMessagesFromSendersOrMembers, or BypassModerationFromSendersOrMembers member:

The following SMTP address was added to the array:

tmcmichael@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_asuxfjkc.4lz' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_asuxfjkc.4lz

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_asuxfjkc.4lz\tmp_asuxfjkc.4lz.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 53da7cd1-71c7-4510-aec5-d495c8c08987

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_asuxfjkc.4lz

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

tmcmichael@domain.org

The recipients were found in Office 365.



Begin processing a AcceptMessagesOnlyFromSendersOrMembers array

This function builds an array of DL members or multivalued attributes....

Processing ModeratedBy, GrantSendOnBehalfTo, AcceptMessagesOnlyFromSendersorMembers, RejectMessagesFromSendersOrMembers, or BypassModerationFromSendersOrMembers member:

Processing ModeratedBy, GrantSendOnBehalfTo, AcceptMessagesOnlyFromSendersorMembers, RejectMessagesFromSendersOrMembers, or BypassModerationFromSendersOrMembers member:

The following SMTP address was added to the array:

bmoran@domain.org

The following SMTP address was added to the array:

Migrate1@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_v3xtlz25.hej' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_v3xtlz25.hej

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_v3xtlz25.hej\tmp_v3xtlz25.hej.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 019f80be-f9d7-4082-bf5b-955c059d170d

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_v3xtlz25.hej

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

bmoran@domain.org

The recipients were found in Office 365.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate1@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate1@domain.org

False

The recipients were found in Office 365.



Begin processing RejectMessagesFromSendersOrMembers array

This function builds an array of DL members or multivalued attributes....

Processing ModeratedBy, GrantSendOnBehalfTo, AcceptMessagesOnlyFromSendersorMembers, RejectMessagesFromSendersOrMembers, or BypassModerationFromSendersOrMembers member:

The following SMTP address was added to the array:

Migrate2@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_zmxben01.bs4' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_zmxben01.bs4

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_zmxben01.bs4\tmp_zmxben01.bs4.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : f13bceb8-a02e-4242-aef7-b63f0adb27d6

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_zmxben01.bs4

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate2@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate2@domain.org

False

The recipients were found in Office 365.



Begin processing BypassModerationFromSendersOrMembers array

This function builds an array of DL members or multivalued attributes....

Processing ModeratedBy, GrantSendOnBehalfTo, AcceptMessagesOnlyFromSendersorMembers, RejectMessagesFromSendersOrMembers, or BypassModerationFromSendersOrMembers member:

The following SMTP address was added to the array:

Migrate1@domain.org



The array was built successfully.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_kqtp23ls.xwx' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_kqtp23ls.xwx

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_kqtp23ls.xwx\tmp_kqtp23ls.xwx.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 31e5aaad-348d-4513-bc4c-01e4cdfb5bc9

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_kqtp23ls.xwx

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function validates that all objects in the passed array exist in Office 365....

Testing user in Office 365...

Migrate1@domain.org

The recipients were found in Office 365.



This function tests to see if any sub groups or groups assigned permissions have been migrated....

Now testing group...

Migrate1@domain.org

False

The recipients were found in Office 365.



This function moves group to the non-sync OU

The group has been moved successfully.



Gets active directory domain controllers...

Succesfully obtained domain controllers.



Gets active directory domain...

Succesfully obtained domain.



Replicates the specified domain controller...

Syncing partition: DC=domain,DC=local

CALLBACK MESSAGE: SyncAll Finished.

SyncAll terminated with no errors.



Successfully replicated the domain controller.



Replicates the specified domain controller...

Syncing partition: DC=domain,DC=local

CALLBACK MESSAGE: SyncAll Finished.

SyncAll terminated with no errors.



Successfully replicated the domain controller.



Replicates the specified domain controller...

Syncing partition: DC=domain,DC=local

CALLBACK MESSAGE: SyncAll Finished.

SyncAll terminated with no errors.



Successfully replicated the domain controller.



Invoking AADConnect Delta Sync Remotely

This function triggers the ad connect process to sync changes...



PSComputerName : azure-adconnect.domain.local

RunspaceId     : 764c99c8-6e48-415a-b319-9847cce42922

Result         : Success



The AD Connect instance has been successfully initiated.



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_ffoelvjn.lws' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_ffoelvjn.lws

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_ffoelvjn.lws\tmp_ffoelvjn.lws.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 001ce520-4538-4f59-a5d4-710d8097b338

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_ffoelvjn.lws

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



Wating for original DL deletion from Office 365

Wating for original DL deletion from Office 365

Wating for original DL deletion from Office 365

The operation couldn't be performed because object 'Migrate@domain.org' couldn't be found on

'CO1PR06A002DC03.NAMPR06A002.prod.outlook.com'.
     + CategoryInfo          : NotSpecified: (:) [Get-Recipient], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=DM6PR06MB4026,RequestId=1f8fe3eb-6b61-4564-be56-c8af5d303a3a,TimeStamp=9/19/2018 3:00:02 PM] [Fail
    ureCategory=Cmdlet-ManagementObjectNotFoundException] 24B7AD96,Microsoft.Exchange.Management.RecipientTasks.GetRecipient
     + PSComputerName        : outlook.office365.com



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_3hao5uao.he4' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_3hao5uao.he4

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_3hao5uao.he4\tmp_3hao5uao.he4.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : f93cff62-1cce-4d83-bce9-991c54b5127e

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_3hao5uao.he4

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function creates the cloud DL with the minimum settings...

Universal

New! Office 365 Groups are the next generation of distribution lists.

Groups give teams shared tools for collaborating using email, files, a calendar, and more.

You can start right away using the New-UnifiedGroup cmdlet.



RunspaceId                             : 8ca722dd-6bea-470d-9fc9-36dc4c73148c

GroupType                              : Universal

SamAccountName                         : Migrate574691357943970

BypassNestedModerationEnabled          : False

IsDirSynced                            : False

ManagedBy                              : {domainAdmin}

MemberJoinRestriction                  : Closed

MemberDepartRestriction                : Open

MigrationToUnifiedGroupInProgress      : False

ExpansionServer                        :

ReportToManagerEnabled                 : False

ReportToOriginatorEnabled              : True

SendOofMessageToOriginatorEnabled      : False

AcceptMessagesOnlyFrom                 : {}

AcceptMessagesOnlyFromDLMembers        : {}

AcceptMessagesOnlyFromSendersOrMembers : {}

AddressListMembership                  : {\Default Global Address List, \All Recipients(VLV), \Groups(VLV), \All Groups(VLV)...}

AdministrativeUnits                    : {}

Alias                                  : Migrate

ArbitrationMailbox                     : SystemMailbox{bb558c35-97f1-4cb9-8ff7-d53741dc928c}

BypassModerationFromSendersOrMembers   : {}

OrganizationalUnit                     : nampr06a002.prod.outlook.com/Microsoft Exchange Hosted
                                          Organizations/domainSquad.onmicrosoft.com

CustomAttribute1                       :

CustomAttribute10                      :

CustomAttribute11                      :

CustomAttribute12                      :

CustomAttribute13                      :

CustomAttribute14                      :

CustomAttribute15                      :

CustomAttribute2                       :

CustomAttribute3                       :

CustomAttribute4                       :

CustomAttribute5                       :

CustomAttribute6                       :

CustomAttribute7                       :

CustomAttribute8                       :

CustomAttribute9                       :

ExtensionCustomAttribute1              : {}

ExtensionCustomAttribute2              : {}

ExtensionCustomAttribute3              : {}

ExtensionCustomAttribute4              : {}

ExtensionCustomAttribute5              : {}

DisplayName                            : Migrate

EmailAddresses                         : {SMTP:Migrate@domain.org}

GrantSendOnBehalfTo                    : {}

ExternalDirectoryObjectId              : d10bc5bd-01dc-4708-a98a-a9c2294149d6

HiddenFromAddressListsEnabled          : False

LastExchangeChangedTime                :

LegacyExchangeDN                       : /o=ExchangeLabs/ou=Exchange Administrative Group
                                          (FYDIBOHF23SPDLT)/cn=Recipients/cn=002d4cd657784b01bccf8b85e5c35519-Migrate

MaxSendSize                            : Unlimited

MaxReceiveSize                         : Unlimited

ModeratedBy                            : {}

ModerationEnabled                      : False

PoliciesIncluded                       : {}

PoliciesExcluded                       : {{26491cfc-9e50-4857-861b-0cb8df22b5d7}}

EmailAddressPolicyEnabled              : False

PrimarySmtpAddress                     : Migrate@domain.org

RecipientType                          : MailUniversalDistributionGroup

RecipientTypeDetails                   : MailUniversalDistributionGroup

RejectMessagesFrom                     : {}

RejectMessagesFromDLMembers            : {}

RejectMessagesFromSendersOrMembers     : {}

RequireSenderAuthenticationEnabled     : True

SimpleDisplayName                      :

SendModerationNotifications            : Always

UMDtmfMap                              : {emailAddress:6447283, lastNameFirstName:6447283, firstNameLastName:6447283}

WindowsEmailAddress                    : Migrate@domain.org

MailTip                                :

MailTipTranslations                    : {}

Identity                               : Migrate

Id                                     : Migrate

IsValid                                : True

ExchangeVersion                        : 0.10 (14.0.100.0)

Name                                   : Migrate

DistinguishedName                      : CN=Migrate,OU=domainSquad.onmicrosoft.com,OU=Microsoft Exchange Hosted
                                          Organizations,DC=NAMPR06A002,DC=prod,DC=outlook,DC=com

ObjectCategory                         : NAMPR06A002.prod.outlook.com/Configuration/Schema/Group

ObjectClass                            : {top, group}

WhenChanged                            : 9/19/2018 3:00:16 PM

WhenCreated                            : 9/19/2018 3:00:16 PM

WhenChangedUTC                         : 9/19/2018 3:00:16 PM

WhenCreatedUTC                         : 9/19/2018 3:00:16 PM

OrganizationId                         : NAMPR06A002.prod.outlook.com/Microsoft Exchange Hosted
                                          Organizations/domainSquad.onmicrosoft.com - NAMPR06A002.prod.outlook.com/ConfigurationUn
                                          its/domainSquad.onmicrosoft.com/Configuration

Guid                                   : b735426e-9551-4441-a710-803946ea176c

OriginatingServer                      : CO1PR06A002DC02.NAMPR06A002.prod.outlook.com

ObjectState                            : Unchanged



Distribution list created successfully in Exchange Online / Office 365.



This function updates the cloud DL settings to match on premise...

This does not update the multivalued attributes...

Distribution group properties updated successfully.



Processing DL Membership member to Office 365...

journal@domain.org

This function sets the multi-valued attributes

DLMembership

The mutilvalued attribute was updated successfully.

DLMembership



Processing DL Membership member to Office 365...

brian@domain.com

This function sets the multi-valued attributes

DLMembership

The mutilvalued attribute was updated successfully.

DLMembership



Processing DL Membership member to Office 365...

tmcmichael@domain.org

This function sets the multi-valued attributes

DLMembership

The mutilvalued attribute was updated successfully.

DLMembership



Processing DL Membership member to Office 365...

Migrate1@domain.org

This function sets the multi-valued attributes

DLMembership

The mutilvalued attribute was updated successfully.

DLMembership



Processing DL Membership member to Office 365...

teammanager@domain.org

This function sets the multi-valued attributes

DLMembership

The mutilvalued attribute was updated successfully.

DLMembership



Processing DL Membership member to Office 365...

Dynamic@domain.org

This function sets the multi-valued attributes

DLMembership

The mutilvalued attribute was updated successfully.

DLMembership



Processing Bypass Managed By member to Office 365...

bmoran@domain.org

This function sets the multi-valued attributes

ManagedBy

The mutilvalued attribute was updated successfully.

ManagedBy



Processing Moderated By member to Office 365...

tmcmichael@domain.org

This function sets the multi-valued attributes

ModeratedBy

The mutilvalued attribute was updated successfully.

ModeratedBy



Processing Grant Send On Behalf To Array member to Office 365...

tmcmichael@domain.org

This function sets the multi-valued attributes

GrantSendOnBehalfTo

The mutilvalued attribute was updated successfully.

GrantSendOnBehalfTo



Processing Accept Messages Only From Senders Or Members member to Office 365...

bmoran@domain.org

This function sets the multi-valued attributes

AcceptMessagesOnlyFromSendersOrMembers

The mutilvalued attribute was updated successfully.

AcceptMessagesOnlyFromSendersOrMembers



Processing Accept Messages Only From Senders Or Members member to Office 365...

Migrate1@domain.org

This function sets the multi-valued attributes

AcceptMessagesOnlyFromSendersOrMembers

The mutilvalued attribute was updated successfully.

AcceptMessagesOnlyFromSendersOrMembers



Processing Reject Messages From Senders Or Members member to Office 365...

Migrate2@domain.org

This function sets the multi-valued attributes

RejectMessagesFromSendersOrMembers

The mutilvalued attribute was updated successfully.

RejectMessagesFromSendersOrMembers



Processing Bypass Moderation From Senders Or Members member to Office 365...

Migrate1@domain.org

This function sets the multi-valued attributes

BypassModerationFromSendersOrMembers

The mutilvalued attribute was updated successfully.

BypassModerationFromSendersOrMembers



This function resets the Office 365 powershell sessions....

This function removes the Office 365 powershell sessions....

All powershell sessions have been cleaned up successfully.



This function creates the powershell session to Office 365....

The powershell session to Office 365 was created successfully.



This function imports the powershell session to Office 365....

WARNING: The names of some imported commands from the module 'tmp_w0eyp2oc.n3o' include unapproved verbs that might make them less

discoverable. To find the commands with unapproved verbs, run the Import-Module command again with the Verbose parameter. For a list of

approved verbs, type Get-Verb.



Name              : tmp_w0eyp2oc.n3o

Path              : C:\Users\admin.domain\AppData\Local\Temp\tmp_w0eyp2oc.n3o\tmp_w0eyp2oc.n3o.psm1

Description       : Implicit remoting for
https://outlook.office365.com/powershell-liveID/

Guid              : 1d8d7722-910f-43e6-ad74-8a8bb4e0a2e8

Version           : 1.0

ModuleBase        : C:\Users\admin.domain\AppData\Local\Temp\tmp_w0eyp2oc.n3o

ModuleType        : Script

PrivateData       : {ImplicitRemoting}

AccessMode        : ReadWrite

ExportedAliases   : {}

ExportedCmdlets   : {}

ExportedFunctions : {[Add-o365AvailabilityAddressSpace, Add-o365AvailabilityAddressSpace], [Add-o365DistributionGroupMember,
                     Add-o365DistributionGroupMember], [Add-o365MailboxFolderPermission, Add-o365MailboxFolderPermission],
                     [Add-o365MailboxLocation, Add-o365MailboxLocation]...}

ExportedVariables : {}

NestedModules     : {}



The powershell session to Office 365 was imported successfully.



All Office 365 powershell sessions have been refreshed.



This function collects the new office 365 distribution list configuration....

The on premises distribution list information was collected successfully.



This function collects the new office 365 distribution list member configuration....

The on premises distribution list information was collected successfully.



This function writes the new Office 365 distribution list configuration to XML....

The on premises distribution list information was written to XML successfully.



This function writes the new Office 365 distribution list membership configuration to XML....

The on premises distribution list information was written to XML successfully.



This function cleans up all powershell sessions....

All powershell sessions have been cleaned up successfully.


===============================================================================


Office 365: Challenges with Distribution Groups for Migrated Mailboxes and a Script Based Solution ( Script Version 1.1 )

$
0
0

===========================================================================================

Group Migration Script v1.1 –> https://github.com/timmcmic/DLConversion/blob/master/src/DLConversion.ps1

===========================================================================================


In script version 1.1 we introduced a new feature to control how the group is provisioned in Office 365.  When a group is create on-premises the group type can be established as either distribution or security.  The group type can be dynamically changed through Active Directory Users and Computers by changing the group type on the groups properties.


image


By changing the radio button to security the group type will change from mail universal distribution to mail universal security.


The same process is not available to administrators in Office 365.  When a distribution list is provisioned in Office 365 the group type selected is persisted.  If the group is created as a mail distribution group it can only be converted to a mail security group if deleted and recreated.  This would essentially prevent administrators from applying security rights to a group in the future. 


In version 1.0 of the script and the default settings in versions 1.1 the group type is retained.  If conversion of a mail enabled security group is selected the new group created in Office 365 is also created as a mail enabled security group.  The same is true for just a mail enabled distribution group.  In the past there have been conditions where this may not be the desired outcome.  For example – in the past security groups may have been provisioned but the desire is not to carry them forward as security groups in Office 365. 


Version 1.1 of the script implements a switch –GroupTypeOverride.  The administrator may specify a value of “DISTRIBUTION” or “SECURITY”.  This value will override the group type specified when creating the Office 365 distribution group.  In essence a security group on-premises may now be created as a distribution group in Office 365.


Here is an example of command execution:


ConvertDL.ps1 -dlToConvert Migrate -ignoreInvalidDLMember:$TRUE -ignoreInvalidManagedByMember:$TRUE -groupTypeOverride:"DISTRIBUTION"

Office 365: Dynamic distribution lists created by email domains.

$
0
0

Dynamic distribution lists offer excellent mechanisms to email groups of users based on their attribute rather than maintaining manual group membership.  One request I often receive is how can we create a distribution list for everyone that has their primary SMTP address within a certain domain.


By their initial design a dynamic distribution list supports a recipient filter property.  The recipient filter property allows administrators to specify a query of objects to ensure those objects are included in the dynamic distribution list.  With this in mind many administrators will attempt to utilize the recipient filter in attempts to filter a domain to create the dynamic distribution list.  Here is an example:


PS C:\> New-DynamicDistributionGroup -Name TestDynamicDL -RecipientFilter {PrimarySMTPAddress -like '*.consoto.com'}

Wildcards cannot be used as the first character. Please revise the filter criteria.
     + CategoryInfo          : NotSpecified: (:) [], TaskArgumentException
     + FullyQualifiedErrorId : [Server=MWHPR06MB2446,RequestId=c6124483-2c49-4542-a783-4177dbe9119e,TimeStamp=1/29/2019
     3:10:33 PM] [FailureCategory=Cmdlet-TaskArgumentException] AE6DCA3
     + PSComputerName        : ps.outlook.com


In the recipient filter the wildcard character cannot be the first character.  This effectively prevents us from querying everyone regardless of alias that contains the domain specified. 


Without the ability to lead off with a wild card character we need to be more creative in how we approach this solution.  I find the easiest and most common recommendation is to utilize a custom attribute that is not being utilized for another purpose.  In an environment where directory synchronization is available the custom attributes are sourced from on premises Active Directory.  Administrators have easy access to the custom attributes through the on-premises Exchange Management Shell.  Utilizing powershell administrators could craft a script that would find all objects with a given primary SMTP address where the designated custom attribute is not set to the predetermaned value.  The custom attribute can then be updated.  The script to perform these operations could be scheduled.  Here is an example:


#Gather all remote mailboxes where the primary SMTP address is *domain.com and where the custom attribute 10 is not already the domain attribute.

PS C:\> $mailboxes = Invoke-Command { Get-RemoteMailbox -ResultSize unlimited | where { $_.primarySMTPAddress -like "*domain.org" -and $_.customAttribute10 -ne "DOMAIN" } }

#Iterate through the array and set the custom attribute.

PS C:\> $mailboxes | % { Set-RemoteMailbox -identity $_.primarySMTPAddress -CustomAttribute10 "DOMAIN" }

#Iterate through all mailboxes where the custom attribute 10 is set to the defined value and where the primary smtp address is not at the designated domain.

#These are users whos primary SMTP address changed form the designated domain.

PS C:\> $mailboxes = Invoke-Command { Get-RemoteMailbox -ResultSize unlimited | where { $_.primarySMTPAddress -notlike "*domain.org" -and $_.customAttribute10 -eq "DOMAIN" } }

#Iterate through the array and NULL the custom attribute.

PS C:\> $mailboxes | % { Set-RemoteMailbox -identity $_.primarySMTPAddress -CustomAttribute10 $NULL }


There are some advantages to this approach.

  • The script can be scheduled eliminating administrator intervention.
  • The script pulls the smallest number of objects to be changed with each iteration through filtering.
  • The script utilizes custom attributes which are included in the default replication set with AD Connect.
  • The script changes the on premises value to match the replicated cloud value – ensuring that it is visually easy to determine how the values are derived.


There are some dis-advantages to this approach.


  • Distribution list membership is only updated / modified after the script has executed leading to delays in group membership delays in Office 365.


An alternate approach is to utilize the Azure Active Directory Connect synchronization rules to populate the designated custom attribute.  Using the ad connect rules editor we can create a low priority inbound rule.  The rule type would be a join, operate on a user object in the local active directory, and translate to a person object in Office 365.  We will transform the specified custom attribute using an expression searching for a field that contains a value.  Let us take a look at how this would operate.


The first item to look at is what attribute will be base the filter off of.  If we perform a metaverse search and locate a reference member, we can review the attributes of the user.  In our instance the mail attribute reflects the primary SMTP address of the user. 


image


Having identified the mail attribute as containing the information we want to filter on – we can begin creating the rule to modify the custom attribute.   The synchronization rule editor is utilized for this operation.


The first step is to ensure that we have the direction is set correctly.  In our instance the direction will be INBOUND. 


image


The second step is to select the “Add New Rule” button.  This launches the create inbound synchronization rule editor.


image


The third step is to establish the properties on the description page.  I recommend a name field that accurate describes what the rule is going to do.  I also recommend that we supply an accurate description that allows future administrators to understand what has changed.  The connected system will be the local active directory.  The connected system object type is “User”.  The metaverse object type is “Person”.  The link type is Join.  The precedence should be lower than any of the default rules.  In this case default rules begin at 100, so we will select a precedence of 50. 


image


The forth step is to review a scoping filter.  In this case there are no scopes that will be defined. 


image


The fifth step is to review join rules.  In this case there will be no join rules.


image


The last step is to create the transformation that will stamp the customer attribute 10.  To begin this process select the add transformation button.  Under flow type – select expression in the drop down menu.  Under target attribute – select the target custom attribute desired.  In this example extensionAttribute10.  The source will be based off supported functions for expressions in transformation.  In this case the following syntax:


IIF(InStr([mail],"fortmillems.org")>0,"DOMAINA","")


If the substring of the domain exists in the mail attribute the position within the string is returned otherwise 0.  If the position is returned stamp DOMAINA otherwise stamp nothing.


image


There are some benefits to this approach:


  • There are no scheduled tasks or scripts involved.
  • The user is immediately added as a member of the dynamic DL upon replication.


There are some disadvantages to this approach:


  • I generally discourage rule modification in AD Connect unless absolutely necessary.  Modifying rules can have un-intended consequences, rule changes must be tracked, and build documentation prepared to ensure that any future builds of AD Connect have the same rules.  IE – this can often introduce complications to installations.
  • The on premises attribute no longer matches the cloud attribute for the custom attribute – since the attribute was transformed via a rule in AD Connect.  This sometimes leads to confusion as to the source of values and how to handle future modifications.
  • Modifying the rule set requires that a full ad connect sync cycle be initiated – which may cause outages in the overall sync cycle depending on the size and number of objects to be resynchronized.
  • The proposed rule only works if there’s a single domain in question.


What happens if there are multiple domains.  If there are multiple domains in play the rule expression must be modified.  A switch statement must be utilized.  The switch statement evaluates the mail attribute for each of the mail domains – and stamps the custom attribute with a value.  As with an IIF statement there must be one results returned that is true.  In this sample I set anyone without a domain that we’re interested in making a dynamic distribution group to NODOMAIN.  Here is the example expression:


Switch(InStr([mail],"domainA.org")>0,"DOMAINA",InStr([mail],"domainB.com")>0,"DOMAINB",True,"NODOMAIN")


You could also have the custom attribute stamped with NULL if there was not a matching domain.


Switch(InStr([mail],"domainA.org")>0,"DOMAINA",InStr([mail],"domainB.com")>0,"DOMAINB",True,"")


These are some example methods to utilize on premises attributes to provision dynamic distribution lists in Office 365 based on email domain.

Office 365: Tracking last run times of the managed folder assistance / exchange life cycle.

$
0
0

In Office 365 the managed folder assistance is responsible for applying data retention policies to mailbox items.  For example, if you have a policy to purge items older that 90 days from deleted items – the managed folder assistant will process this information.


A question that sometimes arises is how can I track the last time the managed folder assistant processed a given mailbox.  Administrators of Exchange Online actually have an interface into this information.  Within the Exchange Online Management Shell there is a commandlet Export-MailboxDiagnosticLogs.  This commandlet will extract the details of the mailbox folder assistant process.  Here is an example:


PS C:\> Export-MailboxDiagnosticLogs -Identity tmcmichael -ExtendedProperties > c:\temp\output.txt


RunspaceId  : 1290130b-c3af-49c2-a42c-b9dd98ed702d

MailboxLog  : <Properties>
                 <MailboxTable>
                   <Property>
                     <Name>DatabaseSchemaVersion</Name>
                     <Value>65543</Value>
                   </Property>
                   <Property>
                     <Name>StorageQuotaLimit</Name>
                     <Value>51380224</Value>
                   </Property>
                   <Property>
                     <Name>NormalMessageSize64</Name>
                     <Value>437365777</Value>
                   </Property>
                   <Property>
                     <Name>SystemMessageSize</Name>
                     <Value>93908012</Value>
                   </Property>
                   <Property>
                     <Name>TotalPages</Name>
                     <Value>41405</Value>
                   </Property>
                   <Property>
                     <Name>PersistableTenantPartitionHint</Name>
                     <Value>0xA8ECFDEE5058A54CA1600716F2D8496E</Value>
                   </Property>
                   <Property>
                     <Name>IsContentIndexingEnabled</Name>
                     <Value>True</Value>
                   </Property>
                   <Property>
                     <Name>ProhibitReceiveQuota</Name>
                     <Value>52428800</Value>
                   </Property>

………………………..

                  <Property>
                     <Name>DisplayName</Name>
                     <Value>Timothy McMichael</Value>
                   </Property>
                   <Property>
                     <Name>StoreEntryId</Name>
                     <Value>0x000000001B55FA20AA6611CD9BC800AA002FC45A09004800534E36505230364D42343132352E6E616D70726430
               362E70726F642E6F75746C6F6F6B2E636F6D0012252C7D0E254B40AA6BABAF0A40F1FE7110C9033B684947B56544938EFF582F</V
               alue>
                   </Property>
                 </MailboxTable>
               </Properties>

LogName     : ExtendedProperties

Identity    : Timothy McMichael

IsValid     : True

ObjectState : Unchanged


The output above is abbreviated as it is quite large.  One of the fields contained within the XML output is the ELCLastSuccessTimestamp.  Here is an example.


<Property>
                    <Name>ELCLastSuccessTimestamp</Name>
                    <Value>2/13/2019 12:20:18 PM</Value>

</Property>


In this example the last time the mailbox folder assistant processed the given mailbox was on 2/13 at 12:20.  The commandlet itself is excellent for extracting single mailbox data.  What happens if we want to generate a report for multiple mailboxes?


If the need arises to query multiple mailboxes the following code can be utilized.


$mailboxes = get-mailbox -resultsize unlimited


$mailboxes |


% { $exportPath = "c:\temp\"+$_.alias+".xml" ;


    $exportPath ;
    
     $xml = Export-MailboxDiagnosticLogs -ExtendedProperties -Identity $_.alias ;
    
     $xml | Export-Clixml -Path $exportPath ;
    
     $mailboxIdentity = ([Xml]$xml.MailboxLog).Properties.MailboxTable.Property | where { $_.Name -eq 'DisplayName' } ;
    
     $mailboxIdentity.value ; $elcLastSuccessTimestamp = ([Xml]$xml.MailboxLog).Properties.MailboxTable.Property | where { $_.Name -eq 'ELCLastSuccessTimestamp' } ;
    
     $elcLastSuccessTimestamp.value ; $object = new-object -TypeName PSObject ;
    
     $object | Add-Member -MemberType NoteProperty -Name DisplayName -Value $mailboxIdentity.value ;
    
     $object | add-member -memberType NoteProperty -name "Alias" -value $_.alias ;
    
     $object | add-member -memberType NoteProperty -name "PrimarySMTPAddress" -value $_.primarySMTPAddress ;
    
     $object | Add-Member -MemberType NoteProperty -Name ELCLastSuccessTimestamp -Value $elcLastSuccessTimestamp.value ;
    
     $object | Export-Csv -Path c:\temp\output.csv -Append ; start-sleep -Milliseconds 500
   }


In the first command we gather all of the mailboxes in the organization.  If your organization is large it is recommended to batch this to smaller numbers of mailboxes by performing a filter on the get-mailbox.  We then take the list of mailboxes and move it into a loop – where we process each mailbox by pulling the diagnostic logging.  With the diagnostic log pulled we extract pertinent information such as display name and last run time.  This is intentionally pulled from the XML to validate we are aligning the output to the correct export data.  An object is then built containing the information from the XML output and from the mailbox output stored in the array.  These objects are then exported to a CSV file.  The CSV file can be manipulated in excel.


Here is a sample CSV file:


#TYPE System.Management.Automation.PSCustomObject

"DisplayName","Alias","PrimarySMTPAddress","ELCLastSuccessTimestamp"

"Alert Mailbox","alert","alert@domain.org","2/12/2019 10:11:34 PM"

"AH","a-alias","a-alias@domain.org","2/12/2019 11:55:21 PM"

"BM","b-alias","b-alias@domain.org","2/13/2019 9:07:35 AM"


In the output directory specified the XML is retained in case further analysis is necessary.


This method utilizing powershell allows us to interrogate multiple mailboxes and determine the last time the managed folder assistant processed the mailbox.

Viewing all 161 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>