spost(8) has been merged into post(8). Its functionality is
authorDavid Levine <levinedl@acm.org>
Mon, 9 Jul 2012 04:17:04 +0000 (23:17 -0500)
committerDavid Levine <levinedl@acm.org>
Mon, 9 Jul 2012 04:17:04 +0000 (23:17 -0500)
enabled by selecting the "pipe" mail transport method in
etc/mts.conf, which in turn can be configured using
--with-mts=pipe.  The spost -noalias, -backup/-nobackup,
-push/-nopush, and -remove/-noremove switches are not
supported by post.  Note that spost did not support -whom or
Dcc, and neither does post when using mts: pipe.  spost is
now deprecated.

15 files changed:
Makefile.am
configure.ac
docs/contrib/build_nmh
docs/pending-release-notes
etc/mts.conf.in
h/mts.h
man/mh-mail.man
man/mh-tailor.man
man/send.man
sbr/mts.c
sbr/readconfig.c
test/common.sh.in
test/fakesendmail [new file with mode: 0755]
test/post/test-pipe [new file with mode: 0755]
uip/post.c

index ff61ab4..841c9ec 100644 (file)
@@ -65,7 +65,7 @@ TESTS = test/ali/test-ali \
        test/post/test-post-basic test/post/test-post-multiple \
        test/post/test-post-dcc test/post/test-post-fcc \
        test/post/test-post-multifrom test/post/test-post-envelope \
-       test/post/test-post-group \
+       test/post/test-post-group test/post/test-pipe \
        test/prompter/test-prompter \
        test/rcv/test-rcvdist test/rcv/test-rcvpack test/rcv/test-rcvstore \
        test/refile/test-refile \
@@ -228,7 +228,7 @@ EXTRA_DIST = config/version.sh sbr/sigmsg.awk etc/mts.conf.in etc/sendfiles.in \
             man/rmf.man man/rmm.man man/scan.man man/send.man \
             man/sendfiles.man man/show.man man/slocal.man man/sortm.man \
             man/unseen.man man/whatnow.man man/whom.man \
-            test/README $(TESTS) test/inc/deb359167.mbox \
+            test/README test/fakesendmail $(TESTS) test/inc/deb359167.mbox \
             test/inc/fromline.txt test/inc/msgheader.txt test/inc/filler.txt \
             test/inc/md5sums test/mhmail/attachment.txt \
             test/post/test-post-common.sh uip/mhmail \
index a0d1756..eaa60b3 100644 (file)
@@ -111,11 +111,12 @@ AC_ARG_ENABLE([lockdir],
 
 dnl What method of posting should post use?
 AC_ARG_WITH([mts],
-  AS_HELP_STRING([--with-mts=@<:@smtp|sendmail@:>@],
+  AS_HELP_STRING([--with-mts=@<:@smtp|sendmail|pipe@:>@],
   [specify the default mail transport agent/service]))
 
 AS_IF([test x"$with_mts" = x"smtp"], [MTS="smtp"],
       [test x"$with_mts" = x"sendmail"], [MTS="sendmail"],
+      [test x"$with_mts" = x"pipe"], [MTS="pipe"],
       [MTS="smtp"])
 AC_SUBST([MTS])dnl
 
index 7d7d9dd..e1905f9 100755 (executable)
@@ -174,7 +174,7 @@ if [ $yes -eq 0 ]; then
   read locking
   [ "$locking" ]  &&  config_locking="$locking"
 
-  printf 'MTS (smtp|sendmail) [%s]: ' $config_mts
+  printf 'MTS (smtp|sendmail|pipe) [%s]: ' $config_mts
   read mts
   [ "$mts" ]  &&  config_mts="$mts"
 
index 7b9a933..f7462a7 100644 (file)
@@ -39,6 +39,13 @@ OBSOLETE/DEPRECATED FEATURES
   http://smtpfilter.sourceforge.net/esmtp.html
 - conflict(8) is deprecated and will be removed from the next release.
 - mhtest(8) is deprecated and will be removed from the next release.
+- spost(8) has been merged into post(8).  Its functionality is enabled
+  by selecting the pipe mail transport method in etc/mts.conf, which
+  in turn can be configured using --with-mts=pipe.  The spost
+  -noalias, -backup/-nobackup, -push/-nopush, and -remove/-noremove
+  switches are not supported by post.  Note that spost did not support
+  -whom or Dcc, and neither does post when using mts: pipe.  spost is
+  deprecated and will be removed from the next release.
 
 ---------
 BUG FIXES
index a9c7494..7cb0a4d 100644 (file)
@@ -4,10 +4,15 @@
 # Check the mh-tailor(5) man page for descriptions of available options.
 #
 
-# The delivery method to use.  Supported values are `smtp' and `sendmail'.
-# When `smtp', nmh will open a socket connection to the mail port on the
-# machine specified below, and speak SMTP directly.
-# When `sendmail', nmh will pipe messages directly to the sendmail program.
+# The delivery method to use, which must be one of the following:
+# smtp:     nmh opens a socket connection to the appropriate port
+#           on the servers listed below and speaks SMTP to the
+#           first one that responds.  This is the default.
+# sendmail: nmh pipes messages directly to the sendmail program,
+#           speaking SMTP.
+# pipe:     nmh pipes messages directly to the sendmail program,
+#           using the -t option so that addresses are retrieved
+#           from the message.
 mts: %mts%
 
 # Name that nmh considers `local'.  If not set, nmh will
diff --git a/h/mts.h b/h/mts.h
index c1c3457..8496c28 100644 (file)
--- a/h/mts.h
+++ b/h/mts.h
@@ -45,6 +45,7 @@ void mts_init (char *);
 /* whether to speak SMTP to localhost:25 or to /usr/sbin/sendmail */
 #define MTS_SMTP     0
 #define MTS_SENDMAIL 1
+#define MTS_PIPE     2
 extern int sm_mts;
 
 extern char *sendmail;
index 87a0535..30506e9 100644 (file)
@@ -180,6 +180,10 @@ line receive the same messsage as recipients on the \*(lqTo:\*(rq and
 \*(lqcc:\*(rq lines.  See
 .BR send (1)
 for more details.
+.B Dcc
+is not supported with the
+.B pipe
+mail transport method.
 .RE
 .PP
 .BR Fcc :
index ca12a8a..9e29a05 100644 (file)
@@ -29,10 +29,12 @@ default values and a description of their meanings are listed below:
 .PP
 .BR mts :
 .RS 5
-The mail transport method to use.  The two acceptable options are
+The mail transport method to use.  The three acceptable options are
 .B smtp
-(which is the default), and
-.BR sendmail .
+(which is the default),
+.BR sendmail ,
+and
+.BR pipe .
 .PP
 If you use
 .BR smtp ,
@@ -54,9 +56,23 @@ then
 will send messages by forking a
 local copy of
 .BR sendmail .
-Currently it will still speak SMTP with this local
-copy of
+It will still speak SMTP with this local copy of
 .BR sendmail .
+.PP
+The third alternative,
+.BR pipe ,
+also forks a local copy of
+.B sendmail
+but feeds the message directly to it, using
+.B sendmail
+.BR -t .
+This replaces the old, undocumented
+.B spost
+mechanism and retains some of its limitations, such as lack of
+support for the
+.B \-whom
+switch and
+\*(lqDcc:\*(rq header field.
 .RE
 .PP
 .BR localname :
@@ -199,8 +215,8 @@ to
 localhost
 .RS 5
 A lists of hosts and networks which to look for SMTP servers when
-posting local mail.  It turns out this is a major win for hosts which
-don't run an message transport system.  The value of
+posting non\-local mail.  It turns out this is a major win for hosts
+which don't run an message transport system.  The value of
 .B servers
 should be one or more items.  Each item is the name of a host which
 is (hopefully) running a SMTP server.
index 4a69b00..b823517 100644 (file)
@@ -254,7 +254,9 @@ sent to sighted recipients.  The blind recipients will receive an entirely
 new message with a minimal set of headers.  Included in the body of the
 message will be a copy of the message sent to the sighted recipients.
 .PP
-If a \*(lqDcc:\*(rq field is encountered, its addresses will be used for
+If a \*(lqDcc:\*(rq field is encountered and the
+.B pipe
+mail transport method is not in use, its addresses will be used for
 delivery, and the \*(lqDcc:\*(rq field will be removed from the message.  The
 blind recipients will receive the same message sent to the sighted
 recipients. *WARNING* Recipients listed in the \*(lqDcc:\*(rq field receive no
@@ -429,7 +431,7 @@ for more information.
 .fi
 
 .SH "SEE ALSO"
-comp(1), dist(1), forw(1), repl(1), mh\-alias(5), post(8)
+comp(1), dist(1), forw(1), repl(1), mh\-alias(5), mh\-tailor(5), post(8)
 
 .SH DEFAULTS
 .nf
index 88bae83..661975b 100644 (file)
--- a/sbr/mts.c
+++ b/sbr/mts.c
@@ -150,6 +150,8 @@ mts_init (char *name)
         sm_mts = MTS_SMTP;
     else if (strcmp(sm_method, "sendmail") == 0)
         sm_mts = MTS_SENDMAIL;
+    else if (strcmp(sm_method, "pipe") == 0)
+        sm_mts = MTS_PIPE;
     else {
         advise(NULL, "unsupported \"mts\" value in mts.conf: %s", sm_method);
         sm_mts = MTS_SMTP;
index 0f38fdf..65ca28a 100644 (file)
@@ -111,8 +111,7 @@ readconfig (struct node **npp, FILE *ib, char *file, int ctx)
            profile entries that are just "#", because that's what the
            mh-profile man page suggests using for comments.  Only do
            this check on the very first call from context_read(), when
-           opp is
-          NULL. */
+           opp is NULL. */
 
        for (np = m_defs; np; np = np->n_next) {
            /* Yes, this is O(N^2).  The profile should be small enough so
index 1c1633b..3e65659 100644 (file)
@@ -152,7 +152,7 @@ setup_test ()
     #### Don't test with sendmail because it would really send the
     #### mail.  If configured to use sendmail, change to smtp instead
     #### so that we use fakesmtp.
-    sed -e 's/mts: *sendmail/mts: smtp/' "${MHMTSCONF}" >"${MHMTSCONF}.new"
+    sed -e 's/mts: *.*/mts: smtp/' "${MHMTSCONF}" >"${MHMTSCONF}.new"
     mv -f "${MHMTSCONF}.new" "${MHMTSCONF}"
   fi
 
diff --git a/test/fakesendmail b/test/fakesendmail
new file mode 100755 (executable)
index 0000000..c3bc4e1
--- /dev/null
@@ -0,0 +1,30 @@
+#! /bin/sh
+##
+# fakesendmail - A fake sendmail program used by the nmh test suite
+#                to test the pipe mts.
+#
+# This code is Copyright (c) 2012, by the authors of nmh.  See the
+# COPYRIGHT file in the root directory of the nmh distribution for
+# complete copyright information.
+##
+
+if [ "$MH_TEST_DIR"x = x ]; then
+  printf "$0 is intended for use only by the nmh test suite\n"
+  exit 1
+fi
+
+found_dasht=0
+for arg in "$@"; do
+  [ "$arg" = -t ]  &&  found_dasht=1
+done
+
+if [ $found_dasht -eq 0 ]; then
+  printf "$0 is intended to fake \"sendmail -t\" only, but no -t provided\n"
+  exit 1
+fi
+
+#### Put the message (on stdin) in a drop that the test knows about.
+#### This will delete any lines in the message body that start with Bcc:,
+#### so avoid those.
+sed -e '/^[Bb][Cc][Cc]:/d' | \
+"${MH_LIB_DIR}"/rcvpack "${MH_TEST_DIR}"/Mail/fakesendmail.mbox
diff --git a/test/post/test-pipe b/test/post/test-pipe
new file mode 100755 (executable)
index 0000000..c9048ed
--- /dev/null
@@ -0,0 +1,120 @@
+#!/bin/sh
+#
+# Test the basic behavior of post when configured with pipe delivery method.
+#
+
+set -e
+
+if test -z "${MH_OBJ_DIR}"; then
+    srcdir=`dirname "$0"`/../..
+    MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR
+fi
+
+. "${MH_OBJ_DIR}/test/common.sh"
+
+setup_test
+testname="${MH_TEST_DIR}/$$"
+
+#### Force test of pipe regardless of configuration.
+mts_pipe="${MHMTSCONF}-pipe"
+sed -e 's/mts: *.*/mts: pipe/' "${MHMTSCONF}" >"$mts_pipe"
+printf "%s\n" "sendmail: ${srcdir}/test/fakesendmail" >>"$mts_pipe"
+MHMTSCONF="$mts_pipe"
+
+test_pipe ()
+{
+  send -draft
+
+  # fakesendmail drops the message and any cc's into this mbox.
+  mbox="${MH_TEST_DIR}"/Mail/fakesendmail.mbox
+  inc -silent -file "$mbox"
+  rm -f "$mbox" "$mbox.map"
+
+  n=1
+  for expected in "$@"; do
+    #
+    # It's hard to calculate the exact Date: header post is going to
+    # use, so we'll just use sed to remove the actual date so we can easily
+    # compare it against our "correct" output.
+    #
+    sed -e 's/^Date:.*/Date:/' "`mhpath cur`" > "${testname}.actual$n"
+
+    check "${testname}.actual$n" "$expected"
+
+    if [ "`mhpath cur`" != "`mhpath last`" ]; then
+      folder next >/dev/null
+      arith_eval $n + 1; n=$arith_val
+    fi
+  done
+}
+
+#
+# Basic test - Simple message, single user, single recipient.
+# Dots are not stuffed because pipe invokes sendmail with -i.
+#
+cat > "${MH_TEST_DIR}/Mail/draft" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: Somebody Else <somebody@example.com>
+Subject: Test
+
+This is a test
+.
+EOF
+
+cat > "${testname}.expected" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: Somebody Else <somebody@example.com>
+Subject: Test
+Date:
+
+This is a test
+.
+EOF
+
+test_pipe "${testname}.expected"
+
+
+# check Bcc
+cat > "${MH_TEST_DIR}/Mail/draft" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: Somebody Else <somebody@example.com>
+Bcc: Silent Partner <bcc@example.com>
+Subject: Test
+
+This is a test
+.
+EOF
+
+cat > "${testname}.expected1" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: Somebody Else <somebody@example.com>
+Subject: Test
+Date:
+
+This is a test
+.
+EOF
+
+cat > "${testname}.expected2" <<EOF
+Date:
+Subject: Test
+
+------- Blind-Carbon-Copy
+
+From: Mr Nobody <nobody@example.com>
+To: Somebody Else <somebody@example.com>
+Subject: Test
+Date:
+
+This is a test
+.
+
+------- End of Blind-Carbon-Copy
+EOF
+
+test_pipe "${testname}.expected1" "${testname}.expected2"
+
+
+rm -f ${MHMTSCONF}
+
+exit ${failed:-0}
index 1116299..f63a286 100644 (file)
@@ -144,20 +144,20 @@ struct headers {
 /*
  * flags for headers->flags
  */
-#define        HNOP  0x0000            /* just used to keep .set around          */
-#define        HBAD  0x0001            /* bad header - don't let it through      */
-#define        HADR  0x0002            /* header has an address field            */
-#define        HSUB  0x0004            /* Subject: header                        */
-#define        HTRY  0x0008            /* try to send to addrs on header         */
-#define        HBCC  0x0010            /* don't output this header               */
-#define        HMNG  0x0020            /* munge this header                      */
-#define        HNGR  0x0040            /* no groups allowed in this header       */
-#define        HFCC  0x0080            /* FCC: type header                       */
-#define        HNIL  0x0100            /* okay for this header not to have addrs */
-#define        HIGN  0x0200            /* ignore this header                     */
-#define        HDCC  0x0400            /* another undocumented feature           */
-#define HONE  0x0800           /* Only (zero or) one address allowed     */
-#define HEFM  0x1000           /* Envelope-From: header                  */
+#define        HNOP  0x0000        /* just used to keep .set around             */
+#define        HBAD  0x0001        /* bad header - don't let it through         */
+#define        HADR  0x0002        /* header has an address field               */
+#define        HSUB  0x0004        /* Subject: header                           */
+#define        HTRY  0x0008        /* try to send to addrs on header            */
+#define        HBCC  0x0010        /* don't output this header, unless MTS_PIPE */
+#define        HMNG  0x0020        /* munge this header                         */
+#define        HNGR  0x0040        /* no groups allowed in this header          */
+#define        HFCC  0x0080        /* FCC: type header                          */
+#define        HNIL  0x0100        /* okay for this header not to have addrs    */
+#define        HIGN  0x0200        /* ignore this header                        */
+#define        HDCC  0x0400        /* another undocumented feature              */
+#define HONE  0x0800       /* Only (zero or) one address allowed        */
+#define HEFM  0x1000       /* Envelope-From: header                     */
 
 /*
  * flags for headers->set
@@ -634,6 +634,7 @@ main (int argc, char **argv)
 
     /* If we are doing a "whom" check */
     if (whomsw) {
+       /* This won't work with MTS_PIPE. */
        verify_all_addresses (1, envelope);
        done (0);
     }
@@ -641,7 +642,13 @@ main (int argc, char **argv)
     if (msgflags & MINV) {
        make_bcc_file (dashstuff);
        if (msgflags & MVIS) {
-           verify_all_addresses (verbose, envelope);
+           if (sm_mts != MTS_PIPE) {
+               /* It would be nice to have support to call
+                  verify_all_addresses with MTS_PIPE, but that might
+                  require running sendmail as root.  Note that spost
+                  didn't verify addresses. */
+               verify_all_addresses (verbose, envelope);
+           }
            post (tmpfil, 0, verbose, envelope);
        }
        post (bccfil, 1, verbose, envelope);
@@ -1058,7 +1065,7 @@ putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flag
 
     if (mp->m_mbox == NULL || ((flags & HTRY) && !insert (mp)))
        return 0;
-    if ((flags & (HBCC | HDCC | HEFM)) || mp->m_ingrp)
+    if (sm_mts != MTS_PIPE && ((flags & (HBCC | HDCC | HEFM)) || mp->m_ingrp))
        return 1;
 
     if (!nameoutput) {
@@ -1102,7 +1109,7 @@ putgrp (char *name, char *group, FILE *out, unsigned int flags)
     int len;
     char *cp;
 
-    if (flags & HBCC)
+    if (sm_mts != MTS_PIPE && (flags & HBCC))
        return;
 
     if (!nameoutput) {
@@ -1465,7 +1472,8 @@ static void
 post (char *file, int bccque, int talk, char *envelope)
 {
     int fd, onex;
-    int        retval;
+    int        retval, i;
+    pid_t child_id;
 
     onex = !(msgflags & MINV) || bccque;
     if (verbose) {
@@ -1478,31 +1486,65 @@ post (char *file, int bccque, int talk, char *envelope)
 
     sigon ();
 
-    if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, verbose,
-                                   snoop, onex, queued, sasl, saslssf,
-                                   saslmech, user, tls))
-           || rp_isbad (retval = sm_winit (envelope)))
-       die (NULL, "problem initializing server; %s", rp_string (retval));
-
-    do_addresses (bccque, talk && verbose);
-    if ((fd = open (file, O_RDONLY)) == NOTOK)
-       die (file, "unable to re-open");
-    do_text (file, fd);
-    close (fd);
-    fflush (stdout);
+    if (sm_mts == MTS_PIPE) {
+       char *sargv[16], **argp;
 
-    sm_end (onex ? OK : DONE);
-    sigoff ();
+       for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
+           sleep (5);
+       switch (child_id) {
+           case NOTOK: 
+               adios ("fork", "unable to");
 
-    if (verbose) {
-       if (msgflags & MINV)
-           printf (" -- %s Recipient Copies Posted --\n",
-                   bccque ? "Blind" : "Sighted");
-       else
-           printf (" -- Recipient Copies Posted --\n");
-    }
+           case OK:
+               if (freopen( file, "r", stdin) == NULL) {
+                   adios (file, "can't reopen for sendmail");
+               }
 
-    fflush (stdout);
+               argp = sargv;
+               *argp++ = "sendmail";
+               *argp++ = "-m"; /* send to me too */
+               *argp++ = "-t"; /* read msg for recipients */
+               *argp++ = "-i"; /* don't stop on "." */
+               if (whomsw)
+                   *argp++ = "-bv";
+               if (snoop)
+                   *argp++ = "-v";
+               *argp = NULL;
+
+               execv (sendmail, sargv);
+               adios (sendmail, "can't exec");
+
+           default: 
+               pidXwait (child_id, NULL);
+               break;
+       }
+    } else {
+        if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch,
+                                        verbose, snoop, onex, queued, sasl,
+                                        saslssf, saslmech, user, tls))  ||
+            rp_isbad (retval = sm_winit (envelope)))
+           die (NULL, "problem initializing server; %s", rp_string (retval));
+
+        do_addresses (bccque, talk && verbose);
+        if ((fd = open (file, O_RDONLY)) == NOTOK)
+          die (file, "unable to re-open");
+        do_text (file, fd);
+        close (fd);
+        fflush (stdout);
+
+        sm_end (onex ? OK : DONE);
+        sigoff ();
+
+        if (verbose) {
+            if (msgflags & MINV)
+               printf (" -- %s Recipient Copies Posted --\n",
+                       bccque ? "Blind" : "Sighted");
+            else
+               printf (" -- Recipient Copies Posted --\n");
+        }
+
+        fflush (stdout);
+    }
 }