Forum Discussion

techno1795's avatar
techno1795
Brass Contributor
Jan 29, 2019
Solved

Share address book from one to other tenants in O365

Dear Adam.,

 

I want to share my address book between two tenants . I am confusing something about the term : address book and contacts.

Dear all friends and experts

 

As my understand:

In contact have all address book ? or in address have all contact ? or address book is same contacts

 

In my case. I want to share ( address book ) to other tenants, actually, I need share address book or contacts ?

 

Please give me some advise, and how to do that. Thank you so much.

Lee Nguyen

19 Replies

  • vivekusa's avatar
    vivekusa
    Copper Contributor

    techno1795 

     

    https://learn.microsoft.com/en-us/entra/identity/multi-tenant-organizations/cross-tenant-synchronization-overview

  • Bernd_Schneider's avatar
    Bernd_Schneider
    Copper Contributor

    techno1795 

     

    Hello Techno1795,

    I was searching for a solution a long time.

    Here the scenario:

     

    - company holding with 3 child companies

    - all 4 companies have their own tenant

    - holding is AD domain synced to O365, only cloud mailboxes

    - 1 child is plain O365

    - 2 childs are hybrid Exchange organizations

    - organizations with local ADs are bidirectional trusted

     

    Goal is, that all organizations see the contacts in the other ones.

     

    I finally used Azure Automation Powershell scripts for that. 

     

    - I created multiple scripts that run once a day

    - read the mailboxes from one Exchange organization or O365 tenant

    - add a suffix to the display name like "(Organization One)" (for users belonging to multiple orgs.)

    - use one attribute to identify the organization

    - create a contact in each other organization, update if already exists

    - run a second script or add a section to the first script that parses all contacts in the tenants and checks, if the mailbox still exists in the organization. If not, delete the contact. That cleans up your contacts. But be careful an check, if the connection to the organization is OK. Otherwise during connection problems, you'll lose all contacts till next run. šŸ˜‰

     

    Not nice, but it works.

    • Sunil50's avatar
      Sunil50
      Copper Contributor

      Bernd_SchneiderI have a similar issue that I'm dealing with and would appreciate if you could share a detailed insight on the script used and steps taken.

      • Bernd_Schneider's avatar
        Bernd_Schneider
        Copper Contributor

        Sunil50 Hi, that's the script.
        It could be optimized, but it works:

         

        # Publish O365 Users as Contacts in another tenant

        # BSSE GmbH, Bernd Schneider

        #

        # Note:

        # The text ā€œ (Source-Tenant)ā€ is appended to every contact to mark the contacts

        # of the source company.

        # Use at own risk!

         

        # Connect Source-Tenant

        Write-Output "Connect Source-Tenant"

        $credObject = Get-AutomationPSCredential -Name "Source-Tenant-Admin"

        Connect-MsolService -Credential $credObject

         

        # Get Source-Tenant Users Excluding Guest Accounts

        Write-Output "Read Source-Tenant MSOLUser"

        $mySourceUsers=Get-MSOLUser -all|Where-Object {($_.UserPrincipalName -LIKE "*@Source-Tenant.*") -AND (-NOT ($_.UserPrincipalName -LIKE ("*#EXT#*")))  }

         

        Get-PSSession | Remove-PSSession

        # Create AzureRunAsConnection

        $connectionName = "AzureRunAsConnection"

        try

        {

            # Get the connection "AzureRunAsConnection "

            $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName   

         

            Write-Output "Logging in to Azure..."

            Add-AzureRmAccount `

                -ServicePrincipal `

                -TenantId $servicePrincipalConnection.TenantId `

                -ApplicationId $servicePrincipalConnection.ApplicationId `

                -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 

        }

        catch 

        {

            if (!$servicePrincipalConnection)

            {

                $ErrorMessage = "Connection $connectionName not found."

                throw $ErrorMessage

            } else{

                Write-Error -Message $_.Exception

                throw $_.Exception

            }

        }

         

        # Connect Target-Tenant

        Write-Output "Connect Target-Tenant"

        $credObject = Get-AutomationPSCredential -Name "Target-Tenant-Admin"

        Connect-MsolService -Credential $credObject

         

        # Function: Update-ExchangeOnlineContact 

        function Update-ExchangeOnlineContact {

            param (

                $User

            )

                $NameAndOrg=$User.DisplayName+" (Source-Tenant)"

                Set-Mailcontact $User.UserPrincipalName -Name $NameAndOrg -DisplayName $NameAndOrg -FirstName $User.FirstName -LastName $User.Lastname `

                -CustomAttribute9 "BSSE Office 365 Synchronisation"

            }

         

        # Function: Update-ExchangeOnlineContactEmail 

        function Update-ExchangeOnlineContactEmail {

            param (

                $User

            )

                $NameAndOrg=$User.DisplayName+" (Source-Tenant)"

                Get-MailContact -resultsize 99999|where-object {$User.DisplayName -eq $NameAndOrg}| Ā“

                    Set-Mailcontact -ExternalEmailAddress $User.UserPrincipalName -CustomAttribute9 "BSSE Office 365 Synchronisation"

            }

         

        # Function: New-ExchangeOnlineContact 

        function New-ExchangeOnlineContact {

            param (

                $User

            )

                $NameAndOrg=$User.DisplayName+" (Source-Tenant)"

                New-Mailcontact -Name $NameAndOrg -DisplayName $NameAndOrg -FirstName $User.FirstName -LastName $User.LastName `

                -ExternalEmailAddress $User.UserPrincipalName 

                Set-Mailcontact -Identity $User.UserPrincipalName -CustomAttribute9 "BSSE Office 365 Synchronisation"

            }

         

        # Function: Connect to Exchange Online 

        function Connect-ExchangeOnline {

            param (

                $Creds

            )

                Write-Output "Connecting to Exchange Online"

                Get-PSSession | Remove-PSSession       

                $Session = New-PSSession ā€“ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Creds -Authentication Basic -AllowRedirection

                $Commands = @("Get-Recipient","New-Mailcontact","Set-Mailcontact","Set-Mailbox","Get-Mailbox","Get-Contact","Get-MailContact", "Remove-Mailcontact", "Get-MailUser")

                Import-PSSession -Session $Session -DisableNameChecking:$true -AllowClobber:$true -CommandName $Commands | Out-Null

            }

         

        # Connect to Exchange Online

        Write-Output "Connect Target-Tenant Exchange"

        Connect-ExchangeOnline -Creds $credObject

        # Load Data in Buffer

        $SourceDisplay=Get-MailContact -resultsize 99999|where-object {$_.DisplayName -like "*(Source-Tenant)"}

        $SourceContacts=Get-MailContact -resultsize 99999|where-object {$_.PrimarySMTPAddress -like "*Source-Tenant.*"}

        $SourceExternal=Get-MailUser -resultsize 99999|where-object {$_.PrimarySMTPAddress -like "*Source-Tenant.*" -and $_.RecipientTypeDetails -eq "GuestMailUser"}

         

        # Check if new Account using Email address

        ForEach($User in $MySourceUsers) {

            $TempContact = $SourceContacts|where {$SourceContacts.PrimarySMTPAddress -eq ($User.UserPrincipalName)}

            if ($TempContact) {

                Write-Output ("Existing Contact: "+$User.DisplayName)

                

                # Check for Update using time last changed

                if ($User.Value.WhenModified.addday -gt (get-date).adddays(-2)) {

                    Write-Output ("Update Contact: "+$User.DisplayName)

                    Update-ExchangeOnlineContact -User $User

                }    

            } 

            else {

                $TempContact = $SourceExternal|where {$SourceExternal.PrimarySMTPAddress -like $User.UserPrincipalName}

                # Check if external contact, if yes, ignore

                if ($TempContact) {

                    Write-Output ("External Contact: "+$User.UserPrincipalName)   

                }

                else {

                    $TempDisplay = $SourceDisplay|where {$SourceDisplay.DisplayName -eq ($User.DisplayName + " (Source-Tenant)")}

                    # Check, if same Displayname exists

                    if ($TempDisplay) {

                        # Change Email-Address

                        Write-Output ("New Email Address: "+$User.DisplayName+", "+$User.UserPrincipalName)

                        Update-ExchangeOnlineContactEmail -User $User

                    }

                    else {

                        # Create new Contact

                        Write-Output ("New Contact: "+$User.DisplayName)

                        New-ExchangeOnlineContact -User $User

                    }

                }

            }

        }

         

        $MySourceUsers|ft UserPrincipalName, DisplayName

         

        # Check Account deletion

        ForEach($Contact in $SourceContacts) {

                $TempUser = $MySourceUsers|where {($MySourceUsers.UserPrincipalName) -like $Contact.PrimarySMTPAddress}

                if ($TempUser) {

                    Write-Output ("Do not delete: "+$Contact.identity)

                } 

                else {

                    Write-Warning ("Delete Contact: "+$Contact.identity)

                    Write-Output ($Contact.PrimarySMTPAddress)

                    $contact|Remove-MailContact -confirm:$false

                }

        }

         

        # Close Session

        Get-PSSession | Remove-PSSession

         

        Write-Output "Script Completed!"

         

    • techno1795's avatar
      techno1795
      Brass Contributor

      Thank you Admin,

       

      So, actually, when people say : Share address book in O356 is share contact right ?

       

      So this is guide for share contact ? and will I follow the the this one ?

      https://support.microsoft.com/en-ca/help/10157/sharing-calendar-and-contacts-in-office-365

       

      Thank you so much,

      Lee Nguyen,

      • A contact is usually an external user and the address book the list of people , addresses within your organization! The first link explains this.

        Make sure to really understand the concept before sharing anything outside the org!!

        Regards / adam

Resources