Template or Form?

D

deko

I need to generate HTML email using Access 2007/Outlook 2007. I have
enough experience with VBA to gin up the code, but Outlook 2007 is
something of a mystery to me.

Here's what I've tried:

1. created an .oft template
2. attempted to insert text into the template like this

Code:
--------------------
Set olApp = GetObject(, "Outlook.Application")
Set olmi = olApp.CreateItemFromTemplate(strOftPath)
olmi.HTMLBody = "<HTML><BODY>text here</BODY></HTML>"
--------------------


Unfortunately, this overwrites all the nice logos and such I had put in
the template.

Should I be using a Outlook Template or Form?

I like the idea of using templates because they are discrete files that
(hopefully) users can administer if they want to change logos/colors,
etc.

Since I can store formatted Rich Text in an Access Memo field, I was
thinking I could just dump that into the .oft - or use bookmarks in the
oft to insert predefined blocks of text, like a NameAddress block.

Can I do that with an .oft? Or should I use an Outlook form?

What are some good resources for programming .oft templates?
 
D

deko

Has anyone had any luck with this?


Code:
--------------------
Public Function EmbeddedHTMLGraphicDemo()

'This technique by Outlook MVP Neo uses undocumented MAPI properties and CDO
'to add an embedded image file to a message and set the CID so that an
'HTMLBody property <img> tag can set that image as the source. In VBA or
'Visual Basic, you will need to add a reference to the CDO 1.21 library
'to use this procedure

'Reference Required:
'[Microsoft CDO 1.21 Library]
'C:\Windows\System32\CDO.DLL

' Outlook objects
Dim objApp As Outlook.Application
Dim l_Msg As MailItem
Dim colAttach As Outlook.Attachments
Dim l_Attach As Outlook.Attachment
Dim oSession As MAPI.Session
' CDO objects
Dim oMsg As MAPI.Message
Dim oAttachs As MAPI.Attachments
Dim oAttach As MAPI.Attachment
Dim colFields As MAPI.Fields
Dim oField As MAPI.Field

Dim strEntryID As String

' create new Outlook MailItem
Set objApp = CreateObject("Outlook.Application")
Set l_Msg = objApp.CreateItem(olMailItem)
' add graphic as attachment to Outlook message
' change path to graphic as needed
Set colAttach = l_Msg.Attachments
Set l_Attach = colAttach.Add("c:\test\graphic.jpg")
l_Msg.Close olSave
strEntryID = l_Msg.EntryID
Set l_Msg = Nothing
' *** POSITION CRITICAL *** you must dereference the
' attachment objects before changing their properties
' via CDO
Set colAttach = Nothing
Set l_Attach = Nothing

' initialize CDO session
On Error Resume Next
Set oSession = CreateObject("MAPI.Session")
oSession.Logon "", "", False, False

' get the message created earlier
Set oMsg = oSession.GetMessage(strEntryID)
' set properties of the attached graphic that make
' it embedded and give it an ID for use in an <IMG> tag
Set oAttachs = oMsg.Attachments
Set oAttach = oAttachs.Item(1)
Set colFields = oAttach.Fields
Set oField = colFields.Add(CdoPR_ATTACH_MIME_TAG, "image/jpeg")
Set oField = colFields.Add(&H3712001E, "myident")
oMsg.Fields.Add "{0820060000000000C000000000000046}0x8514", 11, True
oMsg.Update

' get the Outlook MailItem again
Set l_Msg = objApp.GetNamespace("MAPI").GetItemFromID(strEntryID)
' add HTML content -- the <IMG> tag
l_Msg.HTMLBody = "<IMG align=baseline border=0 hspace=0 src=cid:myident>"
l_Msg.Close (olSave)
l_Msg.Display

' clean up objects
Set oField = Nothing
Set colFields = Nothing
Set oMsg = Nothing
oSession.Logoff
Set oSession = Nothing
Set objApp = Nothing
Set l_Msg = Nothing

End Function
 
K

Ken Slovak - [MVP - Outlook]

www.outlookcode.com has lots of form code samples and information.

However I'm not sure that's what you need. You can create a blank new email
using CreateItem() and then just set the HTMLBody property to your formatted
HTML and that will work just fine. I do that all the time in my code.
 
K

Ken Slovak - [MVP - Outlook]

What about it? What problem are you having, if any?

If you are having a problem indicate where and mention your Outlook version.




deko said:
Has anyone had any luck with this?


Code:
--------------------
Public Function EmbeddedHTMLGraphicDemo()

'This technique by Outlook MVP Neo uses undocumented MAPI properties and
CDO
'to add an embedded image file to a message and set the CID so that an
'HTMLBody property <img> tag can set that image as the source. In VBA or
'Visual Basic, you will need to add a reference to the CDO 1.21 library
'to use this procedure

'Reference Required:
'[Microsoft CDO 1.21 Library]
'C:\Windows\System32\CDO.DLL

' Outlook objects
Dim objApp As Outlook.Application
Dim l_Msg As MailItem
Dim colAttach As Outlook.Attachments
Dim l_Attach As Outlook.Attachment
Dim oSession As MAPI.Session
' CDO objects
Dim oMsg As MAPI.Message
Dim oAttachs As MAPI.Attachments
Dim oAttach As MAPI.Attachment
Dim colFields As MAPI.Fields
Dim oField As MAPI.Field

Dim strEntryID As String

' create new Outlook MailItem
Set objApp = CreateObject("Outlook.Application")
Set l_Msg = objApp.CreateItem(olMailItem)
' add graphic as attachment to Outlook message
' change path to graphic as needed
Set colAttach = l_Msg.Attachments
Set l_Attach = colAttach.Add("c:\test\graphic.jpg")
l_Msg.Close olSave
strEntryID = l_Msg.EntryID
Set l_Msg = Nothing
' *** POSITION CRITICAL *** you must dereference the
' attachment objects before changing their properties
' via CDO
Set colAttach = Nothing
Set l_Attach = Nothing

' initialize CDO session
On Error Resume Next
Set oSession = CreateObject("MAPI.Session")
oSession.Logon "", "", False, False

' get the message created earlier
Set oMsg = oSession.GetMessage(strEntryID)
' set properties of the attached graphic that make
' it embedded and give it an ID for use in an <IMG> tag
Set oAttachs = oMsg.Attachments
Set oAttach = oAttachs.Item(1)
Set colFields = oAttach.Fields
Set oField = colFields.Add(CdoPR_ATTACH_MIME_TAG, "image/jpeg")
Set oField = colFields.Add(&H3712001E, "myident")
oMsg.Fields.Add "{0820060000000000C000000000000046}0x8514", 11, True
oMsg.Update

' get the Outlook MailItem again
Set l_Msg = objApp.GetNamespace("MAPI").GetItemFromID(strEntryID)
' add HTML content -- the <IMG> tag
l_Msg.HTMLBody = "<IMG align=baseline border=0 hspace=0 src=cid:myident>"
l_Msg.Close (olSave)
l_Msg.Display

' clean up objects
Set oField = Nothing
Set colFields = Nothing
Set oMsg = Nothing
oSession.Logoff
Set oSession = Nothing
Set objApp = Nothing
Set l_Msg = Nothing

End Function
 
D

deko

Thanks for the reply. I should have mentioned that I need to include
embedded images in the HTML emails messages.

I'm using Access 2007 (customer database) and Outlook 2007.

The customer database is used to send email confirmations for event
registration. The idea is to send an HTML email message with a JPEG logo
and other GIFs to create a "branded" look to the message.

I can create Outlook messages from Access easily enough, but I'm not
sure how to include images.

I'm in unfamiliar territory here so I'm looking for
suggestions/examples on the best way to accomplish this goal.

That code snippet is, apparently, one way to do it. But I'm not sure
it's the best way. Outlook Templates sound interesting if they enable
use of bookmarks, were I can insert various units of data from Access
(e.g. a NameAddressBlock or something like that).

I'll have a look at the site you mentioned. I'm hoping there are folks
who have traveled this path before who might share some example code.
 
K

Ken Slovak - [MVP - Outlook]

Outlook custom forms don't have bookmarks, they aren't Word documents. They
also aren't real robust and can have many problems, especially when sending
them to other people over the Internet. You are definitely better off not
using them.

Steve's sample uses a lower level API (CDO) to get at properties that
weren't exposed in the Outlook object model at that time. Those are the
attachment and item properties used to embed attachments from code in this
case. With Outlook 2007 you can use the new PropertyAccessor to avoid using
CDO, which has security restrictions these days. It did not when Steve
supplied that code sample.

What that code is doing is attaching an image file and setting 2 attachment
properties. One is PR_ATTACH_MIME_TAG where the type is set to a jpeg image,
and the other is called PR_ATTACH_CONTENT_ID, where he sets a CID for the
attachment. That CID is then used in the HTML to indicate an embedded
attachment and to provide the link to the attachment for rendering. That's
done on this line: "<IMG align=baseline border=0 hspace=0 src=cid:myident>".

The code should work just fine as is. I personally would probably re-write
it to use pure Outlook object model code since it's for Outlook 2007, using
PropertyAccessor in place of CDO. That would eliminate the dependency on the
optional CDO 1.21 library. That code would look something like this if
rewritten to work from outside Outlook (running in Access for example):

Public Function EmbeddedHTMLGraphicDemo()
' With a nod to Neo's original code, rewritten for Outlook 2007
' and PropertyAccessor.

' Outlook objects
Dim objApp As Outlook.Application
Dim l_Msg As MailItem
Dim colAttach As Outlook.Attachments
Dim l_Attach As Outlook.Attachment
Dim oPA As Outlook.PropertyAccessor

Dim strEntryID As String

On Error Resume Next

' create new Outlook MailItem
Set objApp = CreateObject("Outlook.Application")
Set l_Msg = objApp.CreateItem(olMailItem)
' add graphic as attachment to Outlook message
' change path to graphic as needed
Set colAttach = l_Msg.Attachments
Set l_Attach = colAttach.Add("c:\test\graphic.jpg")
l_Msg.Save

Set oPA = l_Attach.PropertyAccessor
' note: these are DASL property tags, not an URLs.

' Set PR_ATTACH_MIME_TAG
oPA.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x370E001E",
"image/jpeg")

'Set PR_ATTACH_CONTENT_ID
oPA.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E",
"myident")

Set oPA = Nothing

Set oPA = l_Msg.PropertyAccessor

' Set HideAttachments
oPA.SetProperty("http://schemas.microsoft.com/mapi/id/{0820060000000000C000000000000046}/8514000B",
true)

l_Msg.Save

' add HTML content -- the <IMG> tag
l_Msg.HTMLBody = "<IMG align=baseline border=0 hspace=0 src=cid:myident>"
l_Msg.Close (olSave)
l_Msg.Display

' clean up objects
Set oPA = Nothing
Set objApp = Nothing
Set l_Msg = Nothing
Set colAttach = Nothing
Set l_Attach = Nothing

End Function
 
D

deko

Thanks Ken! That's exactly the guidance I was looking for. I'll ru
with this and post back with results..
 
D

deko

I tried that code, but ended up doing something else

Code
-------------------
Dim olapp As Outlook.Applicatio
Dim olmi As MailIte
Dim fso As Scripting.FileSystemObjec
Dim txtstrm As Scripting.TextStrea
Set fso = New Scripting.FileSystemObjec
strTemplatePath = "C:\Documents\RegistrationConfirm.htm
Set txtstrm = fso_OpenTextFile(strTemplatePath, ForReading
strMarkup = txtstrm.ReadAl
Set olmi = olapp.CreateItem(olMailItem
olmi.HTMLBody = strMarku
-------------------

This works great because the .htm file is easy to edit, easy to manage
and easy to troubleshoot. I can use things like '%CustomerName%' t
insert blocks of info from Access with Replace(strFind, strReplace). A
for images, I can just set the <img> tags in the .htm file... simple
and saves bandwidth

But just when I thought all was well, I hit a brick wall calle
MS-TNEF

Non-ms clients receiving the evil winmail.dat attachment

Here's the header from an HTML message that renders properly on
non-ms client

Code
-------------------
Message-ID: <1143470602.663191268951490408.JavaMail.wasadmin@frrlysmtp59dmz01.ibu.geico.net
Subject: GEICO Policyholder Services: Your recent quot
MIME-Version: 1.
Content-Type: text/html; charset=us-asci
Content-Transfer-Encoding: 7bi

<html
<head><title>Confirmation</title></head
<body
..
</body
</html
-------------------

Here's what the header looks like when I use my code to send email vi
Outlook

Code
-------------------
Message-ID: <000d31cdc5e4$32f6e445$50e4efs0$@com
MIME-Version: 1.
Content-Type: multipart/mixed
boundary="----=_NextPart_000_000W_01CAR7PA.36950D40
X-Mailer: Microsoft Office Outlook 12.
Thread-Index: AxrH2TF5Cerue/SZT7itvV9oKuK30A=
Content-Language: en-u
X-MS-TNEF-Correlator: 00000000D8046EF4AB6D23479AGE82CAEEAA3517446C290

This is a multi-part message in MIME format

------=_NextPart_000_100E_03CAC7RA.86450D1
Content-Type: text/plain
charset="us-ascii
Content-Transfer-Encoding: 7bi

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesqu
molestie ullamcorper convallis. Sed congue urna eu nisi consequat a

------=_NextPart_000_0075_05CAC7R9.2D2D3F5
Content-Type: application/ms-tnef
name="winmail.dat
Content-Transfer-Encoding: base6
Content-Disposition: attachment
filename="winmail.dat

eJ8+IiYJAQaQCAAEAAAAAAABAREAAQsQBgAIAAAA5AQAAAAAAADoAAEIgAcAGAAAAElQTS5NaWN
b3NvZnQgTWFpbC5Ob3RlADEIAQOQBgA8DgAANAAAAAsAAgABAAAAAwAmAAAAAAALACkAAAAAAAI
-------------------

I enjoy all the proprietary features of Outlook as much as the nex
guy, but I just want to send clean HTML. I don't want my formattin
encapsulated and message bloated with TNEF

Is there some MAPI property I can set, or some DASL schema that wil
nix TNEF

Or am I going to have to just send plain text and use a lot o
asterisks, capital letters and exclamation points
 
D

deko

I've been testing with this. So far my only complaints are 1) the
rubbish (let's be nice and call it "proprietary") HTML generated by
Outlook, and 2) Outlook requiring users to manually download images by
default.

I found an Extended MAPI Wrapper library here:

http://tinyurl.com/ydo8x4p

that may address issue #1. I have not tried it yet. But it I can't find
a client that can't render Outlook's HTML, I won't bother.

For #2, I'll need to instruct users to right click the Outlook InfoBar
and select Add Sender to Safe Senders List. My guess is embedding images
(as opposed to linking to them) would NOT circumvent this security
feature.


Code:
--------------------
Dim olmi as Outlook.MailItem
If GetOutlook Then
Set olmi = m_olapp.CreateItem(olMailItem)
olmi.Recipients.Add strDistribution
olmi.Recipients.ResolveAll
olmi.Subject = strSubject
olmi.HTMLBody = GetMarkup
olmi.Send
End If
Set olmi = Nothing
Set m_olapp = Nothing
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top