Skip to content

Commit 85a7f2a

Browse files
committed
fix: parameterize SMTP config and standardize Send-PasswordExpiryNotification
- Convert hardcoded SMTP server (x.x.x.x), FromAddress, and SearchBase to mandatory parameters - Add CmdletBinding(SupportsShouldProcess) for consistency with other scripts - Convert all parameters to PascalCase (SearchBase, TestMode, EnableLogging, etc.) matching repository convention - Add new parameters: ExpireInDays, TestRecipient, LogDirectory, Language with proper validation - Remove redundant Import-Module (already handled by #Requires) - Remove unnecessary switch-to-bool intermediate variables - Add Creation Date to .NOTES for consistency Closes #6
1 parent 356e3fd commit 85a7f2a

1 file changed

Lines changed: 89 additions & 59 deletions

File tree

Scripts/ActiveDirectory/Send-PasswordExpiryNotification.ps1

Lines changed: 89 additions & 59 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,
68+
69+
[Parameter(Mandatory = $false)]
70+
[ValidateRange(1, 90)]
71+
[int]$ExpireInDays = 10,
72+
73+
[Parameter(Mandatory = $false)]
74+
[switch]$TestMode,
4275

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"
76+
[Parameter(Mandatory = $false)]
77+
[string]$TestRecipient = "admin@company.com",
5078

51-
if ($searchBase) { $defaultSearchBase = $searchBase }
52-
if ($testMode) { $testModeEnabled = $true } else { $testModeEnabled = $false }
53-
if ($enableLogging) { $loggingEnabled = $true } else { $loggingEnabled = $false }
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,
@@ -259,8 +294,8 @@ function Send-PasswordExpiryAlert {
259294
$emailBody = Get-PasswordExpiryEmailBody -UserName $User.Name -DaysToExpire $ExpirationData.DaysToExpire
260295

261296
$mailParams = @{
262-
SmtpServer = $smtpServer
263-
From = $fromAddress
297+
SmtpServer = $SmtpServer
298+
From = $FromAddress
264299
To = $RecipientEmail
265300
Subject = $msg.EmailSubject
266301
Body = $emailBody
@@ -309,27 +344,22 @@ function Write-LogEntry {
309344

310345
try {
311346
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-
347+
Write-LogMessage "Search Base: $SearchBase" -Level "INFO"
348+
Write-LogMessage "Language: $Language" -Level "INFO"
349+
Write-LogMessage "Test Mode: $($TestMode.IsPresent)" -Level "INFO"
350+
Write-LogMessage "Logging: $($EnableLogging.IsPresent)" -Level "INFO"
351+
317352
$logFilePath = $null
318-
if ($loggingEnabled) {
353+
if ($EnableLogging) {
319354
$logFileName = "PasswordNotification_$(Get-Date -Format 'yyyy-MM-dd').csv"
320-
$logFilePath = Join-Path -Path $logDirectory -ChildPath $logFileName
355+
$logFilePath = Join-Path -Path $LogDirectory -ChildPath $logFileName
321356

322357
if (-not (Initialize-LogFile -LogPath $logFilePath)) {
323358
Write-LogMessage "Continuing without logging..." -Level "WARN"
324-
$loggingEnabled = $false
359+
$EnableLogging = $false
325360
}
326361
}
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
362+
333363
Write-LogMessage "Active Directory module loaded successfully" -Level "SUCCESS"
334364

335365
$defaultPasswordPolicy = Get-ADDefaultDomainPasswordPolicy -ErrorAction Stop
@@ -342,9 +372,9 @@ try {
342372
$_.PasswordExpired -eq $false
343373
}
344374

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

347-
$adUsers = Get-ADUser -SearchBase $defaultSearchBase -Filter * -Properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |
377+
$adUsers = Get-ADUser -SearchBase $SearchBase -Filter * -Properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |
348378
Where-Object $userFilter
349379

350380
Write-LogMessage "Found $($adUsers.Count) enabled users to process" -Level "INFO"
@@ -363,11 +393,11 @@ try {
363393
try {
364394
$expirationData = Get-PasswordExpirationData -User $user -DefaultMaxAge $maxPasswordAge
365395

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

369399
if ([string]::IsNullOrWhiteSpace($recipientEmail)) {
370-
$recipientEmail = $testRecipient
400+
$recipientEmail = $TestRecipient
371401
$stats.NoEmail++
372402
Write-LogMessage "User without email address: $($user.Name)" -Level "WARN"
373403
}
@@ -378,7 +408,7 @@ try {
378408
$stats.EmailsSent++
379409
}
380410

381-
if ($loggingEnabled) {
411+
if ($EnableLogging) {
382412
Write-LogEntry -LogPath $logFilePath -User $user -ExpirationData $expirationData -Email $recipientEmail -EmailSent $emailSent
383413
}
384414

@@ -401,11 +431,11 @@ try {
401431
Write-LogMessage "Errors: $($stats.Errors)" -Level "INFO"
402432
Write-LogMessage "Skipped (not expiring): $($stats.Skipped)" -Level "INFO"
403433

404-
if ($testModeEnabled) {
405-
Write-LogMessage "*** TEST MODE ACTIVE - All emails sent to: $testRecipient ***" -Level "WARN"
434+
if ($TestMode) {
435+
Write-LogMessage "*** TEST MODE ACTIVE - All emails sent to: $TestRecipient ***" -Level "WARN"
406436
}
407437

408-
if ($loggingEnabled) {
438+
if ($EnableLogging) {
409439
Write-LogMessage "Detailed log saved to: $logFilePath" -Level "INFO"
410440
}
411441

0 commit comments

Comments
 (0)