The first alias contained in a blind list is now expanded. The
authorDavid Levine <levinedl@acm.org>
Mon, 15 Oct 2012 00:27:17 +0000 (19:27 -0500)
committerDavid Levine <levinedl@acm.org>
Mon, 15 Oct 2012 00:27:17 +0000 (19:27 -0500)
mh-alias(5) man page was updated to show that blind lists must not
be terminated with, or contain, a trailing semicolon [Bug #15604].

Makefile.am
docs/pending-release-notes
man/mh-alias.man
test/ali/test-ali
test/post/test-post-aliases [new file with mode: 0755]
uip/aliasbr.c

index 6d15d9f..8c571d2 100644 (file)
@@ -63,8 +63,8 @@ TESTS = test/ali/test-ali test/anno/test-anno \
        test/mhshow/test-subpart test/mhstore/test-mhstore \
        test/new/test-basic \
        test/pick/test-pick test/pick/test-stderr \
        test/mhshow/test-subpart test/mhstore/test-mhstore \
        test/new/test-basic \
        test/pick/test-pick test/pick/test-stderr \
-       test/post/test-post-basic test/post/test-post-multiple \
-       test/post/test-post-bcc \
+       test/post/test-post-aliases test/post/test-post-basic \
+       test/post/test-post-multiple test/post/test-post-bcc \
        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-mts test/post/test-messageid \
        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-mts test/post/test-messageid \
index cf0cdca..a329ebb 100644 (file)
@@ -72,3 +72,6 @@ BUG FIXES
 - Propagate Mail-Followup-To [Bug #5571].
 - "mark -sequence cur -delete all" now works for cur as well as any
   other sequence, to allow clearing of the current message indication.
 - Propagate Mail-Followup-To [Bug #5571].
 - "mark -sequence cur -delete all" now works for cur as well as any
   other sequence, to allow clearing of the current message indication.
+- The first alias contained in a blind list is now expanded.  The
+  mh-alias(5) man page was updated to show that blind lists must not
+  be terminated with, or contain, a trailing semicolon [Bug #15604].
index e29db4a..926fb89 100644 (file)
@@ -146,10 +146,13 @@ the address list if it is not already on the list.  The alias itself is
 not usually output, rather the address\-group that the alias maps to is
 output instead.  If \*(lqalias\*(rq is terminated with a `;' instead of
 a `:', then both the \*(lqalias\*(rq and the address are output in the
 not usually output, rather the address\-group that the alias maps to is
 output instead.  If \*(lqalias\*(rq is terminated with a `;' instead of
 a `:', then both the \*(lqalias\*(rq and the address are output in the
-correct format.  (This makes replies possible since
+correct format (with the alias quoted if necessary and the address
+wrapped in <>).
+
+This makes replies possible since
 .B nmh
 aliases
 .B nmh
 aliases
-and personal aliases are unknown to the mail transport system.)
+and personal aliases are unknown to the mail transport system.
 .RE
 .PP
 Since the alias file is read line by line, forward references work, but
 .RE
 .PP
 Since the alias file is read line by line, forward references work, but
@@ -161,7 +164,7 @@ Example Alias File:
 .nf
 <%etcdir%/BBoardAliases
 sgroup: fred, fear, freida
 .nf
 <%etcdir%/BBoardAliases
 sgroup: fred, fear, freida
-b-people: Blind List: bill, betty;
+b-people: Blind List: bill, betty
 fred: frated@UCI
 UNIX\-committee: <unix.aliases
 staff: =staff
 fred: frated@UCI
 UNIX\-committee: <unix.aliases
 staff: =staff
@@ -179,10 +182,16 @@ is defined as an alias for \*(lqfrated@UCI\*(rq, and \*(lqsgroup\*(rq
 is defined as an alias for the three names \*(lqfrated@UCI\*(rq,
 \*(rqfear\*(rq, and \*(rqfreida\*(rq.
 .PP
 is defined as an alias for the three names \*(lqfrated@UCI\*(rq,
 \*(rqfear\*(rq, and \*(rqfreida\*(rq.
 .PP
+
 The alias \*(lqb-people\*(rq is a blind list which includes the addresses
 \*(lqbill\*(rq and \*(lqbetty\*(rq; the message will be delivered to those
 The alias \*(lqb-people\*(rq is a blind list which includes the addresses
 \*(lqbill\*(rq and \*(lqbetty\*(rq; the message will be delivered to those
-addresses, but the message header will  show only \*(lqBlind List: ;\*(rq
-(not the addresses).
+addresses, but the message header will show only \*(lqBlind List: ;\*(rq
+(not the addresses).  The alias must not be terminated with, or contain,
+a semicolon; see
+.B Helpful Hints
+below.  Note that blind lists are not supported with the
+.B sendmail/pipe
+mail transport method.
 .PP
 Next, the definition of \*(lqUNIX\-committee\*(rq is given by
 reading the file
 .PP
 Next, the definition of \*(lqUNIX\-committee\*(rq is given by
 reading the file
@@ -251,6 +260,13 @@ Start adding aliases to your
 .RI \*(lq aliases \*(rq
 file as appropriate.
 .RE
 .RI \*(lq aliases \*(rq
 file as appropriate.
 .RE
+.PP
+Earlier versions of this man page showed a semicolon at the end of the
+blind list example.  That caused the preceeding alias to not be
+expanded.  There must not be a semicolon at the end of, or within, the
+address group of a blind list.
+.B post
+will append the semicolon to the blind list name.
 
 .SH FILES
 .fc ^ ~
 
 .SH FILES
 .fc ^ ~
@@ -282,5 +298,3 @@ command may defeat this.
 Since the number of file descriptors is finite (and very limited), such
 infinite recursion will terminate with a meaningless diagnostic when
 all the fds are used up.
 Since the number of file descriptors is finite (and very limited), such
 infinite recursion will terminate with a meaningless diagnostic when
 all the fds are used up.
-.PP
-Forward references do not work correctly inside blind lists.
index 7af25cc..4079790 100755 (executable)
@@ -54,18 +54,24 @@ run_test 'ali -nonexistent' 'ali: -nonexistent unknown'
 run_test 'ali' ''
 
 # check with nonexistent alias file
 run_test 'ali' ''
 
 # check with nonexistent alias file
-run_test 'ali -alias aliases' \
-         "ali: aliasing error in aliases - unable to read 'aliases'"
+run_test 'ali -alias nonexistent' \
+         "ali: aliasing error in nonexistent - unable to read 'nonexistent'"
 
 
-cat >${MH_TEST_DIR}/Mail/aliases <<EOF
+cat >"${MH_TEST_DIR}/Mail/aliases" <<EOF
 me: me@example.com
 me: me@example.com
-rush: geddy@example.com, alex@example.com, neil@example.com
+rush: geddy, alex, neil
+geddy: geddy@example.com
+alex: alex@example.com
+neil: neil@example.com
 EOF
 
 # check -alias
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases" \
          'me: me@example.com
 EOF
 
 # check -alias
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases" \
          'me: me@example.com
-rush: geddy@example.com, alex@example.com, neil@example.com'
+rush: geddy@example.com, alex@example.com, neil@example.com
+geddy: geddy@example.com
+alex: alex@example.com
+neil: neil@example.com'
 
 # check for a specific alias
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases rush" \
 
 # check for a specific alias
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases rush" \
@@ -80,21 +86,49 @@ run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases -list" \
          'me: me@example.com
 rush: geddy@example.com
       alex@example.com
          'me: me@example.com
 rush: geddy@example.com
       alex@example.com
-      neil@example.com'
+      neil@example.com
+geddy: geddy@example.com
+alex: alex@example.com
+neil: neil@example.com'
 
 # check -nolist, which is the default
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases -list -nolist" \
          'me: me@example.com
 
 # check -nolist, which is the default
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases -list -nolist" \
          'me: me@example.com
-rush: geddy@example.com, alex@example.com, neil@example.com'
+rush: geddy@example.com, alex@example.com, neil@example.com
+geddy: geddy@example.com
+alex: alex@example.com
+neil: neil@example.com'
 
 # check -user
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases -user geddy@example.com" \
 
 # check -user
 run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases -user geddy@example.com" \
-         'rush'
+         'rush, geddy'
 
 # check -nouser
 run_test \
   "ali -alias ${MH_TEST_DIR}/Mail/aliases -user -nouser geddy@example.com" \
   'geddy@example.com'
 
 
 # check -nouser
 run_test \
   "ali -alias ${MH_TEST_DIR}/Mail/aliases -user -nouser geddy@example.com" \
   'geddy@example.com'
 
+# check expansion of first address of blind list [Bug #15604]
+cat >"${MH_TEST_DIR}/Mail/aliases" <<EOF
+rush: Rush: geddy, alex, neil
+geddy: geddy@example.com
+alex: alex@example.com
+neil: neil@example.com
+EOF
+
+run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases rush" \
+         'Rush: geddy@example.com, alex@example.com, neil@example.com'
+
+# check that aliases followed by ; are not expanded [Bug #15604]
+cat >"${MH_TEST_DIR}/Mail/aliases" <<EOF
+rush: Rush: geddy, alex, neil;
+geddy: geddy@example.com
+alex: alex@example.com
+neil: neil@example.com
+EOF
+
+run_test "ali -alias ${MH_TEST_DIR}/Mail/aliases rush" \
+         'Rush: geddy@example.com, alex@example.com, neil;'
+
 
 exit $failed
 
 exit $failed
diff --git a/test/post/test-post-aliases b/test/post/test-post-aliases
new file mode 100755 (executable)
index 0000000..6030ad1
--- /dev/null
@@ -0,0 +1,156 @@
+#!/bin/sh
+######################################################
+#
+# Test aliases all the way through post
+#
+######################################################
+
+set -e
+
+if test -z "${MH_OBJ_DIR}"; then
+    srcdir=`dirname "$0"`/../..
+    MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR
+fi
+
+. "${srcdir}/test/post/test-post-common.sh"
+
+# Note that the last address in the blind list does not end with a
+# semicolon.
+cat >"${MH_TEST_DIR}/Mail/aliases" <<EOF
+blind_list: Blind List: one, two, three
+named.list; one@example.com, two@example.com
+one: one@example.com
+two: two@example.com
+three: three@example.com
+EOF
+
+#### Rely on sendmail/smtp or sendmail/pipe below to override default mts.
+mts_fakesendmail="${MHMTSCONF}-fakesendmail"
+cp "${MHMTSCONF}" "$mts_fakesendmail"
+printf "sendmail: ${srcdir}/test/fakesendmail\n" >>"$mts_fakesendmail"
+MHMTSCONF="$mts_fakesendmail"
+
+# $1: -mts switch selection
+# $2: expected output
+test_alias ()
+{
+  if [ "$1" = 'sendmail/smtp' ]; then
+    send -draft -alias "${MH_TEST_DIR}/Mail/aliases" -mts sendmail/smtp
+
+    # 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"
+
+    # 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"
+
+    check "${testname}.actual" "$2"
+
+    if [ "`mhpath cur`" != "`mhpath last`" ]; then
+      folder next >/dev/null
+      arith_eval $n + 1; n=$arith_val
+    fi
+
+  elif [ "$1" = 'sendmail/pipe' ]; then
+    set +e
+    send -draft -alias "${MH_TEST_DIR}/Mail/aliases" -mts sendmail/pipe \
+      >"${testname}.actual" 2>&1
+    if [ $? -eq 0 ]; then
+      printf "$0: sendmail/pipe should have failed but didn't\n"
+    else
+      set -e
+      check "${testname}.actual" "$2"
+    fi
+
+  else
+    printf "$0: invalid -mts switch selection\n"
+    exit 1
+  fi
+}
+
+
+# check blind list
+cat >"${MH_TEST_DIR}/Mail/draft" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: blind_list
+Subject: blind list test
+
+This is test of a blind list.
+EOF
+cp -p "${MH_TEST_DIR}/Mail/draft" "${MH_TEST_DIR}/Mail/draft2"
+
+cat >"${testname}.expected" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: Blind List: ;
+Subject: blind list test
+Date:
+
+This is test of a blind list.
+EOF
+
+test_alias sendmail/smtp "${testname}.expected"
+
+# Make sure the addresses were expanded correctly.
+mv "${MH_TEST_DIR}/Mail/draft2" "${MH_TEST_DIR}/Mail/draft"
+
+cat > "${testname}.expected" <<EOF
+EHLO nosuchhost.example.com
+MAIL FROM:<nobody@example.com>
+RCPT TO:<one@example.com>
+RCPT TO:<two@example.com>
+RCPT TO:<three@example.com>
+DATA
+From: Mr Nobody <nobody@example.com>
+To: Blind List: ;
+Subject: blind list test
+Date:
+
+This is test of a blind list.
+.
+QUIT
+EOF
+
+test_post "${testname}.actual" "${testname}.expected" \
+  "-alias ${MH_TEST_DIR}/Mail/aliases"
+
+# check named list (alias followed by ;)
+cat >"${MH_TEST_DIR}/Mail/draft" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: named.list
+Subject: named list test
+
+This is test of a named list.
+EOF
+
+cat >"${testname}.expected" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: "named.list" <one@example.com>, "named.list" <two@example.com>
+Subject: named list test
+Date:
+
+This is test of a named list.
+EOF
+
+test_alias sendmail/smtp "${testname}.expected"
+
+# check blind list with -mts sendmail/pipe, which should fail
+cat >"${MH_TEST_DIR}/Mail/draft" <<EOF
+From: Mr Nobody <nobody@example.com>
+To: blind_list
+Subject: blind list test
+
+This is test of a blind list.
+EOF
+
+cat >"${testname}.expected" <<EOF
+post: blind lists not compatible with sendmail/pipe
+send: message not delivered to anyone
+EOF
+
+test_alias sendmail/pipe "${testname}.expected"
+
+
+exit ${failed:-0}
index b2e51f5..d8350f9 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <h/mh.h>
 #include <h/aliasbr.h>
 
 #include <h/mh.h>
 #include <h/aliasbr.h>
+#include <h/addrsbr.h>
 #include <h/utils.h>
 #include <grp.h>
 #include <pwd.h>
 #include <h/utils.h>
 #include <grp.h>
 #include <pwd.h>
@@ -25,7 +26,7 @@ struct home *hometail = NULL;
 /*
  * prototypes
  */
 /*
  * prototypes
  */
-int alias (char *); 
+int alias (char *);
 int akvisible (void);
 void init_pw (void);
 char *akresult (struct aka *);
 int akvisible (void);
 void init_pw (void);
 char *akresult (struct aka *);
@@ -104,9 +105,45 @@ akval (struct aka *ak, char *s)
     if (!s)
        return s;                       /* XXX */
 
     if (!s)
        return s;                       /* XXX */
 
-    for (; ak; ak = ak->ak_next)
-       if (aleq (s, ak->ak_name))
+    for (; ak; ak = ak->ak_next) {
+       if (aleq (s, ak->ak_name)) {
            return akresult (ak);
            return akresult (ak);
+       } else if (strchr (s, ':')) {
+           /* The first address in a blind list will contain the
+              alias name, so try to match, but just with just the
+              address (not including the list name).  If there's a
+              match, then replace the alias part with its
+              expansion. */
+
+           char *name = getname (s);
+           char *cp = NULL;
+
+           if (name) {
+               /* s is of the form "Blind list: address".  If address
+                  is an alias, expand it. */
+               struct mailname *mp = getm (name, NULL, 0, AD_NAME, NULL);
+
+               if (mp  &&  mp->m_ingrp) {
+                   char *gname = add (mp->m_gname, NULL);
+
+                   if (gname  &&  aleq (name, ak->ak_name)) {
+                       /* Will leak cp. */
+                       cp = concat (gname, akresult (ak), NULL);
+                       free (gname);
+                   }
+               }
+
+               mnfree (mp);
+           }
+
+           /* Need to flush getname after use. */
+           while (getname ("")) continue;
+
+           if (cp) {
+               return cp;
+           }
+       }
+    }
 
     return getcpy (s);
 }
 
     return getcpy (s);
 }
@@ -429,12 +466,15 @@ getalias (char *addrs)
        if (*cp == 0)
            return (cp = NULL);
 
        if (*cp == 0)
            return (cp = NULL);
 
+    /* Remove leading any space from the address. */
     for (pp = cp; isspace (*pp); pp++)
        continue;
     if (*pp == 0)
        return (cp = NULL);
     for (pp = cp; isspace (*pp); pp++)
        continue;
     if (*pp == 0)
        return (cp = NULL);
+    /* Find the end of the address. */
     for (qp = pp; *qp != 0 && *qp != ','; qp++)
        continue;
     for (qp = pp; *qp != 0 && *qp != ','; qp++)
        continue;
+    /* Set cp to point to the remainder of the addresses. */
     if (*qp == ',')
        *qp++ = 0;
     for (cp = qp, qp--; qp > pp; qp--)
     if (*qp == ',')
        *qp++ = 0;
     for (cp = qp, qp--; qp > pp; qp--)