internal/functions/Move-Contact.ps1
Function Move-Contact { <# .SYNOPSIS Function to handle export and import of mail enable contacts .PARAMETER Sync Decide to perform the export or import of mail contacts .DESCRIPTION Similar to the Export-T2TAttributes, this function dumps attributes from the source AD but only External Contacts. We rely on the same CustomAttributed passed through Export-T2TAttributes to filter which contacts will be fetched by this function. From the Import-T2TAttributes user must pass through param the CSV to import the mail contacts. .EXAMPLE PS C:\> Move-Contacts -Sync Export The cmdlet above perform an export of mail contacts filtered by the custom attribute chosen. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")] [CmdletBinding()] param ( [ValidateSet('Export','Import')] [String[]] $Sync ) Switch ($Sync) { Export { # region variables [int]$counter = 0 $outArray = [System.Collections.ArrayList]::new() $outFile = "$home\desktop\ContactListToImport.csv" $ContactCustomAttribute = $CustomAttribute $ContactCustomAttributeValue = $CustomAttributeValue # region get Contacts filtering by custom attribute $Contacts = (Get-MailContact -ResultSize Unlimited).Where({$_.$CustomAttribute -like $CustomAttributeValue}) Write-PSFMessage -Level Output -Message "$($Contacts.Count) Mail Contacts with $($ContactCustomAttribute) as $($ContactCustomAttributeValue) were returned" $ContactCount = ($Contacts | Measure-Object).count # region iterate objects ForEach ( $i in $Contacts ) { $counter++ Write-Progress -Activity "Exporting Mail Contacts to CSV" -Status "Working on $($i.DisplayName)" -PercentComplete ($counter * 100 / $ContactCount) $user = get-Recipient $i.alias $object = New-Object System.Object $object | Add-Member -type NoteProperty -name PrimarySMTPAddress -value $i.PrimarySMTPAddress $object | Add-Member -type NoteProperty -name alias -value $i.alias $object | Add-Member -type NoteProperty -name FirstName -value $User.FirstName $object | Add-Member -type NoteProperty -name LastName -value $User.LastName $object | Add-Member -type NoteProperty -name DisplayName -value $User.DisplayName $object | Add-Member -type NoteProperty -name Name -value $i.Name $object | Add-Member -type NoteProperty -name legacyExchangeDN -value $i.legacyExchangeDN $object | Add-Member -type NoteProperty -name CustomAttribute -value $ContactCustomAttribute $object | Add-Member -type NoteProperty -name CustomAttributeValue -value $ContactCustomAttributeValue # ExternalEmailAddress should contains "SMTP:" depending on the # deserialization, we just try a replace to avoid that scenario [string]$j = $i.ExternalEmailAddress $object | Add-Member -type NoteProperty -name ExternalEmailAddress -value $j.Replace("SMTP:","") # Get only non-primary smtp and X500 from proxyAddresses. If we get the primary # the CSV mapping domain logic will break as SMTP should be external for contacts $ProxyArray = [System.Collections.ArrayList]::new() $Proxy = $i.EmailAddresses foreach ($email in $Proxy) { if ($email -clike 'smtp:*' -or $email -like 'x500:*' -and $email -notlike '*.onmicrosoft.com') { [void]$ProxyArray.Add($email) } } # Join proxyAddresses using ";" $ProxyToString = $ProxyArray -Join ";" # Map through the CSV which source domain will become which target domain Foreach ($Domain in $MappingCSV) { # Add @ before the domain to avoid issues with subdomains $SourceDomain = $Domain.Source.Insert(0,"@") $TargetDomain = $Domain.Target.Insert(0,"@") if ($ProxyToString -match $Domain.source) { $ProxyToString = $ProxyToString.Replace($SourceDomain,$TargetDomain) } } $object | Add-Member -type NoteProperty -name EmailAddresses -value $ProxyToString # Connect to AD exported module only if this machine has not AD Module installed and # filtering based on what "Include" was passed to avoid dump too many unnecessary stuff if (($IncludeManager.IsPresent -or $IncludeOrganization.IsPresent -or $IncludeGeneral.IsPresent -or $IncludePhones.IsPresent -or $IncludeAddress.IsPresent) -and $LocalMachineIsNotExchange.IsPresent -and $LocalAD -eq '') { $ADUser = Get-ADObject -Identity $i.DistinguishedName -Server $PreferredDC -Properties physicalDeliveryOfficeName,wWWHomePage,url,Description,streetAddress,postOfficeBox,l,postalCode,c,co,countryCode,st,telephoneNumber,otherTelephone,homePhone,otherHomePhone,pager,otherPager,mobile,otherMobile,facsimileTelephoneNumber,otherFacsimileTelephoneNumber,ipPhone,otherIpPhone,info,title,department,company #Call function to dump those "-Include" [void](Export-ADPersonalAttribute) } elseif ($IncludeManager.IsPresent -or $IncludeOrganization.IsPresent -or $IncludeGeneral.IsPresent -or $IncludePhones.IsPresent -or $IncludeAddress.IsPresent) { $ADUser = Get-ADObject -Identity $i.DistinguishedName -Server $PreferredDC -Properties physicalDeliveryOfficeName,wWWHomePage,url,Description,streetAddress,postOfficeBox,l,postalCode,c,co,countryCode,st,telephoneNumber,otherTelephone,homePhone,otherHomePhone,pager,otherPager,mobile,otherMobile,facsimileTelephoneNumber,otherFacsimileTelephoneNumber,ipPhone,otherIpPhone,info,title,department,company #Call function to dump those "-Include" [void](Export-ADPersonalAttribute) } # Add dumped values to ArrayList # 'til the iterator is finished. [void]$outArray.Add($object) } if ($outArray.Count -gt 0) { Write-PSFMessage -Level Output -Message "Saving CSV on $($outfile)" $outArray | Export-CSV $outfile -notypeinformation } } Import { # region local variables [int]$counter = 0 $ContactsCount = ($ImportContactList | Measure-Object).count $CheckContactManager = $ImportContactList[0].psobject.Properties | Where-Object { $_.Name -eq "Manager"} # region iterate contacts. Variable kept as $user cause # the Import-ADPersonalAttribute relies on that value ForEach ($user in $ImportContactList) { $counter++ Write-Progress -Activity "Creating MEU objects and importing attributes from CSV" -Status "Working on $($i.DisplayName)" -PercentComplete ($counter * 100 / $ContactsCount) $Replace = @{} $tmpContact = $null # If OU was passed through param, honor it. # Otherwise create the MEU without OU specification if ($OUContacts) { $tmpContact = New-MailContact -ExternalEmailAddress $user.ExternalEmailAddress -PrimarySmtpAddress ` $user.PrimarySMTPAddress -FirstName $user.FirstName -LastName $user.LastName -Alias $user.alias -Name ` $user.Name -DisplayName $user.DisplayName -OrganizationalUnit $OUContacts } else { $tmpContact = New-MailContact -ExternalEmailAddress $user.ExternalEmailAddress -PrimarySmtpAddress ` $user.PrimarySMTPAddress -FirstName $user.FirstName -LastName $user.LastName -Alias $user.alias -Name ` $user.Name -DisplayName $user.DisplayName } # we must resolve the GUID in order to # use Set-ADObject cmdlet down the road $ResolvedGUID = Get-MailContact -Identity $user.Alias | Select-Object GUID # Convert legacyDN to X500 and add all EmailAddresses to array $x500 = "x500:" + $user.legacyExchangeDN $proxy = $user.EmailAddresses.Replace(";",",") $ProxyArray = @() $ProxyArray = $proxy.Split(",") + $x500 # Matching the variable's name to the parameter's name $CustomAttributeParam = @{$user.CustomAttribute=$user.CustomAttributeValue} # region import old LegacyDN as X500 and CustomAttribute Set-MailContact -Identity $user.Alias -EmailAddresses @{Add=$ProxyArray} @CustomAttributeParam # region import "-Include" values if ($CheckContactManager -or $CheckGeneral -or $CheckAddress -or $CheckPhones -or $CheckOrganization) { [void](Import-ADPersonalAttribute) } # region set $replace hashtable to ADUser if ($LocalMachineIsNotExchange.IsPresent -and $null -eq $LocalAD -and $Replace.Count -gt 0) { Set-RemoteADObject -Identity $ResolvedGUID.Guid -Server $PreferredDC -Replace $Replace } elseif ($Replace.Count -gt 0) { Set-ADObject -Identity $ResolvedGUID.Guid -Server $PreferredDC -Replace $Replace } } } } } |