# NAME

  `ezsmtp` - Easy SMTP client package for text email

# SYNOPSIS

      package require ezsmtp ?1.0?

      ::ezsmtp::config ?options?

      ::ezsmtp::send ?options?

# DESCRIPTION

The `ezsmtp` package provides an easy interface for sending email messages from Tcl 8.0 and newer via a network conversation with a local or remote SMTP-compliant mail server. This package was written to be as portable as possible and is known to work on various *nix, Windows, and Mac systems and will probably work on more exotic systems like MVS and VMS as long as Tcl's sockets function correctly. This extension attempts to be as RFC-compliant as possible, as far as is possible in a relatively small code base. Relevant standards are listed in the REFERENCES section at the end of this document.

This package provides only the text transport mechanism -- no provisions have been made for attachments or other fancier email features. If you require full MIME support and attachments, you should consider one of the C-code packages listed in the `SEE ALSO' section. Support for non-ascii text encodings is available when run with Tcl 8.1 or newer and connected to a modern SMTP server.

The `::ezsmtp::send` command puts a simple interface around mail sending, requiring either a `-body` switch to specify the body of the message directly or a `-channel` switch to read the contents of the message from a Tcl channel, such as an opened file or socket. One or more recipent email addresses should be specified using the -to, -cc, -bcc, or respective list-oriented options.

The `::ezsmtp::config` command provides a way to change or access the package-wide settings, such as the "From" address, SMTP server, or debugging output.

A simple example of its usage is:

      # Ensure the package is loaded
      package require ezsmtp

      # (NOTE: You need to set these correctly) Set the SMTP server
      # to smtp.myprovider.com and set my `From' address using the
      # full-name form.  You only need to do this once.
      ezsmtp::config -mailhost smtp.myprovider.com \
              -from "My Name <me@myprovider.com>"

      # Send a message to the author expressing your enthusiasm.
      ezsmtp::send -to dhagberg@millibits.com \
              -subject "I like ezsmtp!" \
              -body "This ezsmtp stuff rocks!\n\nMy Name"

The in-line comments above provide a fairly good description of what's going on. Note that the body contains two newlines before signing the message as `My Name'. The `ezsmtp::send` command does not perform any line-wrapping other than breaking up really long lines (see below).

# COMMANDS

## `::ezsmtp::config ?options?`

  The `::ezsmtp::config` command is used to set and query package-wide configuration settings. If no options are specified, then the current configuration switches and values for all options is returned in list form. If a single argument is specified, then it should be one of the flags described below. In this case the current value of that setting is returned. Otherwise, the options should be a set of flags and values that define the configuration:

  `-mailhost` hostname
    Where hostname should specify the TCP/IP host name or IP address of the SMTP server to use for sending email. Defaults to localhost, which should work on most Unix machines. Windows and Macintosh users do not (typically) have an SMTP service, so they should always specify the name of their ISP's (or corporate network's) SMTP server.

  `-port` portval
    Where portval specifies either a TCP port number or service name (like smtp) upon which to perform the SMTP conversation with the server. Defaults to 25.

  `-from` emailaddr
    Where emailaddr should specify the default email address that mail will be `From', in a form like `-from dhagberg@millibits.com` or `-from "D. J. Hagberg <dhagberg@millibits.com>"`. Note the quotes around the latter form, which are necessary due to the spaces. Specifying this option with `ezsmtp::config` eliminates the need to specify it in every `ezsmtp::send`.

  `-batchsize` number
    Where number specifies an email recipient batch size, useful for mass-mailings, as SMTP servers typically slow down significantly with large numbers of recipients in a single SMTP conversation. Setting number to 0 indicates that the mail should be sent in a single batch to all recipients (the default). Setting number to a larger value indicates the maximum number of recipients in each SMTP conversation, such as 10.

  `-strictaddr` 0|1
    Sets whether strict RFC 821-compliant email validation should be performed. Default: 0 which requires either a local-username style address with no `@', or a remote-style address with at least one non-@ character preceeding and following a single `@' sign. Set to 1 for strict validation, which has a complicated set of rules documented in the RFC, of which only the common usage cases are allowed.

  `-logproc` procname
    Sets log message behavior. If procname is the empty string {}, which is the default, log messages are output to stdout depending on the -verbose setting. If the user of this library wants to display the log messages differently, they must supply a fully- namespace-qualified procedure name that will be passed a single argument: the message string to be logged. This procedure will be evaluated at global scope.

  `-verbose` number
    Where number ranges from 0 to 9. If number is 0, then no debugging output will be printed. If number is 1, then the start and end of each SMTP conversation will be printed. If number is 9, then heaps of debugging info will be printed. The behavior between 2 and 8 is implementation-defined. Defaults to 0.

## `::ezsmtp::send ?options?`

  This command is used to send a single message to one or more email recipients, the contents of which must come from either the -body parameter or a Tcl channel (an opened file, socket, etc.) specified by the -channel parameter. Recipients may be specified in several different ways as either `To', `Cc', or `Bcc' addressess, which will create email headers of the expected form.

  The following flags may be specified one or more times in the send command. If specified more than once, the effects will be cumulative. For example

        ezsmtp::send -to a -to b -to c ...

  will send the message to all three recipients: a, b, and c. Note that at least one email recipient must be specified via any combination of the -to, -cc, -bcc, -tolist, -cclist, or -bcclist options.

  `-to` addr
    Where addr specifies one recipient email address is in a form like `username@host.domain` or like `"Full Name <user@host.domain>"`. The address is added to the `To:' header and to the list of recipients.

  `-cc` addr
    Where addr specifies one recipient email address is in a form like `username@host.domain` or like `"Full Name <user@host.domain>"`. The address is added to the `Cc:' header and to the list of recipients.

  `-bcc` addr
    Where addr specifies one recipient email address is in a form like `username@host.domain` or like `"Full Name <user@host.domain>"`. The address is added to the list of recipients, but will not be sent in the headers of the email. Typically used for mail lists or to protect the anonymity of the recipients.

  `-replyto` addr
    Where addr specifies one recipient email address is in a form like `username@host.domain` or like `"Full Name <user@host.domain>"`. The address is added to the list of `Reply-To:' addresses. Normally, when the recipient hits the Reply button in their email program, the address(es) listed in this header will be used.

  `-tolist` addrlist
    Where addrlist is a well-formed Tcl list of recipients, typically specified using the `list' command like:

          ezsmtp::send -tolist [list "Bubba <bubba@c.com>" a@b.com e@f.net] ...

    Addresses in the list may be specified as described for the -to option and will be added to both the recipient list and the `To:' header.

  `-cclist` addrlist
    Where addrlist is a well-formed Tcl list of recipients (see -tolist above). Addresses in the list may be specified as described for the -cc option and will be added to both the recipient list and the `Cc:' header.

  `-bcclist` addrlist
    Where addrlist is a well-formed Tcl list of recipients (see -tolist above). Addresses in the list may be specified as described for the -bcc option and will be added to the recipient list but not sent in the headers of the email. Typically used for mailing lists or to protect the anonymity of recipients.

  `-replytolist` addrlist
    Where addrlist is a well-formed Tcl list of recipients (see -tolist above). Addresses in the list may be specified as described for the -replyto option and will be added to the list of `Reply-To:' addresses. Normally, when the recipient hits the Reply button in their email program, the address(es) listed in this header will be used.

  `-headers` keyvaluelist
    Adds to the set of additional headers to be sent before the body in the current send. keyvaluelist must be a well-formed Tcl list (see the list command) with an even number of elements that alternate between keys and values. The keys become the header names and values become their respective values. Usage is discussed much more extensively in the `HEADERS' section below.

  The following flags and values for `ezsmtp::send` are intended to be specified once on the send command. If specified more than once, only the last one will be used.

  `-subject` subjtext
    Where subjtext is a single-line subject to be sent as a `Subject:' header in the outgoing email.

  `-body` text
    Note that either the -body or -channel switch should be specified, never both. The text value should be one or more lines of text separated by newline (\n) characters, with all line wrapping already performed. The text will be sent verbatim, line-by-line, except if longer than 998 characters. Lines longer than 998 characters will be split, not necessarily at word boundaries, to comply with RFC 821, so it's a really good idea to do line wrapping before passing your text.

  `-channel` channame
    Note that either the -body or -channel switch should be specified, never both. channame must be a open Tcl channel, such as one from `[file open ...]`, from which lines of text may be read and sent as the body of the message. If one has specified a -batchsize other than 0, the channel must support ``tell`' and ``seek`' operations to allow rewinding between batches. When the mail has been sent, the channel will be in an eof condition but not closed. Closing the channel is left up to the caller.

    NOTE: if the channel will contain non-7-bit-ascii characters, it must be `fconfigure`'d with the correct `-encoding` before being passed to ezsmtp::send. This is NOT designed for sending binary data, such as images or other non-textual octet-streams but rather for non-ASCII text. Also note that lines longer than 998 characters will be broken at exactly 998 characters to comply with RFC 821, so please ensure any data in this channel already has correct line breaks.

  `-charset` charsetlist
    NOTE: This option is only applicable when running under Tcl versions 8.1 and newer. If a character set/encoding other than `ascii` or `{ascii us-ascii}` is specified, the SMTP server MUST support the ESMTP 8BITMIME [RFC1652] option, else an error will be thrown.

    Specifies the character set/encoding used for the text data in this send as either a one- or two-element Tcl list. A one-element specification like `iso8859-1` may be used when the Tcl encoding name from the ``encoding names`' command is identical to the MIME charset specification [MCHRSET]. A two-element specification like `[list cp1251 windows-1251]` must be used when the Tcl encoding name differs from the equivalent MIME charset specification.

    The case of the elements in charsetlist is not significant, nor preserved. They will be lower-cased for comparison, configuration, and header output purposes.

    This option affects the Content-Type and Content-Transfer-Encoding headers. If you wish to override the values in these headers, specify a `-headers [list content-type VALUE1 content-transfer-encoding VALUE2]` option after this option. This would be necessary if you are doing your own base64 or quoted-printable encoding of the message body.

  `-receipt` returnreceiptspec
    Specifies that return-receipt delivery status messages should be requested for this send. Note that not all SMTP servers support delivery status, per the RFC 1891 spec used in this implementation. If you request return-receipt delivery status notifications and your specified SMTP server does not support delivery status, an error will be thrown before any message is sent.

    The returnreceiptspec may be either a single boolean element or a key/value list containing return-receipt keywords and values. If a single boolean element, return receipt is disabled when `0` or `false` and enabled with default settings when `1` or `true`. If a key/value list, then the following keywords and values may be specified:

    `delivery` 0|1
      Specifies whether successful delivery status messages should be returned. 1 for yes, 0 for no. Default: 1

    `delay` 0|1
      Specifies whether `significantly delayed' status messages should be returned. 1 for yes, 0 for no. Default: 1

    `nsmail` 0|1
      Specifies whether a header should be added to the message that would cause Netscape Mail clients to return a receipt when the receiver opens the message for viewing. 1 for yes, 0 for no. Default: 0

    `returnfull` 0|1
      Specifies whether the body of the sent message should be returned instead of only the headers. 1 for the full body, 0 for headers only. Default: 0

    `envelopeid` text
      Where text specifies an identifier to be returned in any status messages, like `ID000601`, and will be encoded in an ASCII-only form for transmission. In its encoded form (which may triple in length), it must be no longer than 38 characters. If `text` is the empty string {}, then no specific envelope ID will be sent, and the SMTP server's auto-generated envelope ID will be used. Default: {}

  The following options to `ezsmtp::send` allow one to override the package-wide configurations for a single send. This may be useful if you want to avoid the extra `ezsmtp::config` step or change addresses or email servers frequently during operation.

  `-from` addr
    Where addr is in a form like `username@host.domain` or like `"Full Name <username@host.domain>"`, allowing you to override the default (see ezsmtp::config -from) for this single send.

  `-mailhost` hostname
    Hostname or IP address of the SMTP server, allowing you to override the default (see ezsmtp::config -mailhost) for this single send.

  `-port` portval
    Where portval specifies either a TCP port number or service name to talk to the SMTP server, allowing you to override the default (see ezsmtp::config -port) for this single send.

  `-batchsize` number
    Where number sets the recipient batch size, overriding the system default (see ezsmtp::config -batchsize) for this single send.

# HEADERS

The `ezsmtp::send -headers keyvaluelist ...` option adds to the set of additional headers to be sent before the body in the current send.

keyvaluelist must be a well-formed Tcl list (see the Tcl list command) with an even number of elements that alternate between keys and values. The keys become the header names and values become their respective values. The case of the header names (keys) is not significant, nor maintained, in order to comply with RFC822. The values are maintained verbatim with the exception of handling long lines (in order to comply with the same RFC).

Header values should typically be a single line of text with no leading or trailing newlines. Multi-line headers may be specified by separating each line with a newline (\n) character. Each line will have all leading/trailing whitespace discarded and continuing lines (after the first) will be prepended with a tab (\t) per the RFC822 spec. For example the following switch and value:

      -headers [list Content-type text/html x-my-header "This is my header" \
              x-my-head2 "This is a long header\nwith two lines"]

would be reformatted when sent as:

      Content-Type: text/html
      X-My-Header: This is my header
      X-My-Head2: This is a long header
              with two lines

Default headers that will be sent, if not specified directly are:

      Date: (see below)1
      From: (see below)2
      Subject: (see below)3
      X-Mailer: Tcl ezsmtp Mailer Package
      Content-Type: text/plain; charset=us-ascii
      Mime-Version: 1.0

1. The Date: header will be in an RFC-compliant form like: `Mon, 12 Oct 1999, 23:55:12 +0000'.

2. The From: header value will be the one specified by `ezsmtp::send -from` or, if not specified, the default from `ezsmtp::config -from`.

3. The Subject: header will be sent with the value of the `-subject` switch if and only if the switch was specified.

4. The `To:' and `Cc:' headers will be added if the user had specified recipients via the -to, -cc, -tolist, or -cclist options, respectively. Note that no `Bcc:' header will be sent, in order to preserve the anonymity of recipients, as was the intent of that header.

5. The `Reply-To:' header will be added if the user had specified one or more reply addresses via the -replyto or -replytolist options.

Any of the above default headers may be overridden by setting them explicitly using `-headers ...`, typically as the last option in an `ezsmtp::send` command.

# SEE ALSO

Andreas Kupries' site
  Contains links to other email implementations for Tcl, several of which support MIME attachments and other useful features. Located at: http://www.purl.org/NET/akupries/soft/mail/.

# REFERENCES

[RFC821]
  The base specification for the Simple Mail Transport Protocol (SMTP), upon which the other RFCs listed below are based, available at http://www.faqs.org/rfcs/rfc821.html

[RFC822]
  The base specification for the format of text messages to be sent across the Internet. Describes how headers should be formatted, sets limits on body line length, etc. Available at http://www.faqs.org/rfcs/rfc822.html

[RFC1341]
  The base specification for Multipurpose Internet Mail Extensions (MIME), which ezmstp does not currently implement. Available at http://www.faqs.org/rfcs/rfc1341.html.

[RFC1521]
  The base specification for the format of MIME email address headers bodies, which ezsmtp does currently implement, at least the parts about plain text bodies. Available at http://www.faqs.org/rfcs/rfc1521.html.

[RFC1652]
  The specification for ESMTP 8BITMIME, which your SMTP server must support in order for the `ezsmtp::send -charset` option to work. This is implemented by sendmail versions 8.8 and newer (I think) and many other modern SMTP servers. The full spec is available at http://www.faqs.org/rfcs/rfc1652.html.

[RFC1891]
  The specification for delivery status notification, used for `ezsmtp::send -receipt`. The full spec is at http://www.faqs.org/rfcs/rfc1891.html.

[MCHRSET]
  A list of the current IANA-approved MIME charset specifiers may be found at: ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets

# EXAMPLES

The test_examples.txt file contains some examples of ezsmtp usage that I use to test new and old features as I change things. This may help you understand the basic idea.

If you need help with more complex tasks, email me I would be happy to add your question and my answer as a future example in this section.

# COPYRIGHT

Copyright © 1999-2000 by D. J. Hagberg and other parties.

See the file "license.txt" for information on usage and redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.

# REVISION

`$Id: ezsmtp.html,v 1.1 2008/06/22 22:19:45 pgeorges Exp $`