User Profile
Bernd_Schneider
Copper Contributor
Joined May 05, 2020
User Widgets
Recent Discussions
Re: Windows Server 2022 RDS CALs missing in partner benefits
LicensingConcierge1 Are you using Chat GPT for answering this questions or what would be so difficult to understand? - Partners qualify for partner benefits and they are FREE! - Partners use the actual versions, so that customers will follow them. - If we get free Windows Server 2022 licenses and Server CALs, it makes no sense to get free RDS 2019 CALs.3.3KViews1like1CommentRe: Share address book from one to other tenants in O365
Remark: You can also use that method with on premise Exchange, but then you have to split the script. One runs with a local agent in your domain, saving the results in a global variable, the other one picks up the content of the variable and runs in azure.60KViews0likes0CommentsRe: Share address book from one to other tenants in O365
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!"60KViews0likes2CommentsRe: Share address book from one to other tenants in O365
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.61KViews0likes4Comments
Recent Blog Articles
No content to show