- Optionally specify the sending account in Outlook (if you have multiple accounts)
- Keep the default signature associated with the account
- Retain the original formatting
- Produce valid HTML-formatted e-mails
After several hours of working with Outlook's COM library through PowerShell, I figured out the trick to get .SendUsingAccount
working (select a sending account) as well as keeping Outlook's default signature for the specified account.
Parameter | Type | Description | Mandatory |
---|---|---|---|
To |
string | The recipient's email address. | Yes |
Subject |
string | The subject line of the email. | Yes |
Body |
string | The HTML formatted string that makes up the body of the email. | Yes |
FromEmail |
string | The email address of the Outlook account to use for sending. If not specified, uses default account. | No |
Note: The Body
parameter expects an HTML formatted string. The FromEmail
parameter is optional; if not provided, the default Outlook account is used.
Create-NewOutlookEmail -To "[email protected]" -Subject "test subject" -Body "this is a <strong>test</strong>" -FromEmail "[email protected]"
$To = "[email protected]"
$Subject = "test subject"
$Body = "this is a <strong>test</strong>"
$FromEmail = "[email protected]"
Create-NewOutlookEmail -To $To -Subject $Subject -Body $Body -FromEmail $FromEmail
$params = @{
To = "[email protected]"
Subject = "test subject"
Body = "this is a <strong>test</strong>"
FromEmail = "[email protected]"
}
Create-NewOutlookEmail @params
Note
The information below is only provided to explain how the script works. You don't need the information below if you simply want to use the script.
The PowerShell script makes use of the Outlook.Application
COM object library. It creates a new mail item, specifies the To, Subject, and then injects the HTML body into the appropriate section of the message body.
Many online solutions suggest extracting the HTML of the signature, or prepending it to the HTMLBody
, but this results in invalid HTML as shown below...
this is a <strong>test</strong><html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head>....
Instead, the script identifies an empty area where Outlook expects the content, immediately following this tag...
<div class=WordSection1><p class=MsoNormal>
That way we end up with the full message with valid HTML as Outlook expects. 😊
Some may say that the <o:p>
tag should be included, but that tag is considered Office namespace which is typically used for content created by Office applications, not by users (at least, that's my understanding).
Although using .SendUsingAccount
works as is, you'll find that it doesn't actually select the account in Outlook, nor is the default signature for the account invoked by doing so. Some have suggested using .SentOnBehalfOfName
as an alternative, but this approach won't switch the selected account or prompt the signature to generate.
To workaround the issue, this script uses a custom function named Invoke-SetProperty
. This function uses .InvokeMember
to dynamically set properties on the $mail
object, which is $outlook.CreateItem(0)
where $outlook
is the COM object of Outlook.
function Invoke-SetProperty {
param(
[__ComObject] $Object,
[String] $Property,
$Value
)
[Void] $Object.GetType().InvokeMember($Property, "SetProperty", $NULL, $Object, $Value)
}
If you notice, the e-mail is actually displayed before the HTMLBody
modifications take place. This allows time for Outlook to generate the default HTML message body as well as insert the default signature for the associated account.
This is a weird issue. When setting HTML defined in a variable, for some reason Outlook reverts the HTML body back to the default template.
This works:
$mail.HTMLBody = "this is a <strong>test</strong"
But when I tried this:
$Message = "this is a <strong>test</strong"
$mail.HTMLBody = $Message
It would revert the message to the default template, which in my case is this:
<HTML>
<HEAD>
<META NAME="Generator" CONTENT="MS Exchange Server version
14.02.5004.000">
<TITLE></TITLE>
</HEAD>
<BODY>
<!-- Converted from text/plain format -->
</BODY>
</HTML>
This issue, possibly due to a PowerShell bug or string misinterpretation, is resolved by specifying the $Body
variable in braced notation as ${Body}
.