Skip to content

Commit 9f5ffdc

Browse files
authored
Merge pull request #11 from leonardokr/fix/issue-6-password-expiry-notification
Fix: parameterize SMTP config and standardize Send-PasswordExpiryNotification
2 parents 95c75e4 + 4b337b6 commit 9f5ffdc

1 file changed

Lines changed: 95 additions & 63 deletions

File tree

Scripts/ActiveDirectory/Send-PasswordExpiryNotification.ps1

Lines changed: 95 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,54 +3,89 @@
33
<#
44
.SYNOPSIS
55
Active Directory Password Expiration Notification Script
6-
6+
77
.DESCRIPTION
88
Monitors Active Directory users and sends email notifications when passwords are approaching expiration.
99
Supports fine-grained password policies, multilingual messages, and comprehensive logging.
10-
11-
.PARAMETER searchBase
12-
Distinguished Name of the OU to search for users. If not specified, uses default configured base.
13-
14-
.PARAMETER testMode
10+
11+
.PARAMETER SmtpServer
12+
SMTP server address for sending notification emails.
13+
14+
.PARAMETER FromAddress
15+
Email address used as the sender for notifications.
16+
17+
.PARAMETER SearchBase
18+
Distinguished Name of the OU to search for users.
19+
20+
.PARAMETER ExpireInDays
21+
Number of days before expiration to start sending notifications. Default is 10.
22+
23+
.PARAMETER TestMode
1524
Switch to enable test mode. All emails will be sent to the test recipient instead of actual users.
16-
17-
.PARAMETER enableLogging
25+
26+
.PARAMETER TestRecipient
27+
Email address to receive all notifications when running in test mode. Default is "admin@company.com".
28+
29+
.PARAMETER EnableLogging
1830
Switch to enable detailed logging to CSV file.
19-
31+
32+
.PARAMETER LogDirectory
33+
Directory path for log files. Default is "C:\Logs\PasswordNotifications".
34+
35+
.PARAMETER Language
36+
Language for email templates. Supported values: EN, PT. Default is EN.
37+
2038
.EXAMPLE
21-
.\Send-PasswordExpiryNotification.ps1
22-
Runs with default configuration
23-
39+
.\Send-PasswordExpiryNotification.ps1 -SmtpServer "mail.company.com" -FromAddress "noreply@company.com" -SearchBase "OU=Users,DC=domain,DC=com"
40+
41+
Runs with specified SMTP server and search base.
42+
2443
.EXAMPLE
25-
.\Send-PasswordExpiryNotification.ps1 -testMode -enableLogging
26-
Runs in test mode with logging enabled
27-
44+
.\Send-PasswordExpiryNotification.ps1 -SmtpServer "mail.company.com" -FromAddress "noreply@company.com" -SearchBase "OU=Users,DC=domain,DC=com" -TestMode -EnableLogging
45+
46+
Runs in test mode with logging enabled.
47+
2848
.NOTES
29-
File Name : Send-PasswordExpiryNotification.ps1
30-
Author : Leonardo Klein Rezende
31-
Requires : PowerShell 5.1+, ActiveDirectory Module, SMTP Server Access
32-
49+
File Name : Send-PasswordExpiryNotification.ps1
50+
Author : Leonardo Klein Rezende
51+
Prerequisite : PowerShell 5.1+, ActiveDirectory Module, SMTP Server Access
52+
Creation Date : 2025-09-04
53+
3354
.LINK
3455
https://github.com/leonardokr/powershell-scripts
3556
#>
3657

58+
[CmdletBinding(SupportsShouldProcess)]
3759
param(
38-
[string]$searchBase,
39-
[switch]$testMode,
40-
[switch]$enableLogging
41-
)
60+
[Parameter(Mandatory = $true)]
61+
[string]$SmtpServer,
62+
63+
[Parameter(Mandatory = $true)]
64+
[string]$FromAddress,
65+
66+
[Parameter(Mandatory = $true)]
67+
[string]$SearchBase,
4268

43-
$smtpServer = "x.x.x.x"
44-
$expireInDays = 10
45-
$fromAddress = "noreply@company.com"
46-
$testRecipient = "admin@company.com"
47-
$language = "EN" # EN or PT
48-
$logDirectory = "C:\Logs\PasswordNotifications"
49-
$defaultSearchBase = "OU=Users,DC=contoso,DC=local"
69+
[Parameter(Mandatory = $false)]
70+
[ValidateRange(1, 90)]
71+
[int]$ExpireInDays = 10,
5072

51-
if ($searchBase) { $defaultSearchBase = $searchBase }
52-
if ($testMode) { $testModeEnabled = $true } else { $testModeEnabled = $false }
53-
if ($enableLogging) { $loggingEnabled = $true } else { $loggingEnabled = $false }
73+
[Parameter(Mandatory = $false)]
74+
[switch]$TestMode,
75+
76+
[Parameter(Mandatory = $false)]
77+
[string]$TestRecipient = "admin@company.com",
78+
79+
[Parameter(Mandatory = $false)]
80+
[switch]$EnableLogging,
81+
82+
[Parameter(Mandatory = $false)]
83+
[string]$LogDirectory = "C:\Logs\PasswordNotifications",
84+
85+
[Parameter(Mandatory = $false)]
86+
[ValidateSet("EN", "PT")]
87+
[string]$Language = "EN"
88+
)
5489

5590
$messages = @{
5691
EN = @{
@@ -107,7 +142,7 @@ $messages = @{
107142
}
108143
}
109144

110-
$msg = $messages[$language]
145+
$msg = $messages[$Language]
111146
function Write-LogMessage {
112147
param(
113148
[string]$Message,
@@ -252,15 +287,17 @@ function Send-PasswordExpiryAlert {
252287
param(
253288
[Microsoft.ActiveDirectory.Management.ADUser]$User,
254289
[hashtable]$ExpirationData,
255-
[string]$RecipientEmail
290+
[string]$RecipientEmail,
291+
[string]$Server,
292+
[string]$From
256293
)
257-
294+
258295
try {
259296
$emailBody = Get-PasswordExpiryEmailBody -UserName $User.Name -DaysToExpire $ExpirationData.DaysToExpire
260-
297+
261298
$mailParams = @{
262-
SmtpServer = $smtpServer
263-
From = $fromAddress
299+
SmtpServer = $Server
300+
From = $From
264301
To = $RecipientEmail
265302
Subject = $msg.EmailSubject
266303
Body = $emailBody
@@ -309,27 +346,22 @@ function Write-LogEntry {
309346

310347
try {
311348
Write-LogMessage "=== PASSWORD EXPIRATION NOTIFICATION STARTED ===" -Level "INFO"
312-
Write-LogMessage "Search Base: $defaultSearchBase" -Level "INFO"
313-
Write-LogMessage "Language: $language" -Level "INFO"
314-
Write-LogMessage "Test Mode: $testModeEnabled" -Level "INFO"
315-
Write-LogMessage "Logging: $loggingEnabled" -Level "INFO"
316-
349+
Write-LogMessage "Search Base: $SearchBase" -Level "INFO"
350+
Write-LogMessage "Language: $Language" -Level "INFO"
351+
Write-LogMessage "Test Mode: $($TestMode.IsPresent)" -Level "INFO"
352+
Write-LogMessage "Logging: $($EnableLogging.IsPresent)" -Level "INFO"
353+
317354
$logFilePath = $null
318-
if ($loggingEnabled) {
355+
if ($EnableLogging) {
319356
$logFileName = "PasswordNotification_$(Get-Date -Format 'yyyy-MM-dd').csv"
320-
$logFilePath = Join-Path -Path $logDirectory -ChildPath $logFileName
357+
$logFilePath = Join-Path -Path $LogDirectory -ChildPath $logFileName
321358

322359
if (-not (Initialize-LogFile -LogPath $logFilePath)) {
323360
Write-LogMessage "Continuing without logging..." -Level "WARN"
324-
$loggingEnabled = $false
361+
$EnableLogging = $false
325362
}
326363
}
327-
328-
if (-not (Get-Module -Name ActiveDirectory -ListAvailable)) {
329-
throw "Active Directory module not available. Please install RSAT tools."
330-
}
331-
332-
Import-Module ActiveDirectory -ErrorAction Stop
364+
333365
Write-LogMessage "Active Directory module loaded successfully" -Level "SUCCESS"
334366

335367
$defaultPasswordPolicy = Get-ADDefaultDomainPasswordPolicy -ErrorAction Stop
@@ -342,9 +374,9 @@ try {
342374
$_.PasswordExpired -eq $false
343375
}
344376

345-
Write-LogMessage "Searching for users in: $defaultSearchBase" -Level "INFO"
377+
Write-LogMessage "Searching for users in: $SearchBase" -Level "INFO"
346378

347-
$adUsers = Get-ADUser -SearchBase $defaultSearchBase -Filter * -Properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |
379+
$adUsers = Get-ADUser -SearchBase $SearchBase -Filter * -Properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |
348380
Where-Object $userFilter
349381

350382
Write-LogMessage "Found $($adUsers.Count) enabled users to process" -Level "INFO"
@@ -363,22 +395,22 @@ try {
363395
try {
364396
$expirationData = Get-PasswordExpirationData -User $user -DefaultMaxAge $maxPasswordAge
365397

366-
if ($expirationData.DaysToExpire -ge 0 -and $expirationData.DaysToExpire -lt $expireInDays) {
367-
$recipientEmail = if ($testModeEnabled) { $testRecipient } else { $user.EmailAddress }
398+
if ($expirationData.DaysToExpire -ge 0 -and $expirationData.DaysToExpire -lt $ExpireInDays) {
399+
$recipientEmail = if ($TestMode) { $TestRecipient } else { $user.EmailAddress }
368400

369401
if ([string]::IsNullOrWhiteSpace($recipientEmail)) {
370-
$recipientEmail = $testRecipient
402+
$recipientEmail = $TestRecipient
371403
$stats.NoEmail++
372404
Write-LogMessage "User without email address: $($user.Name)" -Level "WARN"
373405
}
374406

375-
$emailSent = Send-PasswordExpiryAlert -User $user -ExpirationData $expirationData -RecipientEmail $recipientEmail
407+
$emailSent = Send-PasswordExpiryAlert -User $user -ExpirationData $expirationData -RecipientEmail $recipientEmail -Server $SmtpServer -From $FromAddress
376408

377409
if ($emailSent) {
378410
$stats.EmailsSent++
379411
}
380412

381-
if ($loggingEnabled) {
413+
if ($EnableLogging) {
382414
Write-LogEntry -LogPath $logFilePath -User $user -ExpirationData $expirationData -Email $recipientEmail -EmailSent $emailSent
383415
}
384416

@@ -401,11 +433,11 @@ try {
401433
Write-LogMessage "Errors: $($stats.Errors)" -Level "INFO"
402434
Write-LogMessage "Skipped (not expiring): $($stats.Skipped)" -Level "INFO"
403435

404-
if ($testModeEnabled) {
405-
Write-LogMessage "*** TEST MODE ACTIVE - All emails sent to: $testRecipient ***" -Level "WARN"
436+
if ($TestMode) {
437+
Write-LogMessage "*** TEST MODE ACTIVE - All emails sent to: $TestRecipient ***" -Level "WARN"
406438
}
407439

408-
if ($loggingEnabled) {
440+
if ($EnableLogging) {
409441
Write-LogMessage "Detailed log saved to: $logFilePath" -Level "INFO"
410442
}
411443

0 commit comments

Comments
 (0)