changeset 298:57d116ad0ea0

New perl-admin, hdradd before mime
author mmj
date Fri, 20 Aug 2004 21:01:50 +1000
parents cb6672e89943
children ec671807a97d
files ChangeLog Makefile.am VERSION contrib/web/perl-admin/conf/config.pl contrib/web/perl-admin/conf/tunables.pl contrib/web/perl-admin/htdocs/dot.htaccess contrib/web/perl-admin/htdocs/edit.cgi contrib/web/perl-admin/htdocs/index.cgi contrib/web/perl-admin/htdocs/save.cgi contrib/web/perl-admin/templates/edit.html contrib/web/perl-admin/templates/edit_boolean.html contrib/web/perl-admin/templates/edit_list.html contrib/web/perl-admin/templates/edit_string.html contrib/web/perl-admin/templates/index.html contrib/web/perl-admin/templates/save.html src/do_all_the_voodo_here.c src/listcontrol.c src/mlmmj-send.c
diffstat 18 files changed, 429 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Aug 18 15:38:21 2004 +1000
+++ b/ChangeLog	Fri Aug 20 21:01:50 2004 +1000
@@ -1,3 +1,9 @@
+1.0.0-RC1
+ o Add web-interface. Thanks Christian Laursen for new perl-admin
+ o Dump the customheaders before any Mime headers
+ o Implement +get-N functionality, so it's possible to send a mail to
+   foolist+get-101@domain.tld to retrieve mail 101 from that list. It's
+   deliberately only possible to request one mail at a time.
  o Make sure that only either root or the listdir owner can execute the
    binaries when it has something to do with lists.
  o Don't leave bounces-help@ mails lying around in queue/
--- a/Makefile.am	Wed Aug 18 15:38:21 2004 +1000
+++ b/Makefile.am	Fri Aug 20 21:01:50 2004 +1000
@@ -2,7 +2,7 @@
 
 AUTOMAKE_OPTIONS = foreign dist-bzip2
 EXTRA_DIST = include VERSION LICENSE UPGRADE listtexts src/log_error.c FAQ \
-	     TUNABLES README.access
+	     TUNABLES README.access contrib
 CLEANFILES = *~ mlmmj-*.tar.*
 
 dist-hook:
--- a/VERSION	Wed Aug 18 15:38:21 2004 +1000
+++ b/VERSION	Fri Aug 20 21:01:50 2004 +1000
@@ -1,1 +1,1 @@
-0.8.4
+1.0.0-RC1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/conf/config.pl	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,2 @@
+$topdir = "/var/spool/mlmmj";
+$templatedir = "/home/mlmmj/templates";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/conf/tunables.pl	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,61 @@
+mlmmj_boolean("closedlist",
+			  "Closed list",
+			  "If this option is set, subscribtion and unsubscription via mail is disabled.");
+
+mlmmj_boolean("moderated",
+			  "Moderated",
+			  "If this option is set, the emailaddresses in the file listdir/control/moderators will act as moderators for the list.");
+
+mlmmj_list("moderators",
+		   "Moderators",
+		   "If the list is moderated, this is the list of moderators.");
+
+mlmmj_boolean("tocc",
+			  "To: Cc:",
+			  "If this option is set, the list address does not have to be in the To: or Cc: header of the email to the list.");
+
+mlmmj_boolean("addtohdr",
+			  "Add To: header",
+			  "If this option is set, a To: header including the recipients emailaddress will be added to outgoing mail. ".
+			  "Recommended usage is to remove existing To: headers with delheaders (see below) first.");
+
+mlmmj_boolean("subonlypost",
+			  "Subscribers only post",
+			  "If this option is set, only people who are subscribed to the list, are allowed to post to it. ".
+			  "The check is made against the \"From:\" header.");
+
+mlmmj_string("prefix",
+			 "Prefix",
+			 "The prefix for the Subject: line of mails to the list. This will alter the Subject: line, ".
+			 "and add a prefix if it's not present elsewhere.");
+
+mlmmj_list("owner",
+		   "Owner",
+		   "The emailaddresses in this list will get mails to ".encode_entities($list)."+owner");
+
+mlmmj_list("delheaders",
+		   "Delete headers",
+		   "In this file is specified *ONE* headertoken to match pr. line. ".
+		   "If the file consists of: Received: Message-ID: Then all occurences of these headers in incoming list mail will be deleted. ".
+		   "\"From \" and \"Return-Path:\" are deleted no matter what.");
+
+mlmmj_list("access",
+		   "Access",
+		   "If this option is set, all headers of a post to the list is matched against the rules. The first rule to match wins. ".
+		   "See README.access for syntax and examples. NOTE: If this field is empty access control is *disabled*, ".
+		   "unlike having an empty control/access file.");
+
+mlmmj_string("memorymailsize",
+			 "Memory mail size",
+			 "Here is specified in bytes how big a mail can be and still be prepared for sending in memory. ".
+			 "It's greatly reducing the amount of write system calls to prepare it in memory before sending it, ".
+			 "but can also lead to denial of service attacks. Default is 16k (16384 bytes).");
+
+mlmmj_string("relayhost",
+			 "Relay host",
+			 "The host specified (IP address og domainname, both works) in this file will be used for relaying the mail sent to the list. ".
+			 "Defaults to 127.0.0.1.");
+
+mlmmj_boolean("notifysub",
+			  "Notify subscribers",
+			  "If this option is set, the owner(s) will get a mail with the address of someone sub/unsubscribing to a mailinglist.");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/htdocs/dot.htaccess	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,4 @@
+Require valid-user
+AuthType Basic
+AuthName "mlmmj web-interface"
+AuthUserFile /home/mlmmj/htpasswd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/htdocs/edit.cgi	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,121 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
+# Copyright (C) 2004 Christian Laursen <christian@pil.dk>
+#
+# $Id$
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+use strict;
+use CGI;
+use CGI::FastTemplate;
+use HTML::Entities;
+
+use vars qw($topdir $templatedir $list);
+
+if (exists $ENV{CONFIG_PATH}) {
+	require $ENV{CONFIG_PATH};
+} else {
+	require "../conf/config.pl";
+}
+
+my $tpl = new CGI::FastTemplate($templatedir);
+
+my $q = new CGI;
+$list = $q->param("list");
+
+die "non-existent list" unless -d("$topdir/$list");
+
+$tpl->define(main => "edit.html",
+			 boolean => "edit_boolean.html",
+			 string => "edit_string.html",
+			 list => "edit_list.html");
+
+$tpl->assign(LIST => encode_entities($list));
+
+my $tunables_file = "../conf/tunables.pl";
+if (exists $ENV{TUNABLES_PATH}) {
+	$tunables_file = $ENV{TUNABLES_PATH};
+}
+
+do $tunables_file;
+
+print "Content-type: text/html\n\n";
+$tpl->parse(CONTENT => "main");
+$tpl->print;
+
+sub mlmmj_boolean {
+	my ($name, $nicename, $text) = @_;
+    my $checked = -f "$topdir/$list/control/$name";
+
+	$tpl->assign(NAME => encode_entities($name));
+	$tpl->assign(NICENAME => encode_entities($nicename));
+	$tpl->assign(TEXT => encode_entities($text));
+	$tpl->assign(CHECKED => $checked ? ' checked' : '');
+
+	$tpl->parse(ROWS => ".boolean");
+}
+
+sub mlmmj_string {
+	my ($name, $nicename, $text) = @_;
+    my $file = "$topdir/$list/control/$name";
+    my $value;
+
+    if (! -f $file) {
+        $value = "";
+    } else {
+        open(F, $file) or die("can't open $file");
+        $value = <F>;
+        close(F);
+        chomp($value);
+    }
+
+	$tpl->assign(NAME => encode_entities($name));
+	$tpl->assign(NICENAME => encode_entities($nicename));
+	$tpl->assign(TEXT => encode_entities($text));
+	$tpl->assign(VALUE => encode_entities($value));
+
+	$tpl->parse(ROWS => ".string");
+}
+
+sub mlmmj_list {
+	my ($name, $nicename, $text) = @_;
+    my $file = "$topdir/$list/control/$name";
+    my $value;
+
+    if (! -f $file) {
+        $value = "";
+    } else {
+        open(F, $file) or die("can't open $file");
+        while (<F>) {
+            $value .= $_;
+        }
+        close(F);
+        chomp($value);
+    }
+
+	$tpl->assign(NAME => encode_entities($name));
+	$tpl->assign(NICENAME => encode_entities($nicename));
+	$tpl->assign(TEXT => encode_entities($text));
+	$tpl->assign(VALUE => encode_entities($value));
+
+	$tpl->parse(ROWS => ".list");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/htdocs/index.cgi	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,56 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
+# Copyright (C) 2004 Christian Laursen <christian@pil.dk>
+#
+# $Id$
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+use strict;
+use URI::Escape;
+use HTML::Entities;
+use CGI::FastTemplate;
+
+use vars qw($topdir $templatedir);
+
+if (exists $ENV{CONFIG_PATH}) {
+	require $ENV{CONFIG_PATH};
+} else {
+	require "../conf/config.pl";
+}
+
+my $tpl = new CGI::FastTemplate($templatedir);
+
+$tpl->define(main => "index.html");
+
+my $lists = "";
+opendir(DIR, $topdir) or die "Couldn't open $topdir for reading: $!";
+while (my $list = readdir(DIR)) {
+    next if $list =~ /^\./;
+    $lists .= "<a href=\"edit.cgi?list=".uri_escape($list)."\">".encode_entities($list)."</a><br />\n";
+}
+closedir(DIR);
+
+$tpl->assign(LISTS => $lists);
+
+print "Content-type: text/html\n\n";
+
+$tpl->parse(CONTENT => "main");
+$tpl->print;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/htdocs/save.cgi	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,97 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2004 Morten K. Poulsen <morten at afdelingp.dk>
+# Copyright (C) 2004 Christian Laursen <christian@pil.dk>
+#
+# $Id$
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+# We might want some kind of validation of the values we are about to save,
+# but that would require save.cgi to know about all kind of options that mlmmj
+# accepts. I am not sure we want that.  -- mortenp 20040709
+
+use strict;
+use CGI;
+use CGI::FastTemplate;
+use HTML::Entities;
+
+use vars qw($topdir $templatedir $list);
+
+if (exists $ENV{CONFIG_PATH}) {
+	require $ENV{CONFIG_PATH};
+} else {
+	require "../conf/config.pl";
+}
+
+my $tpl = new CGI::FastTemplate($templatedir);
+
+my $q = new CGI;
+$list = $q->param("list");
+
+die "non-existent list" unless -d("$topdir/$list");
+
+$tpl->define(main => "save.html");
+$tpl->assign(LIST => encode_entities($list));
+
+my $tunables_file = "../conf/tunables.pl";
+if (exists $ENV{TUNABLES_PATH}) {
+	$tunables_file = $ENV{TUNABLES_PATH};
+}
+
+do $tunables_file;
+
+print "Content-type: text/html\n\n";
+$tpl->parse(CONTENT => "main");
+$tpl->print;
+
+sub mlmmj_boolean {
+	my ($name, $nicename, $text) = @_;
+
+	my $file = "$topdir/$list/control/$name";
+
+	my $value = $q->param($name);
+	if ($value) {
+		open (FILE, ">$file") or die "Couldn't open $file for writing: $!";
+		close FILE;
+	} else {
+		unlink $file;
+	}
+}
+
+sub mlmmj_string {
+	mlmmj_list(@_);
+}
+
+sub mlmmj_list {
+	my ($name, $nicename, $text) = @_;
+
+	my $file = "$topdir/$list/control/$name";
+
+	my $value = $q->param($name);
+
+	if (defined $value && $value !~ /^\s*$/) {
+		$value .= "\n" if $value !~ /\n$/;
+		open (FILE, ">$file") or die "Couldn't open $file for writing: $!";
+		print FILE $value;
+		close FILE;
+	} else {
+		unlink $file;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/templates/edit.html	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,10 @@
+<html><head><title>mlmmj config</title></head><body>
+<h1>mlmmj config</h1>
+<form method="post" action="save.cgi">
+<input type="hidden" name="list" value="$LIST">
+<table border="1">
+$ROWS
+</table>
+<input type="submit" name="submit" />
+</form>
+</body></html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/templates/edit_boolean.html	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,1 @@
+<tr><td>$NICENAME</td><td><input type="checkbox" name="$NAME" value="1"$CHECKED></td><td>$TEXT</td></tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/templates/edit_list.html	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,1 @@
+<tr><td>$NICENAME</td><td><textarea name="$NAME" columns="40">$VALUE</textarea></td><td>$TEXT</td></tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/templates/edit_string.html	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,1 @@
+<tr><td>$NICENAME</td><td><input type="text" name="$NAME" value="$VALUE"></td><td>$TEXT</td></tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/templates/index.html	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,4 @@
+<html><head><title>mlmmj config</title></head><body>
+<h1>mlmmj config</h1>
+$LISTS
+</body></html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/web/perl-admin/templates/save.html	Fri Aug 20 21:01:50 2004 +1000
@@ -0,0 +1,9 @@
+<html><head><title>mlmmj config</title></head><body>
+<h1>mlmmj config</h1>
+<p>
+$LIST control values saved!
+</p>
+<p>
+<a href="index.cgi">Index</a> | <a href="edit.cgi?list=$LIST">$LIST</a>
+</p>
+</body></html>
--- a/src/do_all_the_voodo_here.c	Wed Aug 18 15:38:21 2004 +1000
+++ b/src/do_all_the_voodo_here.c	Fri Aug 20 21:01:50 2004 +1000
@@ -80,31 +80,38 @@
 		 struct strlist *allhdrs, const char *prefix)
 {
 	char *hdrline, *subject, *unqp;
+	int hdrsadded = 0;
 
 	allhdrs->count = 0;
 	allhdrs->strs = NULL;
 
 	while((hdrline = gethdrline(infd))) {
 		/* Done with headers? Then add extra if wanted*/
-		if((strlen(hdrline) == 1) && (hdrline[0] == '\n')){
-			if(hdrfd >= 0) {
+		if((strncasecmp(hdrline, "mime", 4) == NULL) ||
+			((strlen(hdrline) == 1) && (hdrline[0] == '\n'))){
+			if(!hdrsadded && hdrfd >= 0) {
 				if(dumpfd2fd(hdrfd, outfd) < 0) {
 					log_error(LOG_ARGS, "Could not "
 						"add extra headers");
 					myfree(hdrline);
 					return -1;
-				}
-			}
-			if(writen(outfd, hdrline, strlen(hdrline)) < 0) {
-				myfree(hdrline);
-				log_error(LOG_ARGS, "Error writing hdrs.");
-				return -1;
+				} else
+					hdrsadded = 1;
 			}
 			
 			fsync(outfd);
 			myfree(hdrline);
+			if(hdrline[0] == '\n') {
+				if(writen(outfd, hdrline, strlen(hdrline))
+						< 0) {
+					myfree(hdrline);
+					log_error(LOG_ARGS,
+							"Error writing hdrs.");
+					return -1;
+				}
 			break;
 		}
+		}
 		/* Do we want info from hdrs? Get it before it's gone */
 		if(readhdrs)
 			getinfo(hdrline, readhdrs);
--- a/src/listcontrol.c	Wed Aug 18 15:38:21 2004 +1000
+++ b/src/listcontrol.c	Fri Aug 20 21:01:50 2004 +1000
@@ -29,6 +29,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <ctype.h>
 
 #include "mlmmj.h"
 #include "listcontrol.h"
@@ -49,6 +50,7 @@
 	CTRL_BOUNCES,
 	CTRL_MODERATE,
 	CTRL_HELP,
+	CTRL_GET,
 	CTRL_END  /* end marker, must be last */
 };
 
@@ -67,7 +69,8 @@
 	{ "confunsub",   1 },
 	{ "bounces",     1 },
 	{ "moderate",    1 },
-	{ "help",        0 }
+	{ "help",        0 },
+	{ "get",         1 }
 };
 
 
@@ -78,6 +81,7 @@
 {
 	char *atsign, *recipdelimsign, *bouncenr, *tmpstr;
 	char *controlstr, *param, *conffilename, *moderatefilename;
+	char *c, *archivefilename;
 	size_t len;
 	struct stat stbuf;
 	int closedlist, tmpfd;
@@ -248,6 +252,29 @@
 				  mlmmjsend);
 		break;
 
+	case CTRL_GET:
+		errno = 0;
+		unlink(mailname);
+		if(!param) /* malformed get, ignore silently */
+			exit(EXIT_SUCCESS);
+		else { /* sanity check--is it all digits? */
+			for(c = param; *c != '\0'; c++) {
+				if(!isdigit((int)*c))
+					exit(EXIT_SUCCESS);
+			}
+			archivefilename = concatstr(3, listdir, "/archive/",
+							param);
+			if(stat(archivefilename, &stbuf) < 0)
+				exit(EXIT_SUCCESS);
+			else
+				execlp(mlmmjsend, mlmmjsend,
+					"-T", fromemails->emaillist[0],
+					"-L", listdir,
+					"-l", "6",
+					"-m", archivefilename,
+					"-a", "-D", 0);
+		}
+		break;
 	}
 
 	unlink(mailname);
--- a/src/mlmmj-send.c	Wed Aug 18 15:38:21 2004 +1000
+++ b/src/mlmmj-send.c	Fri Aug 20 21:01:50 2004 +1000
@@ -444,6 +444,7 @@
 	       "    '3' means 'resend failed list mail'\n"
 	       "    '4' means 'send to file with recipients'\n"
 	       "    '5' means 'bounceprobe'\n"
+	       "    '6' means 'single listmail to single recipient'\n"
 	       " -L: Full path to list directory\n"
 	       " -m: Full path to mail file\n"
 	       " -r: Relayhost IP address (defaults to 127.0.0.1)\n"
@@ -568,6 +569,7 @@
 		case '3':
 		case '4':
 		case '5':
+		case '6':
 			archive = 0;
 		default:
 			break;
@@ -654,7 +656,13 @@
 			myfree(body);
 			exit(EXIT_FAILURE);
 		}
-
+	case '6':
+		archive = 0;
+		deletewhensent = 0;
+		archivefilename = mystrdup(mailfilename);
+		bounceaddr = bounce_from_adr(to_addr, listaddr,
+						archivefilename);
+		break;
 	default: /* normal list mail -- now handled when forking */
 		break;
 	}
@@ -688,6 +696,7 @@
 
 	switch(listctrl[0]) {
 	case '1': /* A single mail is to be sent */
+	case '6':
 		initsmtp(&sockfd, relay);
 		sendres = send_mail(sockfd, bounceaddr, to_addr, replyto,
 				mailmap, st.st_size, listdir, NULL,