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 \
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 \
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
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"
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
# 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
/* 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;
\*(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 :
.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 ,
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 :
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.
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
.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
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;
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
#### 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
--- /dev/null
+#! /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
--- /dev/null
+#!/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}
/*
* 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
/* If we are doing a "whom" check */
if (whomsw) {
+ /* This won't work with MTS_PIPE. */
verify_all_addresses (1, envelope);
done (0);
}
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);
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) {
int len;
char *cp;
- if (flags & HBCC)
+ if (sm_mts != MTS_PIPE && (flags & HBCC))
return;
if (!nameoutput) {
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) {
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);
+ }
}