Find Users With Mulitple SMTP Addresses

When employees leave the company, many times a manager needs access to the incoming emails for a few weeks… months… even years. What we do is disable the email account. Then tack the SMTP address to the manager’s email address. This way the manager will receive the emails. This is much more secure, but there is a weakness to this. If you need to do any kind of reporting, you get whomever is connected to that SMTP as well. Becomes a small problem quickly.

The Script

function Get-MutlipleSMTPHolders {
    if (!(Get-Command -Name get-mailbox 2>$null)) {Import-Exchange}
    $users = Get-ADUser -Filter * -Properties * -SearchBase <OU Path>
    $return =@()
    foreach ($user in $users) {
        $UserEmail = get-mailbox -Identity $user.samaccountname -ErrorAction SilentlyContinue 
        $UserName = $user.samaccountname 
        $badEmails = $UserEmail.EmailAddresses | Where-Object {$_ -like "smtp:*"} | Where-Object {$_ -notlike "smtp:$UserName*"}
        if ($badEmails.count -gt 0){
            foreach ($bademail in $badEmails) {
                $Return += [pscustomobject]@{
                    Username = $UserName
                    BadEmail = $bademail -replace "smtp:",''
                }
            }
        }
    }
    $Return
}

The Breakdown

The first thing with this little guy is to grab wither or not exchange is imported. If it does not then we import exchange. Next, we grab all the users in the company. Why? Because I’m only searching users not shared mailboxes. I’m targeting users within a single OU. After that, we create the array that we will be filling. Next, we start the loop to go through each user. We grab the mailbox of the user and search the mailbox for the SMTP which isn’t like the username. This will give us another SMTP address. If it’s greater than 0, I want to know who and what’s in that address. Which is what the for-each loop does. After we gather that information, we print it all to the screen.

Once you have the data, you can go through each account and remove that SMTP from that user. The code below will allow this:

Set-Mailbox $User.PrimarySmtpAddress -EmailAddresses @{remove="$email"}

Improvements

We can add the OU to the parameter. We can also target a single user if need be.

Array to String Line

Have you ever need to take an array and make it into a usable string for your code. I have to do this with validateset. I grab all the group names and then I need to make them look like this “group1″,”group2″,”group3″,”group4” and so on. However, the output is every line. When it’s like 50 things it sucks. Lets solve that issue.

The Script

Function Convert-ArraytoLineofText {
    [cmdletbinding()]
    param ($Inputs)
    $Line = ""
    $Inputs = $Inputs | sort
    foreach ($Input in $Inputs) {
        $Line += """$Input"","
    }
    $Line = $Line.Substring(0,$Line.Length -1)
    $Line | Clip
    Write-Host "Input is on in your clipboard: $Line"
}

The Breakdown

First, note, this will only work with one array at a time and only 1 dimension arrays as well. The first thing we do is grab the input, which is an array. Then we create a blank string $line. Next, we sort the input into itself again. Then we start the foreach loop. We add each input into the string $line. Notice the “””$input””,”. This will create this “Input”,”. We place all the inputs into the array. Then we clip off the last , because this will add a final , to the string. Then we push that into the clipboard. Finally, we tell the end user the information has been put into our clipboard and what it looks like. It’s that simple.

Improvements

There is always space to improve. In this script, we can add a checker to see if the input is more than 1 dimension, force input, and handle multiple arrays.

Like always, feel free to ask questions.

Copy User’s Groups To User

Ever need to copy all groups from a target user to another user? Believe it or not, I have to do this often. Recently, many users had to take on some of the jobs in a different department. Thus, Copy-UsersGroupsToUser was born.

The Script

function Copy-UsersGroupsToUser {
    [cmdletbinding()]
    param (
        [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$true)][string]$Source,
        [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$true)][string]$Target
    )
    (Get-ADUser -Identity $Source -Properties *).memberof -Replace '^cn=([^,]+).*$','$1' | sort | ForEach-Object {
        (Get-ADGroup -Filter "name -like '$_'" -Properties samaccountname).samaccountname | Add-ADGroupMember -Members $Target
    }
}

The Breakdown

Lets break the script down. The first thing we are looking for is the source. This is a single user. Then we need the target user. We set both of these to Mandatory because it would suck if you didn’t have the source and target. Kind of makes the script work yall.

Then we grab the source’s groups with the Get-Aduser -Identity $Source -Properties memberof).memberof. We have to filter out the CN name. We do this with the regular expression (regex). We target the first cn= that is followed by the data between the CN and the next ,. Then we look at what is after this information and we replace it with the first part which is stored in the $1. After grabbing the names of the groups, we sort them. Then we start our foreach loop. We get the group information with Get-ADGroup and select the samaccountname of that group. This is needed to add the person to the group. We pass that into add-adgroupmember. If you notice, you don’t need to put the identity in because add-adgroupmember is grabbing that information from the previous item. The Add-adgroupmember adds the group to the target user.

Improvements

This script is far from being amazing. Some of the basic improvements are, Passing the distinguished name over instead of the name of the group. Newer PowerShell’s can handle the distinguished name, some older ones do not. At least that is what I have seen here in this mixed environment. Another item could be adding a filter to see if the source and target exists. Finally, adding multiple targets instead of just one target. That would be a simple foreach loop.

Example of Improvements

Here is where we add multiple targets with minimal impact on resources.

function Copy-UsersGroupsToUser {
    [cmdletbinding()]
    param (
        [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$true)][string]$Source,
        [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$true)][string[]]$Targets
    )
    $Groups = (Get-ADUser -Identity $Source -Properties *).memberof -Replace '^cn=([^,]+).+$','$1' | sort | ForEach-Object {(Get-ADGroup -Filter "name -like '$_'" -Properties samaccountname).samaccountname}
    Foreach ($target in $Targets) {
        $Groups | ForEach-Object {Add-ADGroupMember -Identity $_ -Members $Target}
    }
}

As you see, the groups are captured first. Then we loop through the targets adding each group to the member.

I hope this has been a informative blog post. Feel free to ask me questions.

Life Changes

When life throws you lemons, make lemonade right? Sometimes God does stuff for us to make us depend on Him. Sometimes, it’s just to wake us up. For years I have not loved on myself. I have chosen to allow my body to decay. I made it up to 267 lbs. Now, at the time of this blog, am at 243 lbs and losing. On the 5th of June, God shook me up a little. I became sick and ended up in bed all night long sweating hard. That morning I ended up in the hospital. My sugar at that moment was 412. No telling how high it was the night before. Yep, I have diabetes now. My parents started down their paths when they were my age as well. So, it’s genetic. However, I will not do the same as my father and allow it to control me. It’s been almost 3 weeks now and I am down to 243 lbs. 24 lbs altogether.

Just remember, sometimes God want’s us to pull closer to Him. When we ignore that fact, He will make things happen to help us along the way.