powershellencoding

Send-MailMessage in Scheduled Task has wrong encoding


I use the following script to send two E-Mails to different people:

# Datum von nächstem Samstag ermitteln
$Date = Get-Date "18:00"
while ($Date.DayOfWeek -ne "Saturday") { $date = $date.AddDays(1) }

# UTF-8 Encoding
$utf8 = New-Object System.Text.utf8encoding

# E-Mail Benachrichtigung zusammenstellen
$EmailNotifications = @{

    AlleMAEmail = @{
        From = "xy"
        To = "xy"
        Subject = "Serverarbeiten Update Installation $($Date.DateTime)"
        Body = "abc äöü"
    }

    ITAdminEmail = @{
        From = "xy"
        To = "xy"
        Subject = "Bitte bei XY Updates genehmigen & Ablehnen"
        Body = "abc äöü"
    }

}

# E-Mails versenden.
$EmailNotifications.GetEnumerator() | ForEach-Object {
    $splat = $_.Value
    Send-MailMessage -SmtpServer "xy" -BodyAsHtml -Encoding $utf8 @splat
}

This works when I run the code in Visual Studio Code, however I need a scheduled task on a server to run this. When the scheduled task runs the script, it can't handle the umlauts in the mail body, e.g it sends ü as ü

How can I fix this? I already specified my encoding

This is how my task is set up:

Edit: I noticed that the PowerShell that gets started is the "old" PowerShell which has a black background. Could this be the problem? How to start the new one?


Solution

  • PowerShell interprets the source code of your .ps1 file when it reads it, but not necessarily in the encoding you expect.

    When you save a file as UTF-8, but PowerShell's default is Windows-1252, then ü becomes ü before your code even runs. Send-MailMessage then correctly encodes ü into UTF-8 and so these characters are retained in the email. When you run the program from within Visual Studio Code, different defaults apply and the outcome is different.

    I don't think there is a command line switch that forces PowerShell to interpret script files in a certain encoding, but you can help the encoding auto-detection along by prefixing your file with a byte-order mark (BOM).

    A BOM is mandatory for UTF-16 (that is what's commonly called "Unicode" encoding in various Microsoft tools), but optional in UTF-8. UTF-8 BOMs are wrong for many use cases, so VS Code defaults to "UTF-8 without BOM". When you explicitly save the file as "UTF-8 with BOM" then Powershell will infer the correct encoding when reading the script.

    There is a way to configure VS Code to pick specific encodings per file type, you could set it to always save .ps1 files as UTF-8 with BOM.

    The alternative would be to save the file as Windows-1252, which would match PowerShell's expectation on your machine, but might break on different computers (or when run from within VS Code).