PowerShell retrieve and sort EmailAddresses - email

I'm using the below code for retrieving and simultaneously adding a separator "," for each smtp-attribute in the EmailAddresses-property.
get-mailbox | select-object DisplayName,PrimarySMTPAddress, #{Name='EmailAddresses';Expression={[string]::join(", ", ($_.EmailAddresses))}}
But I would also like to sort the values of EmailAddressess so that uppercase always comes first by using powershell and with as little effort (short code) as possible.
If you're not familiar with Microsoft Exchange: each value inside EmailAddresses first starts with smtp: or SMTP: followed by the users various email addresses. uppercase SMTP means its the primary SMTP-address used when sending an email for example. Lowercase smtp means its just another email address.
I'd like to sort the output so that the SMTP:*-value comes first.
Bonus question, in the Expression-block; can multiple [string]:: overloads be used together, if so how?
I was attempting to achieve a sorted output by using [string]::OrderBy() and [string]::OrderByDescending() but I couldn't figure out how to use them together with [string]::split().
Thanks to user 4c74356b41, I now realize that my string doesn't contain OrderBy() or OrderByDescending() hence they cannot be used.
MSDN: OrderBy Method
MSDN: OrderbyDescending Method

You can just nest a pipeline sort inside of your expression.
#{Name='EmailAddresses';Expression={[string]::join(", ", ($_.EmailAddresses | Sort-Object))}}
99% sure this will work for you but didn't mock up a full test to be sure so let me know if it fails.

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

Powershell: Checking for duplicate email in AD

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.

Query string parsing as number when it should be a string

I am trying to send a search input to a REST service. In some cases the form input is a long string of numbers (example: 1234567890000000000123456789). I am getting 500 error, and it looks like something is trying the convert the string to a number. The data type for the source database is a string.
Is there something that can be done in building the query string that will force the input to be interpreted as a string?
The service is an implementation of ArcGIS server.
More information on this issue per request.
To test, I have been using a client form provided with the service installation (see illustration below).
I have attempted to add single and double quotes, plus wildcard characters in the form entry. The form submission does not error, but no results are found. If I shorten the number("1234"), or add some alpha numeric characters ("1234A"), the form submission does not error.
The problem surfaced after a recent upgrade to 10.1. I have looked for information that would tie this to a known problem, but not found anything yet.
In terms of forcing the input to be interpreted as a string, you enclose the input in single quotes (e.g., '1234567890000000000123456789'). Though if you are querying a field of type string then you need to enclose all search strings in single quotes, and in that case none of your queries should be working. So it's a little hard to tell from the information you've provided what exactly you are doing and what might be going wrong. Can you provide more detail and/or code? Are you formatting a where clause that you are using in a Query object via one of Esri's client side API's (such as the JavaScript API)? In that case, for fields of data type string you definitely need to enclose the search text in single quotes. For example if the field you are querying were called 'FIELD', this is how you'd format the where clause:
FIELD = '1234'
or
FIELD Like '1234%'
for a wildcard search. If you are trying to enter query criteria directly into the Query form of a published ArcGIS Server service/layer, then there too you need to enclose the search in single quotes, as in the above examples.
According to an Esri help technician, this is known bug.

How to send email to multiple addresses in range of cells that updates weekly?

I am a novice at programming. I have setup a google spreadsheet that will send a weekly email reminder to those who have upcoming assignments. The spreadsheet automatically pulls the 4 email addresses of those who are assigned each week and places them in A1, B1, A2, B2 (i.e. A1:B2). I want the script to find the 4 email addresses (that change each week) and send the same email to all four of them.
When I hardcode the cc recipients into the MailApp line, it works fine. But because the recipients list changes weekly I want to reference the cells A1:B2 instead. When I try to do that, I get an Invalid Email error. The debugger shows that var ccrecipients is picking up the right cells, but I think the problem is that it returns it as an array instead of as a string. That's as far as I'm able to reason through it.
A few snippets of my code:
var ccrecipients = sheet.getRange('A1:B2').getValues();
MailApp.sendEmail(recipients, subject, "", {htmlBody: message, cc: ccrecipients});
Thanks in advance for your help. I've relied heavily on these forums to put together the code that I have. I've always been able to find an answer, until this one. Thanks!
Your observation is almost correct, sheet.getRange('A1:B2').getValues(); return an array of arrays, something like [[A1,B1],[A2,B2]] A & B representing the values in the cells to simplify my example.
And what you need in the end is a "flat" string with all the needed recipients separated by commas "A1,B1,A2,B2".
The simplest way to do that is to flatten the whole thing,that will create a string with comma separations and that's exactly what we need.
sheet.getRange('A1:B2').getValues().toString();
That should do the trick ;-)

Exchange 2010 Powershell - Can't view Recipient Filter

I have a dynamic distribution list that I'm trying to modify, however the current filter is complex and was not set up by me. I'm trying to decode it so I can exclude certain emails from it, since currently it seems to include all mailboxes and contacts in the domain.
This is the current filter as displayed in the Exchange Management Console, honestly I don't know enough about the filters to decode this string:
(&(!cn=SystemMailbox{*})(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=contact)) )))
The powershell command below isn't showing me the filter in the Exchange Management Shell, which I would probably be able to decode easier that this query above:
(Get-DynamicDistributionGroup GROUP_NAME).RecipientFilter
I've made sure I'm part of the Organization and Recipient Admin groups, is there something else I'm missing to be able to display this in the Shell? What's the easiest way to decode this filter?
If you need to convert ldap filter to opath you cabn use this script:
http://gallery.technet.microsoft.com/scriptcenter/7c04b866-f83d-4b34-98ec-f944811dd48d