Search code examples
powershelloutlookwindows-11

Powershell Problem in passing a variable to $mail.HTMLBody, the mail is empty when using a $variable but works when its direct string = "asbdas"


i have a mail script but since changeing from windows 10 to windows 11 my script is not working anymore.

I could already figgure out that this exact step is not working (either with the ps7 or the default ps from windows 11). Previously i was using Windows 10 default ps where it was working..

that is the following code as example:


$outlook = New-Object -comObject Outlook.Application
$mail = $outlook.CreateItemFromTemplate(some_template.oft)

$mail.Display()
# opens up the mail in a window for "live" view of the change

$mail.HTMLBody =  "asdasd"
# Working flawlesly, the Mail has the String in it

$body = "asdasd"
$mail.HTMLBody =  $body 
# not working, mail is empty

i couldnt find anything on the web or i dont have the right words for searching. When using the $variable the operator '=' is not working anymore .. i tried with all sorts of ConvertTo or Convert From or the Out-String stuff

Maybe someone have a solution. Best thanks


Solution

  • In a pristine session, the code in your question would not produce the symptom, however, as verified in Outlook version 16.0.0.17628, there appears to be a bug with respect to assigning non-string values to the .HTMLBody property, which is unrelated to whether the value is assigned directly or via a variable:

    • While it makes sense to only assign a string to the .HTMLBody property, Outlook does accept instances of .NET primitive types (loosely speaking numbers, Booleans, and [char] which is treated numerically) and implicitly stringifies them.

      • By contrast, instances of other non-string types, notably enumerables such as arrays, cause an error on assignment (which only shows in the console (terminal), not in the email form).
    • Once an acceptable non-string value has been assigned, bizarrely, future attempts to assign to .HTMLBody - even of a different mail-item instance - are locked into that type, so if you subsequently try to assign a value of a different type - even a string - the assignment fails.

      • E.g., if you first assign 42, you'll lock in [int] as the type and latter assigning 'why?' then fails, because a string ([string]) is not an [int] (and even something like '43' wouldn't work, because conversion is not attempted in this case).

    As a workaround for the bug as well as to generally ensure that a string is assigned to .HTMLBody, use a [string] cast:

    $outlook = New-Object -ComObject Outlook.Application
    $mail = $outlook.CreateItemFromTemplate(some_template.oft)
    
    $mail.Display()
    # opens up the mail in a window for "live" view of the change
    
    # Sample $body value that can NOT be used directly.
    $body = 'one', 'two'
    
    # Casting to [string] ensures that a single string is assigned.
    # The array elements are space-concatenated.
    $mail.HTMLBody = [string] $body
    

    Note:

    • Alternatively, when you initialize your $body variable, you can type-constrain it to a [string], which ensures that any value assigned to it becomes a string; e.g.,
      [string] $body = 42