Programmatically sending emails via the SMTP module.

Go to the tutorial main page.

The SMTP module included with Allegro CL allows users to programmatically send electronic mail messages.

A MIME module has recently been added as a patch to Allegro CL 8.0 and 7.0, allowing users to create MIME-compliant messages. This code has been incorporated into the SMTP module to make it possible to send MIME-compliant email messages as well.

This tutorial gives a brief demonstration of how to use the SMTP module to send a message which contains non us-ascii characters.

(Allegro CL includes a full-fledged post-office module that also provides APIs for fetching mail via IMAP or POP, but this tutorial is specifically intended to focus on SMTP.)

Preamble

Some of the features used in this tutorial were made available after the 8.0 release, most notably MIME and its incorporation into the SMTP module. If you do not know if you have downloaded these patches, you must update your images before proceeding.

These patches are also available in our 7.0 release. 7.0 users likewise must update to the current set of patches before trying the examples in this tutorial.

See http://franz.com/support/patches/ for instructions on how to download patches. This page includes steps for the typical user, as well as those with a wide variety of network and http configuration issues. It includes instruction for those that require the use of proxies, those that require proxy authentication, and for those with limited or no internet access.

Lastly, sending electronic mail requires access to a mail server. The SMTP module is able to communicate with mail servers that accept unencrypted TCP/IP connections. login/password authentication is supported. Each example in this tutorial will bind a global variable to an example, non-existent, server. Likewise, all emails must be sent to a valid email address which you have access to. The below forms should be evaluated and set to appropriate values before using any of the code in this tutorial. The variables *mail-sender* and *mail-recipient* should be set to fully qualified email addresses that belong to you.

(defparameter *mail-server* "mailserver.example.com")
(defparameter *mail-recipient* "acl-tutorial-recipient")
(defparameter *mail-sender* "acl-tutorial-sender")

You will have to modify these values in order to successfully see the results of any example.

International Character Sets

Allegro CL is already well equipped to support non-us-ascii character sets. Most standard Allegro images (all but mlisp8 and alisp8) internally store characters in Unicode. An external-format layer is provided to translate characters from Unicode to the desired character set. Many Common Lisp routines and modules (i.e. Streams) have been updated to accept external-format arguments so that this translation can be controlled by the user. See External Format Usage for some examples.

Using SMTP and MIME.

There is documentation for both the SMTP module and MIME module.

By default, the SMTP module is not loaded in a development Allegro CL image. To load it, evaluate the following at a lisp prompt.

(require :smtp)

You should see a number of files loaded as a result

cl-user(1): (require :smtp)
; Fast loading C:\Program Files\acl80\code\smtp.004
;;; Installing smtp patch, version 4
;   Fast loading C:\Program Files\acl80\code\streamp.002
;;; Installing streamp patch, version 2
;   Fast loading C:\Program Files\acl80\code\sasl.fasl
;     Fast loading C:\Program Files\acl80\code\osi.005
;;; Installing osi patch, version 5
;       Fast loading C:\Program Files\acl80\code\fileutil.001
;;; Installing fileutil patch, version 1
;     Fast loading from bundle code\rc4.fasl.
;     Fast loading from bundle code\hmac.fasl.
;       Fast loading from bundle code\sha1.fasl.
;     Fast loading from bundle code\iodefs.fasl.
;       Fast loading from bundle code\iordefs.fasl.
;         Fast loading from bundle code\efmacs.fasl.
;   Fast loading C:\Program Files\acl80\code\mime.001
;;; Installing mime patch, version 1
;     Fast loading C:\Program Files\acl80\code\regexp2.fasl
;       Fast loading C:\Program Files\acl80\code\yacc.fasl
t

The main interface to message sending is via the function send-letter.

Example 1: Sending a simple text (us-ascii) message

To send a simple letter, you need four pieces of information.

Other items can be included, such as cc and reply-to, but are optional.

(use-package :net.post-office)

(defparameter *mail-server* "mailserver.example.com")
(defparameter *mail-recipient* "acl-tut-recip")
(defparameter *mail-sender* "acl-tut-sender")

(send-letter *mail-server*
	     *mail-sender*
	     *mail-recipient*
	     "hi!! this is my first programmatic email!")

It's as simple as that. If you check your email, you should see the above simple message. If you receive an error, verify that you can reach your mail server from the machine on which you're running the sample code. Check to see if your firewall settings or perhaps virus scanning software is blocking the outgoing connection (smtp port 25).

Note that while send-letter typically returns t upon success, the return value of this routine is unspecified and therefore cannot be relied upon to indicate failure or success. An error should be signalled if there is any issue communicating with the mail server.

Example 2: Sending a MIME-compliant electronic mail message

Sending MIME-compliant email messages is useful since it allows you to take advantage of many of the features provided by modern email clients.

You can send a message as both text and html, allowing the reader to choose which one is best to display.

You can easily send attachments along with the message body.

And, you can transmit messages with international character sets.

MIME parts are constructed via the function make-mime-part. There are a number of items that can be filled out in a mime part, but of primary importance are the contents. The rest, particularly for a simple us-ascii message, can be filled in by default values. There is more on defaulting behavior below:

(use-package :net.post-office)

(defparameter *mail-server* "mailserver.example.com")
(defparameter *mail-recipient* "acl-tut-recip")
(defparameter *mail-sender* "acl-tutorial-sender")

(send-letter *mail-server*
	     *mail-sender*
	     *mail-recipient*
	     (make-mime-part :text "hi!! this is my first mime-compliant programmatic email!"))

Also very simple. Check your email to see the results. You may notice that the mail headers for this look very similar to those in the message from the previous example. This is because send-letter automatically wraps the message body in a mime-part (via make-mime-part) to facilitate the easy addition of attachments.

MIME defaulting behavior?

Each mime-compliant message must have certain header fields filled in, such as content-type and content-transfer-encoding. When not specified, make-mime-part attempts to find suitable defaults based on information it can determine about the message contents. It is important that these fields are correct when packaging binary data or non-us-ascii characters into a message.

The documentation for make-mime-part describes the defaulting behavior employed based on the arguments it is passed.

Sending a MIME based message using intl. chars.

Sending non-us-ascii emails is as simple as sending us-ascii messages. By default, send-letter will deliver messages in a mime body using the utf-8 charset and an appropriate value for content-transfer-encoding will be auto-selected. If this does not suit your needs, it is possible to handcraft your own mime part containing your message using whatever character sets and encodings you desire.

In order to send a message, you'll first need to dig up some non-us-ascii text.

Depending on how you start Allegro CL, your version of emacs, or whether you use the IDE, you will have a different experience with pasting non-ascii text into the REPL.

For example, if you have the proper language packs installed, the following text taken from the first paragraph at http://jp.franz.com will appear as japanese text.

"Allegro Common Lisp  (以下Allegro CLと呼びます)は、高度にオプティマイズされたCommon Lispシステムであり、
 最もパワフルなダイナミックオブジェクト指向プログラミングシステムです。
 Allegro CLは、プログラム開発の生産性向上と、ダイナミックオブジェクト指向のメリットを提供します。"

Elsewise, you likely see a bunch of gibberish. On Windows, if you have the 'Install On Demand' options checked, Internet Explorer will automatically ask if you want to install necessary language packs. Once installed, the same languages should also be available for other web browsers, such as Mozilla Firefox. For help manually installing Language Packs, Windows XP users can click here, and Windows 2000 users here.

For installing on other platforms, try this great Wikipedia page or please consult your System Administrator.

Example 3-1: Sending non-us-ascii characters via send-letter.

As mentioned above, all text strings passed to send-letter are wrapped in a mime container via a call to make-mime-part. This can be problematic when sending international text, as send-letter does not provide arguments to describe the type of text it is placing into the mime container. However, the default external-format used by make-mime-part is utf-8, which should work for most typical uses. From this default, make-mime-part will create a mime wrapper with appropriate charset (utf-8) and content-transfer-encoding.(base64).

(use-package :net.post-office)

(defparameter *mail-server* "mailserver.example.com")
(defparameter *mail-recipient* "acl-tut-recip")
(defparameter *mail-sender* "acl-tutorial-sender")

;; octets of iso-2022-jp text, taken from the first paragraph at http://jp.franz.com
(defparameter *message* 
   (octets-to-string 
      (make-array 
       305
       :element-type '(unsigned-byte 8)
       :initial-contents '(65 108 108 101 103 114 111 32 67 111 109 109 111 110 32
			      76 105 115 112 32 32 27 36 66 33 74 48 74 50 60 27 40 66
			      65 108 108 101 103 114 111 32 67 76 27 36 66 36 72 56 70
			      36 83 36 94 36 57 33 75 36 79 33 34 57 98 69 89 36 75 37
			      42 37 87 37 70 37 35 37 94 37 36 37 58 36 53 36 108 36
			      63 27 40 66 67 111 109 109 111 110 32 76 105 115 112 27
			      36 66 37 55 37 57 37 70 37 96 36 71 36 34 36 106 33 34
			      27 40 66 32 27 36 66 58 71 36 98 37 81 37 111 37 85 37
			      107 36 74 37 64 37 36 37 74 37 95 37 67 37 47 37 42 37
			      86 37 56 37 39 37 47 37 72 59 88 56 126 37 87 37 109 37
			      48 37 105 37 95 37 115 37 48 37 55 37 57 37 70 37 96 36
			      71 36 57 33 35 27 40 66 32 65 108 108 101 103 114 111 32
			      67 76 27 36 66 36 79 33 34 37 87 37 109 37 48 37 105 37
			      96 51 43 72 47 36 78 64 56 59 58 64 45 56 126 62 101 36
			      72 33 34 37 64 37 36 37 74 37 95 37 67 37 47 37 42 37 86
			      37 56 37 39 37 47 37 72 59 88 56 126 36 78 37 97 37 106
			      37 67 37 72 36 114 68 115 54 33 36 55 36 94 36 57 33 35
			      27 40 66 0))
      :external-format :iso-2022-jp))


(send-letter *mail-server*
	     *mail-sender*
	     *mail-recipient*
	     *message*)

If your mail reader is capable, you should see an email message containing Japanese text. When viewing the raw message, however, you should see a mime-message encoded in the utf-8 charset, with a content-transfer-encoding of "base64".

Example 3-2: Creating your own mime-wrapped message to send non-us-ascii characters via send-letter.

If you find that the default behavior of send-letter is not suitable, you can hand-craft your own mime wrapper and pass this as the message argument.

(use-package :net.post-office)

(defparameter *mail-server* "mailserver.example.com")
(defparameter *mail-recipient* "acl-tut-recip")
(defparameter *mail-sender* "acl-tutorial-sender")

(send-letter *mail-server*
	     *mail-sender*
	     *mail-recipient*
	     (make-mime-part
	      :text *message*
	      :external-format :iso-2022-jp))

This should deliver the same message above to your inbox, but with a charset of iso-2022-jp, and a content-transfer-encoding of "7bit".

Note that some MTA's (mail transfer agents) may make changes to the content-transfer-encoding behind your back in the process of delivering your message. For example, a message may be decoded from a "base64" content-transfer-encoding to "7bit" or "8bit". Polite MTA's should include additional mail headers indicating such a change has occurred.

End of tutorial.

Return to the tutorial main page.