Mail Templates in LISTSERV Version 14.3


5 Dec 2004


Scope of this document


Types of templates

            Mail templates

            Message templates

            Message fragments

            Naming convention for message templates/fragments

            Static Web page templates

Complete list of templates in DEFAULT MAILTPL

Template command reference

            Conditional processing

            The .QUIF command

            Using &DAYSEQ()

Common variable substitutions

Other variable substitutions

Scope of this document


This document discusses LISTSERV's mail and static web interface templates as they exist in version 14.3.  It is beyond the scope of this document to discuss modification or management of LISTSERV's dynamic web interface templates, which is a separate and distinct subject. 



Significant changes have been made both to the mail template processor and to the default mail templates themselves for the version 14.3 release.  In the main, these changes allow an unprecedented level of control over what were previously hard-coded, non-optional internal messages sent by LISTSERV in response to various commands.


It is now possible to define site-wide defaults for all template forms without having to edit the DEFAULT MAILTPL file, which is not upgrade-safe.  Any customizations made at the site level to the default templates now go into the site-level SITE MAILTPL file, which will not be disturbed during an upgrade.  Defining site-wide defaults in the old $SITE$ MAILTPL file, which in any case did not work for all templates and was never intended for this use to begin with, is now deprecated, and support for such usage will be removed in LISTSERV 15.


During startup, LISTSERV 14.3 will migrate existing templates from WWW_ARCHIVE MAILTPL to SITE MAILTPL, unless one of the following conditions arises:



If there are no conflicts, WWW_ARCHIVE MAILTPL is then renamed to WWW_ARCHIVE OLDTPL.  If a conflict is detected, LISTSERV will not attempt to determine which version of the template is "correct", but rather will log something like the following:


7 Oct 2004 10:57:05 Migrating templates from WWW_ARCHIVE to SITE...

- $TEST_TEMPLATE: conflicting version found in SITE

7 Oct 2004 10:57:05 Conflicts detected, finish migration manually


It is then incumbent on the site maintainer to harmonize the differing versions of any templates reported to be in conflict.

Types of templates


In LISTSERV 14.3 there are three different types of templates controlling administrative messages:  mail templates, message templates, and message fragments. A fourth type of template, the static Web templates, controls the “.html” files created by LISTSERV in the Web Archives directory.

Mail templates


A mail template is, as in previous versions of LISTSERV, a "complete" mail message.  All commands are available, substitutions that make sense in the context of the specific message are available, the message may be formatted, and while other templates may be imbedded with the .IM command, the message is in and of itself ready for LISTSERV to send.

Message templates


The next level down is a message template, that is, a template that by default does not send any mail but supplies text that will ultimately be shown to the user - not always by e-mail, it could be over the web interface for instance.


Typically, message templates that are sent by mail will be "bundled" into a single message.  However, a given message template can be forced to send an individual unbundled mail by using the new .SM command.


In a message template, you have the following restrictions:




Message fragments


The lowest level is a message fragment. It could be a list of months in French, or a common sequence of words that is put in a template not just to make other templates more readable, but to improve consistency (see &MSGREF). This fragment is used in another messages and is not itself a message, hence the following restrictions:



>>> Mail template "MSG_SUBSCRIBE_FRAGMENT_OPTCHANGED1" does not support .SM


and no email is actually sent.  In the example case, .SM would have to be specified in the message template MSG_SUBSCRIBE_SUCCESS in order for it to succeed.




Naming convention for message templates/fragments


The following naming convention for message templates and message fragments has been introduced:







Static Web page templates


A static Web page template defines the HTML code for the “static” Web interface pages. These pages are “static” because they are in “.html” files, and – unlike the “dynamic” Web pages generated on the fly by the “wa” Web interface CGI – do not change according to the circumstances under which they are accessed. LISTSERV must create these pages because they require information that LISTSERV has, but is not necessarily available to all accounts using the Web interface, such as list configuration information. For example, LISTSERV knows that a “join” link should not be put on the Web page for a list with Subscription=Closed, but wa should not be able to access list header information when being used by a non-owner.


Static Web page templates use the same commands and some of the same variables as the mail templates, and are stored in MAILTPL files. The dynamic Web templates use different commands and variables (not covered in this document).


To summarize:


Complete list of templates in DEFAULT MAILTPL


(As of the 14.3 release.  Other templates may be added in future builds.)


$SIGNUP Standard message to new subscribers

$WWW_ARCHIVE_HEADER Header text for WWW archive interface

$WWW_ARCHIVE_TRAILER Trailer text for WWW archive interface

$WWW_IMAGES_URL URLs for standard images

$WWW_IMAGES_URLDEF -Default URLs for standard images, do not change








$WWW_STYLE_SHEET_THEME7 Static Theme 7 (Big Print)

$WWW_STYLE_SHEET_THEME8 Static Theme8 (default font)

$WWW_STYLE_SHEET_THEME9 Static Theme 9 (no style sheet)

ADD1 You have been added to the &LISTNAME list

ADD2 &LISTNAME: &WHOM joined the list

ADDMOD2 Change in your name registration for the &LISTNAME list

ADDPW1 Your new password for &MYSELF

ADDPW2 Addition of a LISTSERV password for &WHOM

ADDPW3 Request for addition of a LISTSERV password

ADDREQ1 &LISTNAME: &WHOM requested to join

AUTODEL1 Your removal from the &LISTNAME list

AUTODEL2 &LISTNAME: Daily error monitoring report

CHANGE1 Change in your e-mail address for the &LISTNAME list

CONFIRM1 Text of confirmation requests

CONFIRM2 Command confirmation request cancelled

DELETE1 Your removal from the &LISTNAME list

DELPW Removal of your password for &MYSELF

DIRECTORY Template directory for X-GETTPL (overrides only)

HTML_DIGEST HTML digest preamble

HTML_INDEX HTML index preamble

INFO Information about the &LISTNAME list

MOVE1 Change in your host server for the &LISTNAME list





MSG_AVSCAN_FRAGMENT_SPAM1 Spam detected by AV scanner

MSG_AVSCAN_FRAGMENT_VIRUS1 Virus detected by AV scanner














MSG_POSTING_FORWARD_EDITOR Message sent to user when posting is forwarded to editor




MSG_POSTING_HOLD_EXCEED_OVERALL_LIMIT Sent to owner when list is held



MSG_POSTING_REJECT_BAD_ATTACHMENT Received an attachment not allowed by "Attachments="


MSG_POSTING_REJECT_CONTENTFILTER Message rejected by content filter






MSG_POSTING_REJECT_EXCEED_SIZELIM Posting exceeding "Sizelim=" limit



MSG_POSTING_REJECT_SPAM_DETECTED Received a message identified as spam



































NONHTML_INDEX_EPILOGUE Epilogue for non-HTML index

PROBE1 Subscription probe for &LISTNAME - please ignore

PROBE2 Probe failure for &LISTNAME

RENEW1 Renewal of your subscription to the &LISTNAME list

RENEW2 Expiration of your subscription to the &LISTNAME list

REQACK1 Your message to &LISTNAME-request@&MYHOST

REQNAK1 Your message to ALL-request@&MYHOST

SETINFO Change in your subscription options for the &LISTNAME list

SIGNOFF1 &LISTNAME: &WHOM left the list

SIGNOFF2 Your request to sign off the &LISTNAME list

SIGNOFF_CONFIRM1 Text of confirmation requests (SIGNOFF)

SIGNOFF_CONFIRM2 Command confirmation request cancelled (SIGNOFF)

SIGNUP1 You are now subscribed to the &LISTNAME list

SUBSCRIBE_CONFIRM1 Text of confirmation requests (SUBSCRIBE)

SUBSCRIBE_CONFIRM2 Command confirmation request cancelled (SUBSCRIBE)


WWW_ARCHIVE_HEADER Header file included by the CGI script


WWW_ARCHIVE_TRAILER Trailer file included by the CGI script

WWW_ARCHIVE_USER_FORMS A list of additional "user" forms to format

WWW_INDEX HTML for the main list archive screen (listname.html)




Template command reference


Any line starting with a period in column 1 is processed as a formatting command. Note that neither substitutions nor formatting commands are case sensitive. Here is a list of the formatting commands list owners may need to use:



Comment: anything on this line is simply ignored. This is useful for recording changes to template files when there are multiple owners. It is recommended to add a comment line with the date and your initials every time you make a change, for the benefit of the other owners.



.CC emails

.CC OFF removes all "cc:" message recipients, if any. In this context "cc:" is a RFC822 term that stands for "courtesy copy". RFC822 messages may have "cc:" recipients in addition to their "primary" recipients. There is no real technical difference between the two; the "cc:" indicator just denotes a message that is being sent for your information. Some administrative messages sent to list owners are copied to the user for their information, and vice-versa; this behavior can be disabled by adding a .CC OFF statement to the template.


You can also add message recipients by specifying a series of e-mail addresses after the .CC statement, as in .CC JOE@XYZ.EDU.


.CE text

Centers the text you specify (just the text you typed on the same line as the .CE command). This can be useful to highlight the syntax of a command.



Turns off formatting: one template line = one line in the final message. You can resume formatting with .FO ON or .FO RAGGed.


Changes left-and-right-justified text formatting (“block” formatting) to left justified text formatting. You can resume left-and-right-justified formatting with .FO ON.  (.FO RAGGed requires LISTSERV 14.1 [1.8e-2002a] or later, that is, build date of 31 October 2002 or later)


Cancels the message. LISTSERV stops reading the template form and does not send anything. This is useful if you want to completely remove a particular message; note however that this can be confusing with certain commands, as LISTSERV may say "Notification is being sent to the list owners" when in fact nothing will be sent because of the .QQ command in the template form. A .QQ command in an included template will cancel a message just the same as one in the main message template.



(Starting with 14.0 [1.8e]) Ends processing of the current template as if you had reached the end, but without cancelling the message. The main purpose is to avoid multi-level nested .BB/.EB conditional blocks (see below) that are hard to keep track of.



Adds a 'Reply-To:' field pointing to the list owners in the header of the generated message. Use this command when you think users are likely to want to reply with a question. You can also use .RE POSTMASTER to direct replies to the LISTSERV administrator, if this is more appropriate.


Replaces the default recipients of a message with the value specified. For instance, if you use the ADDREQ1 template form to send new subscribers a questionnaire, application form or similar material, you will need to add a '.TO &WHOM' instruction to your modified template form, as by default the user will not receive a copy.


A number of more advanced commands are available to list owners with more sophisticated needs and some programming experience. If you encounter one of these commands in a template, you will probably want to leave it alone.


.ASIS text

Tells LISTSERV to leave the text immediately following the .ASIS directive alone, that is, don't convert "<" and ">" characters into HTML &lt; and &gt; when creating pages.  This is specifically for use in HTML templates where it is important not to convert parts of a URL reference.  For instance,


.ASIS Click <a href="">here</a>.


As with the .CE directive, the text you intend to affect with the .ASIS directive must not wrap.  The .ASIS directive will only work on text it finds on the same physical line into which it is coded.


.BB cond

Begin conditional block.


Related commands are .EB, .ELSE, and .QU .  See the section below entitled "Conditional processing" for usage.


See also .QUIF .


.CS text

Define a (non standard) character set for the template in question, i.e.,


.CS ISO-8559-7


This setting is ignored if the template does not actually contain special characters (for instance, if the template is written in 7-bit ASCII). Otherwise the appropriate headers are created for the message in question when it is sent out.


.DD ddname

Copies the contents of the specified DD into the message. This is meaningful only if a DD has been set up by LISTSERV for this purpose. As a rule of thumb, you should either leave these statements unchanged or remove them.



End conditional block (see .BB).



Conditional ELSE directive (see .BB).


.IM name

Imbeds (inserts) another template form at this point in the message. This is used to avoid duplicating large pieces of text which are mostly identical, such as the templates for "you have been added to list X by Y" and "your subscription to list X has been accepted".


As noted below, LISTSERV will not pick up an "imbedded" template form from $SITE$.MAILTPL. If you wish to include an "imbedded" template form (e.g., $SIGNUP) in $SITE$.MAILTPL, you must also include the template form that calls it with the .IM command.



Stop (in other words, QUit) processing of the current template as if you had reached the end, but without cancelling the message. The main purpose is to avoid multi-level nested .BB/.EB conditional blocks that are hard to keep track of.  Available in 14.0 (1.8e) and following.



(QUit IF) Similar to .QU, stop processing the current template without cancelling the message, based on the result of an inline conditional comparison.  The full syntax is


.QUIF var operator value


For instance,


.QUIF &RC = 0


This single statement is strictly equivalent to the block


.BB &RC = 0




.SE var text

Defines or redefines a substitution variable. This is convenient for storing temporary (text) expression results that need to be used several times. Even standard variables such as &LISTNAME can be redefined - at your own risk. You must enclose the text expression in single quotes if you want leading or trailing blanks.



Set the subject line for the message.  .SJ works differently depending on the type of template:

  • For mail templates, it overrides the Subject text originally set for the template, which by default defines the "Subject:" header of the e-mail.
  • For a message template, LISTSERV uses it only where it makes sense to do so. In message templates, it is generally used in conjunction with .SM.
  • .SJ is not available for message fragments. The subject line should be set in the template that creates the actual message.
  • .SJ is not available for static Web page templates.


Send a copy of the message via email, if echoed to the web interface. 


.SM is not available in message fragments or static Web page templates, and is only available in message templates which do not contain a comment to the effect that .SM is not supported for that particular message template.


.TY text

Types one line of text on the LISTSERV console log. This can be useful to the LISTSERV maintainer for debugging, and also to record information in the console log.


Conditional processing


LISTSERV 14.3 mail templates can be programmed with an if/then/else logic that evaluates available data and performs the appropriate task depending on the outcome of the evaluation.


A conditional block begins with the command .BB (begin block) and ends with .EB (end block).  In the simplest case, the boolean expression following .BB is evaluated and, if false, all the text between the .BB and .EB delimiters is skipped.  For instance, from $SIGNUP:


.bb &DEFOPT ^= ''

Following instructions from the list owner, your subscription options

have been set to "&DEFOPT" rather than the usual LISTSERV defaults.

For more information about subscription options, send a "QUERY &LISTNAME"

command to &MYNAMES.




.ELSE may be specified in cases where an alternate text is required, as in this more complicated example (also from $SIGNUP):


.bb ((&x ^= POSTMASTER) and (&x ^= OWNER)) and (&x ^= OWNERS)

Please note that it is presently possible for

.bb &x = PUBLIC



other people


to determine that you are signed up to the list through the use of the

"REVIEW" command, which returns the e-mail address and name of all

the subscribers. If you do not want your name to be visible,

just issue a "SET &LISTNAME CONCEAL" command.




Additionally, it is possible to simply exit a conditional at an arbitary point by using a .QU (QUit) command.  For instance, the MSG_POSTING_REJECT_BAD_ATTACHMENT message template is used both to reject unwanted attachment types as well as viruses.  In order to avoid processing the entire template (which contains other text that is not germane to a virus rejection), .QU is used to simply exit processing and send the message immediately. 


.bb &VIRUS = 1

.* A virus was detected in the message. Note that this is only possible

.* for messages sent to a list, LISTSERV does not execute attachments so

.* messages sent to LISTSERV are not checked for viruses.

Your posting to the &LISTNAME list has been rejected because it contains

.bb &VIRUS_NAME ^= ''

the '&VIRUS_NAME;'





virus in attachment '&VIRUS_FILENAME;'.




You are strongly advised to check your computer for viruses as soon

as possible!



.* text for rejecting attachments follows


The following should be noted:






The .QUIF command


.QUIF (QUit IF) allows the invoker to stop processing the template if a certain condition is met, but without having to define a full-blown conditional block. For instance, the .IM command used to imbed one template into another returns a success code in the template variable &RC.  If imbedding succeeds, &RC is set to 0, and something like the following is possible:


>>> MSG_POSTING_REJECT_BAD_ATTACHMENT Received an attachment not allowed by "Attachments="

.* Use legacy BAD_ATTACHMENT template if present


.quif &rc = 0

.* at this point template processing stops and the message is sent if &RC = 0

.* otherwise processing would continue with any following text.


"quif &rc = 0" is strictly equivalent to the block


.bb &rc = 0



Using &DAYSEQ()


The DAYSEQ(n) function is quite powerful. This function allows the list owner to code template forms (such as the PROBE1 or BOTTOM_BANNER messages) that change or "rotate" automatically.


The DAYSEQ(n) function is invoked in a .BB - .EB conditional block, and n corresponds to the number of days in the rotation period, i.e., to the number of variations that you want to make to the text of the message. &DAYSEQ(n) returns a number from 1 to n which increases by 1 every day, with no special regard for weekends. That is, if the rotation period is to last for a week, you code DAYSEQ(7). If the rotation period is 15 days, you code DAYSEQ(15). Two examples follow:


Rotating bottom banner


To create a rotating bottom banner, follow this example. A list has three commercial sponsors, each of whom are provided with an advertisement every three days. (Note that this doesn’t take weekends into account; in this example, if company A is featured in the banner on Monday, it will be featured again on Thursday and then again on Sunday. However, in the following week it will be featured on Wednesday, Saturday, and Tuesday, so it will actually get rather good coverage.) Our BOTTOM_BANNER template form would look like this:



.BB &DAYSEQ(3) = 1

Today’s copy of the &LISTNAME newsletter has been brought to you

by Company A.


.BB &DAYSEQ(3) = 2

Today’s copy of the &LISTNAME newsletter has been brought to you by Company B.


.BB &DAYSEQ(3) = 3

Today’s copy of the &LISTNAME newsletter has been brought to you by Company C.




If a company needs to get a higher percentage of "air time” than another, you can simply assign it more than one of the possible n values of &DAYSEQ(n).  For instance, if you have two companies but one should get twice as many days of "air time”, you might code something like this:



.BB (&DAYSEQ(3) = 1) OR (&DAYSEQ(3) = 3)

Today’s copy of the &LISTNAME newsletter has been brought to you

by Company A.


.BB &DAYSEQ(3) = 2

Today’s copy of the &LISTNAME newsletter has been brought to you by Company B.



This would cause Company A’s message to appear on days 1 and 3 of the rotation period and Company B’s message to appear on day 2 only. 


Rotating FAQ via the PROBE1 template and "Renewal= xx-Daily"


Subscription renewal can be coded with daily granularity (however, please note that it is inadvisable to use renewal intervals of less than a week). If you further code subscription probing into the "Renewal=" keyword with the ",Probe" parameter, you open up the possibility of turning the standard PROBE1 template form into a periodic FAQ. Here’s how:


We’ll assume to start that you will code "Renewal= 15-Daily,Probe" in your list header. (You can experiment with other numbers, but since we have two messages and will be using &DAYSEQ(2), we need an odd renewal period.) We’ll also assume that you want to send two versions of your FAQ each month; the first, a complete FAQ document, and the second, an abbreviated "reminder" version that just contains information about how to sign off, how to post to the list, and so forth. The basic algorithm is therefore:


When &DAYSEQ(2) = 1, send the full FAQ.

When &DAYSEQ(2) = 2, as it will 15 days later, send the abbreviated FAQ.


Your PROBE1 template form would thus look like this:


>>> PROBE1 Periodic FAQ posting for &LISTNAME


.BB &DAYSEQ(2) = 1

This is the complete FAQ for &LISTNAME.  Please read it and keep a copy for future reference. A FAQ document for &LISTNAME is distributed every 15 days, the full FAQ alternating with a shorter "reminder" FAQ.


<body of the full FAQ document>


.BB &DAYSEQ(2) = 2

This is the abbreviated FAQ for &LISTNAME. Please read it and keep a copy for future reference. A FAQ document for &LISTNAME is distributed every 15 days, the full FAQ alternating with a shorter "reminder" FAQ.


<body of the abbreviated FAQ document>



Calculating the value for &DAYSEQ()


When you first start using a rotating banner with the &DAYSEQ variable, the &DAYSEQ(n)= 1 period begins based on the number of days elapsed since a baseline. This date format is also known as the "Gregorian serial day". 


On VM (and in REXX generally) you can calculate today's value easily with:


/* */

say Date('B') + 1


If you do not have access to a REXX interpreter, Date('B') is described as "the number of complete days (that is, not including the current day) since and including the base date, 1 Jan 0001, in the format 'dddddd' (no leading zeros or blanks)."[1]


It also is equal to the C language expression time(0)/86400 + 719162 or, for OpenVMS users, to the Smithsonian base date plus 678575.


For example, for Friday 22 Oct 2004, the value of Date('B') + 1 is 731876. This value increases by one every day at midnight.

Common variable substitutions


The following substitutions are available in most templates:



Long-style date (04 Jan 1998)



The type of machine LISTSERV is running on, e.g., "Pentium (512M)". 



Has the value 1 when running the LISTSERV Lite product, and 0 otherwise. This variable can be used to write generic templates that account for the differences between the two products.



Has the value 1 when running the Free Edition of LISTSERV Lite.  Similar to but distinct from &LITE.



Looks up the specified address in LISTSERV's signup file and displays "name <addr>" if a name is available, or just the original address otherwise. This is typically used to give the name of the command originator or target, along with his e-mail address: &MBX(&WHOM) or &MBX(&INVOKER). Please note however that &WHOM and &INVOKER are not always available in every template.


The "addr" parameter is always required; &MBX by itself is syntactically invalid.



LISTSERV's Internet hostname or, if none is available, its NJE address (with '.BITNET').



The substitution you will use most of the time when you need to refer to LISTSERV. For Internet-only or BITNET-only servers, this will display LISTSERV's only e-mail address. For servers with both Internet and BITNET connectivity, it will say "LISTSERV@hostname (or LISTSERV@nodeid.BITNET)".



LISTSERV's BITNET nodeid, without the '.BITNET', or its Internet hostname if no NJE address is available.



LISTSERV's address, in the form LISTSERV@XYZ.EDU or, if no Internet hostname is available, LISTSERV@XYZVM1.BITNET.



The full operating system name including the version number, e.g., "VM/ESA 1.2.3", "Windows NT 4.0", "Linux 2.0.27", "SunOS 5.4", etc.



The operating system under which LISTSERV is running.



LISTSERV’s release number (e.g., "1.8e", "14.3").






Three-letter day of the week, in English



The following substitutions  are also available for  templates related to mailing lists:



Used to create FAQ templates with rotating topics. May also be used to create bottom banners with rotating text (e.g., for lists with multiple commercial sponsors who get "ad space" in the banner on a rotating basis).



Returns today’s date in ISO format, i.e., yyyy-mm-dd.



Value of the specified keyword for the list. You do not need to specify the name of the list - it is implicit. You need not put quotes around the keyword names either, although quotes will be accepted if present. Optionally, you can specify a second numeric argument to extract just one of the terms of a list header keyword; for instance, if the list header contains "Notebook= Yes,L1,Monthly,Private", &KWD(NOTEBOOK,4) has the value "Private". A third argument, also optional, specifies the default value for the keyword in case it was not initialized. It is meant to be used for conditional formatting in the default templates and list owners should not worry about it.



Either the short or long name of the list based on the value of "List-Address=" and/or its system default. By default the long ("List-ID=") name is used if present.



Title of the list, or empty string.


Other variable substitutions


There are a number of variables that are available only in specific templates. In general, if the variable is available in a particular template, it can be found in the default version of that template. This list below is not exhaustive.











































































































[1] Cowlishaw, Michael: The REXX Language: A Practical Approach to Programming, 2nd ed., p.92. Englewood Cliffs, NJ: Prentiss-Hall, Inc., 1990.