Powershell Script does not send email to the user

Kevin Savard Vertisoft 86 Reputation points
2023-01-20T13:28:18.8233333+00:00

Hello,

I have the following script. Everything works fine except the part that it is supposed to send the email to the user. The part that send an email to the supervisor is working properly. I took the original form to a website and I edited it myself. I'm not a master of powershell but I have some basic knowledge. If you could help me to see where is the error that would be awesome. The goal is to send an email, everyday, as soon as the user is at 14 days from having his password expired. There is some addon that send me a report of the Active Directory every morning since it is enforced to a task every morning. I'm hiding personal information for security purposes. Some things are in french. Sorry about that.

Thanks in advance for your precious help.

Configuration des variables

$smtpServer= "server SMTP@hidden.com"

$expireindays = 14

$from = "random@email.com"

$logging = "Enabled" # Set to Disabled to Disable Logging

$logFile = "C:\Users\administrator\Desktop\passwordexpirationlog.csv" # EX: c:\Expiration.csv

$testing = "Disabled" #Mode de test Set to Disabled pour que l'usager reçoit un courriel d'avis

$testRecipient = "random@email.com"

$SendToSupervisor = "Enabled" # Set to Enabled Pour que le superviseur reçoit le fichier de logto Disable Logging

$Supervisor = "random@email.com" # Le superviseur recevra le fichier de log

$Expiration = "Yes"

###########################################################

########################################################

Vérification de la journalisation

if (($logging) -eq "Enabled")

{

Test Log File Path

$logfilePath = (Test-Path $logFile)

if (($logFilePath) -ne "True" -or $SendToSupervisor -eq "Enabled" )

{

if (Test-Path $logFile -PathType leaf)

{

Remove-Item $logFile

}

Create CSV File and Headers

New-Item $logfile -ItemType File

Add-Content $logfile "Date,Name,EmailAddress,DaystoExpire,ExpiresOn,Notified"

}

} # End Logging Check

Paramètre du systeme

$textEncoding = [System.Text.Encoding]::UTF8

$date = Get-Date -format ddMMyyyy

Fin de vérification des paramètres du systeme

Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired

Import-Module ActiveDirectory

$users = get-aduser -filter * -properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress | where {$.Enabled -eq "True"} | where {$.PasswordNeverExpires -eq $false } | where { $_.passwordexpired -eq $false }

$DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge

Process Each User for Password Expiry

foreach ($user in $users)

{

$Name = $user.Name

$emailaddress = $user.emailaddress

$passwordSetDate = $user.PasswordLastSet

$PasswordPol = (Get-AduserResultantPasswordPolicy $user)

$sent = "" # Reset Sent Flag

Check for Fine Grained Password

if (($PasswordPol) -ne $null)

{

$maxPasswordAge = ($PasswordPol).MaxPasswordAge

}

else

{

No FGP set to Domain Default

$maxPasswordAge = $DefaultmaxPasswordAge

}

$expireson = $passwordsetdate + $maxPasswordAge

$today = (get-date)

$daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days

Set Greeting based on Number of Days to Expiry.

Check Number of Days to Expiry

$messageDays = $daystoexpire

if (($messageDays) -gt "1")

{

$messageDays = "in " + "$daystoexpire" + " days."

$messageJours = "dans " + "$daystoexpire" + " jours."

}

else

{

$messageDays = "today."

$messageJours = "Aujourd'hui"

}

Email Subject Set Here

$subject="Votre mot de passe va expirer $messageJours | Your password will expire

$messageDays"

Email Body Set Here, Note You can use HTML, including Images.

$body ="

À l'attention de $name,

<p> Votre mot de passe réseau va expirer $messageJours<br>

Pour changer votre mot de passe sur un ordinateur quand vous êtes au bureau, appuyez sur

CTRL+ALT+Delete et sélectionnez « changer de mot de passe ». <br>

Pour changer votre mot de passe sur un ordinateur quand vous êtes à la maison, votre VPN doit être

actif, appuyez sur CTRL+ALT+Delete et sélectionnez « changer de mot de passe ». Assurez-vous d'être connecter au VPN pour le faire, sauf si vous êtes au bureau. <br>

<p>Merci, <br>

</P>

Dear $name,

<p> Your Password will expire $messageDays<br>

To change your password on a computer when you are at the office, press CTRL+ALT+Delete

and choose « Change Password ». <br>

To change your password on a computer when you are at home, your VPN need to be active ,

press CTRL+ALT+Delete and choose « Change Password ». Make sure you are connected with the VPN unless you are at the office. <br>

<p>Thanks, <br>

</P>"

If Testing Is Enabled - Email Administrator

if (($testing) -eq "Enabled")

{

$emailaddress = $testRecipient

} # End Testing

If a user has no email address listed

if (($emailaddress) -eq $null)

{

$emailaddress = $testRecipient

}# End No Valid Email

Send Email Message

if (($daystoexpire -ge "0") -and ($daystoexpire -lt $expireindays))

{

$sent = "Yes"

$Expiration = "Yes"

If Logging is Enabled Log Details

if (($logging) -eq "Enabled")

{

Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent"

}

Send Email Message

Send-Mailmessage -smtpServer $smtpServer -from $from -to $emailaddress -subject $subject -body $body -bodyasHTML -priority High -Encoding $textEncoding

} # End Send Message

else # Log Non Expiring Password

{

$sent = "No"

If Logging is Enabled Log Details

if (($logging) -eq "Enabled")

{

Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent"

}

}

} # End User Processing

Si $Logging et $SendToSupervisor sont a "Enabled le fichier de log est envoyer au superviseur seulement si un mot de passe envoie d'expiration est trouvé

if (($logging) -eq "Enabled" -and $SendToSupervisor -eq "Enabled" -and $Expiration -eq "Yes" )

{

$Subject = "Rapport d'expiration des mots de passe des usagers"

$Body = "Bonjour, Voici le rapport d'expiration des mots de passe. Merci!"

#write-host $Subjet

#write-host $Body

#write-host $Supervisor

#write-host $logFile

#write-host $smtpServer

#Pause

Send-MailMessage -to $Supervisor -subject $Subject -body $Body -smtpserver $SMTPServer -from $From -Attachments $logFile

#write-host "Courriel envoyé"

}

End

Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,552 questions
PowerShell
PowerShell
A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
2,595 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. DaveK 1,861 Reputation points
    2023-01-31T09:31:58.97+00:00

    Hi,

    Firstly just a note on how you've posted the question, you likely haven't got much response as the question isn't formatted very well with no indentation so its hard to read increasing the time it takes for someone to help. I'd recommend posting any code using the 'inline code' option - its the button which has '<>' on it. Also I'd recommend if your going to comment code, do it using # rather than large font text.

    Can you test it using the same command as you do for the supervisor email? i.e.

    Send-MailMessage -to $emailaddress -subject $Subject -body $Body -smtpserver $SMTPServer -from $From

    If that works ok, it must be something else in the command you run for the user email such as bodyasHTML, priority or Encoding. Have you verified the value of $emailaddress before sending the email? Is there any error messages?

    I've been doing something very similar for mobile users to notify before password expiry but I used Net.Mail.SmtpClient instead of Send-MailMessage as I believe at the time I had some issues with using HTML for the body and using Net.Mail.SmtpClient it just all worked fine.

    0 comments No comments

  2. Rich Matheisen 46,811 Reputation points
    2023-02-01T02:52:40.35+00:00

    Are any errors generated by the script? I can see there are no checks for errors when the Send-MailMessage is executed.

    There is a problem in the way you calculate the values for when a password will expire. The problem will probably only have an effect on users that have never set their password (e.g. a new user that hasn't yet logged on).

    I've added comments at the end of lines that lead to the problem. I also added comments about how to eliminate such users from consideration.

    I also cleaned up the formatting of what you posted.

    I did NOT add any error detection to the code.

    #Configuration des variables
    $smtpServer = "server.hidden.com"
    $expireindays = 14
    $from = "random@email.com"
    $logging = "Enabled" # Set to Disabled to Disable Logging
    $logFile = "C:\Users\administrator\Desktop\passwordexpirationlog.csv" # EX: c:\Expiration.csv
    $testing = "Disabled" #Mode de test Set to Disabled pour que l'usager reçoit un courriel d'avis
    $testRecipient = "random@email.com"
    $SendToSupervisor = "Enabled" # Set to Enabled Pour que le superviseur reçoit le fichier de logto Disable Logging
    $Supervisor = "random@email.com" # Le superviseur recevra le fichier de log
    $Expiration = "Yes"
    
    ###########################################################
    
    ########################################################
    
    # Vérification de la journalisation
    if (($logging) -eq "Enabled") {
        # Test Log File Path
        $logfilePath = (Test-Path $logFile)
        if (($logFilePath) -ne "True" -or $SendToSupervisor -eq "Enabled" ) {
            if (Test-Path $logFile -PathType leaf) {
                Remove-Item $logFile
            }
            # Create CSV File and Headers
            New-Item $logfile -ItemType File
            Add-Content $logfile "Date,Name,EmailAddress,DaystoExpire,ExpiresOn,Notified"
        }
    } # End Logging Check
    
    # Paramètre du systeme
    $textEncoding = [System.Text.Encoding]::UTF8
    $date = Get-Date -Format ddMMyyyy
    
    # Fin de vérification des paramètres du systeme
    # Get Users From AD who are Enabled, Passwords Expire and are Not Currently Expired
    #Import-Module ActiveDirectory
    
    #$users = Get-ADUser -Filter * -Properties Name, PasswordNeverExpires, PasswordExpired, PasswordLastSet, EmailAddress |
        Where-Object {  $_.Enabled -AND
                        $_.PasswordNeverExpires -EQ $false -AND
                        $_.passwordexpired -eq $false 
                        # Add additional test here if you want to exclude users that have NEVER set their password
                        # I.e., User must set password at next logon
                        # $null -ne $_.PasswordLastSet
                     }
    $DefaultmaxPasswordAge = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge
    # Process Each User for Password Expiry
    foreach ($user in $users) {
        $Name = $user.Name
        $emailaddress = $user.emailaddress
        $passwordSetDate = $user.PasswordLastSet                # What if the password has never been set? This property is $null
        $PasswordPol = (Get-ADUserResultantPasswordPolicy $user)
        $sent = "" # Reset Sent Flag
        # Check for Fine Grained Password
        if ($null -ne $PasswordPol) {
            $maxPasswordAge = $PasswordPol.MaxPasswordAge
        }
        else {
            #No FGP set to Domain Default
            $maxPasswordAge = $DefaultmaxPasswordAge            # $maxPasswordAge is a TimeSpan
        }
        $expireson = $passwordsetdate + $maxPasswordAge         # $passwordsetdate is [DateTime], $maxpasswordage is [TimeSpan]
                                                                # If $passwordsetdate is $null, $expireson will be a TimeSpan, not a date
        $today = (Get-Date)
        $daystoexpire = (New-TimeSpan -Start $today -End $Expireson).Days   # Will fail if $expireson is a TimeSpan object (see previous comment)
        #Set Greeting based on Number of Days to Expiry.
        #Check Number of Days to Expiry
        $messageDays = $daystoexpire
        if (($messageDays) -gt "1") {
            $messageDays = "in " + "$daystoexpire" + " days."
            $messageJours = "dans " + "$daystoexpire" + " jours."
        }
        else {
            $messageDays = "today."
            $messageJours = "Aujourd'hui"
        }
        # Email Subject Set Here
        $subject = "Votre mot de passe va expirer $messageJours | Your password will expire $messageDays"
        # Email Body Set Here, Note You can use HTML, including Images.
        $body = "
    À l'attention de $name,
    <p> Votre mot de passe réseau va expirer $messageJours<br>
    Pour changer votre mot de passe sur un ordinateur quand vous êtes au bureau, appuyez sur
    CTRL+ALT+Delete et sélectionnez « changer de mot de passe ». <br>
    Pour changer votre mot de passe sur un ordinateur quand vous êtes à la maison, votre VPN doit être
    actif, appuyez sur CTRL+ALT+Delete et sélectionnez « changer de mot de passe ». Assurez-vous d'être connecter au VPN pour le faire, sauf si vous êtes au bureau. <br>
    <p>Merci, <br>
    </P>
    Dear $name,
    <p> Your Password will expire $messageDays<br>
    To change your password on a computer when you are at the office, press CTRL+ALT+Delete
    and choose « Change Password ». <br>
    To change your password on a computer when you are at home, your VPN need to be active ,
    press CTRL+ALT+Delete and choose « Change Password ». Make sure you are connected with the VPN unless you are at the office. <br>
    <p>Thanks, <br>
    </P>"
    
        #If Testing Is Enabled - Email Administrator
        if (($testing) -eq "Enabled") {
            $emailaddress = $testRecipient
        } # End Testing
        # If a user has no email address listed
        if ($null -eq $emailaddress) {
            $emailaddress = $testRecipient
        }   # End No Valid Email
    
        #Send Email Message
        if (($daystoexpire -ge 0) -and ($daystoexpire -lt $expireindays)) {
            $sent = "Yes"
            $Expiration = "Yes"
            # If Logging is Enabled Log Details
            if (($logging) -eq "Enabled") {
                Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent"
            }
            # Send Email Message
            Send-MailMessage -SmtpServer $smtpServer -From $from -To $emailaddress -Subject $subject -Body $body -BodyAsHtml -Priority High -Encoding $textEncoding
        } # End Send Message
        else {
            # Log Non Expiring Password
            $sent = "No"
            # If Logging is Enabled Log Details
            if (($logging) -eq "Enabled") {
                Add-Content $logfile "$date,$Name,$emailaddress,$daystoExpire,$expireson,$sent"
            }
        }
    
    } # End User Processing
    
    # Si $Logging et $SendToSupervisor sont a "Enabled le fichier de log est envoyer au superviseur seulement si un mot de passe envoie d'expiration est trouvé
    if (($logging) -eq "Enabled" -and $SendToSupervisor -eq "Enabled" -and $Expiration -eq "Yes" ) {
        $Subject = "Rapport d'expiration des mots de passe des usagers"
        $Body = "Bonjour, Voici le rapport d'expiration des mots de passe. Merci!"
        #write-host $Subjet
        #write-host $Body
        #write-host $Supervisor
        #write-host $logFile
        #write-host $smtpServer
        #Pause
        Send-MailMessage -To $Supervisor -Subject $Subject -Body $Body -SmtpServer $SMTPServer -From $From -Attachments $logFile
        #write-host "Courriel envoyé"
    }
    
    #End
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.