Script Repository


Import mail-enabled contacts from CSV

February 24, 2021
1351

The script imports contact objects from a CSV file, mail-enables, and then adds them to the necessary AD groups.

To import contacts with the help of the script, create a custom command for Organizational-Unit objects that runs the script, then execute the command on the OU where you want to import the contacts. To schedule import of contacts, create a scheduled task and include the OU in its Activity Scope.

Parameters:

  • $csvFilePath - Specifies a path to the CSV file to import contacts from. You can use value references in the path. For example, if you add %name% to the path, this reference will be replaced with the name of the OU on which the script is executed.
  • $customColumnNames - Specifies a map of custom column names and the corresponding LDAP attribute names. If a column name is not included in this list, it must correspond to the LDAP name of an AD attribute.
  • $mailAddressesToRemove - Specifies an email domain of email proxy addresses that will be removed from the contact after mail-enabling. If you do not want to remove any addresses, set the parameter to an empty string.
  • $hideFromGAL - Specifies whether to hide contacts from the Global Address List (GAL).
  • $contactNameColumn - Specifies the name of the column that contains the contact name.
  • $externalMailAddressColumn - Specifies the name of the column that contains the external email address of the contact.
  • $groupIdentitiesColumn - Specifies the name of the column that contains identities of the groups to add contacts to.
  • $groupIdentitiesDelimiter - Specifies a delimiter for group identities.
  • $groupIdentityProperty - Specifies the LDAP name of the property that is used as group identities in $groupIdentitiesColumn.
  • $countryColumn - Specifies the name of the column that contains the 2-letter country code for the contacts.
  • $countryInfos - Specifies a map of 2-letter country codes to the corresponding country names and numeric country codes.
Edit Remove
PowerShell
$csvFilePath = "\\SERVER\share\ImportContacts.csv" # TODO: modify me
$customColumnNames = @{
    "Display Name" = "displayName";
    "Street" = "street";
    "City" = "l";
    "State" = "st";
    "ZIP Code" = "postalCode";
} # TODO: modify me
$mailAddressesToRemove = "domain.com" # TODO: modify me
$hideFromGAL = $True # TODO: modify me
$contactNameColumn = "Display Name" # TODO: modify me
$externalMailAddressColumn = "SMTP (External Email)" # TODO: modify me
$groupIdentitiesColumn = "Member of" # TODO: modify me
$groupIdentitiesDelimiter = ";" # TODO: modify me
$groupIdentityProperty = "sAMAccountName" # TODO: modify me
$countryColumn = "Country" # TODO: modify me
$countryInfos = @{
    "US" = @("United States", "840");
    "AU" = @("Australia", "36");
    "CA" = @("Canada", "124");
    "FR" = @("France", "250");
    "DE" = @("Germany", "276");
    "UA" = @("Ukraine", "804");
    "GB" = @("United Kingdom", "826")} # TODO: modify me. Format:
                                       # "2-letter country code" = @("Country name", "Numeric country code");

function SearchObjects($filter, $properties)
{
    $domain = $Context.GetObjectDomain("%distinguishedName%")
    $searcher = $Context.BindToObject("Adaxes://$domain/rootDSE")
    $searcher.SearchFilter = $filter
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
    $searcher.SetPropertiesToLoad($properties)
    
    try
    {
        $searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()
        
        return ,$searchResults
    }
    finally
    {
        # Release resources
        if ($searchResultIterator){ $searchResultIterator.Dispose() }
    }
}

# Import CSV file
$records = Import-Csv -Path $csvFilePath

$groupInfos = @{}
foreach ($record in $records)
{
    $externalMailAddress = $NULL
    $groupIdentities = @()
    $contactName = $record.$contactNameColumn
    $contact = $Context.TargetObject.Create("contact", "CN=$contactName")

    foreach ($property in $record.PSObject.Properties)
    {
        $columnName = $property.Name
        $value = $property.Value
        
        if ([System.String]::IsNullOrEmpty($value))
        {
            continue
        }
        
        switch ($columnName)
        {
            $externalMailAddressColumn
            {
                $externalMailAddress = $value
            }
            $groupIdentitiesColumn
            {
                $groupIdentities = $value.Split($groupIdentitiesDelimiter)
            }
            $countryColumn
            {
                # Update country
                $contact.Put("c", $value)

                if ($countryInfo.ContainsKey($value))
                {
                    $contact.Put("co", ($countryInfo[$value])[0])
                    $contact.Put("countryCode", ($countryInfo[$value])[1])
                }
            }
            default
            {
                if ($customColumnNames.ContainsKey($columnName))
                {
                    $propertyName = $customColumnNames[$columnName]
                }
                else
                {
                    $propertyName = $columnName
                }

                $contact.Put($propertyName, $value)
            }
        }
    }
    
    # Commit changes
    try
    {
        $contact.SetInfo()
    }
    catch
    {
        $Context.LogMessage("An error occurred when creating contact '$contactName'. Error: " + $_.Exception.Message, "Warning")
        continue
    }
    
    if (-not([System.String]::IsNullOrEmpty($externalMailAddress)))
    {
        # Mail-enable the contact
        $contact.MailEnable($contactName.Replace(" ", ""), $externalMailAddress, "SMTP", $NULL)
        
        # Hide from Exchange address lists
        if ($hideFromGAL)
        {
            $contact.Put("msExchHideFromAddressLists", $True)
            $contact.Put("showInAddressBook", $NULL)
        }
        
        # Check Email Proxy Addresses
        $proxyAddresses = $contact.GetEx("proxyAddresses") -notlike "*@$mailAddressesToRemove"
        $contact.Put("proxyAddresses", $proxyAddresses)
        
        # Don't update e-mail addresses based on e-mail address policy automatically
        $contact.Put("msExchPoliciesExcluded", "{26491cfc-9e50-4857-861b-0cb8df22b5d7}")
        
        # Save Exchange properties
        $contact.SetInfoEx(@("msExchHideFromAddressLists", "showInAddressBook", "proxyAddresses", "msExchPoliciesExcluded"))
    }
    
    if ($groupIdentities.Length -eq 0)
    {
        continue
    }
    
    foreach ($identity in $groupIdentities)
    {
        if ($groupInfos.ContainsKey($identity))
        {
            [void]$groupInfos[$identity].Add($contact.AdsPath)
        }
        else
        {
            $arrayList = New-Object "System.Collections.ArrayList"
            [void]$arrayList.Add($contact.AdsPath)
            $groupInfos.Add($identity, $arrayList)
        }
    }
}

if ($groupInfos.Count -eq 0)
{
    return
}

# Search groups
$filter = New-Object "System.Text.StringBuilder"
[void]$filter.Append("(&(objectCategory=group)(|")
foreach ($identity in $groupInfos.Keys)
{
    [void]$filter.Append("($groupIdentityProperty=$identity)")
}
[void]$filter.Append("))")

$searchResults = SearchObjects $filter.ToString() @($groupIdentityProperty)

# Update groups
foreach ($searchResult in $searchResults)
{
    $groupIdentity = $searchResult.Properties[$groupIdentityProperty].Value
    $contactsPath = $groupInfos[$groupIdentity]
    
    # Bind to group
    $group = $Context.BindToObject($searchResult.AdsPath)
    
    # Add contacts to group
    foreach ($path in $contactsPath)
    {
        try
        {
            $group.Add($path)
        }
        catch
        {
            $contactName = $Context.GetDisplayNameFromAdsPath($path)
            $Context.LogMessage("An error occurred when adding contact '$contactName' to group '$groupIdentity'. Error: " + $_.Exception.Message, "Warning")
        }
    }
}


Comments ( 0 )
No results found.
Leave a comment