Powershell: Checking for duplicate email in AD - powershell

Background:
I'm trying to make a script that will see if a new users email ($email) is the same as one already existing (which would cause an error). I have a very remedial understanding of objects so this is what I have so far (yes it is ugly):
$email = "smithj#company.com"
$mailcheck = Get-ADUser -filter * -Properties * | ForEach-Object {$_.mail}
$mailcheck | ForEach-Object {if ($email -eq $_.mail){"$email = $($_.mail) - Matching email"}else{"$email = $($_.mail) - No duplicate email"}}
Problem 1:
The script doesn't match emails. When I have a matching email in AD it doesn't recognize it.
Problem 2: When executing just the 2nd line, indexing doesn't work properly. While it looks like a consecutive list of emails, if a user doesn't have an email at all (blank) really it could be something like this:
smithj#company.com
johnsonj#company.com
robertsr#company.com
doej#company.com
So $mailcheck[0] returns smithj#company.com while $mailcheck[1] returns blank despite the list actually looking like this:
smithj#company.com
johnsonj#company.com
robertsr#company.com
doej#company.com
Conclusion: I really just need problem 1 solved but problem 2 peaked my curiosity. Thanks.

The way you are doing it above is really inefficient. -Properties * will return every property on the user, some properties are expensive in terms of processing power to return. Only use the properties you need. The properties returned by default without specifying that parameters do not need to be specified with -Properties, only additional nondefault properties. -Filter * will also match on literally any value for any field, effectively returning every ADUser, further increasing the resources required for your script to execute as you will now have to process every user to find any accounts matching that email.
Now that that's out of the way, here is a more efficient method to implement what you're asking:
# Set the email address to search for
$emailAddress = 'box#domain.tld'
# Get all users where the email address matches what is set above
# Force it as an array so you can treat it like one even if only
# one or zero users are returned
$adUsers = #( Get-ADUser -Filter "EmailAddress -eq '${emailAddress}'" )
# Make sure no accounts were returned
# If there are, throw an error with the number of users and who they are
if( $adUsers ) {
throw "Found $($adUsers.Count) users matching EmailAddress ${emailAddress}: $($adUsers.SamAccountName -join ', ')"
}
By using the filter to only match the specific email address, Powershell does not need to collect every single AD user in the system, or iterate over all of them to find a specific email address. This will take a long time to check, especially in larger environments, whereas filtering the returned objects based on email address (or on any other property) results in a faster operation and less data to sift through.
You can then check whether $adUsers contains anything (an array count of anything but 0 evaluates to $True, you could also use if( $adUsers.Count -gt 0 ) as the condition), and if so, throw an error with more information as I do above.
Update for comment question:
To answer your other question in the comment, "I didn't know what object to compare $email to", EmailAddress and Mail both look to be valid properties, but I don't know the difference between them. In my environment, both Mail and EmailAddress are populated with my email address, but have always used EmailAddress and haven't run into issues using that. Maybe one is deprecated and the other is new or something, but I'm not really sure.
There is also yet another property called proxyAddresses as well, which preliminary research shows that both EmailAddress and Mail are related to it, but I don't know much about it. It's not populated on my ADUser objects, so I can't poke around with it.

Related

Adding contact to multiple address lists with recipientfilter

Is there a proper way to add users to multiple address lists, using only a single extensionAttribute on the users?
I'm currently creating some address lists for our employees to use.
Let's say i have an addresslist called "CompanyA" and "CompanyB"
I then have a single user that needs to be shown in both "CompanyA" and "CompanyB".
I have currently created a recipient filter for each addresslist that says
CompanyA:
-RecipientFilter "(CustomAttribute14 -like 'CompanyA')"
CompanyB:
-RecipientFilter "(CustomAttribute14 -like 'CompanyB')"
I have then on the user in AD, found extentionAttribute14 and added the values CompanyA; CompanyB
In the hopes that the delimiter ; would make it read both values for each list.
I have found this to not work and i think i need to redo the filters on the address lists, but i can't find any sort of hints of where to start or how to approach these filters.
I can of course do
-RecipientFilter "(CustomAttribute14 -like 'CompanyB') or (CustomAttribute14 -like 'CompanyA')"
However that would take all the users with either values into this list.
As Mathias wrote, i was missing the wildcard tags before and after the name i wanted to filter for.
Filter would have to be -like '*CompanyA*' since the attribute now
contains more than just the single string – Mathias R. Jessen

Get AD user by providing fullName and manager full name

It might look silly but I'm struggling with finding user with Powershell by providing his full name and his manager full name. Purpose of script is to get SamAccountName and Email Address by using mentioned values which are provided by other team (these are the only unique values I get - getting user by Full Name is not any kind of problem, but it's possible that it'll return multiple results, and that's why Manager Full Name would determine appropriate result).
First I was using simple command
Get-ADUser -server $gc -Filter { (CN -eq $uFullName) -and (extensionAttribute4 -eq $mFullName) }
It worked great, but unfortunately I noticed that not all accounts use extensionAttribute4 to hold manager full name. I thought of using Filter on manager property but when I tried to use (Manager -like "*value*") it returned that like operator isn't supported by this attribute.
I'm still trying to find solution for this but maybe someone will have some solution to this situation.
Thank you in advance.

O365 Powershell | Breaking up a long list into two sets of 100

I am looking to create a rule in Office 365 applied to all of the members in our org.
I would like this rule to append a warning on all incoming email from outside the organization with the same Display Names as our users.
When I attempt to apply it to all of the users in our org I get an error stating that the rule is too long.
In order to solve that I pulled a group, but I am still about 1000 characters over the limit.
I would like to make two variables, that each hold one half of the list, created by this command:
(Get-DistibutionGroupMember -Identity email#contoso.com -ResultSize Unlimited).DisplayName
I have attempted to modify the ResultSize parameter, but what I would need is result 1-100 and then 100-200 from the same list.
Another caveat to this problem is that the list cannot be static. It is something that the script will have to update every time it is run.
There is a sub-string command that you can use on a particular username that I have utilized when I made something for AD, but I am not aware of any way to break up a list like this.
If anyone has any other ways to solve this issue I would be more than open to any suggestion.
Thanks for taking the time to read this!
There are many ways of doing it. I found it very readable.
My favorite one is this one:
$ObjectList = 1..1000
$Step = 100
$counter = [pscustomobject] #{ Value = 0 }
$ObjectListSplitted = $ObjectList | Group-Object -Property { math]::Floor($counter.Value++ / $step) }
Then if you want to show the third subset just use this format :
$ObjectListSplitted[3].Group
Have a look to this solution already explained.
As a note other languages are capable of slicing an array of object with a start, stop and a step, have a look here if you're curious.

PowerShell Populate multi value attribute and convert case

I've tried to search but could not find anything whcih is not a surprise as I don't think what we're trying to do is so common.
I have a script that gathers a AD users according to filter together with custom attributes properties, we use a custom extended schema, and their values.
I do have an attribute called smtpHistory where an history of SMTP assigned to user are stored, I need to add what's in the $_.email attribute as the primary SMTP address (with SMTP in uppercase) while convertting any existing entry in lower case.
What I am doing right now is similar to
$mailHistory = $_.smtpHistory
$lowerMailHistory = $mailHistory.tolower()
# Insert all existing addresses in lowercase to the history attribute
Set-ADUser $_.SamAccountName -add #{ smtpHistory= $lowerMailHistory }
$newMail = $_.mail
# Append new default email address to smtpHistory
#Set-ADUser $_.SamAccountNAme -Add #{ smtpHistory= "SMTP:$newMail" }
Technically speaking the above works but when I check the smtpHistory attribute what I get is multiple values on a single line like
smtp:test7#gmail.com smtp:test6#gmail.com
Instead of one value per line like
smtp:test7#gmail.com
smtp:test6#gmail.com
The way I'm cycling through the users is via
$usersProxyAddress | ForEach-Object { ...
As using a foreach ($a in $usersProxyAddress ) is yielding the DN of each user and I cannot access the single properties (probably my fault).
Probably this is something silly that I'm overlooking but I cannot find a solution to the issue and any pointer/help would be highly appreciated.
Thanks in advance, Dan.
try something like this
$mailHistory = $_.smtpHistory -join ';'
$mHistory = $mailHistory -spilt ";"
foreach($mH in $mHisotry)
{
#yourcode
}
"Need to be tested as i dont have domain controller available with me now."

Find and replace custom attribute values in AD using Powershell

So I have an interesting script I am trying to figure out, basically I need to change a custom attribute value to a new one. The problem is its for both users and computers and not specific to the groups. So for instance the value might be Billing1 for several users in an OU and this need to be Billing2. So I need to find any instance of the Value of Billing1 and change it to Billing2 not knowing the user or computer object. I can successfully change one at a time if I know who the user is by using Set-ADUser, Set-ADComputer and even with Set-AdObject but I need to figure out a Find and replace function.
I have searched for this and I have found examples of where I can use CSV for users and computers but again I don't know who has what since the value in the attribute can vary and also changes if a reorg happens.
got the correct script...
Get-ADComputer -Properties enterattributename -Filter {enterattributename -like "value to search" } |Set-ADComputer –replace #{ enterattributename =”value to change”}
this also can be applied to Get-ADUser and Get-ADObject