HTML Emails The Easy Way

Jake Howlett, 2 April 2007

Category: Miscellaneous; Keywords: MIME Email HTML Alternate

Almost exactly five years ago I wrote a series of articles that described how to send emails in HTML format. At the time they were ground-breaking in that there was no other easy way to do it in Notes and I like to think my methods helped a lot of people achieve the goal of easily sending formatted emails.

Times change though and new methods are always coming to light. Recently I found a way of achieving the same goal using new Domino 6 LotusScript classes. There's now no need to use any tools other than those we already have. The approaches I discussed all that time ago are now defunct and no longer needed.

Not needing complicated additions to your applications is a godsend. Personally, I was always put off using my own mailing methods due to the awkwardness of their implementation.

The Old Approach

The first solution I came up with involved using a scheduled Java agent to send the mails. Emails would be queued in a special database. The agent would then loop through them every five minutes or so and send the queued mail. Java was used as it allowed us to open TCP sockets and directly send the mail to port 25 on any SMTP server, line by line.

Developing this approach required a knowledge of the SMTP protocol and how emails are constructed. Although we no longer need to know this I'd still recommend you read the first part of the series for some valuable background information on SMTP and the basics of how emails work.

Shortly after developing this solution somebody told me about a way to connect to sockets on servers using Win32 methods. This approach was similar but there was no need to use Java. Still it was far from perfect and even worse than being in Java it was Windows-only. The shame.

The New Approach

Domino 6 introduced a new method to the NotesMIMEEntity class called setContentFromText(). This allows us to add MIME entities to a message and add our own text content to it. Not only this but we can dictate the headers and content types of the message. This gives us the ability to send emails in multiple formats. We'll talk about why we might want to send in more than one format later. For now, let's·look at the·code you need to do this:

Dim body As NotesMIMEEntity
Dim mh As NotesMimeHeader
Dim mc As NotesMIMEEntity
Dim stream As NotesStream 
session.convertMIME = False
MailDoc.Form="Memo" MailDoc.SendTo="me@me.com" MailDoc.Subject="Test HTML Messages" 'Create the MIME headers Set body = MailDoc.CreateMIMEEntity Set mh = body.CreateHeader({MIME-Version}) Call mh.SetHeaderVal("1.0") Set mh = body.CreateHeader("Content-Type") Call mh.SetHeaderValAndParams( {multipart/alternative;boundary="=NextPart_="} ) 'Send the plain text part first Set mc = body.createChildEntity() Set stream = session.createStream() Call stream.WriteText("Hello. I'm boring.") Call mc.setContentFromText(stream, {text/plain}, ENC_NONE) 'Now send the HTML part. Order is important! Set mc = body.createChildEntity() Set stream = session.createStream() Call stream.WriteText("Hello. I'm <b>exciting</b>") Call mc.setContentFromText(stream, {text/html;charset="iso-8859-1"}, ENC_NONE) 'Close the stream Call stream.close() 'Send it Call MailDoc.Send(False)

Working through it bit by bit it should be obvious what's going on. If not, don't worry. In the demo download I've put the code in a sub routine in a Script Library called "CommonRoutines", so you don't need to worry about it too much. If you want to understand the code you can digest it at will.

Note: It's important to get the message parts in right order — HTML then plain text. Also, if you use Principal field overrides, that code has to come after the MIME streams in the code.

Let's look at how we can use this code:

Using the Code:

The way I've begun to use the code is pretty much as it is in the sample database. There's a script library called CommonRoutines, which I tend have in all my databases and which all Agents tend to include, much like all my Forms use the CommonFields subform.

In this library is the routine called sendMessage() which contains the code outlined above. Calling this method looks like this:

Call sendMessage("SendTo", "Subject", "<p>Hello</p>", "Hello")

The first two arguments are self-explanatory. The second two are the email body in HTML and plain format, respectively.

In most case the last two arguments will contain the same text, but the HTML part will be formatted with extra markup. Whereas the plain string might contain a splattering of Chr(10) the HTML string can make do with using <p> and/or <br> tags.

Here's a more typical real world demo:

Dim BodyHTML as String, BodyPlain as String, FullURL as String
'FullURL best controlled by config/app setting, rather than hardcoded!
FullURL = "http://myserver/myDb.nsf/"
BodyHTML = "<h1>A New Ticket Has Been Submitted</h1>"
BodyHTML = BodyHTML + "<p>Click the link below to open this ticket</p>"
BodyHTML = BodyHTML + |<p><a href="|+FullURL + |/tickets/| + doc.unid +|">| _
        + doc.Title(0) + |</a></p>|
BodyText = "A New Ticket Has Been Submitted" + Chr(10) + Chr(10)
BodyText = BodyText + "Click the link below to open this ticket" + Chr(10) + Chr(10)
BodyText = BodyText + doc.Title(0) + Chr(10)
BodyText = BodyText + FullURL + "/tickets/" + doc.unid
Call sendMessage(doc.Responsible, db.Title + ": New Ticket", BodyHTML, BodyText)

There's an obvious drawback to this — we need to create two strings with the same information in them. This adds up to twice (if not more) coding each time you want to compose a message. True, but, once you've read what's to follow I'll hope you'll agree it's worth the effort. Certainly I've used this duplicate approach to all automated messages I've created since discovering this.

Nothing's Ever Simple:

The ability to use HTML in an email should be an absolute godsend, both to developer and to user. Instead, what was a great idea, has become a bit of headache for all involved.

Why the need for multiple formats? Well, quite simply, not all mail clients support HTML emails. Not only that but some users — myself included — opt to display all received email in plain text format, which is a global config setting in the Thunderbird mail client. This is only possible if the mail has a plain text alternative part.

Here's an test email message being read in Thunderbird. First, in HTML format:

Now here's the same message after I've told Thunderbird to view it in plain text mode.

Notice the same content gets to the user, just with different styling. This isn't true of messages where you miss out the alternate part. Sure, most people probably will have the ability to read HTML emails but assuming this is a brave step for any developer.

Creating a Look and Feel

Notice how the HTML string in the demo code above started with a H1 and no HTML, BODY or HEAD tag. This doesn't mean you don't need the complete HTML structure for an email, as you do. It just means I've taken the whole HTML envelope structure needed to wrap the message and placed it in the SendMessage routine. This assumes all emails you send from that one database will have a common look and feel. For this reason I've shown how, in the SendMessage routine, you can add some CSS to the HEAD tag. You could go one step further, as I tend to do, and add a banner to the top of all outgoing messages - perhaps including the company logo and the database title. You can see this in effect in my blog entry about my "CRM".

Talking of logos...

Attaching Images

Although it's possible to embed images as attachments to email I'd advise against it and not only because it doesn't work in all clients. It's much easier to add an inline image to your HTML email which simply point to an image on a remote server. Saves space in the email as well. It's annoying getting bloaty emails form people where they've attached their company logo to the footer of every message.

Summary

Like it or not, HTML email are here to stay. Used in a considerate way they are a brilliant way to get information out to a system's users. Although I've never actually used the previous methods of sending them that I've talked about I'm now a big user of this approach. Having to code the content of emails twice is a pain, but it's worth it to feel safe in the knowledge the email works at a lowest common denominator level of email clients.

I know the last article I wrote about HTML emails was called Sending HTML emails, the final word, but I now believe this is the final word on sending HTML emails from Domino!

Further Reading