# csv2mailcontact # # Simple PowerShell Script to import Users from a CSV-File and manage mail contacts # requires Exchange 2007/2010 commandlets # # uses SMTP-Address as target CN # tries to find target based on Mail # if there and in target ou -> Update # otherwise warning # store handled objects and remove orphaned objects later # # Version 1.0 20111112 # Initial Version as sample # # # Pending # - skip empty lines in CSV # - more sophisticated handling of errors. currently script stops # - Eventlog loggin für unatttended processing # - Better handling of writing properties, skip empty ones param ( [string]$csvfile = '.\Users.csv' , # path to the input file [string]$domaincontroller = "WIN-TIT899W5KN4" , # specify a DC here [string]$contactou = "ou=csv2mailcontact,dc=e2007,dc=msxfaq,dc=de", # [switch]$verbose # enable verbose output ) function find-recipient ($mailaddress) { # Search für existing target Write-Verbose -Message "find-recipient: $mailaddress" $gcsearcher = [DirectoryServices.DirectorySearcher]"" #$gcsearcher.searchroot = "GC:" $gcsearcher.filter = "(|(proxyaddresses=$mailaddress)(mail=$mailaddress)(targetaddress=$mailaddress)(cn=$mailaddress))" $result = $gcsearcher.findone() Write-Verbose -Message "find-recipient: Found $result.properties.distinguishedname[0].tolower()" if ($result -ne $null) { $result.properties.distinguishedname[0].tolower() } } # enforce strict variable declaration set-psdebug -strict # stop on any errors. to dangerous to remove missed Mailcontacts afterwards $ErrorActionPreference = "stop" $Error.Clear() if ($verbose) { $VerbosePreference = "continue" } # load Exchange SnapIns, if not already loaded. we need them Write-Verbose -Message "Test für Exchange SnapIn" Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue Add-PSSnapin Microsoft.Exchange.Management.PowerShell.admin -ErrorAction:SilentlyContinue if ((Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue) ) { Write-Verbose -Message "Found Exchange 2010 SnapIns" } elseif ((Get-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin -ErrorAction:SilentlyContinue) ) { Write-Verbose -Message "Found Exchange 2007 SnapIns" } else { Write-Error -Message "Unable to load Exchange Snapins" break } if ((Get-ADPermission -DomainController $domaincontroller -Identity $contactou -ErrorAction:SilentlyContinue) -eq $null) { Write-Error -Message "TargetOU not found" } $contactou = $contactou.ToLower() # use lowercase für later comparisons # Hastable to store processed contacts [hashtable]$processedcontacts=@{} [long]$line = 0 Write-Verbose -Message "Loading CSV-File" foreach ($entry in Import-Csv $csvfile){ $line +=1 Write-Host -NoNewline "." if ($entry.mail -eq $null) { Write-Error -Message "Attribute Mail missing in CSV on Line $line" break } $key = $entry.mail Write-Verbose -Message "Processing $line $key" # Check if source element ist already in hashtable to stop duplicate entries in source if ($processedcontacts.item($key)) { Write-Error -Message "Duplicate Mailaddress in Source CSV" break } # search für recipient in global catalog, do not use the exchange "get-recipient" or others due limitations $target = find-recipient $key Write-Verbose -Message "Search existing target: $target" if ($target -eq $null) { Write-Verbose "NO Contact with Targetaddress found, create a new" $targetcontact = New-MailContact ` -DomainController $domaincontroller ` -OrganizationalUnit $contactou ` -Name $key ` -ExternalEmailAddress $key } elseif ($target.endswith($contactou)){ Write-Verbose -Message "Target in contact-OU. updating" $targetcontact = Get-MailContact ` -IgnoreDefaultScope ` -Identity $target } else { Write-Error -Message "Conflict found $target" break } # add Contact as matched, processes $processedcontacts.Add($key,$true) # Updates of properties, can be done with Exchange Commandlet or with ADSI. [adsi]$adcontact = [adsi]("LDAP://"+$domaincontroller+"/"+$targetcontact.DistinguishedName) $adcontact.Put("GivenName",$entry.givenname) $adcontact.Put("sn",$entry.lastname) $adcontact.Put("telephoneNumber",$entry.phone) $adcontact.setinfo() #$adcontact.CommitChanges() #Set-Contact ` # -Identity $targetcontact.DistinguishedName ` # -Company $entry.lastname # -Title $entry.Title ` # -Department $entry.Department ` # -Fax $entry.Fax ` # -MobilePhone $entry.MobilePhone ` # -Office $entry.Office ` # -Phone $entry.Phone ` # -PostalCode $entry.PostalCode ` # -City $entry.City ` # -StreetAddress $entry.StreetAddress ` # -CountryorRegion $entry.CountryRegion ` # -HomePhone $entry.PhoneGeneral # Force a Update-recipient to apply Addressbooks etc, if based on modified properties Update-Recipient ` -DomainController $domaincontroller ` -Identity $targetcontact.DistinguishedName ` } Write-Verbose -Message "Removing orphaned contacts" foreach ($entry in (Get-MailContact -OrganizationalUnit $contactou -ResultSize unlimited)) { Write-Host -NoNewline "." $key = $entry.windowsemailaddress Write-Verbose -Message "Processing $entry" if ($processedcontacts.item($entry.WindowsEmailAddress.ToString())) { Write-Verbose -Message "Object found in hashtable. Removing from List" $processedcontacts.remove($entry.WindowsEmailAddress.ToString()) } else { Write-Verbose -Message "Remove orphaned Contact" Remove-MailContact ` -Identity $entry.distinguishedname ` -DomainController $domaincontroller ` -Confirm:$false } } if ($processedcontacts.count -ne 0) { Write-Error -Message "Hastable not empty. created contact not found during orphancheck" }