README.listtexts
List texts in mlmmj
===================
List texts are stored in listdir/text. They specify the content of various
automatic emails that Mlmmj sends. They are provided in a number of different
languages. The language to use for a list is chosen when you run the
mlmmj-make-ml script and the appropriate files are copied into your
listdir/text directory.
This file documents the following aspects of list texts:
- Naming scheme
- Supported list texts
- Format
- Conditionals
- Wrapping
- Formatting and comments
- Formatted substitutions
- Unformatted substitutions
- Escapes
Naming scheme
-------------
List texts are named following a scheme of:
purpose-action-reason-type
Mlmmj will look for the full four-part name first, then for files with shorter
names obtained by dropping parts off the end, and finally for a file with a
compatibility filename. It will use the first one it finds. (Note that use of
the compatibility filename is DEPRECATED and will be removed in a future
release.)
So, the complete search order is:
- purpose-action-reason-type
- purpose-action-reason
- purpose-action
- purpose
- compatibility filename (DEPRECATED)
When using shortened names, the %ifaction%, %ifreason%, %iftype% and related
conditionals can be used to customise the list text according to the values of
the missing parts.
Supported list texts
--------------------
The following list texts are supported. The compatibility filename (DEPRECATED)
is given in brackets. Those with asterisks (*) are not yet used.
- help (listhelp)
sent in response to an email to listname+help@domain.tld
- faq (listfaq)
sent in response to an email to listname+faq@domain.tld
- confirm-sub-{request|admin}-normal (sub-confirm)
- confirm-sub-{request|admin}-digest (sub-confirm-digest)
- confirm-sub-{request|admin}-nomail (sub-confirm-nomail)
- confirm-unsub-{request|admin}-normal (unsub-confirm)
- confirm-unsub-{request|admin}-digest (unsub-confirm-digest)
- confirm-unsub-{request|admin}-nomail (unsub-confirm-nomail)
sent to a requester to allow them to confirm a (un-)subscription request
- moderate-post-{modnonsubposts|access|moderated} (moderation)
sent to the appropriate moderators when moderation is required because a user
has submitted a post
- gatekeep-sub-{request|admin|confirm}-{normal|digest|nomail} (submod-moderator)
sent to the appropriate gatekeepers when gatekeeping is required because a
subscription request has been received
- wait-post-{modnonsubposts|access|moderated} (moderation-poster)
sent to a person submitting a post when they need to wait for moderation
before it is released to the list
- wait-sub-{request|admin|confirm}-{normal|digest|nomail} (submod-requester)
sent to a person requesting subscription when they need to wait for
gatekeeping for permission to join
- deny-sub-disabled-{digest|both} (sub-deny-digest)
- deny-sub-disabled-nomail (sub-deny-nomail)
- deny-sub-subbed-{normal|digest|nomail|both} (sub-subscribed)
- deny-sub-closed *
- deny-sub-expired *
- deny-sub-obstruct *
- deny-unsub-unsubbed-{normal|digest|nomail|all} (unsub-notsubscribed)
- deny-post-subonlypost (subonlypost)
- deny-post-access (access)
- deny-post-maxmailsize (maxmailsize)
- deny-post-tocc (notintocc)
- deny-post-expired *
- deny-post-reject *
- deny-release-notfound *
- deny-release-moderators *
- deny-reject-notfound *
- deny-reject-moderators *
- deny-permit-notfound *
- deny-permit-gatekeepers *
- deny-obstruct-notfound *
- deny-obstruct-gatekeepers *
sent to the requestor when an action is denied or fails for some reason
('requestor' here means the person who requested the action, so e.g. for a
reject action, deny-reject will go to the moderator requesting the rejection
if the rejection fails; but deny-post-reject will go to the person requesting
the post if the rejection succeeds, causing the post to fail)
- finish-sub-{request|confirm|admin|permit|switch}-normal (sub-ok)
- finish-sub-{request|confirm|admin|permit|switch}-digest (sub-ok-digest)
- finish-sub-{request|confirm|admin|permit|switch}-nomail (sub-ok-nomail)
- finish-unsub-{request|confirm|admin}-normal (unsub-ok)
- finish-unsub-{request|confirm|admin}-digest (unsub-ok-digest)
- finish-unsub-{request|confirm|admin}-nomail (unsub-ok-nomail)
- finish-post-request *
- finish-post-confirm *
- finish-post-release *
- finish-release *
- finish-reject *
- finish-permit *
- finish-obstruct *
sent to the requestor when an action completes successfully
('requestor' here means the person who requested the action, so e.g. for a
release action, the moderator requesting the release will receive
finish-release, and the person who submitted the released post will receive
finish-post-release because the release action caused their post action to
succeed)
- notify-sub-{request|confirm|admin|permit}-normal (notifysub)
- notify-sub-{request|confirm|admin|permit}-digest (notifysub-digest)
- notify-sub-{request|confirm|admin|permit}-nomail (notifysub-nomail)
- notify-unsub-{request|confirm|admin|bouncing}-normal (notifyunsub)
- notify-unsub-{request|confirm|admin|bouncing}-digest (notifyunsub-digest)
- notify-unsub-{request|confirm|admin|bouncing}-nomail (notifyunsub-nomail)
sent to the list owner when somebody is (un-)subscribed
- digest
sent at the start of a digest (NOTE: the only header supported in this list
text so far is a single-line 'Subject:' header; however, the contents of
control/customheaders is included when digests are sent)
- probe (bounce-probe)
sent to a subscriber after an email to them bounced to inform them of the
bounce and probe when the address is no longer bouncing
- list---all (listsubs)
- list---normal *
- list---digest *
- list---nomail *
sent in response to an email to listname+list@domain.tld from the list owner
(DEPRECATED: if none of %listsubs%, %digestsubs% and %nomailsubs% is
encountered in the text, then they will be automatically added with some
default formatting; this functionality is expected to be removed in the
future)
* Not yet used.
Format
------
List texts have the following format:
- Headers
- Blank line
- Body
They are expected to be in UTF-8 encoding and have Unix line endings.
The headers should be formatted as they should appear in the mail message. They
will begin the mail message. Header continuation via lines beginning with
linear whitespace is supported.
Following the headers found in the list text, Mlmmj will output the following
default headers, unless the same header is already provided in the list text.
- From:
- To:
- Message-ID:
- Date:
- Subject: mlmmj administrivia
- MIME-Version: 1.0
- Content-Type: text/plain; charset=utf-8
- Content-Transfer-Encoding: 8bit
The Subject: header is treated specially: it may include UTF-8 characters,
which will automatically be escaped using the =?utf-8?q?...?= quoting
mechanism.
(NOTE: the 'digest' list text is a bit different. See its description above.)
Both headers and bodies of list texts may include conditionals, formatting
directives and substitutions. These are explained in the following sections.
Conditionals
------------
Conditionals allow text in list texts to be included or omitted based on
conditions. The following are available:
- %ifaction A ...%
the action is one of those given
- %ifreason R ...%
the reason is one of those given
- %iftype T ...%
the type is one of those given
- %ifcontrol C ...%
one of the given control files exists
- %ifnaction A%
the action is not the one given
- %ifnreason R%
the reason is not the one given
- %ifntype T%
the type is not the one given
- %ifncontrol C ...%
at least one of the given control files does not exist
The text after the %if...% directive is only included if the condition is
satisfied, until an %else% or %endif% is encountered. These behave as you
would expect. The %else% is optional.
If a line with any of these conditional directives (%if...%, %else% or
%endif%), after processing, contains only whitespace, the line does not appear
at all in the output (the newline and any whitespace is omitted).
Furthermore, if the preceding processed output ends with a blank line, when an
unsatisfied conditional is encountered which has no %else% part, that
preceding blank line is removed (unless it is the blank line that ends the
headers).
On the whole, this is what you would want and expect, so you probably don't
need to worry about it.
Note that when multiple parameters can be given for the directives, these have
'or' behaviour; to get 'and' behaviour, nest conditionals.
Wrapping
--------
There are various directives available to assist with wrapping and formatting.
Wrapping needs to be enabled for each paragraph with:
- %wrap%
- %wrap W%
concatenate and rewrap lines until the next empty line, whitespace-only line,
or %nowrap% directive to a width of W (or 76 if W is omitted); second and
later lines are preceded with as many spaces as the width preceding the
directive; the width is reckoned including any text preceding the directive
and any indentation preserved from a file which included the current one, so
it is an absolute maximum width
To turn off wrapping before the end of a paragraph, use:
- %nowrap%
stop wrapping; usually placed at the end of a line so the following line
break is honoured but all preceding text is properly wrapped; if you want
wrapping to continue after the break, you need to use %wrap% to turn it on
again on the following line
To cater for various languages, there are a number of different wrapping modes
that can be set. These can be set either before or after wrapping is specified,
and can even be changed part way through a paragraph if desired. The following
directives control them:
- %wordwrap%
- %ww%
use word-wrapping (this is the default; good for English, French, Greek and
other languages that use an alphabet and spaces between words); lines have
whitespace trimmed from both ends and are joined with a single space; lines
are broken at spaces or at points marked for breaking with \/, but not at
spaces escaped with a backslash
- %charwrap%
- %cw%
use character-wrapping (good for Chinese, Japanese and Korean which use
characters without spaces between words); lines have only leading whitespace
trimmed and are joined without inserting anything at the joint; lines are
broken at space or any non-ASCII character except where disallowed with \=
- %userwrap%
- %uw%
use user-wrapping (for more complex languages or wherever complete manual
control is desired); lines have only leading whitespace trimmed and are
joined without inserting anything at the joint; lines are broken only where
marked for breaking with \/
- %thin%
assume non-ASCII characters are thin (equivalent to one unit, the same as
ASCII characters) when reckoning the width for wrapping (this is the default;
good for languages like Greek which use a non-Latin alphabet)
- %wide%
assume non-ASCII characters are wide (equivalent to two units, twice as wide
as ASCII characters) when reckoning the width for wrapping (good for Chinese,
Japanese, Korean)
- %zero ABC%
(ABC represents a sequence of non-ASCII characters)
treat the listed characters as having zero-width when reckoning the width for
wrapping (useful for ignoring combining characters such as accents so they
don't affect the width calculation); usefully, the listed characters can be
represented as unicode escapes (\uNNNN)
If a line with any of the directives in this section, after processing,
contains only whitespace, the line does not appear at all in the output (the
newline and any whitespace is omitted).
Formatting and comments
-----------------------
The following directives are available to assist with formatting and
readability:
- %^%
start the line here; anything preceding this directive is ignored (useful for
using indentation for readability without ruining the formatting of the text
when it is processed)
- %comment%
- %$%
end the line here; anything following this directive is ignored/a comment
If a line with any of these directives, after processing, contains only
whitespace, the line does not appear at all in the output (the newline and any
whitespace is omitted).
Formatted substitutions
-----------------------
These formatted substitutions work with multiple lines, so are generally not
appropriate for use in headers. They are:
- %text T%
text from the file named T in the listdir/text directory; the name may only
include letters, digits, underscore, dot and hyphen, and may not start with a
dot; note that there is an unformatted version of this directive
- %control C%
the contents of the control file named C in listir/control; the name may only
include letters, digits, underscore, dot and hyphen, and may not start with a
dot; note that there is an unformatted version of this directive
- %originalmail%
- %originalmail N%
(available only in moderate-post-*, wait-post-* and
deny-post-{access|maxmailsize|tocc|subonlypost})
the email message being processed (usually a mail being moderated); N
represents a number, which is how many lines of the message (including
headers) to include: if omitted, the whole message will be included
- %digestthreads%
(available only in digest)
the list of threads included in the digest
- %gatekeepers%
(available only in gatekeep-sub and wait-sub)
the list of moderators to whom the moderation request has been sent
- %listsubs%
(available only in list---*)
the list of normal subscribers
- %digestsubs%
(available only in list---*)
the list of digest subscribers
- %nomailsubs%
(available only in list---*)
the list of nomail subscribers
- %moderators%
(available only in moderate-post-* and wait-post-*)
the list of moderators to whom the moderation request has been sent
- %bouncenumbers%
(available only in probe)
the list of indexes of messages which may not have been received as they
bounced
Directives which include a list of items have the behaviour that each item is
preceded and followed by the same text as preceded and followed the directive
on its line; only one such directive is supported per line. Those which include
a block of text have the behaviour that second and later lines are preceded
with as many spaces as there were bytes preceding the directive; any text
following such directives on the same line is omitted.
If a line with any of these directives, after processing, contains only
whitespace, the line does not appear at all in the output (the newline and any
whitespace is omitted).
Unformatted substitutions
-------------------------
Unformatted substitutions that are available are:
- $bouncenumbers$
(available only in probe)
the formatted list of indexes of messages which may not have been received as
they bounced
DEPRECATED: use %bouncenumbers%
- $confaddr$
- $confirmaddr$
(available only in confirm-[un]sub-*)
the address to which to send mail to confirm the (un-)subscription in
question
NOTE: the short version of this substitution is DEPRECATED
- $control C$
the contents of the control file named C in listdir/control, with its final
newline stripped; the name may only include letters, digits, underscore, dot
and hyphen, and may not start with a dot; note that there is a formatted
version of this directive
- $digestfirst$
(available only in digest)
index of the first message included in a digest
- $digestinterval$
(available only in digest)
indexes of the first and last messages included in a digest (e.g. 1-5), or
just the index if only a single message is included
- $digestissue$
(available only in digest)
the issue number of the digest
- $digestlast$
(available only in digest)
index of the last message included in a digest
- $digestsubaddr$
listname+subscribe-digest@domain.tld
DEPRECATED: use $list+$subscribe-digest@$domain$ instead
- $digestthreads$
(available only in digest)
the formatted list of threads included in the digest
DEPRECATED: use %digestthreads%
- $digestunsubaddr$
listname+unsubscribe-digest@domain.tld
DEPRECATED: use $list+$unsubscribe-digest@$domain$ instead
- $domain$
domain.tld
- $faqaddr$
listname+faq@domain.tld
DEPRECATED: use $list+$faq@$domain$ instead
- $helpaddr$
listname+help@domain.tld
DEPRECATED: use $list+$help@$domain$ instead
- $list$
listname
- $list+$
listname+
- $listaddr$
listname@domain.tld
DEPRECATED: use $list$@$domain$ instead
- $listgetN$
listname+get-N@domain.tld
(the N here is nothing special, so this won't actually work, but is used to
explain to users how to use the +get functionality)
DEPRECATED: use $list+$get-N@$domain$ instead
- $listowner$
listname+owner@domain.tld
DEPRECATED: use $list+$owner@$domain$ instead
- $listsubaddr$
listname+subscribe@domain.tld
DEPRECATED: use $list+$subscribe@$domain$ instead
- $listunsubaddr$
listname+unsubscribe@domain.tld
DEPRECATED: use $list+$unsubscribe@$domain$ instead
- $maxmailsize$
(available only in deny-post-maxmailsize)
the maximum size of mail that Mlmmj will accept
- $moderateaddr$
(available only in moderate-post-* and gatekeep-sub)
the address to which to send mail to approve the post or subscription in
question
DEPRECATED: use $releaseaddr$ or $permitaddr$ instead
- $moderators$
(available only in moderate-post-*, wait-post-*, gatekeep-sub and wait-sub)
the formatted list of moderators to whom the moderation request has been sent
DEPRECATED: use %moderators% or %gatekeepers% instead
- $newsub$
(available only in notify-sub-*-*)
the address that has been subscribed
DEPRECATED: use $subaddr$ instead
- $nomailsubaddr$
listname+subscribe-nomail@domain.tld
DEPRECATED: use $list+$subscribe-nomail@$domain$ instead
- $nomailunsubaddr$
listname+unsubscribe-nomail@domain.tld
DEPRECATED: use $list+$unsubscribe-nomail@$domain$ instead
- $oldsub$
(available only in notify-sub-*-*)
the address that has been unsubscribed
DEPRECATED: use $subaddr$ instead
- $originalmail$
the same as %originalmail 100% preceded by a space
DEPRECATED: use %originalmail%
- $permitaddr$
(available only in gatekeep-sub)
the address to which to send mail to permit the subscription in question
- $posteraddr$
(available only in deny-post-{access|tocc|subonlypost|maxmailsize},
moderate-post-* and wait-post-*)
the from address of the message that was received as determined by Mlmmj
- $random0$
- $random1$
- $random2$
- $random3$
- $random4$
- $random5$
these are 6 distinct random strings; they allow list texts to be constructed
that are MIME messages with attachments by creating boundaries that are
unlikely to appear in the attached messages
- $releaseaddr$
(available only in moderate-post-*)
the address to which to send mail to release the post in question
- $subaddr$
(available only in gatekeep-sub, confirm-[un]sub-*, finish-[un]sub-*,
notify-[un]sub-* and deny-[un]sub-*)
the address requested to be (un-)subscribed
- $subject$
(available only in deny-post-{access|tocc|subonlypost|maxmailsize},
moderate-post-* and wait-post-*)
the subject line of the message in question
- $text T$
text from the file named T in the listdir/text directory, with its final
newline stripped; the name may only include letters, digits, underscore, dot
and hyphen, and may not start with a dot; note that there is a formatted
version of this directive
Escapes
-------
These allow you to avoid special meanings of characters used for other purposes
in list texts, as well as control the construction of the texts at a fairly low
level.
- $$
a single $
- %%
a single %
- \\
a single \
- \uNNNN
(NNNN represents four hex digits)
a Unicode character
(this is not really appropriate for use in a header, except perhaps the
Subject: header as Mlmmj does automatic quoting for that header as described
above)
- \<space>
a space, but don't allow the line to be broken here when wrapping
- \/
nothing, but allow the line to be broken here when wrapping
- \=
nothing, but don't allow the line to be broken here when wrapping