cl-smtp vs Exchange server

Tue Apr 17, 2012

For those of you just here for the easy, googlable answer. To send an HTML email with cl-smtp, do this:

(cl-smtp:send-email [server] [from] [to] [subject]
                    [plaintext message, or possibly NIL]
                    :html-message [HTML message])

Making sure to replace the things with square brackets, obviously. Passing nil instead of the mandatory message parameter causes all the clients I've tested with so far to automatically display your email as a standard HTML message.

Now then.

The documentation in the module itself follows the usual Common Lisp standards of being minimal, verging on nonexistent1. The best [example I managed to find](http://ryepup.unwashedmeme.com/blog/2008/10/31/some-simple-cl-smtp-examples/) of sending an HTML-formatted email from cl-smtp can be seen here. The suggestion is to do

(cl-smtp:send-email
 +mail-server+ from to subject
 "<html><body>
    <h2>
      YES. THIS IS DOG.
    </h2>
      <img src=\"http://my.site.url/dog.jpg\" alt=\"A dog comically answering a phone\"/>
  </body></html>"
 :extra-headers '(("Content-type" "text/html; charset=\"iso-8859-1\"")))

And if you do that, it will seem to work unless you run into someone with a particularly configured Exchange server. You might be thinking2 "Oh, \fantastic, MS once again cocks up what should be a simple and straightforward task", but I'm not so sure. Lets take a look at the headers produced by using the :extra-headers approach above.

...
From: from@email.com
To:  someone@else.com
Subject: Serious Business
X-Mailer: cl-smtp(SBCL 1.0.54.0.debian)
Content-type: text/html; charset="iso-8859-1" ## the result of our option
Mime-Version: 1.0
Content-type: text/plain; charset="UTF-8" ## the default cl-smtp header
...

Now like I said, this seems to get interpreted as intended in most places. Notably, gmail, hotmail, yahoo mail, my companies' exchange server, and probably mailinator as well, all output the result of this multi-Content-type-headered email as text/html. The thing is, it seems fairly reasonable to parse this strictly and accept the last Content-type declaration rather than the most general. So I guess another way of saying it is "this won't work on a properly configured Exchange server".

The actually working way of accomplishing this task is to use the built-in :html-message parameter

(cl-smtp:send-email
 +mail-server+ from to subject
 "Ok, the HTML version of this email is totally impressive. Just trust me on this."
 :html-message
 "<html><body>
    <h2>
      YES. THIS IS DOG.
    </h2>
      <img src=\"http://my.site.url/dog.jpg\" alt=\"A dog comically answering a phone\"/>
  </body></html>")

if you don't want to send a plaintext message at all, it's possible3 to pass nil as the message body

(cl-smtp:send-email
 +mail-server+ from to subject nil
 :html-message
 "<html><body>
    <h2>
      YES. THIS IS DOG.
    </h2>
      <img src=\"http://my.site.url/dog.jpg\" alt=\"A dog comically answering a phone\"/>
  </body></html>")

Doing it this way causes cl-smtp to break your message up into a plaintext and HTML version. You then rely on a client showing its user the appropriate one depending on their context4.

From: from@email.com
To:  someone@else.com
Subject: Serious Business
X-Mailer: cl-smtp(SBCL 1.0.54.0.debian)
Mime-Version: 1.0
Content-type: multipart/alternative;
 Boundary="_---------_2IQrElfHaDK71IdkZlEq5L3C0etr5t"
Message-Id: blahblahblah

--_---------_2IQrElfHaDK71IdkZlEq5L3C0etr5t
Content-type: text/plain; charset="UTF-8"
Content-Disposition: inline

Ok, the HTML version of this email is totally impressive. Just trust me on this.


--_---------_2IQrElfHaDK71IdkZlEq5L3C0etr5t
Content-type: text/html; charset="UTF-8"
Content-Disposition: inline

<html><body><h2>YES. THIS IS DOG.</h2><img src=\"http://my.site.url/dog.jpg\" alt=\"A dog comically answering a phone\"/></body></html>


--_---------_2IQrElfHaDK71IdkZlEq5L3C0etr5t--

The 'The More You Know' rainbow image

  1. Though it does show you a useful example of how to put an attachment in a sent email.
  2. As I did initially.
  3. Though probably not advisable in all cases.
  4. Which most seem to, but there are still one or two Exchange-server related hiccups for some users with particular versions of the software.


Creative Commons License

all articles at langnostic are licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License

Reprint, rehost and distribute freely (even for profit), but attribute the work and allow your readers the same freedoms. Here's a license widget you can use.

The menu background image is Jewel Wash, taken from Dan Zen's flickr stream and released under a CC-BY license