PowerShell: Active Directory Reporting by Emails


Monitoring a large Active Directory environment always comes with so many requirements at times. Some of these might be based on various business requirements while some of them are meant for being proactive over the changes in the environment based on daily activities. All the codes applicable to Windows 2003 environment but should work for higher than that as well.

Let’s visit some of the Powershell scripts which might come useful at times:

Dump of all AD User’s info + group Membership of each user along with all relevant attributes

The below code isn’t sending HTML email, but plain text with two attachments only. We can schedule the same weekly basis or fortnight basis to keep snapshots of AD on regular basis to refer at any point of time in cases of requirement.

# !Author! Nitish Kumar

#Would talk about pre-requisites for importing ActiveDirectory Module at end of post
import-module ActiveDirectory

#Preparing files to write data and attach to email
$file1 = "c:\temp\AllADusers_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"
$file2 = "c:\temp\GroupMembershipDetails_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"

#Powershell command to fetch all AD Users data, Columns can be added/ removed
Get-ADUser -Properties * -filter *| select SamAccountName,CN,DisplayName,EmailAddress,MobilePhone,Department,City,Company,Enabled,ObjectClass,Created,msExchWhenMailboxCreated,Modified,LastLogonDate,LastBadPasswordAttempt,PasswordLastSet,PasswordNeverExpires,AccountExpirationDate,BadLogonCount,Manager,DistinguishedName,whenCreated | export-csv "$file1" -noTypeInformation

#Powershell command to fetch group memberships of each single user in AD
Get-ADUser -Filter * -Properties SamAccountName,DisplayName,memberof | % { New-Object PSObject -Property @{ DomainID = $_.SamAccountName UserName = $_.DisplayName Groups = ($_.memberof | Get-ADGroup | Select -ExpandProperty Name) -join "," } } | Select DomainID,UserName,Groups | Export-Csv "$file2" -noTypeInformation

#Email related settings
$smtpServer = "mail.xyz.com"
$att1 = new-object Net.Mail.Attachment($file1)
$att2 = new-object Net.Mail.Attachment($file2)
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "email_1@xyz.com"
$msg.To.Add("email_2@xyz.com")
$msg.To.Add("email_3@xyz.com")
$msg.Subject = "All AD Users Info"
$msg.Body = "Attached is the All AD Users Report and Group memberships."
$msg.Attachments.Add($att1)
$msg.Attachments.Add($att2)
$smtp.Send($msg)
$att1.Dispose()
$att2.Dispose()

#Script ends here

Little modification in the script and one can get any number of columns or related info. The generated files can even be used for restoring things in cases of emergency, but we wouldn’t be discussing that part as of now.

HTML Report of All Users created in last one day, last week, last month

Getting updates on daily, weekly, monthly basis that how many news users have been added into your infra can be quite useful at times. Below code serves for the purpose of getting report of all users created in last 24 hrs.

# !Author! Nitish Kumar

#Would talk about pre-requisites for importing ActiveDirectory Module at end of post
import-module ActiveDirectory

$file = "c:\temp\NewUsers_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"

$When = ((Get-Date).AddDays(-1)).Date
Get-ADUser -Filter {whenCreated -ge $When} -Properties *| select SamAccountName,EmailAddress,whenCreated |Export-Csv "$file" -noTypeInformation

$style = "BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + ""

$smtpServer = "mail.xyz.com"
$att = new-object Net.Mail.Attachment($file)
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "email_1@xyz.com"
$msg.To.Add("email_2@xyz.com")
$msg.Subject = "Report of users created in last 24 hrs"
$body = "<b>Dear Team</b>
"
$body += "Attached is the Report of users and their emails created today

"
$body += Get-ADUser -Filter {whenCreated -ge $When} -Properties *| Select-Object @{Label=”Domain ID”;Expression={($_.SamAccountName)}},@{Label=”User Name”;Expression={($_.Name)}},@{Label=”Email Address”;Expression={($_.EmailAddress)}}, @{Label=”Created on”;Expression={($_.whenCreated)}} | ConvertTo-Html -Head $style
$body += "
<b>Regards</b>
"
$body += "IT Team
"
$msg.Body = $body
$msg.IsBodyHTML = $true
$msg.Attachments.Add($att)
$smtp.Send($msg)
$att.Dispose()

#End of script

By changing $When variable to 1, 7, 30, you can get the desired results (would require to modify the email message accordingly).

HTML Report of All Users deleted in last one day, last week, last month, last six months

When we talking about notifications on users created in last 24 hrs, last 7 days, last month, then we would sure like to have similar reports about the users who got deleted. Here we go

# !Author! Nitish Kumar

#Would talk about pre-requisites for importing ActiveDirectory Module at end of post
import-module ActiveDirectory

$file = "c:\temp\Last1DaysDeletedUsers_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"

$When = ((Get-Date).AddDays(-1)).Date

Get-ADObject -Filter {(isdeleted -eq $true) -and (name -ne "Deleted Objects") -and (objectclass -eq "user")} -includeDeletedObjects -property * | Where-Object {$_.whenChanged -gt $When} | Sort-Object whenChanged| Select-Object @{Label=”Domain ID”;Expression={($_.SamAccountName)}}, @{Label=”User Name”;Expression={($_.Name)}}, @{Label=”Deleted on”;Expression={($_.whenChanged)}} |Export-Csv "$file" -noTypeInformation

$style = "BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + ""

$smtpServer = "mail.xyz.com"
$att = new-object Net.Mail.Attachment($file)
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "email_1@xyz.com"
$msg.To.Add("email_2@xyz.com")
$msg.Subject = "Report of Users Deleted in last 24 hours"
$body = "<b>Dear Team</b>
"
$body += "Attached is the Report of users deleted in last 24 hours.

"
$body += Get-ADObject -Filter {(isdeleted -eq $true) -and (name -ne "Deleted Objects") -and (objectclass -eq "user")} -includeDeletedObjects -property * | Where-Object {$_.whenChanged -gt $When}  | Sort-Object whenChanged| Select-Object @{Label=”Domain ID”;Expression={($_.SamAccountName)}}, @{Label=”User Name”;Expression={($_.Name)}}, @{Label=”Deleted on”;Expression={($_.whenChanged)}} | ConvertTo-Html -Head $style
$body += "
<b>Regards</b>
"
$body += "IT Team
"
$msg.Body = $body
$msg.IsBodyHTML = $true
$msg.Attachments.Add($att)
$smtp.Send($msg)
$att.Dispose()

#End of script

Similarly by changing $When variable, we can get information for last 24 hrs, 7 days, 30 days or 180 days (max possible).

HTML Report of All Users disabled in last one day, last week, last month, last six months

Many Organizations disable the user ID first rather than deleting the same, so one might need the reports of users disabled in last 24 hours, last week or last month. Here we go …

# !Author! Nitish Kumar

#Would talk about pre-requisites for importing ActiveDirectory Module at end of post
import-module ActiveDirectory

$file = "c:\temp\DisabledUsers_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"

$When = ((Get-Date).AddDays(-1)).Date

Get-ADUser -LDAPFilter {(useraccountcontrol:1.2.840.113556.1.4.803:=2)} -Properties whenChanged | Where-Object {$_.whenChanged -gt $When} | Select-Object @{Label=”Domain ID”;Expression={($_.SamAccountName)}},@{Label=”User Name”;Expression={($_.Name)}}, @{Label=”Disabled on”;Expression={($_.whenChanged)}} |Export-Csv "$file" -noTypeInformation

$style = "BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + ""

#Settings related to mail
$smtpServer = "mail.xyz.com"
$att = new-object Net.Mail.Attachment($file)
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = "email_1@xyz.com"
$msg.To.Add("email_1@xyz.com")
$msg.Subject = "Report of Users disabled in last 24 hours."
$body = "<b>Dear Team</b>
"
$body += "Attached is the Report of users disabled in last 24 hours.

"
$body += Get-ADUser -LDAPFilter {(useraccountcontrol:1.2.840.113556.1.4.803:=2)} -Properties whenChanged | Where-Object {$_.whenChanged -gt $When} | Select-Object @{Label=”Domain ID”;Expression={($_.SamAccountName)}},@{Label=”User Name”;Expression={($_.Name)}}, @{Label=”Disabled on”;Expression={($_.whenChanged)}} | ConvertTo-Html -Head $style
$body += "
<b>Regards</b>
"
$body += "IT Team
"
$msg.Body = $body
$msg.IsBodyHTML = $true
$msg.Attachments.Add($att)
$smtp.Send($msg)
$att.Dispose()

Its for disabled users in last 24 hours. One can get report of users disabled in last week and last month accordingly by changing $When variable…

Disabling a user and removing it from all the groups it is member of

Let’s say someone has left the organization and you want to disable the ID along with removing all the groups he/ she is member of. It takes SamAccountName of the concerned person as input …

# !Author! Nitish Kumar

import-module ActiveDirectory

$ErrorActionPreference = "SilentlyContinue"
$user = Read-Host -Prompt 'Input Domain ID to Delete: '
Disable-ADAccount -Identity $user
Get-ADPrincipalGroupMembership $user | select -ExpandProperty Name | foreach-object{  remove-adgroupmember -identity $_ -member $user -Confirm:$False  }

Getting emails of a number of users

Don’t know if IT guys in other companies get such kind of requests but it was a frequent case at my office that we would get a huge list of users (their SamAccountNames) and would be asked to provide email IDs against them.

Easier option to accomplish the same is to do a vlookup from the AD data (as obtained by the last script), but in case one directly wants updated data from AD then the below script can be used.

# !Author! Nitish Kumar

Get-Content c:\temp\user.txt | ForEach {Get-ADUser -Identity $_ -Properties DisplayName,EmailAddress |Select SamAccountName,DisplayName,EmailAddress} | Export-Csv c:\temp\EmailAddresses1.csv -NoTypeInformation

Distribution group members and their emails

Many times you might require the updated list of members along with their Email IDs for a given distribution group. The below command takes display name of Distribution Group and gives output at c:\temp

# !Author! Nitish Kumar

import-module ActiveDirectory

$group = Read-Host -Prompt 'Input Group Display Name'
$file = "c:\temp\"+$group+"_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv"

Get-ADGroupMember -Identity $group -Recursive | Get-ADUser -Properties Mail | Select-Object @{Label=”Domain ID”;Expression={($_.SamAccountName)}},@{Label=”User Name”;Expression={($_.Name)}},@{Label=”Email Address”;Expression={($_.Mail)}} |Export-Csv "$file" -noTypeInformation

Pre-requisites for import-module ActiveDirectory

While its non-issue for the environments where you have Windows 2012 based ActiveDirecory servers, in case of Windows 2003/2008 only domains, one requires to install the below package on one server in the domain at least (Personally I found that its safer to install the same on more than one servers).

https://www.microsoft.com/en-in/download/details.aspx?id=2852

In case of Windows 2003 installing the above package isn’t enough. .Net 3.5.1 should be installed along with patches. The below hotfix also needs to be installed on all servers over which above package is installed.

https://support.microsoft.com/en-us/kb/969166

If failing to find the hotfix as Windows 2003 is out of support now then you can get the same directly from here

https://1drv.ms/u/s!Ag5VPL5rMr_Nh4thXPxHby0MJ_LjXQ

If you facing issues in installation of any one of above, then may be you require to replace the .dll at location C:\WINDOWS\Assembly\GAC_MSIL\System.DirectoryServices.AccountManagement\3.5.0.0__b77a5c561934e089 with the given below one as was my case:

https://1drv.ms/u/s!Ag5VPL5rMr_Nh4tg1xMjunTGVxPYyQ

Build Your Admin Workstation

Install the appropriate version of Windows RSAT.
Add these Windows RSAT features bolded below (Control Panel, Programs, Turn Windows features on or off):
Remote Server Administration Tools
– Role Administration Tools
– – AD DS and AD LDS Tools
– – – Active Directory Module for Windows PowerShell
– – – AD DS Tools
– – – – Active Directory Administrative Center
– – – – AD DS Snap-ins and Command-line Tools

In case you still face the issue then below is the Technet Article

https://blogs.technet.microsoft.com/ashleymcglone/2011/03/17/step-by-step-how-to-use-active-directory-powershell-cmdlets-against-2003-domain-controllers/

3 thoughts on “PowerShell: Active Directory Reporting by Emails

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.