• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

contrib/H24-May-2017-10,4367,441

include/H03-May-2022-1,414388

listtexts/H24-May-2017-6,9265,680

man/H02-Oct-2016-466422

src/H03-May-2022-14,69311,596

AUTHORSH A D03-May-2012120 43

COPYINGH A D06-Jul-20101.1 KiB2318

ChangeLogH A D24-May-201728 KiB580579

FAQH A D06-Jul-2010639 119

LICENSEH A D06-Jul-20101.1 KiB2318

Makefile.amH A D02-Oct-2016574 1510

Makefile.inH A D24-May-201727.2 KiB855758

READMEH A D24-May-20175.6 KiB153111

README.accessH A D27-Mar-20123.7 KiB10477

README.archivesH A D27-Mar-2012702 3218

README.exim4H A D13-Mar-20123.6 KiB11982

README.footersH A D02-Oct-20161.6 KiB4832

README.listtextsH A D02-Oct-201620.7 KiB623486

README.postfixH A D27-Mar-20128.2 KiB190137

README.qmailH A D13-Mar-20122.8 KiB6552

README.securityH A D06-Jul-2010617 1914

README.sendmailH A D13-Mar-20123.6 KiB9761

TODOH A D10-Jul-2010356 118

TUNABLESH A D02-Oct-20169 KiB261171

UPGRADEH A D29-May-20121.9 KiB4734

VERSIONH A D24-May-20176 21

aclocal.m4H A D24-May-201742.1 KiB1,1821,072

compileH A D24-May-20177.2 KiB348258

config.h.inH A D24-May-20173.5 KiB13892

configureH A D24-May-2017175.4 KiB6,1125,039

configure.acH A D24-May-20171.6 KiB5543

depcompH A D24-May-201723 KiB792502

install-shH A D24-May-201714.3 KiB502327

missingH A D24-May-20176.7 KiB216143

README

1README mlmmj-1.3.0                                                 May 25, 2017
2
3This is an attempt at implementing a mailing list manager with the same
4functionality as the brilliant ezmlm, but with a decent license and mail server
5independence.
6
7The functionality:
8
9 · Archive
10 · Custom headers / footer
11 · Fully automated bounce handling (similar to ezmlm)
12 · Complete requeueing functionality
13 · Moderation functionality
14 · Subject prefix
15 · Subscribers only posting
16 · Regular expression access control
17 · Functionality to retrieve old posts
18 · Web interface
19 · Digests
20 · No-mail subscription
21 · VERP support
22 · Delivery Status Notification (RFC1891) support
23 · Rich, customisable texts for automated operations
24
25To use mlmmj, do the following:
26
27 0) Compile it if you're not using a binary package such as dpkg, rpm or
28    a ports collection from a BSD or Gentoo. To compile, untar the tar-ball
29    and do:
30
31    $ ./configure && make && make install
32
33		If you want to filter multipart/mime messages, pass the option
34		--enable-receive-strip to configure, and take a look at
35		contrib/receivestrip/README.
36
37 1) Configure a recipient delimiter. The default is to use '+', and in
38    Postfix it's done by adding
39
40        recipient_delimiter = +
41
42    to /etc/postfix/main.cf. In Exim it can be done by adding
43
44        local_part_suffix = +*
45	local_part_suffix_optional
46
47    to the "userforward:" and the "localuser:" router in /etc/exim/exim.conf,
48    and also add "local_part_suffix = +*" to the system_aliases function. Also
49    make sure that exim will add the envelope from in the Return-Path: header.
50
51    There is a nice FAQ explaining recipient delimiter configuration here:
52
53    http://faqs.org/faqs/mail/addressing/
54
55    The mlmmj TUNABLE "delimiter" configures this on a per list basis
56
57    NOTE: Using '-' as a delimiter is unlikely to work. Mlmmj uses '-' as its
58    own kind of minor delimiter. Of course, you also cannot use the delimiter
59    in your list names or you will encounter problems.
60
61 2) Create the mailinglist.  There's a script, mlmmj-make-ml, that will make
62    a mailinglist for mlmmj. It is highly recommended to use this script to make
63    the lists! What is does is described here:
64
65    In the case of a list called mlmmj-test below /var/spool/mlmmj it makes the
66    following directories:
67
68    /var/spool/mlmmj/mlmmj-test/incoming
69    /var/spool/mlmmj/mlmmj-test/queue
70    /var/spool/mlmmj/mlmmj-test/queue/discarded
71    /var/spool/mlmmj/mlmmj-test/archive
72    /var/spool/mlmmj/mlmmj-test/text
73    /var/spool/mlmmj/mlmmj-test/subconf
74    /var/spool/mlmmj/mlmmj-test/unsubconf
75    /var/spool/mlmmj/mlmmj-test/bounce
76    /var/spool/mlmmj/mlmmj-test/control
77    /var/spool/mlmmj/mlmmj-test/moderation
78    /var/spool/mlmmj/mlmmj-test/subscribers.d
79    /var/spool/mlmmj/mlmmj-test/digesters.d
80    /var/spool/mlmmj/mlmmj-test/nomailsubs.d
81    /var/spool/mlmmj/mlmmj-test/requeue
82
83    NOTE: The mailinglist directory (/var/spool/mlmmj/mlmmj-test in our
84    example) have to be owned by the user the mailserver writes as. On some
85    Postfix installations Postfix is run by the user postfix, but still writes
86    files as nobody:nogroup or nobody:nobody
87
88 3) Make the changes to your mailserver aliases that came as output from
89    mlmmj-make-ml. Following the example above they will look like this:
90
91    mlmmj-test:     "|/usr/bin/mlmmj-receive -L /var/spool/mlmmj/mlmmj-test"
92
93    NOTE: Don't forget newaliases.
94
95 4) Start mlmmj-maintd (remember full path when starting it!) or add it to
96    crontab with -F switch. The recommended way for now is to run it via cron:
97
98    "0 */2 * * *  /usr/bin/mlmmj-maintd -F -L /var/spool/mlmmj/mlmmj-test"
99
100    It should be started as root, as mlmmj-maintd will become the user owning
101    the listdir (/var/spool/mlmmj/mlmmj-test), and log it's last maintenance
102    run to listdir/mlmmj-maintd.lastrun.log.
103
104    If you have several lists below /var/spool/mlmmj you can use -d:
105    /usr/bin/mlmmj-maintd -F -d /var/spool/mlmmj
106
107    If you have lists more deeply nested below /var/spool/mlmmj, use
108    something like:
109    find /var/spool/mlmmj -mindepth 1 -maxdepth 1 -type d \
110        -exec /usr/bin/mlmmj-maintd -F -d {} \;
111
112That's it! You probably want to go through the next steps too.
113
114 5) Subscribe some people
115
116    /usr/bin/mlmmj-sub -L /var/spool/mlmmj/mlmmj-test/ -a joe@domain.tld
117
118    etc.
119
120 6) If you want custom headers like X-Mailinglist, Reply-To: etc. just add a
121    file called 'customheaders' in the list control/ directory like this:
122    $ cat /var/spool/mlmmj/mlmmj-test/control/customheaders
123    X-Mailinglist: mlmmj-test
124    Reply-To: mlmmj-test@domain.tld
125
126 7) If you want every mail to have something like:
127    --
128    To unsubscribe send a mail to coollist+unsubscribe@lists.domain.net
129
130    Just add what you want to a file named "footer" in the same dir as
131    "customheaders" (listdir/control/).
132
133 8) If you want a prefix on the subject, to make it look like this:
134    Subject: [mlmmj-test] how are we doing?
135    Simply do 'echo "[mlmmj-test]" > control/prefix
136
137 9) For having a moderated list, simply create a file called 'moderated' in the
138    control/ directory. Moderators are added to a file called 'moderators' in
139    the control/ dir as well.
140
14110) Have a look at the file TUNABLES for runtime configurable things.
142
143Tunables in include/mlmmj.h:
144 · There's some time intervals for how mlmmj-maintd operates. I've chosen
145   non-strict defaults, so depending on your BOFH rate you might want to tweak.
146   The defaults should be good for most people though.
147
148Have fun!
149
150	Mads Martin Joergensen <mmj at mmj dot dk>
151	Morten K. Poulsen <morten at afdelingp dot dk>
152	Ben Schmidt <mail_ben_schmidt at yahoo dot com dot au>
153

README.access

1README.access                           present in mlmmj versions >= 0.8.0
2                                        (moderate tag since 1.1.0-RC3)
3Access control in mlmmj
4=======================
5
6If the file listdir/control/access is present, access control is enabled.
7
8NOTE: the default action is to deny access (reject the mail), so an empty
9access control file will cause mlmmj to reject all posts, whereas a non-
10existant file will change nothing, and mlmmj will behave as usual.
11
12Each header in the mail is tested against each rule, rule by rule. That is,
13all headers are first tested against the first rule, then all headers are
14tested against the second rule, and so on.
15
16The first rule to match a header decides which action to take - allow, deny,
17discard or moderate the post.
18
19The syntax is quite simple: action[ [!]regexp]
20- "Action" can be "allow", "send", "deny", "discard" or "moderate".
21- The optional "!" makes the rule a match, if NO header matches the regular
22  expression.
23- "Regexp" is a POSIX.2 extended regular expression. Matching is done case
24  insensitive.
25
26The action "allow" will pass the mail on to the next step in processing. The
27mail may still be held for moderation, if it would have been so without access
28rules.
29
30The action "send" will send the mail unconditionally. It will not be
31moderated, nor subject to subonlypost, nor modnonsubposts.
32
33The action "deny" will not send the mail to the mailing list, but will send a
34rejection mail to the sender.
35
36The action "discard" will not send the mail to the list, and will not send a
37rejection mail.
38
39The action "moderate" will hold the mail for moderation.
40
41IMPORTANT: if "moderate" is used then don't forget to add people who should
42           function as moderators in listdir/control/moderators
43
44
45The flow through the access system is something like this:
46
47               deny       +------+
48       +----------------->| deny |
49       |                  +------+
50       |
51       |       discard    +---------+
52       |  +-------------->| discard |
53       |  |               +---------+
54       |  |                   ^
55       |  |                   | expire
56    +--------+ moderate   +------+           +------+
57--->| access |----------->| hold |---------->| send |--->
58    +--------+            +------+ confirm   +------+
59       |  |                   ^                ^  ^
60       |  |                   | yes            |  |
61       |  |    allow      +--------------+ no  |  |
62       |  +-------------->| moderation * |-----+  |
63       |                  +--------------+        |
64       |       send                               |
65       +------------------------------------------+
66
67* modnonsubposts is also processed here, and subonlypost (the flow
68  may be to deny or discard for subonlypost without modnonsubposts).
69
70
71First a simple example. This rule set will reject any mail that is NOT plain
72text, or has a subject that contains "BayStar", and allow anything else:
73
74 deny !^Content-Type: text/plain
75 deny ^Subject:.*BayStar
76 allow
77
78To allow only text mails, but have the moderators moderate every html mail one
79would use this:
80
81 allow ^Content-Type: text/plain
82 moderate ^Content-Type: text/html
83 deny
84
85Now on to a more advanced example. Morten can post anything, Mads Martin can
86post if the subject does not contain "SCO". Everything else is denied:
87
88 allow ^From: Morten
89 deny ^Subject:.*SCO
90 allow ^From: Mads Martin
91 deny
92
93The last rule (deny) can be left out, as deny is the default action.
94
95A third example. Deny any mails with "discount", "weightloss", or "bonus" in
96the subject. Allow PGP signed and plain text mails. Anything else is denied:
97
98 deny ^Subject:.*discount
99 deny ^Subject:.*weightloss
100 deny ^Subject:.*bonus
101 allow ^Content-Type: multipart/signed
102 allow ^Content-Type: text/plain
103
104

README.archives

1README.archives
2
3Generating web-browseable archives of Mlmmj lists
4=================================================
5
6There are a couple of options for making web-browseable archives of Mlmmj
7lists.
8
9mlmmj-webarchiver (mhonarc)
10---------------------------
11
12Andreas Schneider has created mlmmj-webarchiver, based on mhonarc and perl.
13
14You can get it here:
15
16http://git.cryptomilk.org/projects/mlmmj-webarchiver.git/
17
18And see the kind of output it gives here:
19
20http://www.libssh.org/archive/
21
22hypermail
23---------
24
25Wolf Bergenheim has written some scripts which use hypermail to create
26web-browseable archives.
27
28The scripts and details can be found here:
29
30http://mlmmj.org/archive/mlmmj/2010-08/1710.html
31
32

README.exim4

1
2README.exim4                                                      May 7th 2005
3
4
5This is a step-by-step guide to run mlmmj with Exim4. The most current version
6of this can be found on http://plonk.de/sw/mlmmj/README.exim4.
7
8
9
10Notes:
11- We assume that you have a user and group called mlmmj to use with mlmmj
12- The exim user needs rx access rights to mlmmj's spool directory. (If you
13  don't want that, see below.) The easiest way is
14  "chmod 755 /path/to/mlmmj/spool", if it's ok that local users can see which
15  lists there are.
16  Note that the owner of the mlmmj spool must still be the mlmmj user (and
17  this user must have at least x rights to the directories below).
18- Existence of mailing lists is automatically checked ($listdir) and you
19  don't need to put anything into your aliases file
20- If you want VERP to be done by your MTA, follow the instructions below and
21  put an empty file named verp into the control directory of your lists
22
23
241. In the main configuration section:
25
26MLMMJ_HOME=/var/spool/mlmmj
27domainlist mlmmj_domains = list.example.net
28
29
302. Add +mlmmj_domains to relay_to_domains:
31
32domainlist relay_to_domains = other.domain : +mlmmj_domains
33
34
353. mlmmj is barely interested in delay warnings, so add this in the main
36configuration:
37
38delay_warning_condition = ${if match_domain{$domain}{+mlmmj_domains}{no}{yes}}
39
40
414. In the routers section (before the dnslookup router, preferably at the
42beginning):
43
44mlmmj_router:
45  driver = accept
46  domains = +mlmmj_domains
47  require_files = MLMMJ_HOME/${lc::$local_part}
48  # Use this instead, if you don't want to give Exim rx rights to mlmmj spool.
49  # Exim will then spawn a new process running under the UID of "mlmmj".
50  #require_files = mlmmj:MLMMJ_HOME/${lc::$local_part}
51  local_part_suffix = +*
52  local_part_suffix_optional
53  headers_remove = Delivered-To
54  headers_add = Delivered-To: $local_part$local_part_suffix@$domain
55  transport = mlmmj_transport
56
57
58If you want VERP to be done by your MTA, also add this:
59
60verp_router:
61  driver = dnslookup
62  domains = !+mlmmj_domains
63  # we only consider messages sent in through loopback
64  condition = ${if eq{$sender_host_address}{127.0.0.1}{yes}{no}}
65  ignore_target_hosts = <; 0.0.0.0; 127.0.0.0/8; ::1/128; fe80::/10; ff00::/8
66  # only the un-VERPed bounce addresses are handled
67  senders = \N^.+\+bounces-\d+@.+\N
68  transport = verp_smtp
69
70
71To prevent temporary errors for not-existing lists, add !+mlmmj_domains to the
72domains condition of the dnslookup router:
73
74dnslookup:
75  driver = dnslookup
76  domains = !+mlmmj_domains : !+local_domains
77[...]
78
795. Somewhere in the transports section. (Change the path of mlmmj-receive if you
80don't use the default location!):
81
82mlmmj_transport:
83  driver = pipe
84  return_path_add
85  user = mlmmj
86  group = mlmmj
87  home_directory = MLMMJ_HOME
88  current_directory = MLMMJ_HOME
89  command = /usr/local/bin/mlmmj-receive -F -L MLMMJ_HOME/${lc:$local_part}
90
91If you want VERP to be done by your MTA, also add this:
92
93verp_smtp:
94  driver = smtp
95  # put recipient address into return_path
96  return_path = ${quote_local_part:${local_part:$return_path}}-\
97                ${original_local_part}=${original_domain}@\
98                ${domain:$return_path}
99  # must restrict to one recipient at a time
100  max_rcpt = 1
101  # Errors-To: may carry old return_path
102  headers_remove = Errors-To
103  headers_add = Errors-To: $return_path
104
105
1066. Test your setup with
107
108$ exim -bt mlmmj-test@your.list.domain
109mlmmj-test@your.list.domain
110  router = mlmmj_router, transport = mlmmj_transport
111
112If you get different output, run it with -d to see what's going wrong.
113If not, you're done!
114
115
116
117	Jakob Hirsch (jh at plonk dot de)
118
119

README.footers

1README.footers
2
3Footers in Mlmmj
4================
5
6Mlmmj's built-in footer support is very rudimentary. It will work for plain
7text emails, and that's about it. It doesn't understand HTML or MIME or
8anything like that.
9
10There are a few solutions to this. They all involve piping incoming mail
11through a filter before it reaches Mlmmj. A script to do this, called
12mlmmj-amime-receive, is included in amime-receive in the contrib directory.
13
14It can be used with a number of different pre-processors. One day we also hope
15to improve the integration of these external filters with Mlmmj, e.g. so only
16list posts are processed. However, the piping solution has worked for a number
17of people over the years quite satisfactorily, so this is not a high priority.
18
19Here are some pre-processors you can use.
20
21alterMIME
22---------
23
24The mlmmj-amime-receive script is designed to work with a program called
25alterMIME. The script itself (in amime-receive in the contrib directory)
26contains links to that software, and instructions.
27
28Foot Filter
29-----------
30
31alterMIME didn't allow me to reach my particular goals, so I wrote an
32alternative called Foot Filter. It is a single source-file C program; the code
33and a very simple Makefile can be found in foot_filter in the contrib
34directory, along with an altered version of mlmmj-amime-receive, called
35mlmmj-recieve-ff.
36
37Foot Filter will output documentation if you run it without arguments, and
38again, instructions for the script that handles the piping are found within it.
39
40Py-MIME
41-------
42
43A third option is Py-MIME. It was developed for use at The Document Foundation
44(LibreOffice) and is included in pymime in the contrib directory.
45
46
47
48

README.listtexts

1README.listtexts
2
3List texts in Mlmmj
4===================
5
6List texts are stored in listdir/text and subdirectories of
7prefix/share/mlmmj/text.skel. They specify the content of various automatic
8emails that Mlmmj sends. They are provided in a number of different languages.
9The language to use for a list is chosen when you run the mlmmj-make-ml script
10and the appropriate files are copied into your listdir/text directory.
11
12This file documents the following aspects of list texts:
13
14- Naming scheme
15- Supported list texts
16- Format
17- Conditionals
18- Wrapping
19- Formatting and comments
20- Formatted substitutions
21- Unformatted substitutions
22- Escapes
23
24Naming scheme
25-------------
26
27List texts are named following a scheme of:
28
29  purpose-action-reason-type
30
31Mlmmj will look for the full four-part name first, then for files with shorter
32names obtained by dropping parts off the end, and finally for a file with a
33compatibility filename. It will use the first one it finds. (Note that use of
34the compatibility filename is DEPRECATED and will be removed in a future
35release.)
36
37So, the complete search order is:
38
39- purpose-action-reason-type
40- purpose-action-reason
41- purpose-action
42- purpose
43- compatibility filename (DEPRECATED)
44
45When using shortened names, the %ifaction%, %ifreason%, %iftype% and related
46conditionals can be used to customise the list text according to the values of
47the missing parts.
48
49Mlmmj checks these three paths for each candidate filename, and then moves on
50to the next candidate filename:
51
52- listdir/text
53- prefix/share/mlmmj/text.skel/default
54- prefix/share/mlmmj/text.skel/en
55
56The second path does not exist by default, but can be created by copying or
57symlinking the language of your choice to that path.
58
59Note that this search order means that if there is a more specific list text in
60a system directory, it will override a less-specific or compatibility list text
61in the listdir. This may be surprising, and may change in a future version, so
62should not be relied upon. Best practice is to ensure each list has its own
63copy of all textx present in system directories, or none of them.
64
65Supported list texts
66--------------------
67
68The following list texts are supported. The compatibility filename (DEPRECATED)
69is given in brackets. Those with asterisks (*) are not yet used.
70
71- help (listhelp)
72  sent in response to an email to listname+help@domain.tld
73
74- faq (listfaq)
75  sent in response to an email to listname+faq@domain.tld
76
77- confirm-sub-{request|admin}-normal (sub-confirm)
78- confirm-sub-{request|admin}-digest (sub-confirm-digest)
79- confirm-sub-{request|admin}-nomail (sub-confirm-nomail)
80- confirm-unsub-{request|admin}-normal (unsub-confirm)
81- confirm-unsub-{request|admin}-digest (unsub-confirm-digest)
82- confirm-unsub-{request|admin}-nomail (unsub-confirm-nomail)
83  sent to a requester to allow them to confirm a (un-)subscription request
84
85- moderate-post-{modnonsubposts|access|moderated} (moderation)
86  sent to the appropriate moderators when moderation is required because a user
87  has submitted a post
88
89- gatekeep-sub-{request|admin|confirm}-{normal|digest|nomail} (submod-moderator)
90  sent to the appropriate gatekeepers when gatekeeping is required because a
91  subscription request has been received
92
93- wait-post-{modnonsubposts|access|moderated} (moderation-poster)
94  sent to a person submitting a post when they need to wait for moderation
95  before it is released to the list
96
97- wait-sub-{request|admin|confirm}-{normal|digest|nomail} (submod-requester)
98  sent to a person requesting subscription when they need to wait for
99  gatekeeping for permission to join
100
101- deny-sub-disabled-{digest|both} (sub-deny-digest)
102- deny-sub-disabled-nomail (sub-deny-nomail)
103- deny-sub-subbed-{normal|digest|nomail|both} (sub-subscribed)
104- deny-sub-closed *
105- deny-sub-expired *
106- deny-sub-obstruct *
107- deny-unsub-unsubbed-{normal|digest|nomail|all} (unsub-notsubscribed)
108- deny-post-subonlypost (subonlypost)
109- deny-post-modonlypost
110- deny-post-access (access)
111- deny-post-maxmailsize (maxmailsize)
112- deny-post-tocc (notintocc)
113- deny-post-expired *
114- deny-post-reject *
115- deny-release-notfound *
116- deny-release-moderators *
117- deny-reject-notfound *
118- deny-reject-moderators *
119- deny-permit-notfound *
120- deny-permit-gatekeepers *
121- deny-obstruct-notfound *
122- deny-obstruct-gatekeepers *
123  sent to the requestor when an action is denied or fails for some reason
124  ('requestor' here means the person who requested the action, so e.g. for a
125  reject action, deny-reject will go to the moderator requesting the rejection
126  if the rejection fails; but deny-post-reject will go to the person requesting
127  the post if the rejection succeeds, causing the post to fail)
128
129- finish-sub-{request|confirm|admin|permit|switch}-normal (sub-ok)
130- finish-sub-{request|confirm|admin|permit|switch}-digest (sub-ok-digest)
131- finish-sub-{request|confirm|admin|permit|switch}-nomail (sub-ok-nomail)
132- finish-unsub-{request|confirm|admin}-normal (unsub-ok)
133- finish-unsub-{request|confirm|admin}-digest (unsub-ok-digest)
134- finish-unsub-{request|confirm|admin}-nomail (unsub-ok-nomail)
135- finish-post-request *
136- finish-post-confirm *
137- finish-post-release *
138- finish-release *
139- finish-reject *
140- finish-permit *
141- finish-obstruct *
142  sent to the requestor when an action completes successfully
143  ('requestor' here means the person who requested the action, so e.g. for a
144  release action, the moderator requesting the release will receive
145  finish-release, and the person who submitted the released post will receive
146  finish-post-release because the release action caused their post action to
147  succeed)
148
149- notify-sub-{request|confirm|admin|permit}-normal (notifysub)
150- notify-sub-{request|confirm|admin|permit}-digest (notifysub-digest)
151- notify-sub-{request|confirm|admin|permit}-nomail (notifysub-nomail)
152- notify-unsub-{request|confirm|admin|bouncing}-normal (notifyunsub)
153- notify-unsub-{request|confirm|admin|bouncing}-digest (notifyunsub-digest)
154- notify-unsub-{request|confirm|admin|bouncing}-nomail (notifyunsub-nomail)
155  sent to the list owner when somebody is (un-)subscribed
156
157- digest
158  sent at the start of a digest (NOTE: the only header supported in this list
159  text so far is a single-line 'Subject:' header; however, the contents of
160  control/customheaders is included when digests are sent)
161
162- probe (bounce-probe)
163  sent to a subscriber after an email to them bounced to inform them of the
164  bounce and probe when the address is no longer bouncing
165
166- list---all (listsubs)
167- list---normal *
168- list---digest *
169- list---nomail *
170  sent in response to an email to listname+list@domain.tld from the list owner
171  (DEPRECATED: if none of %listsubs%, %digestsubs% and %nomailsubs% is
172  encountered in the text, then they will be automatically added with some
173  default formatting; this functionality is expected to be removed in the
174  future)
175
176* Not yet used.
177
178Format
179------
180
181List texts have the following format:
182
183- Headers
184- Blank line
185- Body
186
187They are expected to be in UTF-8 encoding and have Unix line endings.
188
189The headers should be formatted as they should appear in the mail message. They
190will begin the mail message. Header continuation via lines beginning with
191linear whitespace is supported.
192
193Following the headers found in the list text, Mlmmj will output the following
194default headers, unless the same header is already provided in the list text.
195
196- From:
197- To:
198- Message-ID:
199- Date:
200- Subject: mlmmj administrivia
201- MIME-Version: 1.0
202- Content-Type: text/plain; charset=utf-8
203- Content-Transfer-Encoding: 8bit
204
205The Subject: header is treated specially: it may include UTF-8 characters,
206which will automatically be escaped using the =?utf-8?q?...?= quoting
207mechanism.
208
209(NOTE: the 'digest' list text is a bit different. See its description above.)
210
211Both headers and bodies of list texts may include conditionals, formatting
212directives and substitutions. These are explained in the following sections.
213
214Conditionals
215------------
216
217Conditionals allow text in list texts to be included or omitted based on
218conditions. The following are available:
219
220- %ifaction A ...%
221  the action is one of those given
222
223- %ifreason R ...%
224  the reason is one of those given
225
226- %iftype T ...%
227  the type is one of those given
228
229- %ifcontrol C ...%
230  one of the given control files exists
231
232- %ifnaction A%
233  the action is not the one given
234
235- %ifnreason R%
236  the reason is not the one given
237
238- %ifntype T%
239  the type is not the one given
240
241- %ifncontrol C ...%
242  at least one of the given control files does not exist
243
244The text after the %if...% directive is only included if the condition is
245satisfied, until an %else% or %endif% is encountered. These behave as you
246would expect. The %else% is optional.
247
248If a line with any of these conditional directives (%if...%, %else% or
249%endif%), after processing, contains only whitespace, the line does not appear
250at all in the output (the newline and any whitespace is omitted).
251
252Furthermore, if the preceding processed output ends with a blank line, when an
253unsatisfied conditional is encountered which has no %else% part, that
254preceding blank line is removed (unless it is the blank line that ends the
255headers).
256
257On the whole, this is what you would want and expect, so you probably don't
258need to worry about it.
259
260Note that when multiple parameters can be given for the directives, these have
261'or' behaviour; to get 'and' behaviour, nest conditionals.
262
263Wrapping
264--------
265
266There are various directives available to assist with wrapping and formatting.
267Wrapping needs to be enabled for each paragraph with:
268
269- %wrap%
270- %wrap W%
271  concatenate and rewrap lines until the next empty line, whitespace-only line,
272  or %nowrap% directive to a width of W (or 76 if W is omitted); second and
273  later lines are preceded with as many spaces as the width preceding the
274  directive; the width is reckoned including any text preceding the directive
275  and any indentation preserved from a file which included the current one, so
276  it is an absolute maximum width
277
278To turn off wrapping before the end of a paragraph, use:
279
280- %nowrap%
281  stop wrapping; usually placed at the end of a line so the following line
282  break is honoured but all preceding text is properly wrapped; if you want
283  wrapping to continue after the break, you need to use %wrap% to turn it on
284  again on the following line
285
286To cater for various languages, there are a number of different wrapping modes
287that can be set. These can be set either before or after wrapping is specified,
288and can even be changed part way through a paragraph if desired. The following
289directives control them:
290
291- %wordwrap%
292- %ww%
293  use word-wrapping (this is the default; good for English, French, Greek and
294  other languages that use an alphabet and spaces between words); lines have
295  whitespace trimmed from both ends and are joined with a single space; lines
296  are broken at spaces or at points marked for breaking with \/, but not at
297  spaces escaped with a backslash
298
299- %charwrap%
300- %cw%
301  use character-wrapping (good for Chinese, Japanese and Korean which use
302  characters without spaces between words); lines have only leading whitespace
303  trimmed and are joined without inserting anything at the joint; lines are
304  broken at space or any non-ASCII character except where disallowed with \=
305
306- %userwrap%
307- %uw%
308  use user-wrapping (for more complex languages or wherever complete manual
309  control is desired); lines have only leading whitespace trimmed and are
310  joined without inserting anything at the joint; lines are broken only where
311  marked for breaking with \/
312
313- %thin%
314  assume non-ASCII characters are thin (equivalent to one unit, the same as
315  ASCII characters) when reckoning the width for wrapping (this is the default;
316  good for languages like Greek which use a non-Latin alphabet)
317
318- %wide%
319  assume non-ASCII characters are wide (equivalent to two units, twice as wide
320  as ASCII characters) when reckoning the width for wrapping (good for Chinese,
321  Japanese, Korean)
322
323- %zero ABC%
324  (ABC represents a sequence of non-ASCII characters)
325  treat the listed characters as having zero-width when reckoning the width for
326  wrapping (useful for ignoring combining characters such as accents so they
327  don't affect the width calculation); usefully, the listed characters can be
328  represented as unicode escapes (\uNNNN)
329
330If a line with any of the directives in this section, after processing,
331contains only whitespace, the line does not appear at all in the output (the
332newline and any whitespace is omitted).
333
334Formatting and comments
335-----------------------
336
337The following directives are available to assist with formatting and
338readability:
339
340- %^%
341  start the line here; anything preceding this directive is ignored (useful for
342  using indentation for readability without ruining the formatting of the text
343  when it is processed)
344
345- %comment%
346- %$%
347  end the line here; anything following this directive is ignored/a comment
348
349If a line with any of these directives, after processing, contains only
350whitespace, the line does not appear at all in the output (the newline and any
351whitespace is omitted).
352
353Formatted substitutions
354-----------------------
355
356These formatted substitutions work with multiple lines, so are generally not
357appropriate for use in headers. They are:
358
359- %text T%
360  text from the file named T in the listdir/text directory; the name may only
361  include letters, digits, underscore, dot and hyphen, and may not start with a
362  dot; note that there is an unformatted version of this directive
363
364- %control C%
365  the contents of the control file named C in listir/control; the name may only
366  include letters, digits, underscore, dot and hyphen, and may not start with a
367  dot; note that there is an unformatted version of this directive
368
369- %originalmail%
370- %originalmail N%
371  (available only in moderate-post-*, wait-post-* and
372  deny-post-{access|maxmailsize|tocc|subonlypost|modonlypost})
373  the email message being processed (usually a mail being moderated); N
374  represents a number, which is how many lines of the message (including
375  headers) to include: if omitted, the whole message will be included
376
377- %digestthreads%
378  (available only in digest)
379  the list of threads included in the digest
380
381- %gatekeepers%
382  (available only in gatekeep-sub and wait-sub)
383  the list of moderators to whom the moderation request has been sent
384
385- %listsubs%
386  (available only in list---*)
387  the list of normal subscribers
388  DEPRECATED: use %normalsubs%
389
390- %normalsubs%
391  (available only in list---*)
392  the list of normal subscribers
393
394- %digestsubs%
395  (available only in list---*)
396  the list of digest subscribers
397
398- %nomailsubs%
399  (available only in list---*)
400  the list of nomail subscribers
401
402- %moderators%
403  (available only in moderate-post-* and wait-post-*)
404  the list of moderators to whom the moderation request has been sent
405
406- %bouncenumbers%
407  (available only in probe)
408  the list of indexes of messages which may not have been received as they
409  bounced
410
411Directives which include a list of items have the behaviour that each item is
412preceded and followed by the same text as preceded and followed the directive
413on its line; only one such directive is supported per line. Those which include
414a block of text have the behaviour that second and later lines are preceded
415with as many spaces as there were bytes preceding the directive; any text
416following such directives on the same line is omitted.
417
418If a line with any of these directives, after processing, contains only
419whitespace, the line does not appear at all in the output (the newline and any
420whitespace is omitted).
421
422Unformatted substitutions
423-------------------------
424
425Unformatted substitutions that are available are:
426
427- $bouncenumbers$
428  (available only in probe)
429  the formatted list of indexes of messages which may not have been received as
430  they bounced
431  DEPRECATED: use %bouncenumbers%
432
433- $confaddr$
434- $confirmaddr$
435  (available only in confirm-[un]sub-*)
436  the address to which to send mail to confirm the (un-)subscription in
437  question
438  NOTE: the short version of this substitution is DEPRECATED
439
440- $control C$
441  the contents of the control file named C in listdir/control, with its final
442  newline stripped; the name may only include letters, digits, underscore, dot
443  and hyphen, and may not start with a dot; note that there is a formatted
444  version of this directive
445
446- $digestfirst$
447  (available only in digest)
448  index of the first message included in a digest
449
450- $digestinterval$
451  (available only in digest)
452  indexes of the first and last messages included in a digest (e.g. 1-5), or
453  just the index if only a single message is included
454
455- $digestissue$
456  (available only in digest)
457  the issue number of the digest
458
459- $digestlast$
460  (available only in digest)
461  index of the last message included in a digest
462
463- $digestsubaddr$
464  listname+subscribe-digest@domain.tld
465  DEPRECATED: use $list+$subscribe-digest@$domain$ instead
466
467- $digestthreads$
468  (available only in digest)
469  the formatted list of threads included in the digest
470  DEPRECATED: use %digestthreads%
471
472- $digestunsubaddr$
473  listname+unsubscribe-digest@domain.tld
474  DEPRECATED: use $list+$unsubscribe-digest@$domain$ instead
475
476- $domain$
477  domain.tld
478
479- $faqaddr$
480  listname+faq@domain.tld
481  DEPRECATED: use $list+$faq@$domain$ instead
482
483- $helpaddr$
484  listname+help@domain.tld
485  DEPRECATED: use $list+$help@$domain$ instead
486
487- $list$
488  listname
489
490- $list+$
491  listname+
492
493- $listaddr$
494  listname@domain.tld
495  DEPRECATED: use $list$@$domain$ instead
496
497- $listgetN$
498  listname+get-N@domain.tld
499  (the N here is nothing special, so this won't actually work, but is used to
500  explain to users how to use the +get functionality)
501  DEPRECATED: use $list+$get-N@$domain$ instead
502
503- $listowner$
504  listname+owner@domain.tld
505  DEPRECATED: use $list+$owner@$domain$ instead
506
507- $listsubaddr$
508  listname+subscribe@domain.tld
509  DEPRECATED: use $list+$subscribe@$domain$ instead
510
511- $listunsubaddr$
512  listname+unsubscribe@domain.tld
513  DEPRECATED: use $list+$unsubscribe@$domain$ instead
514
515- $maxmailsize$
516  (available only in deny-post-maxmailsize)
517  the maximum size of mail that Mlmmj will accept
518
519- $moderateaddr$
520  (available only in moderate-post-* and gatekeep-sub)
521  the address to which to send mail to approve the post or subscription in
522  question
523  DEPRECATED: use $releaseaddr$ or $permitaddr$ instead
524
525- $moderators$
526  (available only in moderate-post-*, wait-post-*, gatekeep-sub and wait-sub)
527  the formatted list of moderators to whom the moderation request has been sent
528  DEPRECATED: use %moderators% or %gatekeepers% instead
529
530- $newsub$
531  (available only in notify-sub-*-*)
532  the address that has been subscribed
533  DEPRECATED: use $subaddr$ instead
534
535- $nomailsubaddr$
536  listname+subscribe-nomail@domain.tld
537  DEPRECATED: use $list+$subscribe-nomail@$domain$ instead
538
539- $nomailunsubaddr$
540  listname+unsubscribe-nomail@domain.tld
541  DEPRECATED: use $list+$unsubscribe-nomail@$domain$ instead
542
543- $oldsub$
544  (available only in notify-sub-*-*)
545  the address that has been unsubscribed
546  DEPRECATED: use $subaddr$ instead
547
548- $originalmail$
549  the same as %originalmail 100% preceded by a space
550  DEPRECATED: use %originalmail%
551
552- $permitaddr$
553  (available only in gatekeep-sub)
554  the address to which to send mail to permit the subscription in question
555
556- $posteraddr$
557  (available only in deny-post-{access|tocc|subonlypost|modonlypost|
558  maxmailsize}, moderate-post-* and wait-post-*)
559  the from address of the message that was received as determined by Mlmmj
560
561- $random0$
562- $random1$
563- $random2$
564- $random3$
565- $random4$
566- $random5$
567  these are 6 distinct random strings; they allow list texts to be constructed
568  that are MIME messages with attachments by creating boundaries that are
569  unlikely to appear in the attached messages
570
571- $releaseaddr$
572  (available only in moderate-post-*)
573  the address to which to send mail to release the post in question
574
575- $subaddr$
576  (available only in gatekeep-sub, confirm-[un]sub-*, finish-[un]sub-*,
577  notify-[un]sub-* and deny-[un]sub-*)
578  the address requested to be (un-)subscribed
579
580- $subject$
581  (available only in deny-post-{access|tocc|subonlypost|modonlypost|
582  maxmailsize}, moderate-post-* and wait-post-*)
583  the subject line of the message in question
584
585- $text T$
586  text from the file named T in the listdir/text directory, with its final
587  newline stripped; the name may only include letters, digits, underscore, dot
588  and hyphen, and may not start with a dot; note that there is a formatted
589  version of this directive
590
591Escapes
592-------
593
594These allow you to avoid special meanings of characters used for other purposes
595in list texts, as well as control the construction of the texts at a fairly low
596level.
597
598- $$
599  a single $
600
601- %%
602  a single %
603
604- \\
605  a single \
606
607- \uNNNN
608  (NNNN represents four hex digits)
609  a Unicode character
610  (this is not really appropriate for use in a header, except perhaps the
611  Subject: header as Mlmmj does automatic quoting for that header as described
612  above)
613
614- \<space>
615  a space, but don't allow the line to be broken here when wrapping
616
617- \/
618  nothing, but allow the line to be broken here when wrapping
619
620- \=
621  nothing, but don't allow the line to be broken here when wrapping
622
623

README.postfix

1README.postfix                                                   Jan 28th 2012
2
3The main challenge to setting up Mlmmj with Postfix is that Mlmmj must be
4executed by root or the owner of the list directory, but by default Postfix
5will execute Mlmmj as 'nobody'[1].
6
7There are a number of possible ways around this:
8
9- Making 'nobody' own your lists (insecure) [2]
10- Changing the Postfix default to an 'mlmmj' user (possibly insecure or
11  impractical) [3]
12- .forward files (impractical) [4]
13- Using an :include: file owned by an 'mlmmj' user (possibly insecure and
14  suboptimal) [5]
15- Adding an alias table owned by an 'mlmmj' user (suboptimal) [6]
16- Using a Postfix transport to run Mlmmj as an 'mlmmj' user (recommended)
17
18As you can see, the last option is recommended. Here is how to set it up using
19Postfix virtual domains (so you can host multiple domains on the same server).
20(It can also be done with regular non-virtual aliases[7].)
21
22 1) Add an 'mlmmj' user to your system (e.g. using 'useradd'). It usually
23    makes sense to make this a 'system' user, with no password and no shell
24    (/usr/false for the shell), and for its home directory to be
25    /var/spool/mlmmj (or wherever you want to put your Mlmmj spool directory).
26
27 2) Create your Mlmmj spool directory (we'll assume it's /var/spool/mlmmj)
28    and change its owner to the 'mlmmj' user.
29
30 3) Add an 'mlmmj' transport which uses the pipe(8) delivery agent to execute
31    mlmmj-receive as the mlmmj user by adding something like the following to
32    master.cf (often in /etc/postfix)[8]:
33
34        # mlmmj mailing lists
35        mlmmj   unix  -       n       n       -       -       pipe
36            flags=ORhu user=mlmmj argv=/usr/local/bin/mlmmj-receive -F -L /var/spool/mlmmj/$nexthop
37
38    Note that $nexthop is used to specify the list directory. We will return
39    to that later.
40
41 4) Integrate some necessary options in main.cf (also often in /etc/postfix):
42
43        # Only deliver one message to Mlmmj at a time
44        mlmmj_destination_recipient_limit = 1
45
46        # Consider the part after '+' but before '@' to be an address extension
47        # i.e. addresses have the form user+extension@domain.tld
48        recipient_delimiter = +
49
50        # A map to forward mail to a dummy domain
51        virtual_alias_maps = hash:/var/spool/mlmmj/virtual
52
53	# Allow virtual alias maps to specify only the user part of the address
54	# and have the +extension part preserved when forwarding, so that
55	# list-name+subscribe, list-name+confsub012345678, etc. will all work
56        propagate_unmatched_extensions = virtual
57
58        # A map to forward mail for the dummy domain to the Mlmmj transport
59        transport_maps = hash:/var/spool/mlmmj/transport
60
61    Of course, you may need to merge these options with existing ones (e.g.
62    you probably have existing virtual_alias_maps if you run a multi-domain
63    server).
64
65    It is probably unnecessary to change propagate_unmatched_extensions because
66    it defaults to something including 'virtual'. You can check this with
67    something like 'postconf | grep propagate'.
68
69 5) (For each list) Create a mailing list (e.g. by using mlmmj-make-ml). The
70    list directory should be like /var/spool/mlmmj/list-dir for a flat
71    structure, or /var/spool/mlmmj/domain.tld/list-name for a hierarchical
72    structure (the -s option to mlmmj-make-ml may be useful to get the list
73    created where you want it). Ensure the list directory and everything in it
74    is owned by the mlmmj user (except you may want control files to be owned
75    by your www server user in order to use web configuration interfaces; they
76    must be readable by the mlmmj user though).
77
78 6) (For each list) Add entries to the Postfix tables to accept mail for the
79    list and forward it to the Mlmmj transport:
80
81    /var/spool/mlmmj/virtual:
82        list-name@domain.tld    domain.tld--list-name@localhost.mlmmj
83
84    /var/spool/mlmmj/transport:
85        # for a flat structure
86        domain.tld--list-name@localhost.mlmmj   mlmmj:list-dir
87        # for a hierarchical structure
88        domain.tld--list-name@localhost.mlmmj   mlmmj:domain.tld/list-name
89
90    Note that we have used a dummy domain 'localhost.mlmmj' to connect the
91    virtual alias with the Mlmmj transport. This could be anything as long as
92    it isn't a real domain. The user part of the address could also be
93    anything; as long as the address matches in both tables it should work.
94
95    Also note that the text after 'mlmmj:' becomes $nexthop which was mentioned
96    earlier, so it is used to specify the list directory when executing
97    mlmmj-receive.
98
99 7) Refresh your postfix tables and reload your configuration so it takes
100    effect.
101
102        postmap /var/spool/mlmmj/virtual
103        postmap /var/spool/mlmmj/transport
104        postfix reload
105
106    Enjoy your new lists!
107
108
109
110[1] Actually, the standard local(8) delivery agent will execute external
111    programs (such as Mlmmj) as the 'receiving user'. However, unless you
112    direct your mail to Mlmmj using a .forward file (see local(8)) or an
113    :include: file (see aliases(5)), or your aliases file is not owned by root,
114    there is no 'receiving user'. Without a 'receiving user', Postfix uses the
115    user from the configuration option 'default_privs', which defaults to
116    'nobody'.
117
118[2] Making 'nobody' own your lists is insecure because other programs and
119    daemons rely on 'nobody' not owning any files or having access to anything;
120    they use 'nobody' as a way of denying access and keeping all your files and
121    system secure. Most notably, some NFS implementations use 'nobody' when
122    somebody connects but fails to authenticate. Your mailing lists should not
123    be accessible in such situations, but they may be if they are owned by
124    'nobody'.
125
126[3] Changing 'default_privs' to an 'mlmmj' user may open other security holes,
127    and may not be appropriate if Postfix is used for other external programs
128    besides Mlmmj.
129
130[4] Using .forward files is not practical, as it requires a user to be created
131    for every mailing list.
132
133[5] Using :include: files would require delivery to commands to be enabled in
134    :include: files, which is not recommended for security reasons. It is also
135    messy for virtual domains in the same way as an alias table owned by an
136    'mlmmj' user is[6].
137
138[6] Adding an alias table owned by an 'mlmmj' user works, and doesn't pose any
139    great security risk. However, it is messy for virtual domains as you need
140    to forward mail from the virtual domain to your non-virtual domain and then
141    to Mlmmj. This results in each list having an additional address, which is
142    not desirable. That extra intermediate address is also included in mail
143    headers, which is not desirable (though it could be filtered out by Mlmmj).
144    Setting up an Mlmmj transport is about the same amount of work and doesn't
145    have these drawbacks. However, If you are not using virtual domains, this
146    is a good and simple option; but it will not be explained in detail here.
147
148[7] To use non-virtual alises, at step 4, you'll need to incorporate:
149
150        alias_maps = hash:/var/spool/mlmmj/aliases
151        propagate_unmatched_extensions = alias
152
153    You probably will need to adjust propagate_unmatched_extensions in this
154    case, probably by adding 'alias' to the existing value rather than using
155    'alias' alone.
156
157    If you want to use 'newaliases' to update the alias table, you should also
158    incorporate:
159
160        alias_database = hash:/var/spool/mlmmj/aliases
161
162    At step 6, entries in /var/spool/mlmmj/aliases should look something like:
163
164        list-name:    list-name@localhost.mlmmj
165
166    At step 7, you'll need:
167
168        postalias /var/spool/mlmmj/aliases
169
170    or (if you included alias_database above)
171
172        newaliases
173
174    And of course you can omit the virtual stuff if you're not using it.
175
176    Note that this has not been tested, but we believe it should work.
177
178[8] The flags for the transport are pretty critical. In particular if the 'R'
179    option is not used mlmmj-receive fails to receive the mail correctly. The
180    options mean:
181
182        D - Prepend a 'Delivered-To: recipient' header (not used)
183        O - Prepend an 'X-Original-To: recipient' header
184        R - Prepend a 'Return-Path:'. header
185        h - fold $nexthop to lowercase
186        u - fold $recipient to lowercase
187
188
189
190

README.qmail

1|------------------------------------------------------------------------------|
2|                     Using mlmmj with qmail (and vpopmail)                    |
3|------------------------------------------------------------------------------|
4|--------------- Fabio Busatto <fabio.busatto@programmazione.it> --------------|
5|------------------------------------------------------------------------------|
6
7This mini-HOWTO is a step-by-step guide for using mlmmj with qmail MTA
8(http://www.qmail.org/), and it has been successfully tested also with vpopmail
9virtual domains (http://www.inter7.com/vpopmail/).
10
11Prerequisites:
12- qmail (and vpopmail) correctly installed
13- mlmmj correctly installed
14
15Conventions:
16- ${BINDIR}: directory with mlmmj binary files (/usr/local/bin/)
17- ${LISTDIR}: directory with list configuration files
18              (/var/spool/mlmmj/listname)
19- ${DQFILE}: dot-qmail file (see below)
20
21Configuration:
22- the first thing you've to do is to create the list, using the
23  mlmmj-make-ml script (follow the classic procedure to do this step)
24- enter the control directory for the list (${LISTDIR}/control/), and execute
25  the following command:
26   # cd ${LISTDIR}/control/; echo '-' > delimiter
27- chown and chmod the file according to the mlmmj configuration
28- create dot-qmail files for the list to handle direct requests and extensions:
29   # echo -e "|${BINDIR}/mlmmj-receive -L ${LISTDIR}" > ${DQFILE}
30- chown and chmod the files according to the qmail (and vpopmail) configuration
31
32WARNING: REMEMBER that the delimiter is -, so do not use + when composing mail
33addresses for extensions!!!
34
35WARNING: DO NOT USE 'preline' command in dot-qmail files, it will result in
36mlmmj to not work properly!!!
37
38|------------------------------------------------------------------------------|
39
40Example:
41
42- Configuring mlmmj to handle ml@programmazione.it mailing list using qmail as
43  MTA and vpopmail for virtual domain support:
44
45# mlmmj-make-ml -c vpopmail:vchkpw -L ml
46Creating Directorys below /var/spool/mlmmj. Use '-s spooldir' to change
47The Domain for the List? [] : programmazione.it
48The emailaddress of the list owner? [postmaster] : postmaster@programmazione.it
49The path to texts for the list? [/usr/local/share/mlmmj/text.skel] :
50chown -R vpopmail:vchkpw /var/spool/mlmmj/ml? [y/n]: y
51
52# cd /var/spool/mlmmj/ml/control/
53# echo '-' > delimiter
54# chown vpopmail:vchkpw delimiter
55# cd /home/vpopmail/domains/programmazione.it/
56# echo -e "|/usr/local/bin/mlmmj-receive -L /var/spool/mlmmj/ml/" > .qmail-ml
57# cp -a .qmail-ml .qmail-ml-default
58# cat *-default
59# chown vpopmail:vchkpw .qmail-ml .qmail-ml-default
60# chmod 600 .qmail-ml .qmail-ml-default
61
62|------------------------------------------------------------------------------|
63|--------------- Fabio Busatto <fabio.busatto@programmazione.it> --------------|
64|------------------------------------------------------------------------------|
65

README.security

1Date: Sun, 1 May 2005 12:54:41 +0200
2From: Mads Martin Joergensen <mmj@mmj.dk>
3To: mlmmj@mmj.dk
4Subject: Security audit
5
6Hey list,
7
8Sebastian Krahmer (http://www.novell.com/linux/security/team.html)
9recently did a security audit of mlmmj, and didn't find any issues.
10
11That doesn't necessarily mean that there isn't any, but at least the
12code have been looked by different eyes with security in mind.
13
14--
15Mads Martin Joergensen, http://mmj.dk
16"Why make things difficult, when it is possible to make them cryptic
17 and totally illogical, with just a little bit more effort?"
18                                -- A. P. J.
19

README.sendmail

1Using sendmail + VERP
2
3--------------------------------------------------------------------------------
4
5The following configuration enables VERP (http://cr.yp.to/proto/verp.txt) which
6is useful for mailing list managers that are able to take advantage of that
7feature.
8
9This configuration is currently used for using the mlmmj manager
10(http://mlmmj.mmj.dk) with VERP enabled + sendmail.
11
12The hack consists in hooking VERP rewriting in a replacement ruleset for the
13existing EnvFromSMTP one (called VerpEnvFromSMTP). This is going to work *only*
14if we are splitting messages with multiple recipients in separate queue files
15since the macro we are using for the rewriting ($u) is not set when multiple
16rcpt are present.
17
18The first step consists in forcing envelope splitting, this is done using the
19QUEUE_GROUP feature, here we are definining r=1 (max 1 rcpt per message) for the
20default queue group:
21
22
23QUEUE_GROUP(`mqueue', `P=/var/spool/mqueue, F=f, I=1m,  R=2, r=1')
24
25
26Since we are going to split a lot it's advisable to use the FAST_SPLIT option,
27additionally we need to enforce return-path inclusion in the local mailer:
28
29
30define(`confFAST_SPLIT', `100')dnl
31define(`LOCAL_SHELL_FLAGS', `eu9P')dnl
32
33
34Then we define a regex map for matching the addresses that we are going to
35rewrite, in our example we'll rewrite addresses like
36
37<listname+bounces-123@domain.net>
38
39with
40
41<listname+bounces-123-user=foo.net@domain.net>
42
43where user@foo.net is the recipient address of the message. So we need to apply
44our verp ruleset *only* to those addresses. Additionally we are also adding the
45Delivered-To header:
46
47
48LOCAL_CONFIG
49Kmatch_verp regex -m -a@VERP (listname\+bounces\-[0-9]+<@domain\.net\.?>)
50H?l?Delivered-To: $u
51
52
53Here's the ruleset, the first half of the ruleset is the existing EnvFromSMTP
54ruleset present in default sendmail.cf, the seconf half is the VERP stuff:
55
56
57SVerpEnvFromSMTP
58R$+                     $: $>PseudoToReal $1            sender/recipient common
59R$* :; <@>              $@                              list:; special case
60R$*                     $: $>MasqSMTP $1                qualify unqual'ed names
61R$+                     $: $>MasqEnv $1                 do masquerading
62
63R $*                                    $: $(match_verp $1 $)                            match the address
64R $* + $* < @ $* . > $* @VERP           $: $1 + $2 - $&u < @ $3 . > $4 VERP              rewrite it using $u macro and add VERP string for failsafe
65R $* - < @ $* . > $* VERP               $: $1 < @ $2 . > $3                              if $u wasn't defined rewrite the address back
66R $* - < $+ @ $+ > < @ $* . > $* VERP   $: $(dequote $1 "-" $2 "=" $3 $) < @ $4 . > $5   replace the "@" in rcpt address with "="
67R $* - $+ @ $+ < @ $* . > $* VERP       $: $(dequote $1 "-" $2 "=" $3 $) < @ $4 . > $5   replace the "@" in rcpt address with "="
68
69
70Finally we need to rewrite the mailer definition for the used mailer (typically
71esmtp) specifying VerpEnvFromSMTP as the sender rewrite ruleset:
72
73
74MAILER_DEFINITIONS
75Mesmtp,		P=[IPC], F=mDFMuXa, S=VerpEnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990,
76		T=DNS/RFC822/SMTP,
77		A=TCP $h
78
79
80
81NOTE: for mailing list servers it's also a good idea keeping existing
82Delivered-To headers, sendmail needs the following patch for doing this
83
84--- sendmail/conf.c.orig	2004-07-14 21:54:23.000000000 +0000
85+++ sendmail/conf.c	2004-12-06 15:22:05.000000000 +0000
86@@ -117,6 +117,7 @@
87 	{ "content-length",		H_ACHECK,		NULL	},
88 	{ "subject",			H_ENCODABLE,		NULL	},
89 	{ "x-authentication-warning",	H_FORCE,		NULL	},
90+	{ "delivered-to",	    H_FORCE,		NULL	},
91
92 	{ NULL,				0,			NULL	}
93 };
94
95
96Andrea Barisani <andrea@inversepath.com>
97