In users' e-mail addresses, remove all references to a domain - powershell

On our cloud-hosted O365 tenancy, I would like to run a PowerShell script which looks at every user and removes any reference to an e-mail domain I'm trying to get rid of.
As an example, if we have the following user:
Jimbob Goodemails
Jimbob.Goodemails#newdomain.com
Jimbob.Goodemails#olddomain.com
Jimbob.Goodemails#domain.onmicrosoft.com (the default O365 domain)
I would like to remove #olddomain.com addresses (in the above case, Jimbob.Goodemails#olddomain.com) from every user.
On most of these accounts, that domain will be set up as an alias - e.g. smtp:Jimbob.Goodemails#olddomain.com in the proxyAddresses field.
However, some users (far fewer, perhaps only 3 or 4) may have it as their main e-mail address (e.g. SMTP:Jimbob.Goodemails#olddomain.com in proxyAddresses but also as the mail and UPN attributes). These users can just use the default O365 e-mail address instead.
I have tried the following script, to no avail:
foreach($i in Get-Mailbox -ResultSize Unlimited) {
  $i.EmailAddresses |
    ?{$_.AddressString -like '*#olddomain.com'} | %{
      Set-Mailbox $i -EmailAddresses #{remove=$_}
    }
}
It sits for a while, then appears to finish, but nothing has changed.
I have used an Active Directory PowerShell script which does this for my AD-synchronised users, so I'm primarily looking to change Cloud users and groups.
It would also be useful to know how to search for such users too.

The Method:
Create an Array of your Current SMTP's:
$SMTPs = $Mailbox.EmailAddresses -split ","
Remove the Unwanted SMTP Addresses:
$SMTPs | ? {$_ -notmatch 'olddomain.com'}
Then Update The Mailbox with the filtered SMTPs:
Set-Mailbox $Mailbox -EmailAddresses $SMTPs
In your Example:
foreach ($i in Get-Mailbox -ResultSize Unlimited)
{
$SMTPs = $i.EmailAddresses -split "," | ? {$_ -notmatch 'olddomain.com'}
Set-Mailbox $i -EmailAddresses $SMTPs
}

Related

Using filter to find email addresses matching a domain

I'm trying to find email addresses in O365 Exchange that matches a particular domain using PowerShell.
If I use:
Get-Recipient -ResultSize unlimited -filter '(PrimarySMTPAddress -like "*smith*")' | fl primarysmtpaddress
I get all the addresses that have the string
If I use:
Get-Recipient -ResultSize unlimited -filter '(PrimarySMTPAddress -like "*#domain*")' | fl primarysmtpaddress
I get no results.
It looks like nothing is matched after the #.
I want to use -filter rather than a where statement because it is so much faster.
I was able to reproduce your issue. It seems to be related to the the specific attribute you filtered on, "PrimarySMTPAddress".
I was able to get the filter statement to return results by changing it to leverage "EmailAddresses", another attribute the email address is stored in:
Get-Recipient -ResultSize unlimited -filter '(EmailAddresses -like "*#domain*")' | fl primarysmtpaddress
Something else I saw of note: the "filterable properties" documentation mentions avoiding using "PrimarySMTPAddress" for another reason that I didn't know of:
Don't use the PrimarySmtpAddress property; use the EmailAddresses property instead. Any filter that uses the PrimarySmtpAddress property will also search values in the EmailAddresses property. For example, if a mailbox has the primary email address dario#contoso.com, and the additional proxy addresses dario2#contoso.com and dario3#contoso.com, all of the following filters will return that mailbox in the result: "PrimarySmtpAddress -eq 'dario#contoso.com'", "PrimarySmtpAddress -eq 'dario2#contoso.com'", or "PrimarySmtpAddress -eq 'dario3#contoso.com'".
Source
https://learn.microsoft.com/en-us/powershell/exchange/filter-properties?view=exchange-ps

Using Powershell to get Office 365 SMTP: email addresses

Found the exact script I need:
https://unlockpowershell.wordpress.com/2010/01/27/powershell-get-mailbox-display-smtp-addresses/
Get-Mailbox -ResultSize Unlimited |Select-Object DisplayName,ServerName,PrimarySmtpAddress, #{Name=“EmailAddresses”;Expression={$_.EmailAddresses |Where-Object {$_.PrefixString -ceq “smtp”} | ForEach-Object {$_.SmtpAddress}}}
When I run this using Powershell5 against Office 365, "Email Addresses" is returned blank.
Any ideas?
This may have worked on Exchange 2007/2010, where the blog post says it was tested, but O365 mailboxes are a little different.
The EmailAddresses property of a mailbox object in O365 is an array list containing strings and they have no PrefixString property here. The issue is at this point
Where-Object {$_.PrefixString -ceq “smtp”}
Since PrefixString doesn't exist, you get blank results.
Instead, since the EmailAddresses array is just a bunch of strings, you can filter on those directly.
Get-Mailbox -ResultSize Unlimited | Select-Object DisplayName,ServerName,PrimarySmtpAddress, #{Name=“EmailAddresses”;Expression={$_.EmailAddresses | Where-Object {$_ -clike “smtp*”}}}

How to extract field content in powershell

History: I'm making a Powershell script in order to create user from a defined table containing list of users and put them in a defined OrganizationalUnit.
Problem: At the end of the script, I'd like to have a report in order to list whether or not there is one or many user account disabled amoung newly created account
In my script, I have to input a password for each user, but I may enter a password that won't meet the password policy defined in Active Directory; in this case, the account will be created but disabled.
To proceed, I tried :
dsquery user "ou=sp,dc=mydomain,dc=local" -disabled
and it print me this :
"CN=user1,OU=SP,DC=mydomain,DC=local"
"CN=user2,OU=SP,DC=mydomain,DC=local"
"CN=user3,OU=SP,DC=mydomain,DC=local"
My goal : I'd like to extract in a variable the values in "CN" field in order to compare them to the inital user table in my script.
dsquery user "dc=mydomain,dc=local" -disabled | where-object {$_.CN -ne $null}
or
dsquery user "dc=mydomain,dc=local" -disabled | where-object {$_.Common-Name -ne $null}
But it didn't help (doesn't work). How can I proceed please?
It's not tested - just "from my mind"
$csvData = Import-Csv 'UserList.csv' -Delimiter ';' -Encoding UTF8
$userList = dsquery user "ou=sp,dc=mydomain,dc=local" -disabled
$listOfDisabledAccounts = #()
foreach ($user in $userList)
{
if ($csvData.Name -contains (($user -split ',')[0] -replace 'CN=',''))
{
$listOfDisabledAccounts += $csvData.Name
}
}
$listOfDisabledAccounts
dsquery is not a PowerShell cmdlet, but an executable. This means that it is not going to return PowerShell objects to the pipeline. Kongstead's method works off of the knowing that it returns string output. By manipulating the string using split and replace you can get the output into something usable for your purposes. The other two methods to get this information would be to use the the AD module (from RSAT on desktop OSs) and ADSI methods from .Net. Both of these would return data that would be directly usable.
The AD cmdlets would be the easiest. To get all the disabled accounts would look something like this:
Search-ADAccount -AccountDisabled -SearchBase "dc=mydomain,dc=local"
The following example uses PowerShell's match function to parse the CN field, similar to the answer from Kongsted. It should help you achieve what you are looking for, if using AD cmdlets is not an option.
#This is the output from your current query, from the question, it appears to be an array.
$output = ("CN=user1,OU=SP,DC=mydomain,DC=local","CN=user2,OU=SP,DC=mydomain,DC=local","CN=user3,OU=SP,DC=mydomain,DC=local")
$disabledAccs = #()
foreach ($line in $output) {
#match everything after CN= up to the next comma
if([string]$line -match "CN=([^,]*)"){
$disabledAccs += , $Matches[1]
}
}

Search members in Group Distribution Exchange

I'm using the following code to get all members in a group.
Get-DistributionGroupMember -Identity "Marketing USA"
The problems is, some of groups have more than 1000 members. So instead of loading all the records, is there a better way I can filter the result to see only the members I need.
I would like to search by Primary Email and Display Name.
My Exchange versions are 2010 and 2013.
For both Exchange 2010 and 2013 you can search by email address by creating a list of email addresses in regex form separated by |. Then use -imatch to match the email addresses you need. Note: This will search both primary and secondary address.
$EmailAddress = [regex]"Username1#Domain.com|Username2#Domain.com|Username3#Domain.com"
Get-DistributionGroupMember -Identity "Marketing USA" | Where { $_.EmailAddresses.SmtpAddress -imatch $EmailAddress }
Then to searching by display name you can all so use regex in the same way separating the names by |.
$DisplayName = [regex]"FirstName1 LastName1|FirstName2 LastName2|FirstName3 LastName3"
Get-DistributionGroupMember -Identity "Marketing USA" | Where { $_.DisplayName -imatch $DisplayName }
With this method of filtering you can also do partial searches. If you only put in the first name of the user you will get back all users with that name. The same goes will the email address search.
According to documentation by default the result size is limited to 1000. You will need to include -ResultSize Unlimited e.g. Get-DistributionGroupMember -Identity "Marketing USA" -ResultSize Unlimited to return more than that.
A distribution group is also an AD group. With the Get-ADGroup cmdlet you also get the possibility to filter the search in a much more effective way.
For example:
Get-ADGroup -Filter {proxyaddresses -like "SMTP:address#DOMAIN.COM"} (or use the mail attribute if that is equal to the primary email address in your org)
or
Get-ADGroup -Filter {displayname -eq "MyDL"} -Properties *
To use this cmdlet you might need to load the activedirectory ps module with 'import-module activedirectory' first in your powershell session.

List all mailboxes that forward to a specific user

I have this script that lists all mailboxes that are forwarding email, however, I am curious if there would be a way to make it return all mailboxes that forward to a specific user. Basically I'm trying to find out every mailbox that forwards mail to "johndoe". Any help would be greatly appreciated! This is for exchange 2007 btw...
Here's the script so far:
$fwds = get-mailbox | Where-Object { $_.ForwardingAddress -ne $null }
| select Name, ForwardingAddress
foreach ($fwd in $fwds) {$fwd | add-member -membertype noteproperty
-name “ContactAddress” -value (get-contact $fwd.ForwardingAddress).WindowsEmailAddress}
$fwds
Exchange uses CanonicalName for the forwarding address, so you'll need to look that up from the user name. Since it could be a Mailbox, DL, or Contact, the easiest way I know of is to use Get-Recipient, and grab the Identity property.
$RecipientCN = (get-recipient johndoe).Identity
get-mailbox | Where-Object { $_.ForwardingAddress -eq $RecipientCN }
#mjolinor's version works, but is rather slow, since it loads all the mailboxes. On my system it took about 30 seconds to go through ~300 mailboxes.
This can be speed up by adding a filter to the Get-Mailbox command to only return ones that are actually being forwarded, like so:
$RecipientCN = (get-recipient johndoe).Identity
Get-Mailbox -ResultSize Unlimited -Filter {ForwardingAddress -ne $null} | Where-Object {$_.ForwardingAddress -eq $RecipientCN}
But wait, we can get even faster! Why not search for the correct user right in the filter? Probably because it's hard to get the syntax right, because using variables in -Filter gets confusing.
The trick is to use double quotes around the entire filter expression, and single quotes around the variable:
$RecipientCN = (get-recipient johndoe).Identity
Get-Mailbox -ResultSize Unlimited -Filter "ForwardingAddress -eq '$RecipientCN'"
This version returns the same results in 0.6s - about 50 times faster.