Working with Outlook HTMLBody – a guide for Office developers
If you’ve ever tried to design an attractive and somewhat complex e-mail message using Microsoft Outlook and HTML, chances are you very quickly realized that the Outlook mail message body format performs rather differently than a normal web browser.
- Outlook HTMLBody is not a web page
- Outlook HTML and CSS limitations
- HTML templates
- Embedding images in an Outlook E-mail
Outlook HTMLBody is not a web page
The primary reason that your carefully designed Outlook HTML e-mail templates might not always look exactly the same in an e-mail body as it does inside your browser, is because since Outlook 2007, the Microsoft Word 2007 rendering engine has been used to parse and render HTML inside Outlook e-mail messages.
In previous versions of Outlook, Microsoft employed two rendering engines. For displaying / reading e-mail content, they employed the Internet Explorer rendering engine and used MS Word’s rendering engine for composing messages. Word 2007 made significant advancements in the way it handled HTML and CSS and the Outlook team decided to combine both reading and composing of Outlook e-mail messages with one technology.
In essence, the Word 2007 supports a subset of the HTML 4 specifications as well as a subset of the CSS specifications level 1. What this means is that not all HTML elements are supported inside an Outlook e-mail body.
Outlook HTML and CSS limitations
There is a rather wide range of limitations imposed on Outlook email HTML due to the fact that the MS Word rendering engine is being used. Some of the more obvious features that are not supported are:
- Background images;
- Animated GIF images;
- HTML Forms; and
- CSS Positioning and floats.
Inline styles
As a general rule of thumb, using inline styles are preferred over specifying your CSS inside a <style> tag. You should avoid linking to external style sheets altogether as it will not work at all. For example, in order to set a table’s border style, use the following syntax:
<table style="width: 100%;border-style: solid;border-width: 3px;">
Use Tables
Although the general consensus with regards to using HTML tables for web page layout is to rather avoid them, this is not the case with Outlook e-mail design. <div> elements inside Outlook e-mails tend to have a mind of their own and behave erratically. HTML Tables will give you a predictable layout experience and will work in almost all e-mail clients.
Text does not wrap
Speaking of Tables, text does not automatically wrap inside a table, which can cause some confusing results. To avoid this, style your table cell (<td>) elements as follows:
<td style="word-break:break-all"></td>
Unsupported HTML tags
The following table lists the HTML tags that are not supported in Outlook e-mails / Word rendering engine:
- applet
- bdo
- button
- form
- iframe
- input
- isindex
- menu
- noframes
- noscript
- object
- optgroup
- option
- param
- q
- script
- select
- accept-charset
- accept
- accesskey
- archive
- background (only when there is a URL)
- checked
- classid
- code
- codecore
- codetype
- compact
- data
- declare
- defer
- disabled
- enctype
- longdesc
- marginheight
- marginwidth
- media ( screen | print | projection | braille | speech | all )
- method
- multiple
- noresize
- object
- onblur
- onchange
- onclick
- ondblclick
- onfocus
- onkeydown
- onkeypress
- onkeyup
- onload
- onmousedown
- onmousemove
- onmouseout
- onmouseover
- onmouseup
- onreset
- onselect
- onsubmit
- onunload
- readonly
- scrolling
- selected
- standby
- tabindex
- title
- valuetype
Supported CSS
Below is a list of CSS properties that are supported inside an Outlook e-mail body:
- color
- font
- font-family
- font-style
- font-variant
- font-size
- font-weight
- text-decoration
- background (only color)
- background-color
- text-align
- vertical-align
- letter-spacing
- line-height
- white-space
- display
- border
- border-color
- border-style
- border-width
- src
- size
- marks
- page-break-before
- page-break-after
- page-break-inside
- list-style
- list-style-type
- unicode-bidi
- border-collapse
- text-indent
- margin
- margin-left
- margin-right
- margin-top
- margin-bottom
- width
- height
- padding
- padding-left
- padding-right
- padding-top
- padding-bottom
- border-left
- border-right
- border-top
- border-bottom
- border-left-color
- border-left-width
- border-left-style
- border-right-color
- border-right-width
- border-right-style
- border-top-color
- border-top-width
- border-top-style
- border-bottom-color
- border-bottom-width
- border-bottom-style
A good list on what CSS properties are supported can be found on campaignmonitor.com.
HTML templates by Zurb
You might know Zurb from a previous article on this blog where we discussed their Foundation Framework for creating ASP.Net MVC websites. Their Foundation Framework can assist you with building responsive emails that will work on any device even Outlook as stated on the front page of their website.
The Ink framework provides a grid layout structure to help build the e-mail layout as well as easy ways to add padding to text, centre element and much more. Of course, one of the best features are their ready-to-use templates. They provide four templates that you can download and use immediately in order to build your HTML emails in Outlook.
These templates contain all the necessary HTML and CSS to make your email content look good inside Outlook. For example, in the following image, I’ve simply inserted the HTML from the Ink Sidebar template, and everything displays great inside Outlook:
Embedding images in an Outlook E-mail
When it comes to embedding images into your Outlook e-mails, you have a choice to either embed you images directly into the e-mail or reference the image from an internet URL.
The problem with referencing an URL for the image is that Outlook would probably block the image and display the “To help protect your privacy, Outlook prevented automatic downloads of some pictures in this message” message.
This is done for a very specific reason, because the image URL could contain more information than simply the URL to the image. It could also contain information that could inform the sender when you read the message – this is a technique that can also be exploited by spammer in order to determine whether the e-mail addresses used does exist.
The safer route is to embed your images in the e-mail when creating them. This does take some doing, but the end result is a good formatted email, which makes it worth the effort.
To illustrate, I’ve included the following code. By setting three properties, we’ll embed an image of the Add-in Express logo into the Outlook e-mail once the user clicks a button on the Mail Inspector window. This is done by first adding the image as an attachment to the email and then setting the <img> tags’ source property to the unique id.
private void adxRibbonButtonEmbedImage_OnClick(object sender, IRibbonControl control, bool pressed) { Outlook.Inspector currInspector = null; Outlook.MailItem currMail = null; Outlook.Attachments attachments = null; Outlook.Attachment image = null; Outlook.PropertyAccessor propertyAccessor = null; try { currInspector = OutlookApp.ActiveInspector(); if (currInspector.CurrentItem is Outlook.MailItem) { currMail = currInspector.CurrentItem as Outlook.MailItem; attachments = currMail.Attachments; image = attachments.Add(@"C:\temp\Add-in_Express_Logo.jpg"); propertyAccessor = image.PropertyAccessor; propertyAccessor.SetProperty( "https://schemas.microsoft.com/mapi/proptag/0x370E001F", "image/jpeg"); propertyAccessor.SetProperty( "https://schemas.microsoft.com/mapi/proptag/0x3712001F", "myImageId"); propertyAccessor.SetProperty( "https://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8514000B", true); string htmlBody = "<html><head><title></title></head><body><img src=\"cid:myImageId\"/></body></html>"; currMail.HTMLBody = htmlBody; } } finally { if (attachments != null) Marshal.ReleaseComObject(attachments); if (image != null) Marshal.ReleaseComObject(image); if (propertyAccessor != null) Marshal.ReleaseComObject(propertyAccessor); if (currMail != null) Marshal.ReleaseComObject(currMail); if (currInspector != null) Marshal.ReleaseComObject(currInspector); } }
The resulting Outlook e-mail will have the image embedded inside its HTML body as illustrated below:
Thank you for reading. Until next time, keep coding!
Available downloads:
This sample Excel add-in was developed using Add-in Express for Office and .net:
16 Comments
Here is my Screen view, i can put it inside the outlook mail new item (it is OK)
But i have photo and text problem :( i want to write text on photo :(
https://s9.postimg.org/turyh5o27/mainn.jpg
Here is codes…
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
Outlook: OleVariant;
Mail: OleVariant;
const
olMailItem = 0;
olByValue = 1;
olFormatHTML = 2;
begin
i:=0;
for i:= 0 to listbox1.Count-1 do
begin
try
Outlook := GetActiveOleObject(‘Outlook.Application’);
except
Outlook := CreateOleObject(‘Outlook.Application’);
end;
Mail := Outlook.CreateItem(olMailItem);
Mail.To:=ListBox5.Items[i];
mail.cc :=’kabinyolsefmg at thy dot com; ‘;
Mail.Subject :=COMBOBOX1.Text;
Mail.Attachments.Add(‘c:\tts\mainn.png’, olByValue, 1, ‘My Test Image’);
Mail.BodyFormat := olFormatHTML;
Mail.HTMLBody:= ”+
‘.font {font-family: Calibri;}.font {font-size: 14px;}’+
”+
”+
”+
‘
‘+
‘Hello’+
‘This is my email text’+
‘i cant put it inside the box’+
”+
”;
Mail.Display;
end;
end;
Hello Ferhat,
You can create such an email manually, then extract the HTML using the context menu item ViewSource, study the HTML and create the same in the code of your add-in.
Hello.
Is this tested Outlook 2016?
I can’t get the htmlbody property in Outlook 2016 HtmlFormat MailItem.
Hello,
Make sure MailItem.BodyFormat returns olFormatHTML. If “can’t get” means the call produces an exception, please provide details.
In Outlook 2016, I can’t access the HTMLBody property either. I get this error in the debugger when I try to examine the variable in the Immediate Window:
?mailItem.HTMLBody
error CS1061: ‘MailItem’ does not contain a definition for ‘HTMLBody’ and no extension method ‘HTMLBody’ accepting a first argument of type ‘MailItem’ could be found (are you missing a using directive or an assembly reference?)
but
?mailItem.Subject
works fine.
Hello,
Make sure that you set an Outlook.MailItem to the mailItem variable. For instance, you can check mailItem.Class; if mailItem contains an Outlook.MailItem, mailItem.Class will return olMail (=43). I would declare the variable as Outlook.MailItem to avoid such issues.
In Outlook 2016, I can’t access the HTMLBody property either too.
Is this issue closed? if so, please help me..
My outlook can’t access HTMLBody, and Body properties.
And I also declare like ‘Outlook._MailItem mail = (Outlook._MailItem)ItemObj;’
Hello Allen,
What do you mean by “can’t access”? Are you getting an exception? What’s the error message?
Hello I’m trying to open an .oft file (this works) and take the location and body of the template and place these into a new outlook appointment which I’ve also just created. So far everything works except I can’t figure out how to get the body of the template into the new outlook appointment. Code below. The code is run when a button in excel is clicked.
Sub CreateInvite()
Dim otlApp As Object
Dim otlNewMail As Object
Dim objItem As Object
Dim location As String
Dim meetingTemplate As String
Dim i As Integer
Dim EmailTo As String
‘ Create the Outlook session
Set myoutlook = CreateObject(“Outlook.Application”)
‘ Create the AppointmentItem
Set myapt = myoutlook.CreateItem(olAppointmentItem) ‘ Set the appointment properties
i = 10
meetingTemplate = “C:\..\..\..\myfile.oft”
‘ Create the Outlook session
Set otlApp = CreateObject(“Outlook.Application”)
‘ Create the AppointmentItem from template
Set otlNewMail = otlApp.CreateItemFromTemplate(meetingTemplate)
With myapt
.Actions(“Forward”).Enabled = False
.Actions(“Reply to All”).Enabled = False
.Subject = “Tamayoz ExxonMobil Qatar Training: ” & Cells(1, 2).Value & ” on ”
.location = otlNewMail.location
.Start = Cells(1, 6).Value & ” 08:00:00 AM”
.End = Cells(1, 8).Value & ” 17:00:00 PM”
.MeetingStatus = olMeeting
Do While Cells(i, “J”).Value “” Or i <= 39 'continue through loop i is less than 21 and it doesn't hit an empty cell
'.RequiredAttendees = Cells(i, "J").Value & ";"
EmailTo = EmailTo + Cells(i, "J").Value & ";"
i = i + 1
Loop
.RequiredAttendees = EmailTo
.BusyStatus = "2"
.ReminderSet = False
.BodyFormat = olFormatHTML
.HTMLBody = otlNewMail.HTMLBody
.Display
End With
otlNewMail.Close 1
Set otlNewMail = Nothing
Set otlApp = Nothing
End Sub
Hello MissBow,
Please check https://social.msdn.microsoft.com/Forums/vstudio/en-US/78c206d0-9fd0-4e7a-8d62-e79689b74fb4/c-adding-hyperlink-in-appointment-item-of-outlook?forum=outlookdev.
Hi,
I am creating a outlook addin to insert HTML template in mail body.
Can anyone tell me how to insert my HTML template in mailitem.HTMLBody at cursor position without loosing any previous HTML formating?
Hello Manish,
I would research this way. If pasting an HTML template to the email works correctly, I would check all the formats available in the clipboard at this moment. Then I would prepare all the formats relating to pasting the HTML template and “click” the Paste Ribbon button programmatically. To do this, you call Inspector.CommandBars.ExecuteMso(“Paste”). If you execute this code line in a compose inspector, it pastes the content of the clipboard to the email in the current cursor location.
Another variant is this. You can get Inspector.WordEditor, cast it to Word.Document and then use the Word object model to find the cursor location (see Eord.Selection) and paste the template using the Range.PasteSpecial() method (see https://msdn.microsoft.com/en-us/library/office/ff821124(v=office.15).aspx) or Selection.PasteSpecial(). This also requires preparing the content of the Clipboard.
HTH ))
Hi Andrei,
I am using this method to get the current cursor location and paste the template at cursor position. (see https://msdn.microsoft.com/en-us/library/6b9478cs(VS.80).aspx). and my requirement is that user should be able to insert multiple HTML templates in a single mail and also the new template should be inserted at the current cursor position. So every thing works fine till 1st template. but when user insert the second template all the html formation is lost for the 1st template. I am using below code
SelectionInsertTemplate(subjetBody[1], document);
mailItem.HTMLBody = document.Content.Text;
mailItem.Subject = subjetBody[0];
uniqueKey = subjetBody[2];
mailItem.Save();
Where subjetBody[1] contains HTML template.
SelectionInsertTemplate is function which contains code mention at above link.
Can you suggest any modification?
Thanks in advance.
Hello Manish,
You shouldn’t modify HTMLBody. You should only modify the Word.Document object which you retrieve using Outlook.Inspector.WordEditor. The cursor location is Document.Windows(1).Selection.
Inserting HTML is only supported by Word in two forms: 1) set the HTML to Clipboard and call Range.PasteSpecial (Selection.PasteSpecial) or 2) set the HTML to a file and call Range.InsertFile (Selection.InsertFile). These methods invokes the internal HTML converter. Alternatively, you can prepare an RTF text and insert it.
Hi Pieter,
This is a Very nice post.I have done my work by this post.
Thank you so much.
Rajesh Somvanshi
Hi Andrei,
Thanks Your suggestion works for me.
Regards,
Manish