Get Disabled Users who have an Exchange Mailbox with PowerShell

Get Disabled Users who have an Exchange Mailbox with PowerShell

If there’s one thing most IT department are not great at its removing Exchange Mailboxes for Disabled Users. So here’s a quick Powershell win to determine who within your Exchange organisation has a mailbox and a disabled AD account.

On-Premises Users


1
2
3
4
5
6
7
8
9
$Mailboxes = Get-Mailbox | where {$_.RecipientTypeDetails -eq 'UserMailbox'}
$Disabled = @()

Foreach ($Mailbox in $Mailboxes) {
    if((Get-ADUser -Identity $Mailbox.SamAccountName).Enabled -eq $False){
        $Disabled += Get-MailboxStatistics $Mailbox.SamAccountName | Select -Property DisplayName,TotalItemSize
    }    
}
$Disabled | Export-Csv -Path $env:userprofile\desktop\DisabledADUserwithMailbox.csv -NoTypeInformation

Cloud Users


1
2
3
4
5
6
7
8
9
10
11
Connect-MsolService
 
  $Mailboxes = Get-Mailbox | Where-Object {$_.RecipientTypeDetails -eq 'UserMailbox'}
  $Disabled = @()

  Foreach ($Mailbox in $Mailboxes) {
    if((Get-msolUser -userprincipalname $Mailbox.userprincipalname).Enabled -eq $False){
        $Disabled += Get-MailboxStatistics $Mailbox.userprincipalname | Select-Object -Property DisplayName,TotalItemSize
    }    
  }
  $Disabled | Export-Csv -Path $env:userprofile\desktop\DisabledAzureADUserwithMailbox.csv -NoTypeInformation

Regards

The Author – Blogabout.Cloud

Method invocation failed because [System.Management.Automation.PSObject] doesn’t contain a method named ‘op_Addition’.

Method invocation failed because [System.Management.Automation.PSObject] doesn’t contain a method named ‘op_Addition’.

While constructing a PowerShell script for gathering information about Distribution Lists within a customers environment, I ran into the following error

Method invocation failed because [System.Management.Automation.PSObject] doesn’t contain a method named ‘op_Addition’. 

ERROR!!!
1

This error was being generated by a missing array within my PowerShell code


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Call Distribution Lists
$dist = @(Get-DistributionGroup -resultsize unlimited)

# Start Transcript
Start-Transcript -Path $env:USERPROFILE\desktop\DLsandMember.txt

# Report on Distribution List
foreach ($dl in $dist)
{
 
  $count =@(Get-DistributionGroup $dl.samaccountname).count
  $report = New-Object -TypeName PSObject
  $report | Add-Member -MemberType NoteProperty -Name 'Group Name' -Value $dl.Name
  $report | Add-Member -MemberType NoteProperty -Name 'samAccountname' -Value $dl.samaccountname
  $report | Add-Member -MemberType NoteProperty -Name 'Group Type' -Value $dl.grouptype
  $report | Add-Member -MemberType NoteProperty -Name 'DN' -Value $dl.distinguishedName
  $report | Add-Member -MemberType NoteProperty -Name 'Manager' -Value $dl.managedby
  $report | Add-Member -MemberType NoteProperty -Name 'Member Depart Restriction' -Value $dl.memberdepartrestriction
  $report | Add-Member -MemberType NoteProperty -Name 'Member Join Restriction' -Value $dl.memberjoinrestriction
  $report | Add-Member -MemberType NoteProperty -Name 'PrimarySMTPAddress' -Value $dl.primarysmtpaddress
  $report | Add-Member -MemberType NoteProperty -Name 'EmailAddress' -Value $dl.emailaddresses
  $report | Add-Member -MemberType NoteProperty -Name 'GrantSendOnBehalfto' -Value $dl.GrantSendOnBehalfto
  $report | Add-Member -MemberType NoteProperty -Name 'EmailAddressPolicyEnabled' -Value $dl.EmailAddressPolicyEnabled
  $report | Add-Member -MemberType NoteProperty -Name 'Number of Members' -Value $count
  Write-Host ('INFO: {0} has {1} members' -f $dl.name, ($count))
 
  $reportoutput += $report
}

# Stop Transcript
Stop-Transcript

By adding the following lines to my above script I was able to successful export the required information into an Array and dump out to CSV.


1
2
# Array
$reportoutput=@()

Regards

The Author – Blogabout.Cloud

PowerShell – ForEach do  action X or do Y

PowerShell – ForEach do action X or do Y

PowerShell is one of the greatest tools within any IT Professional toolkit, it enables you to do far more than any GUI available to you today. In my life as a Consultant for a Global Microsoft SI (System Integrator), I face challenges every day where PowerShell has come to the rescue. One of the best cmdlet I use in a lot of script is

ForEach which is the alias name of ForEach-Object

Imagine you need to modify an ExtensionAttribute for your entire organization or grant a permission to a subset of users, ask yourself this? How would I do this in a GUI? and the answer would be “with great difficulty or very time consuming”. This is Foreach-Object comes into play, in the below example I need to modify the PrimarySMTPAddress due to special characters being used

Get-DistributionGroup

In order to correct this, I will be using a source CSV file which contains SamAccountName for the identity of each DistributionList and the correct PrimarySMTPAddress.

Source CSV file

Now for the most important element, the powershell script which will be used to modify the PrimarySMTPAddress. The below script has been designed to achieve the required outcome but also includes the ability to;

  • Be ran using native PowerShell for On-Premises Exchange Servers (2007 through to 2019)
  • Be ran against Exchange Online

So as we can see the Foreach command is being used in the following;

  • For each $row within the $csv which is being imported try and get the distribution list using the column heading SamAccountName
    • If the Identity cannot be found the script will move to the catch
    • If the Identity can be found the script will set the distribution list using the column heading PrimarySMTPAddress
  • The catch is alert if there are any unsuccessful attempts at setting the PrimarySMTPAddress

Simples!!

 Clear-Host
$file = "$env:USERPROFILE\OneDrive\Desktop\groups.csv"
$csv = import-csv -Path $file
region Exchange Module SnapIn
# Exchange 2007
#Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin;
# Exchange 2010
#Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010;
# Exchange 2013/2016
#Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn;
endregion
Transcript
Start-Transcript -Path $env:USERPROFILE\OneDrive\Desktop\Get-DistributionGroup.txt
Foreach ($row in $csv)
{
try {
Get-DistributionGroup -Identity $row.SamAccountName | Set-DistributionGroup -PrimarySmtpAddress $row.PrimarySmtpAddress
Write-Host 'INFO:' ($row.SamAccountName),'Primary SMTP Address has now been modified to',($row.PrimarySmtpAddress) -BackgroundColor Green
}
catch
{
Write-Host 'ERROR:' ($row.SamAccountName),'Primary SMTP Address has not been modified to',($row.PrimarySmtpAddress) -BackgroundColor Red
}
}
Stop-Transcript
Get-DistributionGroup
Image result for meerkat simples gif

I have included Start-Transcript as this will dump out all Write-Host entry whether they was successful or not.

Regards

The Author – Blogabout.Cloud

Do I have duplicate Recipient Alias within my Exchange organization?

Do I have duplicate Recipient Alias within my Exchange organization?

So do you know if you have duplicate recipient alias within your Exchange organisation? Heres a quick script that will look at your Exchange Environment and download all recipient address into a handy csv file you to play with.

The script

 Clear-Host
$start = [datetime]::Now
Start Transcript
Start-Transcript -Path "$env:USERPROFILE\Desktop\Mailbox Alias\mailboxaliaslog.txt"
Get-Recipent
$Mailboxes = Get-Recipient -ResultSize Unlimited -RecipientType UserMailbox |
Sort-Object -Property @{ Expression = { $_.EmailAddresses.Count } } -Descending
$Results = foreach( $Mailbox in $Mailboxes ){
$Stats = $Mailbox | Get-MailboxStatistics

$Properties = [ordered]@{ FirstName = $Mailbox.FirstName LastName = $Mailbox.LastName DisplayName = $Mailbox.DisplayName TotalItemSize = $Stats.TotalItemSize PrimarySmtpAddress = $Mailbox.PrimarySmtpAddress } $AltAddresses = $Mailbox.EmailAddresses | Where-Object { $_ -match '^smtp:' -and $_ -ne $Mailbox.PrimarySmtpAddress } $i = 1 Write-Host ('INFO: Working {0}.PrimarySmptAddress' -f $Mailbox) foreach( $Address in $AltAddresses ){ $Properties.Add( ('AltAddress{0}' -f $i), $Address -replace '^smtp:' ) $i++ } [pscustomobject]$Properties }

$Results |
Export-Csv -Path "$env:USERPROFILE\desktop\MailboxAliasReport.csv"
$end = [datetime]::Now
$resulttime = $end - $start
Stop Transcript
Stop-Transcript
Write-Host ('Execution : {0}Days:{1}Hr:{2}Min:{3}Sec' -f $resultTime.Days, $resultTime.Hours, $resultTime.Minutes, $resultTime.Seconds)

Download

Get-RecipientAlias (54 downloads)

Is Get-ADUser a bit slow in getting required result? Hello ADSISearcher using PowerShell.

Is Get-ADUser a bit slow in getting required result? Hello ADSISearcher using PowerShell.

Sometimes Get-ADUser just isn’t enough if you are working thousands upon thousands of AD Objects. In a recent scenario, while resolving an Active Directory Health issue. I needed the ability to be able to compare AD Objects from 2 Active Directory Domains from within a resource forest.


What is ADSISearcher?

ADSISearcher is a command line driven LDAP Lookup procedure has the ability to query Active Directory. As ADSISearcher looks up Active Directory it enables a faster discovery of the required AD Objects.

My scenario

I need to ensure CustomAttribute10 in Child1.domain.com matches CustomAttribute10 in Child2.domain.com, yes I could use Get-ADUser | export-csv but this has proved to take to long and needed a faster solution.

ADSISearcher has proved to reduce the time required to execute this script and dumping out to a transcript file with “,” separating the text allows the information to be imported to excel if required.

The script

 Clear-Host
Write-Host "You are currently running Version 1.0" -BackgroundColor DarkGray
[string] $Menu = @'
┌─────────────────────────────────────────────────────────────┐
ADSISearcher for CustomAttribute10
Created by @thewatchernode
└─────────────────────────────────────────────────────────────┘
'@
Menu
$Menu
Transcript
Start-Transcript -Path "$env:userprofile\Desktop\Child1vsChild2.txt"
Start Time
$start = [datetime]::Now
region Client Array
$Child1LDAPFilter = '(objectclass=user)'
$PageSize = 1000
$Child1DN = 'DC=child1,DC=domain,DC=com'
$Child1SB = 'DC=child1,DC=domain,DC=com'
$Child1Searcher = [ADSISearcher]('{0}' -f $child1LDAPFilter)
$Child1Searcher.SearchRoot = [ADSI]('GC://{0}' -f $Child1SB)
$Child1Searcher.SearchRoot = [ADSI]('GC://{0}' -f $child1DN)
$Child1Searcher.PageSize = $PageSize
$Child1Objects = $Child1Searcher.FindAll()
endregion
region Collab Array
$Child2SB = 'DC=child2,DC=domain,DC=com'
$Child2DN = 'DC=child2,DC=domain,DC=com'
endregion
region Client vs Collab
Foreach($Object in $child1Objects){
$childca10 = $Object.Properties.'customattribute10'
$Child2LDAPFilter = "(objectclass=user,customattribute10=$childca10)"
$child2Searcher1 = [ADSISearcher]("{0}" -f $child2LDAPFilter)
$child2Searcher1.SearchRoot = [ADSI]("GC://{0}" -f $Child2SB)
$child2Searcher1.SearchRoot = [ADSI]("GC://{0}" -f $Child2DN)
$child2Searcher1.PageSize = $PageSize
#$AllObjects1 = $collabSearcher1.FindAll()
$nullvalue = $object.Properties.'customattribute10'
if ($nullvalue -eq $null)
{
Write-Host 'INFO, Null Value Found in Child Domain 1,' $Object.Properties.samaccountname -BackgroundColor Red
}
else
{
try
{
($Object.Properties.'customattribute10' -eq $child2searcher1.Properties.'customattribute10')
Write-Host 'Skipping, Attribute match found in Child domain 2 using Child domain 1,' $Object.Properties.samaccountname -ForegroundColor Green
}
catch
{
Write-Host 'INFO, No Attribute match found in Child domain 2 using Child domain 1,' $Object.Properties.samaccountname -BackgroundColor Red
}
}
}
endregion
Stop Transcript
Stop-Transcript
End Time
$end = [datetime]::Now
$resultTime = $end - $start
Write-Host ('Execution : {0}Days:{1}Hr:{2}Min:{3}Sec' -f $resultTime.Days, $resultTime.Hours, $resultTime.Minutes, $resultTime.Seconds)

Download

Get-ADSISearcher (52 downloads)

Regards

The Author – Blogabout.Cloud

Working with Active Directory Attributes with multi-values.

Working with Active Directory Attributes with multi-values.

It is common for organisations to use or create Active Directory Attributes that may contain multiple different values and when trying to obtain the information using PowerShell you might receive

Microsoft.ActiveDirectory.Management.ADPropertyValueCollection

Which isn’t helpful to man or beast. However, I have been recently working with custom attributes so its time to share my experiences once again. In this post I will be working with information that is located within my personal lab, where I have customattribute10 defined with O365.

# Command
Get-ADUser -Properties * -Filter * | Select-Object samaccountname,customattribute10 | export-csv -Path $env:USERPROFILE\desktop\test1.csv

As you can see that from the above I am not receiving the desired output from Get-ADUser. So lets use a PowerShell string that obtains the required information

Let’s discuss the below string in detail to explain what each part does

@{name=” customattribute10 ”;expression={$_. customattribute10}}

The @ symbol, is the property you are retrieving is an array, which means it contains multiple values. Then you gave the property a name/label (you can name it anything you like). This will be the header of the column in the CSV file

@{name=” customattribute10 ”;

Then you provide an expression; this is the script block where you tell the PowerShell cmdlet what you are trying to fetch. For example; we want to fetch the values for the customattribute10 attribute.

expression={$_. customattribute10}}

So, now we understand the require array to pull the multi-values from lets execute the below command

# Command
Get-ADUser -Filter * -Properties proxyaddresses,customattribute10 | select samaccountname, @{L='customAttribute10'; E={$_.customAttribute10}} | Export-Csv -Path $env:USERPROFILE\desktop\test.csv

Now executing this command you will receive the correct output from the attribute which you desired.

Regards
The Author – Blogabout.Cloud



Granting permissions to users based on Group Membership with PowerShell

Granting permissions to users based on Group Membership with PowerShell

Hello,

Question: Have you ever had to perform a task for multiple users like granting a permission, policy or something else? and did you do it manually?

I can honestly say I have and it was so time consuming, especially when we have free tools available to use to perform theses actions within seconds/minutes instead of hours/days.

I have generated a script below which I have created to grant a Skype for Business Online policy to a number of users based on their Group Membership. Before you run this script the following assumputions will be made.

  • You have a basic understanding of PowerShell Scripting
  • You have modified all locations shown with ‘#########’ to your requirements

For the below script I have left in ‘IMOnly’ to show exactly what this script is designed to achieve. If a User doesnt have the IMOnly policy they will be granted the policy but if a User already has IMOnly granted. The script will skip the user and generate an output on screen plus to a definited .txt file before moving onto the next user.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
clear-host
# Define Service Account
$username = '#########'
$password = '#########'
$pass = Convertto-Securestring -String $password -asPlaintext -Force
$credential = New-Object -TypeName System.Management.Automation.PScredential -ArgumentList ($username, $pass)

# Connect to Office 365
Import-Module MSOnline
Connect-MsolService -Credential $credential

# Connect to Skype for Business Online
Import-Module -Name SkypeOnlineConnector
$sfboSession = New-CsOnlineSession -Credential $credential
Import-PSSession -Session $sfboSession -AllowClobber

# Get Group Members
Get-MsolGroupMember -GroupObjectId '#########' | export-csv -Path $env:HOMEDRIVE\INSTALL\#########.csv

# Import Users
$csv = Import-Csv -Path $env:HOMEDRIVE\#########\#########.csv

# Assign CsClientPolicy
Foreach ($row in $csv) {
If(Get-CsOnlineUser -Identity $row.EmailAddress | Where-object {$_.ClientPolicy -notcontains 'IMOnly'})
{
Grant-CsClientPolicy -Identity $row.EmailAddress -PolicyName 'IMOnly'
}
else
{
Write-Host -ForegroundColor Yellow $row.EmailAddress "Skipped User"
get-csonlineuser -id $row.EmailAddress | Where-object {$_.ClientPolicy -contains 'IMOnly'} | select-object DisplayName,ClientPolicy | out-file -FilePath $env:HOMEDRIVE\INSTALL\groupuserenbled.txt
}
}

You can also complete this command for On-Premises users by modifying the script to use Get-ADGroupMember as shown below.


1
2
# Get Group Members
Get-ADGroupMember -Identity '#########' | export-csv -Path $env:HOMEDRIVE\INSTALL\#########.csv

This script can be modified to complete other provisioning based on Group Membership, just copy and paste into PowerShell ISE and make the necessary changes

Regards

The Author