Try-Catch-Finally not working with Send-Mailmessage in PowerShell script

848 Views Asked by At

I'm using try-catch-finally blocks in my account expiration notification email and the if condition in the finally block isn't considered:


    Write-Host $sName " : Selected to receive email: password will expire in "$days
         if (($emailaddress) -ne $null) {
             try {
                    Send-Mailmessage -smtpServer $SMTPServer -from $MailSender -to $emailaddress -subject $subject2 -body $EmailBody -bodyasHTML -priority High -Encoding $textEncoding -ErrorAction Stop 
                } 
                catch {
                    write-host "Error: Could not send email to $recipient via $smtpServer"
                    $sent = "Send fail"
                    $countfailed++
                } 
                finally {
                    if ($error.Count -eq 0) {
                        write-host "Sent email for $sName to $emailaddress"
                        $countsent0++
                        }
                }
        } else {
                Write-Host "$dName ($sName) has no email address."
                $sent = "No"
                $countnotsent++
            }



Expecting $countsent0 to increment and $sent to be set to the appropriate message. The catch block works ($countfailed increments and $sent is set to "Send fail"). The last else statement after the finally block works as well (if there is no email address for the account $countnotsent increments and $sent is set to "No").

1

There are 1 best solutions below

0
mklement0 On
  • The automatic $Error variable is a running log of all errors that have occurred in the entire session so far, so unless you run $Error.Clear() beforehand, you may get false positives with if ($error.Count -eq 0) { ... }

  • However, since you may not want to erase this log for the entire session, consider using a simple Boolean variable to indicate whether an error was caught or not.

A simplified example:

$countsent0 = 0
$ok = $false  # Helper Boolean variable.
try {
  # Simulate an error that can be caught. 
  # This is a stand-in for your Send-Mailmessage -ErrorAction Stop ... call.
  1 / 0  
  # Getting here would imply that NO error occurred,
  # so set a variable to signal that.
  $ok = $true 
}
catch {
  Write-Warning 'oops!'
}
finally {
  if ($ok) { $countsent0++; Write-Host 'All''s well'. }
}

"`$countsent0: $countsent0"

However, given that your catch block doesn't abort execution, you don't even need a finally block:

$countsent0 = 0
try {
  1 / 0  # Simulate an error that can be caught.
  # Getting here implies success.
  $countsent0++ 
}
catch {
  Write-Warning 'oops!'
}

"`$countsent0: $countsent0"