I need to change a lot of users "email" field on their active directory profile however I cant seem to find the answer Im looking for looking at other posts.
I`m quite new to powershell but I've landed this task to be done at work.
The email address format is in the style of "first name" and "lastname" seperated by a "." with the domain appended on the end naturally.
An example would be John.Doe#domain.com
How would I go about this with powershell with users in 6 different OUs but all under the same root OU?
Kind regards
It depends on how you have the data. If you already have the emails in say a csv with a column titled "OldEmail" and "NewEmail" you could do something like:
$csv = import-csv \\path\to\csv
foreach($user in $csv) {
get-aduser -filter {mail -eq $user.OldEmail} | Set-ADUser -EmailAddress $user.NewEmail
}
You could do something like below, but as always when changing stuff in Active Directory,
try it out on a bunch of testusers first
# enter the root OU DistinguishedName where the sub OU's are here
$rootOU = "OU=Users,DC=yourdomain,DC=com"
# Get a list of user objects that do not have an email address in 'firstname.lastname#yourdomain.com' format.
# you only have to ask for property EmailAddress (LDAP name is 'mail'), because these properties are returned by default:
# DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName
Get-ADUser -Filter * -SearchBase $rootOU -SearchScope Subtree -Properties EmailAddress |
Where-Object { $_.EmailAddress -ne ('{0}.{1}#yourdomain.com' -f $_.GivenName, $_.Surname) } |
ForEach-Object {
$mail = '{0}.{1}#yourdomain.com' -f $_.GivenName, $_.Surname
Write-Host "Setting up email address $mail for user $($_.SamAccountName)"
$_ | Set-ADUser -EmailAddress $mail
}
Related
Recently completed an Azure AD provisioning integration between SuccessFactors and On-Prem AD.
In order for some of our existing users to get 'scoped in' to the Update provisioning, they first need to match on employee id (we currently do not use the Create functionality).
There are about 400 users that we've identified need to be matched, and our HR team has provided us with a csv with the following attributes (Full Name, EmployeeID). I need to somehow compare this file with all users in AD who have no employee id, and if not, update EmployeeId with the contents from the HR provided file.
I'm a bit stuck on how to attack this. Need a Big Brain :)
#import HR file with required attributes "Formal Name, EmployeeId"
#returns ~6500 entries
$SFUsers = Import-Csv Z:\ExportsFromProd\Global_ActiveHeadcountReport_08292022.csv
#returns ~1400 entries
#some accounts never get an employee id
$users = Get-ADUser -Filter "*" -Properties EmployeeID | Where-Object {$_.employeeID -eq $null}
foreach ($account in $users) {
$accountName = $account.name
get-aduser -Filter {Name -eq $accountName} -Properties * | Select-Object samaccountname, displayName
#this is where i need help:
<#
try {
Lookup $SFUser.'Formal Name' in $SFUsers array???
Get $SFUser.'EmployeeID' | set-aduser $account -employeeId $SFUser.'EmployeeId'
}
catch {
}
finally {
}
#>
}
'''
You can use the faster -Filter or LDAPFilter parameters of Get-ADUser to find only users where the EmployeeID property is unset.
Also, your code could be done by using Get-ADUser only once:
#import HR file with required attributes "Formal Name, EmployeeId"
#returns ~6500 entries
$SFUsers = Import-Csv -Path 'Z:\ExportsFromProd\Global_ActiveHeadcountReport_08292022.csv'
#returns ~1400 entries
#some accounts never get an employee id
$users = Get-ADUser -Filter "employeeid -notlike '*'" -Properties DisplayName, EmployeeID
# or use LDAPFilter
# $users = Get-ADUser -LDAPFilter "(!employeeID=*)" -Properties DisplayName, EmployeeID
foreach ($account in $users) {
# try and find this user in the csv file either by .Name or .DisplayName property
$HRUser = $SFUsers | Where-Object { $_.'Formal Name' -eq $account.Name -or
$_.'Formal Name' -eq $account.DisplayName}
if ($HRUser) {
$account | Set-ADUser -EmployeeID $HRUser.EmployeeId
}
else {
Write-Warning "AD user $($account.Name) not found in the CSV file.."
}
}
I am trying to get a CSV output of all the users in the 'VPN Users' group that are also in the 'Domain Users' group. I'd like it to give their name and then their group membership. Each member should only be in the VPN group. I am looking to identify who is in both groups.
To achieve this I have first exported a list of the users in the VPN Group to a CSV which works fine. Second part of the code is meant to go through the list of users in the CSV from that AD group and export an output as a CSV containing the users and their group membership which isn't working for me. For each user in the CSV it returns the error: Get-ADUser : Cannot find an object with identity: '"User001_vpn"'.....
I'm not sure if the way I'm going about it is the best way to achieve the task in hand or if any of you might be able to help me make it work? It seems like Get-ADUser isn't finding the users from the CSV.
#Retrieves list of users that are in the VPN Users group and exports them into a CSV
(Get-ADGroupMember "VPN Users" -Recursive | Get-ADUser -Properties * |
Select-Object SamAccountName |
ConvertTo-Csv -NoTypeInformation) |
Select-Object -Skip 1 |
Set-Content -Path "C:\Documents\VPN Users Report\VPNUsers.csv”
Get-Content “C:\Documents\VPN Users Report\VPNUsers.csv” | Get-ADUser | ForEach{
$user = $_
$groups = Get-ADPrincipalGroupMembership $user
$groups | %{ New-Object PSObject -Property #{ User = $user.SamAccountName; Group = $_.SamAccountName } }
} | Export-Csv "C:\VPN Users Report\Results\Output.csv"
I believe the problem is with the quotes, since you are using ConvertTo-Csv while retrieving the users, all user SamAccountNames will be quoted.
Afterwards you read this csv file using Get-Content, not Import-Csv, so the quotes will not be removed and you have user names like "User001_vpn" instead of User001_vpn
You do not have to use this 'in-between' cvs at all and on second thought, you can leave out Get-ADUser too unless you want other properties from these users than what Get-ADGroupMember already returns (i.e. distinguishedName, name, objectClass, objectGUID, SamAccountName, SID)
Try
# Retrieves list of users that are in the VPN Users group
(Get-ADGroupMember "VPN Users" -Recursive | Where-Object { $_.objectClass -eq 'user' }).SamAccountName | ForEach-Object {
foreach ($group in (Get-ADPrincipalGroupMembership -Identity $_)) {
[PsCustomObject]#{
User = $_
Group = $group.SamAccountName
}
}
} | Export-Csv "C:\VPN Users Report\Results\Output.csv" -NoTypeInformation
I have added Where-Object { $_.objectClass -eq 'user' }, because the Get-ADGroupMember cmdlet can return users, groups, and/or computer objects
As per your latest comment:
If you want more properties from the user, you need Get-ADUser, which by default returns objects with these properties:
DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName
If you still need more, like for instance the users email address, you need to ask for it by adding -Properties EmailAddress
# demo to include the users first and last name
Get-ADGroupMember "VPN Users" -Recursive | Where-Object { $_.objectClass -eq 'user' } | ForEach-Object {
$user = Get-ADUser -Identity $_.DistinguishedName
foreach ($group in (Get-ADPrincipalGroupMembership -Identity $user.DistinguishedName)) {
[PsCustomObject]#{
User = $user.SamAccountName
FirstName = $user.GivenName
LastName = $user.Surname
Group = $group.SamAccountName
}
}
} | Export-Csv "C:\VPN Users Report\Results\Output.csv" -NoTypeInformation
I propose an alternative to Theo's helpful answer letting LDAP handle the filtering of users.
The result of this query would be those users which are members of GroupX and members of GroupY:
$groupX = (Get-ADGroup 'VPN Users').DistinguishedName
$groupY = (Get-ADGroup 'Domain Users').DistinguishedName
Get-ADUser -LDAPFilter "(&(memberOf=$groupX)(memberOf=$groupY))"
If you were looking for indirect members of one of the groups or both groups, meaning, possible members of nested groups in those groups you could use memberOf:1.2.840.113556.1.4.1941:. Example:
Get-ADUser -LDAPFilter "(&(memberOf:1.2.840.113556.1.4.1941:=$groupX)(memberOf=$groupY))"
Would bring all members (recursive) of GroupX which are also direct members of GroupY.
I have a list of displaynames and I need to get their AD informations.
Get-Content "C:\displaynames.txt" |
foreach {
$givenname,$surname = $_ -split ' '
if (Get-ADUser -Filter "surname -eq '$surname' -and givenname -eq '$givenname'"){
Get-ADUser -Filter { displayName -match $_} -Properties EmailAddress, Manager | Select Givenname, Surname, SamAccountName, EmailAddress, Manager}
else {Get-ADUser -Filter { displayName -like "AD Test"} -Properties EmailAddress, Manager | Select Givenname, Surname, SamAccountName, EmailAddress, Manager}
} | Export-Csv -Path C:\result.csv
This works fine, but only if users have no middle names ex. John Moore
If the user has a middle name, it doesn't pick it up.
How can I change the script so it picks up users with middle names ex. John Roger Moore?
As Mathias R. Jessen already commented, you can use the -Filter on property DisplayName directly.
The Filter should be a string, not a scriptblock.
Using -Filter also has the advantage that you can suppress exceptions being thrown, so I would build in a step to confirm that we indeed did find a user with that displayname:
Get-Content "C:\displaynames.txt" | ForEach-Object {
$user = Get-ADUSer -Filter "DisplayName -eq '$_'" -Properties DisplayName, EmailAddress, Manager -ErrorAction SilentlyContinue
if ($user) {
# output the wanted properties as **object**
$user | Select-Object Givenname, Surname, SamAccountName, EmailAddress, Manager
}
else {
# nobody in this domain with a displayname like that..
Write-Warning "User '$_' could not be found.."
}
} | Export-Csv -Path 'C:\result.csv' -NoTypeInformation
Note that the Manager property is in the form of the managers DistinguishedName. If you want to get other properties for the manager, like his/her name, you will have to use Get-ADUser -Identity $user.Manager to get the wanted property there too
The basic question here is how to account for middle names.
PowerShell 5 has some AI-powered cmdlets.
Here, I will quote an example from the documentation.
Example 2: Simplify format of a string
$composers = #("Johann Sebastian Bach", "Wolfgang Amadeus Mozart", "Frederic Francois Chopin", "Johannes Brahms")
$composers | Convert-String -Example "first middle last=last, first"
Bach, Johann
Mozart, Wolfgang
Chopin, Frederic
Brahms, Johannes
The first command creates an array that contains first, middle and last names. Note that the last entry has no middle name.
The second command formats the names according to the example. It puts the last name first in the output, followed by the first name. All middle names removed; entry without middle name is handled correctly.
Convert-String (Microsoft.PowerShell.Utility) - PowerShell | Microsoft Docs
I want to make a script that deletes bulk users, instead of using SAMACCOUNTNAME I want to use the first and last name, is that possible?
Import-Module ActiveDirectory
$ADusers = Import-csv C:\TEST\Delete.CSV
Foreach ($user in $ADusers) {
#Confirming the identity
$users = Get-ADUser -Identity $user -Properties | Select-Object Givenname, Surename
#Removing the user
Remove-ADUser -Identity $user.samAccountName -Confirm:$false
}
I like Ambiguous Name Resolution when searching for users in AD:
Get-ADUser -LDAPFilter "(anr=Jim Smith)"
This will search for all objects where any of the naming attributes (see link above for list) start with the string "jim smith", plus all objects where (givenName=jim*) and (sn=smith*), plus objects where (givenName=smith*) and (sn=jim*).
This is useful when 'Jims' account uses his fully name of 'Jimmy', this would be returned by ANR but not by a direct givenName/sn filter.
You can have multiple users with the same First/Last name, so you will need to deal with the situation of multiple users being returned.
SAMAccoutName, however is unique to a single account
EDIT:
If you've got a csv with the two columns GivenName & Surname:
foreach ($user in $ADusers) {
$firstname = $user.GivenName
$lastname = $user.Surname
Get-ADUser -LDAPFilter "(anr=$firstname $lastname)"
}
The above just lists the users returned from Get-ADUser, to remove them just pipe to Remove-ADUser. I'm using WhatIf to test, remove to actually delete the users:
Get-ADUser -LDAPFilter "(anr=$firstname $lastname)" | Remove-ADUser -WhatIf
Yes it is.
Get-ADUser -Filter {GivenName -eq "Max" -and sn -eq "Muller"} | Remove-ADUser
You need to alter your script accordingly.
I am having an issue with this script. I am using it to look for certain users in an OU on AD and change the email address field to something I want. However, once I run the command, it chooses all of users with empty emails correctly, but seems to have replaced them all with the same email address, let's say "brubble#domain.com".
I need to target the ones with that email address now, and change them to the appropriate email address, but it just keeps changing it to "brubble#domain.com".
$SearchBase = "OU=Dead Accounts,DC=Domain,DC=Domain,DC=COM"
$Filter = {EmailAddress -notlike "*"}
get-ADUser -Filter $Filter -SearchBase $SearchBase -Properties emailaddress | ForEach-Object {
Write-Host $_.EmailAddress
$newEmail = $_.samaccountname + "#esilicon.com"
Set-Aduser $($_.SamAccountName) -EmailAddress $newEmail
}