]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.3-20051117
authorWietse Venema <wietse@porcupine.org>
Thu, 17 Nov 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:31:42 +0000 (06:31 +0000)
26 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/html/postconf.1.html
postfix/man/man1/postconf.1
postfix/src/bounce/Makefile.in
postfix/src/bounce/bounce.c
postfix/src/bounce/bounce_notify_service.c
postfix/src/bounce/bounce_notify_util.c
postfix/src/bounce/bounce_notify_verp.c
postfix/src/bounce/bounce_one_service.c
postfix/src/bounce/bounce_service.h
postfix/src/bounce/bounce_template.c
postfix/src/bounce/bounce_template.h [new file with mode: 0644]
postfix/src/bounce/bounce_templates.c [new file with mode: 0644]
postfix/src/bounce/bounce_trace_service.c
postfix/src/bounce/bounce_warn_service.c
postfix/src/bounce/dict_ml.c [deleted file]
postfix/src/bounce/dict_ml.h [deleted file]
postfix/src/bounce/template_test.ref [new file with mode: 0644]
postfix/src/dns/dns.h
postfix/src/global/mail_version.h
postfix/src/postconf/postconf.c
postfix/src/util/Makefile.in
postfix/src/util/load_file.c [new file with mode: 0644]
postfix/src/util/load_file.h [new file with mode: 0644]
postfix/src/util/sys_defs.h

index 00e85e8cd1ad9ac932247e8dd407fdf25852fec3..1dea5debd926b0bbe04eac5ef63f1083bafa92e7 100644 (file)
@@ -22,6 +22,7 @@
 -TBOUNCE_LOG_RCPT_BUF
 -TBOUNCE_STAT
 -TBOUNCE_TEMPLATE
+-TBOUNCE_TEMPLATES
 -TBOUNCE_TIME_DIVISOR
 -TBOUNCE_TIME_PARAMETER
 -TCFG_PARSER
index 57780f515bbfb026e0381a2834e24e25ef6deb9f..a2ff4fa233ff7ca05f24a8c7ccfabf6fa09943ee 100644 (file)
@@ -11394,6 +11394,12 @@ Apologies for any names omitted.
 
        Cleanup: renamed fail_template into failure_template.
 
+20051117
+
+       Cleanup: bounce template code reorg, no functionality change.
+       Files: bounce/bounce_template.[hc], bounce/bounce_templates.c,
+       bounce/bounce_notify_util.c.
+
 Open problems:
 
        "postsuper -r" no longer resets the message arrival time,
index 55d8c2cec458b3575cadd813764d3bb3abd67ddf..0d0de949d7126ad846cb4f71224aaf97bfb7ab5f 100644 (file)
@@ -217,7 +217,7 @@ POSTCONF(1)                                                        POSTCONF(1)
        /etc/postfix/main.cf, Postfix configuration parameters
 
 <b>SEE ALSO</b>
-       <a href="bounce.5.html">bounce(5)</a>, bouce template file format
+       <a href="bounce.5.html">bounce(5)</a>, bounce template file format
        <a href="postconf.5.html">postconf(5)</a>, configuration parameters
 
 <b>README FILES</b>
index ee179c3bece7b8d4a3f35a70fc702b7dd743989d..05ee5f8d5949242410475b3f3ba279ae3d467370 100644 (file)
@@ -187,7 +187,7 @@ Pathname of a configuration file with bounce message templates.
 .SH "SEE ALSO"
 .na
 .nf
-bounce(5), bouce template file format
+bounce(5), bounce template file format
 postconf(5), configuration parameters
 .SH "README FILES"
 .na
index 4a1edaae156f4edd8480ad1ec6c5ea1c8639ba6a..7c2b2febb4c27165ac97b715c733ee97d0263344 100644 (file)
@@ -2,11 +2,11 @@ SHELL = /bin/sh
 SRCS   = bounce.c bounce_append_service.c bounce_notify_service.c \
        bounce_cleanup.c bounce_notify_util.c bounce_notify_verp.c \
        bounce_one_service.c bounce_warn_service.c bounce_trace_service.c \
-       bounce_template.c dict_ml.c
+       bounce_template.c bounce_templates.c
 OBJS   = bounce.o bounce_append_service.o bounce_notify_service.o \
        bounce_cleanup.o bounce_notify_util.o bounce_notify_verp.o \
        bounce_one_service.o bounce_warn_service.o bounce_trace_service.o \
-       bounce_template.o dict_ml.o
+       bounce_template.o bounce_templates.o
 HDRS   = 
 TESTSRC        = 
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -23,11 +23,12 @@ $(PROG):    $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 # Avoid dependency on installed Postfix.
-../../conf/bounce.cf.default: $(PROG) annotate.pl
+../../conf/bounce.cf.default: $(PROG) annotate.pl main.cf
        rm -f $@
-       echo queue_directory=. >main.cf
        MAIL_CONFIG=. ./$(PROG) -SVzndump_templates | perl annotate.pl >$@
-       rm -f main.cf
+
+main.cf:
+       echo queue_directory=. >main.cf
 
 $(OBJS): ../../conf/makedefs.out
 
@@ -61,12 +62,13 @@ clean:
 tidy:  clean
 
 # Avoid dependency on installed Postfix.
-template_test: $(PROG)
-       echo queue_directory=. >main.cf
-       MAIL_CONFIG=. ./$(PROG) -SVzndump_templates >junk
+template_test: $(PROG) main.cf template_test.ref
+       MAIL_CONFIG=. ./$(PROG) -SVzndump_templates >template_test.tmp
+       diff template_test.ref template_test.tmp
        MAIL_CONFIG=. ./$(PROG) -SVzndump_templates \
-           -o bounce_template_file=junk | diff junk -
-       rm -f junk main.cf
+           -o bounce_template_file=template_test.ref > template_test.tmp
+       diff template_test.ref template_test.tmp
+       rm -f template_test.tmp
 
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
@@ -86,6 +88,7 @@ bounce.o: ../../include/dsb_scan.h
 bounce.o: ../../include/dsn.h
 bounce.o: ../../include/dsn_buf.h
 bounce.o: ../../include/iostuff.h
+bounce.o: ../../include/load_file.h
 bounce.o: ../../include/mail_addr.h
 bounce.o: ../../include/mail_conf.h
 bounce.o: ../../include/mail_params.h
@@ -103,6 +106,7 @@ bounce.o: ../../include/vstream.h
 bounce.o: ../../include/vstring.h
 bounce.o: bounce.c
 bounce.o: bounce_service.h
+bounce.o: bounce_template.h
 bounce_append_service.o: ../../include/attr.h
 bounce_append_service.o: ../../include/bounce_log.h
 bounce_append_service.o: ../../include/deliver_flock.h
@@ -125,6 +129,7 @@ bounce_append_service.o: ../../include/vstream.h
 bounce_append_service.o: ../../include/vstring.h
 bounce_append_service.o: bounce_append_service.c
 bounce_append_service.o: bounce_service.h
+bounce_append_service.o: bounce_template.h
 bounce_cleanup.o: ../../include/attr.h
 bounce_cleanup.o: ../../include/bounce_log.h
 bounce_cleanup.o: ../../include/dsn.h
@@ -140,6 +145,7 @@ bounce_cleanup.o: ../../include/vstream.h
 bounce_cleanup.o: ../../include/vstring.h
 bounce_cleanup.o: bounce_cleanup.c
 bounce_cleanup.o: bounce_service.h
+bounce_cleanup.o: bounce_template.h
 bounce_notify_service.o: ../../include/attr.h
 bounce_notify_service.o: ../../include/bounce.h
 bounce_notify_service.o: ../../include/bounce_log.h
@@ -164,6 +170,7 @@ bounce_notify_service.o: ../../include/vstream.h
 bounce_notify_service.o: ../../include/vstring.h
 bounce_notify_service.o: bounce_notify_service.c
 bounce_notify_service.o: bounce_service.h
+bounce_notify_service.o: bounce_template.h
 bounce_notify_util.o: ../../include/attr.h
 bounce_notify_util.o: ../../include/bounce_log.h
 bounce_notify_util.o: ../../include/cleanup_user.h
@@ -200,6 +207,7 @@ bounce_notify_util.o: ../../include/vstream.h
 bounce_notify_util.o: ../../include/vstring.h
 bounce_notify_util.o: bounce_notify_util.c
 bounce_notify_util.o: bounce_service.h
+bounce_notify_util.o: bounce_template.h
 bounce_notify_verp.o: ../../include/attr.h
 bounce_notify_verp.o: ../../include/bounce.h
 bounce_notify_verp.o: ../../include/bounce_log.h
@@ -225,6 +233,7 @@ bounce_notify_verp.o: ../../include/vstream.h
 bounce_notify_verp.o: ../../include/vstring.h
 bounce_notify_verp.o: bounce_notify_verp.c
 bounce_notify_verp.o: bounce_service.h
+bounce_notify_verp.o: bounce_template.h
 bounce_one_service.o: ../../include/attr.h
 bounce_one_service.o: ../../include/bounce.h
 bounce_one_service.o: ../../include/bounce_log.h
@@ -248,34 +257,39 @@ bounce_one_service.o: ../../include/vstream.h
 bounce_one_service.o: ../../include/vstring.h
 bounce_one_service.o: bounce_one_service.c
 bounce_one_service.o: bounce_service.h
-bounce_template.o: ../../include/argv.h
+bounce_one_service.o: bounce_template.h
 bounce_template.o: ../../include/attr.h
-bounce_template.o: ../../include/bounce_log.h
-bounce_template.o: ../../include/cleanup_user.h
-bounce_template.o: ../../include/dict.h
-bounce_template.o: ../../include/dsn.h
-bounce_template.o: ../../include/dsn_buf.h
 bounce_template.o: ../../include/iostuff.h
 bounce_template.o: ../../include/is_header.h
 bounce_template.o: ../../include/mac_expand.h
 bounce_template.o: ../../include/mac_parse.h
-bounce_template.o: ../../include/mail_addr.h
 bounce_template.o: ../../include/mail_conf.h
 bounce_template.o: ../../include/mail_params.h
 bounce_template.o: ../../include/mail_proto.h
 bounce_template.o: ../../include/msg.h
 bounce_template.o: ../../include/mymalloc.h
-bounce_template.o: ../../include/post_mail.h
-bounce_template.o: ../../include/rcpt_buf.h
-bounce_template.o: ../../include/recipient_list.h
+bounce_template.o: ../../include/split_at.h
 bounce_template.o: ../../include/stringops.h
 bounce_template.o: ../../include/sys_defs.h
 bounce_template.o: ../../include/vbuf.h
 bounce_template.o: ../../include/vstream.h
 bounce_template.o: ../../include/vstring.h
-bounce_template.o: bounce_service.h
 bounce_template.o: bounce_template.c
-bounce_template.o: dict_ml.h
+bounce_template.o: bounce_template.h
+bounce_templates.o: ../../include/attr.h
+bounce_templates.o: ../../include/iostuff.h
+bounce_templates.o: ../../include/mail_addr.h
+bounce_templates.o: ../../include/mail_proto.h
+bounce_templates.o: ../../include/msg.h
+bounce_templates.o: ../../include/mymalloc.h
+bounce_templates.o: ../../include/stringops.h
+bounce_templates.o: ../../include/sys_defs.h
+bounce_templates.o: ../../include/vbuf.h
+bounce_templates.o: ../../include/vstream.h
+bounce_templates.o: ../../include/vstring.h
+bounce_templates.o: ../../include/vstring_vstream.h
+bounce_templates.o: bounce_template.h
+bounce_templates.o: bounce_templates.c
 bounce_trace_service.o: ../../include/attr.h
 bounce_trace_service.o: ../../include/bounce_log.h
 bounce_trace_service.o: ../../include/cleanup_user.h
@@ -298,6 +312,7 @@ bounce_trace_service.o: ../../include/vbuf.h
 bounce_trace_service.o: ../../include/vstream.h
 bounce_trace_service.o: ../../include/vstring.h
 bounce_trace_service.o: bounce_service.h
+bounce_trace_service.o: bounce_template.h
 bounce_trace_service.o: bounce_trace_service.c
 bounce_warn_service.o: ../../include/attr.h
 bounce_warn_service.o: ../../include/bounce_log.h
@@ -319,16 +334,5 @@ bounce_warn_service.o: ../../include/vbuf.h
 bounce_warn_service.o: ../../include/vstream.h
 bounce_warn_service.o: ../../include/vstring.h
 bounce_warn_service.o: bounce_service.h
+bounce_warn_service.o: bounce_template.h
 bounce_warn_service.o: bounce_warn_service.c
-dict_ml.o: ../../include/argv.h
-dict_ml.o: ../../include/dict.h
-dict_ml.o: ../../include/iostuff.h
-dict_ml.o: ../../include/msg.h
-dict_ml.o: ../../include/stringops.h
-dict_ml.o: ../../include/sys_defs.h
-dict_ml.o: ../../include/vbuf.h
-dict_ml.o: ../../include/vstream.h
-dict_ml.o: ../../include/vstring.h
-dict_ml.o: ../../include/vstring_vstream.h
-dict_ml.o: dict_ml.c
-dict_ml.o: dict_ml.h
index 76f410b1991242e85d727b68ce8ddc8d51a50194..1a19890c73276f3523dcb39a86a4a4ac1d29e7b5 100644 (file)
 #include <vstring.h>
 #include <vstream.h>
 #include <stringops.h>
+#include <load_file.h>
 
 /* Global library. */
 
 
 /* Application-specific. */
 
-#include "bounce_service.h"
+#include <bounce_service.h>
 
  /*
   * Tunables.
@@ -186,6 +187,11 @@ static VSTRING *dsn_envid;
 static VSTRING *verp_delims;
 static DSN_BUF *dsn_buf;
 
+ /*
+  * Templates.
+  */
+BOUNCE_TEMPLATES *bounce_templates;
+
 #define STR vstring_str
 
 /* bounce_append_proto - bounce_append server protocol */
@@ -247,7 +253,8 @@ static int bounce_append_proto(char *service_name, VSTREAM *client)
 
 static int bounce_notify_proto(char *service_name, VSTREAM *client,
                                int (*service) (int, char *, char *, char *,
-                                              char *, char *, char *, int))
+                                               char *, char *, char *, int,
+                                                       BOUNCE_TEMPLATES *))
 {
     char   *myname = "bounce_notify_proto";
     int     flags;
@@ -294,7 +301,8 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client,
      */
     return (service(flags, service_name, STR(queue_name),
                    STR(queue_id), STR(encoding),
-                   STR(sender), STR(dsn_envid), dsn_ret));
+                   STR(sender), STR(dsn_envid), dsn_ret,
+                   bounce_templates));
 }
 
 /* bounce_verp_proto - bounce_notify server protocol, VERP style */
@@ -356,12 +364,13 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client)
        msg_warn("request to send VERP-style notification of bounced mail");
        return (bounce_notify_service(flags, service_name, STR(queue_name),
                                      STR(queue_id), STR(encoding),
-                                     STR(sender), STR(dsn_envid), dsn_ret));
+                                     STR(sender), STR(dsn_envid), dsn_ret,
+                                     bounce_templates));
     } else
        return (bounce_notify_verp(flags, service_name, STR(queue_name),
                                   STR(queue_id), STR(encoding),
                                   STR(sender), STR(dsn_envid), dsn_ret,
-                                  STR(verp_delims)));
+                                  STR(verp_delims), bounce_templates));
 }
 
 /* bounce_one_proto - bounce_one server protocol */
@@ -427,7 +436,7 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
      */
     return (bounce_one_service(flags, STR(queue_name), STR(queue_id),
                               STR(encoding), STR(sender), STR(dsn_envid),
-                              dsn_ret, &rcpt, &dsn));
+                              dsn_ret, &rcpt, &dsn, bounce_templates));
 }
 
 /* bounce_service - parse bounce command type and delegate */
@@ -495,38 +504,50 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv)
     }
 }
 
+static void load_helper(VSTREAM *stream, void *context)
+{
+    BOUNCE_TEMPLATES *templates = (BOUNCE_TEMPLATES *) context;
+
+    bounce_templates_load(stream, templates);
+}
+
 /* pre_jail_init - pre-jail initialization */
 
-static void pre_jail_init(char *service_name, char **unused_argv)
+static void pre_jail_init(char *unused_name, char **unused_argv)
 {
 
     /*
-     * Load the alternate message files (if specified) before entering the ch
-     * root jail.
+     * Bundle up a bunch of bounce template information.
+     */
+    bounce_templates = bounce_templates_create();
+
+    /*
+     * Load the alternate message files (if specified) before entering the
+     * chroot jail.
      */
     if (*var_bounce_tmpl)
-       bounce_template_load(var_bounce_tmpl);
+       load_file(var_bounce_tmpl, load_helper, (char *) bounce_templates);
+}
+
+/* post_jail_init - initialize after entering chroot jail */
+
+static void post_jail_init(char *service_name, char **unused_argv)
+{
 
     /*
-     * Special case: dump bounce templates. This is not part of the
-     * master(5) public interface.
+     * Special case: dump bounce templates. This is not part of the master(5)
+     * public interface.
      */
     if (strcmp(service_name, "dump_templates") == 0) {
-       bounce_template_dump_all(VSTREAM_OUT);
+       bounce_templates_dump(VSTREAM_OUT, bounce_templates);
        vstream_fflush(VSTREAM_OUT);
        exit(0);
     }
     if (strcmp(service_name, "expand_templates") == 0) {
-       bounce_template_expand_all(VSTREAM_OUT);
+       bounce_templates_expand(VSTREAM_OUT, bounce_templates);
        vstream_fflush(VSTREAM_OUT);
        exit(0);
     }
-}
-
-/* post_jail_init - initialize after entering chroot jail */
-
-static void post_jail_init(char *unused_name, char **unused_argv)
-{
 
     /*
      * Initialize. We're single threaded so we can reuse some memory upon
index 415bdeec411dc38a76926dcc21241e5c09f3419b..c02ffb9c3cdee4120968c0c971baf484a42ed2df 100644 (file)
@@ -7,7 +7,7 @@
 /*     #include "bounce_service.h"
 /*
 /*     int     bounce_notify_service(flags, queue_name, queue_id, encoding,
-/*                                     sender, dsn_envid, dsn_ret)
+/*                                     sender, dsn_envid, dsn_ret, templates)
 /*     int     flags;
 /*     char    *queue_name;
 /*     char    *queue_id;
@@ -15,6 +15,7 @@
 /*     char    *sender;
 /*     char    *dsn_envid;
 /*     int     dsn_ret;
+/*     BOUNCE_TEMPLATES *templates;
 /* DESCRIPTION
 /*     This module implements the server side of the bounce_flush()
 /*     (send bounce message) request.
@@ -83,7 +84,7 @@
 int     bounce_notify_service(int flags, char *service, char *queue_name,
                                      char *queue_id, char *encoding,
                                      char *recipient, char *dsn_envid,
-                                     int dsn_ret)
+                                     int dsn_ret, BOUNCE_TEMPLATES *ts)
 {
     BOUNCE_INFO *bounce_info;
     int     bounce_status = 1;
@@ -127,7 +128,7 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
      * notification is enabled.
      */
     bounce_info = bounce_mail_init(service, queue_name, queue_id,
-                                  encoding, dsn_envid, FAIL_TEMPLATE());
+                                  encoding, dsn_envid, ts->failure);
 
 #define NULL_SENDER            MAIL_ADDR_EMPTY /* special address */
 #define NULL_TRACE_FLAGS       0
@@ -182,7 +183,8 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
                 * message. Don't bother sending the boiler-plate text.
                 */
                count = -1;
-               if (bounce_header(bounce, bounce_info, postmaster) == 0
+               if (bounce_header(bounce, bounce_info, postmaster,
+                                 POSTMASTER_COPY) == 0
                    && (count = bounce_diagnostic_log(bounce, bounce_info,
                                                   DSN_NOTIFY_OVERRIDE)) > 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
@@ -215,7 +217,8 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
             * reason for the bounce, and a copy of the original message.
             */
            count = -1;
-           if (bounce_header(bounce, bounce_info, recipient) == 0
+           if (bounce_header(bounce, bounce_info, recipient,
+                             NO_POSTMASTER_COPY) == 0
                && bounce_boilerplate(bounce, bounce_info) == 0
                && (count = bounce_diagnostic_log(bounce, bounce_info,
                                                  DSN_NOTIFY_FAILURE)) > 0
@@ -258,7 +261,8 @@ int     bounce_notify_service(int flags, char *service, char *queue_name,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
                                                 NULL_TRACE_FLAGS)) != 0) {
                count = -1;
-               if (bounce_header(bounce, bounce_info, postmaster) == 0
+               if (bounce_header(bounce, bounce_info, postmaster,
+                                 POSTMASTER_COPY) == 0
                    && (count = bounce_diagnostic_log(bounce, bounce_info,
                                                   DSN_NOTIFY_OVERRIDE)) > 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
index fe74aedcf6d3cbee7dcaf03fa7d6f5ff7dd04830..0078b680c1bf51e1cc9cb56798b546de32ed9904 100644 (file)
@@ -22,7 +22,8 @@
 /*     const BOUNCE_TEMPLATE *template;
 /*
 /*     BOUNCE_INFO *bounce_mail_one_init(queue_name, queue_id, encoding,
-/*                                     dsn_envid, dsn_notify, rcpt, dsn)
+/*                                     dsn_envid, dsn_notify, rcpt, dsn,
+/*                                     template)
 /*     const char *queue_name;
 /*     const char *queue_id;
 /*     const char *encoding;
 /*     const char *dsn_envid;
 /*     RECIPIENT *rcpt;
 /*     DSN     *dsn;
+/*     const BOUNCE_TEMPLATE *template;
 /*
 /*     void    bounce_mail_free(bounce_info)
 /*     BOUNCE_INFO *bounce_info;
 /*
-/*     int     bounce_header(fp, bounce_info, recipient)
+/*     int     bounce_header(fp, bounce_info, recipient, postmaster_copy)
 /*     VSTREAM *fp;
 /*     BOUNCE_INFO *bounce_info;
 /*     const char *recipient;
+/*     int     postmaster_copy;
 /*
 /*     int     bounce_boilerplate(fp, bounce_info)
 /*     VSTREAM *fp;
 /*     undeliverable message.
 /*
 /*     bounce_mail_one_init() provides the same function for only
-/*     one recipient that is not read from bounce logfile. It
-/*     assumes a template type of FAIL_TEMPLATE().
+/*     one recipient that is not read from bounce logfile.
 /*
 /*     bounce_mail_free() releases memory allocated by bounce_mail_init()
 /*     and closes any files opened by bounce_mail_init().
 /*
 /*     bounce_header() produces a standard mail header with the specified
 /*     recipient and starts a text/plain message segment for the
-/*     human-readable problem description.
+/*     human-readable problem description. postmaster_copy is either
+/*     POSTMASTER_COPY or NO_POSTMASTER_COPY.
 /*
 /*     bounce_boilerplate() produces the standard "sorry" text that
 /*     creates the illusion that mail systems are civilized.
@@ -208,7 +211,7 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
                                              const char *queue_id,
                                              const char *encoding,
                                              const char *dsn_envid,
-                                           const BOUNCE_TEMPLATE *template,
+                                             BOUNCE_TEMPLATE *template,
                                              BOUNCE_LOG *log_handle)
 {
     BOUNCE_INFO *bounce_info;
@@ -324,7 +327,7 @@ BOUNCE_INFO *bounce_mail_init(const char *service,
                                      const char *queue_id,
                                      const char *encoding,
                                      const char *dsn_envid,
-                                     const BOUNCE_TEMPLATE *template)
+                                     BOUNCE_TEMPLATE *template)
 {
     BOUNCE_INFO *bounce_info;
     BOUNCE_LOG *log_handle;
@@ -352,7 +355,8 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name,
                                          const char *encoding,
                                          const char *dsn_envid,
                                          RECIPIENT *rcpt,
-                                         DSN *dsn)
+                                         DSN *dsn,
+                                         BOUNCE_TEMPLATE *template)
 {
     BOUNCE_INFO *bounce_info;
     BOUNCE_LOG *log_handle;
@@ -363,7 +367,7 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name,
      */
     log_handle = bounce_log_forge(rcpt, dsn);
     bounce_info = bounce_mail_alloc("none", queue_name, queue_id, encoding,
-                                   dsn_envid, FAIL_TEMPLATE(), log_handle);
+                                   dsn_envid, template, log_handle);
     return (bounce_info);
 }
 
@@ -388,10 +392,9 @@ void    bounce_mail_free(BOUNCE_INFO *bounce_info)
 /* bounce_header - generate bounce message header */
 
 int     bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
-                             const char *dest)
+                             const char *dest, int postmaster_copy)
 {
-    const BOUNCE_TEMPLATE *template = bounce_info->template;
-    int     postmaster_copy;
+    BOUNCE_TEMPLATE *template = bounce_info->template;
 
     /*
      * Print a minimal bounce header. The cleanup service will add other
@@ -399,22 +402,12 @@ int     bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
      */
 #define STREQ(a, b) (strcasecmp((a), (b)) == 0)
 
-    /*
-     * XXX This should be caller specified.
-     */
-    postmaster_copy =
-       (template->postmaster_subject != 0
-        && (dest == var_bounce_rcpt || dest == var_2bounce_rcpt
-            || dest == var_delay_rcpt));
-
     /*
      * Generic headers.
      */
-    post_mail_fprintf(bounce, "From: %s", template->from);
-    post_mail_fprintf(bounce, "Subject: %s", postmaster_copy ?
-                     template->postmaster_subject : template->subject);
-    post_mail_fprintf(bounce, "To: %s",
-                     STR(quote_822_local(bounce_info->buf, dest)));
+    bounce_template_headers(post_mail_fprintf, bounce, template,
+                           STR(quote_822_local(bounce_info->buf, dest)),
+                           postmaster_copy);
 
     /*
      * MIME header. Use 8bit encoding when either the bounced message or the
@@ -427,7 +420,8 @@ int     bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
     if (bounce_info->mime_encoding)
        post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s",
                     STREQ(bounce_info->mime_encoding, MAIL_ATTR_ENC_7BIT) ?
-                     template->mime_encoding : bounce_info->mime_encoding);
+                         bounce_template_encoding(template) :
+                         bounce_info->mime_encoding);
     post_mail_fputs(bounce, "");
     post_mail_fputs(bounce, "This is a MIME-encapsulated message.");
 
@@ -438,7 +432,7 @@ int     bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
     post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary);
     post_mail_fprintf(bounce, "Content-Description: %s", "Notification");
     post_mail_fprintf(bounce, "Content-Type: %s; charset=%s",
-                     "text/plain", template->charset);
+                     "text/plain", bounce_template_charset(template));
     post_mail_fputs(bounce, "");
 
     return (vstream_ferror(bounce));
@@ -525,7 +519,7 @@ int     bounce_diagnostic_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
      */
     if (bounce_info->log_handle == 0
        || bounce_log_rewind(bounce_info->log_handle)) {
-       if (IS_FAIL_TEMPLATE(bounce_info->template)) {
+       if (IS_FAILURE_TEMPLATE(bounce_info->template)) {
            post_mail_fputs(bounce, "\t--- Delivery report unavailable ---");
            count = 1;                          /* XXX don't abort */
        }
@@ -617,7 +611,7 @@ int     bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
                          bounce_info->log_handle->rcpt.orig_addr);
     }
     post_mail_fprintf(bounce, "Action: %s",
-                     IS_FAIL_TEMPLATE(bounce_info->template) ?
+                     IS_FAILURE_TEMPLATE(bounce_info->template) ?
                      "failed" : bounce_info->log_handle->dsn.action);
     post_mail_fprintf(bounce, "Status: %s",
                      bounce_info->log_handle->dsn.status);
@@ -663,7 +657,7 @@ int     bounce_diagnostic_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
      */
     if (bounce_info->log_handle == 0
        || bounce_log_rewind(bounce_info->log_handle)) {
-       if (IS_FAIL_TEMPLATE(bounce_info->template))
+       if (IS_FAILURE_TEMPLATE(bounce_info->template))
            count = 1;                          /* XXX don't abort */
     } else {
        while (bounce_log_read(bounce_info->log_handle) != 0) {
@@ -700,7 +694,7 @@ int     bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
      * MIME headers.
      */
 #define IS_UNDELIVERED_TEMPLATE(template) \
-        (IS_FAIL_TEMPLATE(template) || IS_DELAY_TEMPLATE(template))
+        (IS_FAILURE_TEMPLATE(template) || IS_DELAY_TEMPLATE(template))
 
     post_mail_fputs(bounce, "");
     post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary);
index 2c938be8d2f887cdfb954e0e32c9502699b9cbf8..e1f69dc017047e3b744665628c2c918e85696bd1 100644 (file)
@@ -7,7 +7,8 @@
 /*     #include "bounce_service.h"
 /*
 /*     int     bounce_notify_verp(flags, service, queue_name, queue_id, sender,
-/*                                     dsn_envid, dsn_ret, verp_delims)
+/*                                     dsn_envid, dsn_ret, verp_delims,
+/*                                     templates)
 /*     int     flags;
 /*     char    *queue_name;
 /*     char    *queue_id;
@@ -15,6 +16,7 @@
 /*     char    *dsn_envid;
 /*     int     dsn_ret;
 /*     char    *verp_delims;
+/*     BOUNCE_TEMPLATES *templates;
 /* DESCRIPTION
 /*     This module implements the server side of the bounce_notify()
 /*     (send bounce message) request. The logfile
@@ -84,7 +86,8 @@
 int     bounce_notify_verp(int flags, char *service, char *queue_name,
                                   char *queue_id, char *encoding,
                                   char *recipient, char *dsn_envid,
-                                  int dsn_ret, char *verp_delims)
+                                  int dsn_ret, char *verp_delims,
+                                  BOUNCE_TEMPLATES *ts)
 {
     char   *myname = "bounce_notify_verp";
     BOUNCE_INFO *bounce_info;
@@ -109,7 +112,7 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
      * Initialize. Open queue file, bounce log, etc.
      */
     bounce_info = bounce_mail_init(service, queue_name, queue_id,
-                                  encoding, dsn_envid, FAIL_TEMPLATE());
+                                  encoding, dsn_envid, ts->failure);
 
 #define NULL_SENDER            MAIL_ADDR_EMPTY /* special address */
 #define NULL_TRACE_FLAGS       0
@@ -138,7 +141,8 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
                 * pretends that we are a polite mail system, the text with
                 * reason for the bounce, and a copy of the original message.
                 */
-               if (bounce_header(bounce, bounce_info, STR(verp_buf)) == 0
+               if (bounce_header(bounce, bounce_info, STR(verp_buf),
+                                 NO_POSTMASTER_COPY) == 0
                    && bounce_boilerplate(bounce, bounce_info) == 0
                    && bounce_recipient_log(bounce, bounce_info) == 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
@@ -186,7 +190,8 @@ int     bounce_notify_verp(int flags, char *service, char *queue_name,
                                                 postmaster,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
                                                 NULL_TRACE_FLAGS)) != 0) {
-               if (bounce_header(bounce, bounce_info, postmaster) == 0
+               if (bounce_header(bounce, bounce_info, postmaster,
+                                 POSTMASTER_COPY) == 0
                    && bounce_recipient_log(bounce, bounce_info) == 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
                    && bounce_recipient_dsn(bounce, bounce_info) == 0)
index 45e42c00ea9069e93cdbb11245519eea4d08f01b..d6355afba90b8fc2cf21f886847ddffad47cf884 100644 (file)
@@ -8,7 +8,7 @@
 /*
 /*     int     bounce_one_service(flags, queue_name, queue_id, encoding,
 /*                                     orig_sender, envid, ret,
-/*                                     rcpt, dsn)
+/*                                     rcpt, dsn, templates)
 /*     int     flags;
 /*     char    *queue_name;
 /*     char    *queue_id;
@@ -18,6 +18,7 @@
 /*     int     ret;
 /*     RECIPIENT *rcpt;
 /*     DSN     *dsn;
+/*     BOUNCE_TEMPLATES *templates;
 /* DESCRIPTION
 /*     This module implements the server side of the bounce_one()
 /*     (send bounce message for one recipient) request.
@@ -85,7 +86,8 @@
 int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                                   char *encoding, char *orig_sender,
                                   char *dsn_envid, int dsn_ret,
-                                  RECIPIENT *rcpt, DSN *dsn)
+                                  RECIPIENT *rcpt, DSN *dsn,
+                                  BOUNCE_TEMPLATES *ts)
 {
     BOUNCE_INFO *bounce_info;
     int     bounce_status = 1;
@@ -98,7 +100,7 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
      * Initialize. Open queue file, bounce log, etc.
      */
     bounce_info = bounce_mail_one_init(queue_name, queue_id, encoding,
-                                      dsn_envid, rcpt, dsn);
+                                      dsn_envid, rcpt, dsn, ts->failure);
 
 #define NULL_SENDER            MAIL_ADDR_EMPTY /* special address */
 #define NULL_TRACE_FLAGS       0
@@ -152,7 +154,8 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                 * reason for the bounce, and the headers of the original
                 * message. Don't bother sending the boiler-plate text.
                 */
-               if (!bounce_header(bounce, bounce_info, var_2bounce_rcpt)
+               if (!bounce_header(bounce, bounce_info, var_2bounce_rcpt,
+                                  POSTMASTER_COPY)
                    && bounce_recipient_log(bounce, bounce_info) == 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
                    && bounce_recipient_dsn(bounce, bounce_info) == 0)
@@ -180,7 +183,8 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                 * pretends that we are a polite mail system, the text with
                 * reason for the bounce, and a copy of the original message.
                 */
-               if (bounce_header(bounce, bounce_info, orig_sender) == 0
+               if (bounce_header(bounce, bounce_info, orig_sender,
+                                 NO_POSTMASTER_COPY) == 0
                    && bounce_boilerplate(bounce, bounce_info) == 0
                    && bounce_recipient_log(bounce, bounce_info) == 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
@@ -214,7 +218,8 @@ int     bounce_one_service(int flags, char *queue_name, char *queue_id,
                                                 var_bounce_rcpt,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
                                                 NULL_TRACE_FLAGS)) != 0) {
-               if (bounce_header(bounce, bounce_info, var_bounce_rcpt) == 0
+               if (bounce_header(bounce, bounce_info, var_bounce_rcpt,
+                                 POSTMASTER_COPY) == 0
                    && bounce_recipient_log(bounce, bounce_info) == 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
                    && bounce_recipient_dsn(bounce, bounce_info) == 0)
index 9a51116092a7013de5a13ff51c93500e235c9570..fb3af89c72c0ccf4e0ab5df4e8d568d8f2c8aad7 100644 (file)
   */
 #include <bounce_log.h>
 
+ /*
+  * Application-specific.
+  */
+#include <bounce_template.h>
+
  /*
   * bounce_append_service.c
   */
@@ -26,27 +31,27 @@ extern int bounce_append_service(int, char *, char *, RECIPIENT_VAR *, DSN_VAR *
  /*
   * bounce_notify_service.c
   */
-extern int bounce_notify_service(int, char *, char *, char *, char *, char *, char *, int);
+extern int bounce_notify_service(int, char *, char *, char *, char *, char *, char *, int, BOUNCE_TEMPLATES *);
 
  /*
   * bounce_warn_service.c
   */
-extern int bounce_warn_service(int, char *, char *, char *, char *, char *, char *, int);
+extern int bounce_warn_service(int, char *, char *, char *, char *, char *, char *, int, BOUNCE_TEMPLATES *);
 
  /*
   * bounce_trace_service.c
   */
-extern int bounce_trace_service(int, char *, char *, char *, char *, char *, char *, int);
+extern int bounce_trace_service(int, char *, char *, char *, char *, char *, char *, int, BOUNCE_TEMPLATES *);
 
  /*
   * bounce_notify_verp.c
   */
-extern int bounce_notify_verp(int, char *, char *, char *, char *, char *, char *, int, char *);
+extern int bounce_notify_verp(int, char *, char *, char *, char *, char *, char *, int, char *, BOUNCE_TEMPLATES *);
 
  /*
   * bounce_one_service.c
   */
-extern int bounce_one_service(int, char *, char *, char *, char *, char *, int, RECIPIENT *, DSN *);
+extern int bounce_one_service(int, char *, char *, char *, char *, char *, int, RECIPIENT *, DSN *, BOUNCE_TEMPLATES *);
 
  /*
   * bounce_cleanup.c
@@ -58,80 +63,6 @@ extern void bounce_cleanup_unregister(void);
 
 #define bounce_cleanup_registered() (bounce_cleanup_path != 0)
 
- /*
-  * bounce_template.c
-  */
-typedef struct {
-    const char *class;                 /* for diagnostics (fixed) */
-    const char *charset;               /* character set (configurable) */
-    const char *mime_encoding;         /* 7bit or 8bit (derived) */
-    const char *from;                  /* originator (configurable) */
-    const char *subject;               /* general subject (configurable) */
-    const char *postmaster_subject;    /* postmaster subject (configurable) */
-    const char **message_text;         /* message text (configurable) */
-} BOUNCE_TEMPLATE;
-
-typedef int (*BOUNCE_OUT_FN)(VSTREAM *, const char *);
-extern void bounce_template_load(const char *);
-extern void bounce_template_expand(BOUNCE_OUT_FN, VSTREAM *, const BOUNCE_TEMPLATE *);
-extern const BOUNCE_TEMPLATE *bounce_template_find(const char *, const BOUNCE_TEMPLATE *);
-extern void bounce_template_dump_all(VSTREAM *);
-extern void bounce_template_expand_all(VSTREAM *);
-
-#define BOUNCE_TMPL_CLASS_FAIL "failure"
-#define BOUNCE_TMPL_CLASS_DELAY        "delay"
-#define BOUNCE_TMPL_CLASS_SUCCESS "success"
-#define BOUNCE_TMPL_CLASS_VERIFY "verify"
-
-#define BOUNCE_TEMPLATE_DICT   "bounce_templates"
-#define BOUNCE_TMPL_DICT_FAIL  (BOUNCE_TMPL_CLASS_FAIL "_template")
-#define BOUNCE_TMPL_DICT_DELAY (BOUNCE_TMPL_CLASS_DELAY "_template")
-#define BOUNCE_TMPL_DICT_SUCCESS (BOUNCE_TMPL_CLASS_SUCCESS "_template")
-#define BOUNCE_TMPL_DICT_VERIFY        (BOUNCE_TMPL_CLASS_VERIFY "_template")
-
-#define FAIL_TEMPLATE() \
-    (bounce_fail_template ? bounce_fail_template : \
-       (bounce_fail_template = \
-           bounce_template_find(BOUNCE_TMPL_DICT_FAIL, \
-               &def_bounce_fail_template)))
-
-#define DELAY_TEMPLATE() \
-    (bounce_delay_template ? bounce_delay_template : \
-       (bounce_delay_template = \
-           bounce_template_find(BOUNCE_TMPL_DICT_DELAY, \
-               &def_bounce_delay_template)))
-
-#define SUCCESS_TEMPLATE() \
-    (bounce_success_template ? bounce_success_template : \
-       (bounce_success_template = \
-           bounce_template_find(BOUNCE_TMPL_DICT_SUCCESS, \
-               &def_bounce_success_template)))
-
-#define VERIFY_TEMPLATE() \
-    (bounce_verify_template ? bounce_verify_template : \
-       (bounce_verify_template = \
-           bounce_template_find(BOUNCE_TMPL_DICT_VERIFY, \
-               &def_bounce_verify_template)))
-
-#define IS_FAIL_TEMPLATE(t)    ((t) == bounce_fail_template)
-#define IS_DELAY_TEMPLATE(t)   ((t) == bounce_delay_template)
-#define IS_SUCCESS_TEMPLATE(t) ((t) == bounce_success_template)
-#define IS_VERIFY_TEMPLATE(t)  ((t) == bounce_verify_template)
-
- /*
-  * The following are not part of the bounce_template() interface. Use the
-  * above macros instead.
-  */
-extern const BOUNCE_TEMPLATE *bounce_fail_template;
-extern const BOUNCE_TEMPLATE *bounce_delay_template;
-extern const BOUNCE_TEMPLATE *bounce_success_template;
-extern const BOUNCE_TEMPLATE *bounce_verify_template;
-
-extern const BOUNCE_TEMPLATE def_bounce_fail_template;
-extern const BOUNCE_TEMPLATE def_bounce_delay_template;
-extern const BOUNCE_TEMPLATE def_bounce_success_template;
-extern const BOUNCE_TEMPLATE def_bounce_verify_template;
-
  /*
   * bounce_notify_util.c
   */
@@ -142,7 +73,7 @@ typedef struct {
     const char *mime_encoding;         /* null or encoding */
     const char *dsn_envid;             /* DSN envelope ID */
     const char *mime_boundary;         /* for MIME */
-    const BOUNCE_TEMPLATE *template;   /* see above */
+    BOUNCE_TEMPLATE *template;         /* bounce message template */
     VSTRING *buf;                      /* scratch pad */
     VSTRING *sender;                   /* envelope sender */
     VSTREAM *orig_fp;                  /* open queue file */
@@ -155,10 +86,10 @@ typedef struct {
 
  /* */
 
-extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, const char *, const BOUNCE_TEMPLATE *);
-extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, const char *, RECIPIENT *, DSN *);
+extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, const char *, BOUNCE_TEMPLATE *);
+extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, const char *, RECIPIENT *, DSN *, BOUNCE_TEMPLATE *);
 extern void bounce_mail_free(BOUNCE_INFO *);
-extern int bounce_header(VSTREAM *, BOUNCE_INFO *, const char *);
+extern int bounce_header(VSTREAM *, BOUNCE_INFO *, const char *, int);
 extern int bounce_boilerplate(VSTREAM *, BOUNCE_INFO *);
 extern int bounce_recipient_log(VSTREAM *, BOUNCE_INFO *);
 extern int bounce_diagnostic_log(VSTREAM *, BOUNCE_INFO *, int);
index 619cf6ebe3505881ce8d30010337a0ff114f7d6a..029c41a7bc718aef701b702648af2877dee1ce6f 100644 (file)
@@ -2,61 +2,90 @@
 /* NAME
 /*     bounce_template 3
 /* SUMMARY
-/*     bounce template processing
+/*     bounce template support
 /* SYNOPSIS
-/*     #include "bounce_service.h"
+/*     #include <bounce_template.h>
 /*
-/*     void    bounce_template_load(path)
-/*     const char *path;
+/*     BOUNCE_TEMPLATE *bounce_template_create(def_template)
+/*     const BOUNCE_TEMPLATE *def_template;
 /*
-/*     const BOUNCE_TEMPLATE *FAIL_TEMPLATE()
+/*     void    bounce_template_free(template)
+/*     BOUNCE_TEMPLATE *template;
 /*
-/*     const BOUNCE_TEMPLATE *DELAY_TEMPLATE()
+/*     void    bounce_template_load(stream, buffer, origin)
+/*     VSTREAM *stream;
+/*     const char *buffer;
+/*     const char *origin;
 /*
-/*     const BOUNCE_TEMPLATE *SUCCESS_TEMPLATE()
+/*     void    bounce_template_headers(out_fn, stream, template,
+/*                                     rcpt, postmaster_copy)
+/*     int     (*out_fn)(VSTREAM *, const char *, ...);
+/*     VSTREAM *stream;
+/*     BOUNCE_TEMPLATE *template;
+/*     const char *rcpt;
+/*     int     postmaster_copy;
 /*
-/*     const BOUNCE_TEMPLATE *VERIFY_TEMPLATE()
+/*     const char *bounce_template_encoding(template)
+/*     BOUNCE_TEMPLATE *template;
 /*
-/*     void    bounce_template_expand(stream, template)
-/*     VSTREAM *stream;
+/*     const char *bounce_template_charset(template)
 /*     BOUNCE_TEMPLATE *template;
-/* AUXILIARY FUNCTIONS
-/*     void    bounce_template_dump_all(stream)
+/*
+/*     void    bounce_template_expand(out_fn, stream, template)
+/*     int     (*out_fn)(VSTREAM *, const char *);
 /*     VSTREAM *stream;
+/*     BOUNCE_TEMPLATE *template;
 /*
-/*     void    bounce_template_expand_all(stream)
+/*     void    bounce_template_dump(stream, template)
 /*     VSTREAM *stream;
+/*     BOUNCE_TEMPLATE *template;
+/*
+/*     int     IS_FAILURE_TEMPLATE(template)
+/*     int     IS_DELAY_TEMPLATE(template)
+/*     int     IS_SUCCESS_TEMPLATE(template)
+/*     int     IS_VERIFY_TEMPLATE(template)
+/*     BOUNCE_TEMPLATE *template;
 /* DESCRIPTION
 /*     This module implements the built-in and external bounce
 /*     message template support.
 /*
-/*     bounce_template_load() reads bounce templates from the
-/*     specified file.
+/*     bounce_template_create() creates a template, with the
+/*     specified default settings. The template defaults are not
+/*     copied.
 /*
-/*     FAIL_TEMPLATE() etc. look up the corresponding bounce
-/*     template from file, or use a built-in template when no
-/*     template was specified externally.
+/*     bounce_template_free() destroys a bounce message template.
+/*
+/*     bounce_template_load() reads a bounce template from the
+/*     specified buffer with the specified origin. The buffer and
+/*     origin are copied. Specify a null buffer and origin pointer
+/*     to reset the template to the defaults specified with
+/*     bounce_template_create().
+/*
+/*     bounce_template_headers() sends the postmaster or non-postmaster
+/*     From/Subject/To message headers to the specified stream.
+/*     The recipient address is expected to be in RFC822 external
+/*     form. The postmaster_copy argument is one of POSTMASTER_COPY
+/*     or NO_POSTMASTER_COPY.
+/*
+/*     bounce_template_encoding() returns the encoding (MAIL_ATTR_ENC_7BIT
+/*     or MAIL_ATTR_ENC_8BIT) for the bounce template message text.
+/*
+/*     bounce_template_charset() returns the character set for the
+/*     bounce template message text.
 /*
 /*     bounce_template_expand() expands the body text of the
 /*     specified template and writes the result to the specified
-/*     queue file record stream.
-/*
-/*     bounce_template_dump_default() dumps the built-in default templates
-/*     to the specified stream. This can be used to generate input
-/*     for the default bounce service configuration file.
+/*     stream.
 /*
-/*     bounce_template_dump_actual() dumps the actually-used templates
-/*     to the specified stream. This can be used to verify that
-/*     the bounce server correctly reads its own bounce_template_dump_default()
-/*     output.
+/*     bounce_template_dump() dumps the specified template to the
+/*     specified stream.
 /*
-/*     bounce_template_expand_actual() expands the template message
-/*     text and dumps the result to the specified stream. This can
-/*     be used to verify that templates produce the desired text.
+/*     The IS_MUMBLE_TEMPLATE() macros are predicates that
+/*     return when the template is of the specified type.
 /* DIAGNOSTICS
-/*     Fatal error: error opening template file, out of memory,
-/*     undefined macro name in template.
-/* BUGS
+/*     Fatal error: out of memory, undefined macro name in template.
+/* SEE ALSO
+/*     bounce_templates(3) bounce template group support
 /* LICENSE
 /* .ad
 /* .fi
 #include <split_at.h>
 #include <stringops.h>
 #include <mymalloc.h>
-#include <dict_ml.h>
 
 /* Global library. */
 
 #include <mail_params.h>
+#include <mail_proto.h>
 #include <mail_conf.h>
-#include <mail_addr.h>
-#include <post_mail.h>
 #include <is_header.h>
-#include <mail_proto.h>
 
 /* Application-specific. */
 
-#include <bounce_service.h>
-
- /*
-  * The fail template is for permanent failure.
-  */
-static const char *def_bounce_fail_body[];
-
-const BOUNCE_TEMPLATE def_bounce_fail_template = {
-    BOUNCE_TMPL_CLASS_FAIL,
-    "us-ascii",
-    MAIL_ATTR_ENC_7BIT,
-    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
-    "Undelivered Mail Returned to Sender",
-    "Postmaster Copy: Undelivered Mail",
-    def_bounce_fail_body,
-};
-
-static const char *def_bounce_fail_body[] = {
-    "This is the $mail_name program at host $myhostname.",
-    "",
-    "I'm sorry to have to inform you that your message could not",
-    "be delivered to one or more recipients. It's attached below.",
-    "",
-    "For further assistance, please send mail to <" MAIL_ADDR_POSTMASTER ">",
-    "",
-    "If you do so, please include this problem report. You can",
-    "delete your own text from the attached returned message.",
-    "",
-    "                   The $mail_name program",
-    0,
-};
-
- /*
-  * The delay template is for delayed mail notifications.
-  */
-static const char *def_bounce_delay_body[];
-
-const BOUNCE_TEMPLATE def_bounce_delay_template = {
-    BOUNCE_TMPL_CLASS_DELAY,
-    "us-ascii",
-    MAIL_ATTR_ENC_7BIT,
-    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
-    "Delayed Mail (still being retried)",
-    "Postmaster Warning: Delayed Mail",
-    def_bounce_delay_body,
-};
-
-static const char *def_bounce_delay_body[] = {
-    "This is the $mail_name program at host $myhostname.",
-    "",
-    "####################################################################",
-    "# THIS IS A WARNING ONLY.  YOU DO NOT NEED TO RESEND YOUR MESSAGE. #",
-    "####################################################################",
-    "",
-    "Your message could not be delivered for $delay_warning_time_hours hour(s).",
-    "It will be retried until it is $maximal_queue_lifetime_days day(s) old.",
-    "",
-    "For further assistance, please send mail to <" MAIL_ADDR_POSTMASTER ">",
-    "",
-    "If you do so, please include this problem report. You can",
-    "delete your own text from the attached returned message.",
-    "",
-    "                   The $mail_name program",
-    0,
-};
-
- /*
-  * The success template is for "delivered", "expanded" and "relayed" success
-  * notifications.
-  */
-static const char *def_bounce_success_body[];
-
-const BOUNCE_TEMPLATE def_bounce_success_template = {
-    BOUNCE_TMPL_CLASS_SUCCESS,
-    "us-ascii",
-    MAIL_ATTR_ENC_7BIT,
-    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
-    "Successful Mail Delivery Report",
-    0,
-    def_bounce_success_body,
-};
-
-static const char *def_bounce_success_body[] = {
-    "This is the $mail_name program at host $myhostname.",
-    "",
-    "Your message was successfully delivered to the destination(s)",
-    "listed below. If the message was delivered to mailbox you will",
-    "receive no further notifications. Otherwise you may still receive",
-    "notifications of mail delivery errors from other systems.",
-    "",
-    "                   The $mail_name program",
-    0,
-};
-
- /*
-  * The "verify" template is for verbose delivery (sendmail -v) and for
-  * address verification (sendmail -bv).
-  */
-static const char *def_bounce_verify_body[];
-
-const BOUNCE_TEMPLATE def_bounce_verify_template = {
-    BOUNCE_TMPL_CLASS_VERIFY,
-    "us-ascii",
-    MAIL_ATTR_ENC_7BIT,
-    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
-    "Mail Delivery Status Report",
-    0,
-    def_bounce_verify_body,
-};
-
-static const char *def_bounce_verify_body[] = {
-    "This is the $mail_name program at host $myhostname.",
-    "",
-    "Enclosed is the mail delivery report that you requested.",
-    "",
-    "                   The $mail_name program",
-    0,
-};
-
- /*
-  * Pointers, so that we can override a built-in template with one from file
-  * without clobbering the built-in template.
-  */
-const BOUNCE_TEMPLATE *bounce_fail_template;
-const BOUNCE_TEMPLATE *bounce_delay_template;
-const BOUNCE_TEMPLATE *bounce_success_template;
-const BOUNCE_TEMPLATE *bounce_verify_template;
+#include <bounce_template.h>
 
  /*
   * The following tables implement support for bounce template expansions of
@@ -300,108 +200,61 @@ static BOUNCE_TIME_PARAMETER time_parameter[] = {
   */
 #define STR(x) vstring_str(x)
 
-/* bounce_template_lookup - lookup $name value */
+/* bounce_template_create - create one template */
 
-static const char *bounce_template_lookup(const char *key, int unused_mode,
-                                                 char *context)
+BOUNCE_TEMPLATE *bounce_template_create(const BOUNCE_TEMPLATE *prototype)
 {
-    BOUNCE_TEMPLATE *template = (BOUNCE_TEMPLATE *) context;
-    BOUNCE_TIME_PARAMETER *bp;
-    BOUNCE_TIME_DIVISOR *bd;
-    static VSTRING *buf;
-    int     result;
+    BOUNCE_TEMPLATE *tp;
 
-    /*
-     * Look for parameter names that can have a time unit suffix, and scale
-     * the time value according to the suffix.
-     */
-    for (bp = time_parameter; bp->param_name; bp++) {
-       if (strncmp(key, bp->param_name, bp->param_name_len) == 0
-           && key[bp->param_name_len] == '_') {
-           for (bd = time_divisors; bd->suffix; bd++) {
-               if (strcmp(key + bp->param_name_len + 1, bd->suffix) == 0) {
-                   result = bp->value[0] / bd->divisor;
-                   if (result > 999 && bd->divisor < 86400) {
-                       msg_warn("%s: excessive result \"%d\" in %s "
-                                "template conversion of parameter \"%s\"",
-                         *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                                result, template->class, key);
-                       msg_warn("please increase time unit \"%s\" of \"%s\" "
-                                "in %s template", bd->suffix, key,
-                                template->class);
-                   } else if (result == 0 && bp->value[0] && bd->divisor > 1) {
-                       msg_warn("%s: zero result in %s template "
-                                "conversion of parameter \"%s\"",
-                         *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                                template->class, key);
-                       msg_warn("please reduce time unit \"%s\" of \"%s\" "
-                                "in %s template", bd->suffix, key,
-                                template->class);
-                   }
-                   if (buf == 0)
-                       buf = vstring_alloc(10);
-                   vstring_sprintf(buf, "%d", result);
-                   return (STR(buf));
-               }
-           }
-           msg_fatal("%s: unrecognized suffix \"%s\" in parameter \"%s\"",
-                     *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                     key + bp->param_name_len + 1, key);
-       }
-    }
-    return (mail_conf_lookup_eval(key));
+    tp = (BOUNCE_TEMPLATE *) mymalloc(sizeof(*tp));
+    *tp = *prototype;
+    return (tp);
 }
 
-/* bounce_template_expand - expand template body */
+/* bounce_template_free - destroy one template */
 
-void    bounce_template_expand(BOUNCE_OUT_FN out_fn, VSTREAM *stream,
-                                      const BOUNCE_TEMPLATE *template)
+void    bounce_template_free(BOUNCE_TEMPLATE *tp)
 {
-    VSTRING *buf = vstring_alloc(100);
-    const char **cpp;
-    int     stat;
-    const char *filter = "\t !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
-
-#define NO_CONTEXT      ((char *) 0)
-
-    for (cpp = template->message_text; *cpp; cpp++) {
-       stat = mac_expand(buf, *cpp, MAC_EXP_FLAG_NONE, filter,
-                         bounce_template_lookup, (char *) template);
-       if (stat & MAC_PARSE_ERROR)
-           msg_fatal("%s: bad $name syntax in %s template: %s",
-                     *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                     template->class, *cpp);
-       if (stat & MAC_PARSE_UNDEF)
-           msg_fatal("%s: undefined $name in %s template: %s",
-                     *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                     template->class, *cpp);
-       out_fn(stream, STR(buf));
+    if (tp->buffer) {
+       myfree(tp->buffer);
+       myfree((char *) tp->origin);
     }
-    vstring_free(buf);
+    myfree((char *) tp);
 }
 
-/* bounce_template_load - load template(s) from file */
+/* bounce_template_load - override one template */
 
-void    bounce_template_load(const char *path)
+void    bounce_template_load(BOUNCE_TEMPLATE *tp, const char *origin,
+                                    const char *buffer)
 {
-    static int once = 0;
 
     /*
-     * Split the input stream into chunks between begin/end markers, ignoring
-     * comment lines.
+     * Clean up after a previous call.
+     */
+    if (tp->buffer) {
+       myfree(tp->buffer);
+       myfree((char *) tp->origin);
+    }
+
+    /*
+     * Postpone the work of template parsing until it is really needed. Most
+     * bounce service calls never need a template.
      */
-    if (once++ > 0)
-       msg_panic("bounce_template_load: multiple calls");
-    dict_ml_load_file(BOUNCE_TEMPLATE_DICT, path);
+    if (buffer && origin) {
+       tp->flags |= BOUNCE_TMPL_FLAG_NEW_BUFFER;
+       tp->buffer = mystrdup(buffer);
+       tp->origin = mystrdup(origin);
+    } else {
+       *tp = *(tp->prototype);
+       /* Also resets the buffer and origin fields. */
+    }
 }
 
-/* bounce_template_find - return default or user-specified template */
+/* bounce_template_parse_buffer - initialize template */
 
-const BOUNCE_TEMPLATE *bounce_template_find(const char *template_name,
-                                       const BOUNCE_TEMPLATE *def_template)
+static void bounce_template_parse_buffer(BOUNCE_TEMPLATE *tp)
 {
-    BOUNCE_TEMPLATE *tp;
-    char   *tval;
+    char   *tval = tp->buffer;
     char   *cp;
     char  **cpp;
     int     cpp_len;
@@ -410,31 +263,26 @@ const BOUNCE_TEMPLATE *bounce_template_find(const char *template_name,
     char   *hval;
 
     /*
-     * Look up a non-default template. Once we found it we are going to
-     * destroy it; no-one will access this data again.
+     * Sanity check.
      */
-    if (*var_bounce_tmpl == 0
-       || (tval = (char *) dict_lookup(BOUNCE_TEMPLATE_DICT, template_name)) == 0)
-       return (def_template);
+    if ((tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER) == 0)
+       msg_panic("bounce_template_parse_buffer: nothing to do here");
+    tp->flags &= ~BOUNCE_TMPL_FLAG_NEW_BUFFER;
 
     /*
-     * Initialize a new template. We're not going to use the message text
-     * from the default template.
+     * Discard the unusable template and use the default one instead.
      */
-    tp = (BOUNCE_TEMPLATE *) mymalloc(sizeof(*tp));
-    *tp = *def_template;
-
-#define CLEANUP_AND_RETURN(x) do { \
-       myfree((char *) tp); \
-       return (x); \
+#define CLEANUP_AND_RETURN() do { \
+       myfree(tp->buffer); \
+       myfree((char *) tp->origin); \
+       *tp = *(tp->prototype); \
     } while (0)
 
-
     /*
      * Parse pseudo-header labels and values.
      */
 #define GETLINE(line, buf) \
-       (((line) = (buf)) ? ((buf) = split_at((buf), '\n'), (line)) : 0)
+        (((line) = (buf)) ? ((buf) = split_at((buf), '\n'), (line)) : 0)
 
     while ((GETLINE(cp, tval)) != 0 && (hlen = is_header(cp)) > 0) {
        for (hval = cp + hlen; *hval && (*hval == ':' || ISSPACE(*hval)); hval++)
@@ -442,19 +290,17 @@ const BOUNCE_TEMPLATE *bounce_template_find(const char *template_name,
        if (*hval == 0) {
            msg_warn("%s: empty \"%s\" header value in %s template "
                     "-- ignoring this template",
-                    *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                    cp, template_name);
-           CLEANUP_AND_RETURN(def_template);
+                    tp->origin, cp, tp->class);
+           CLEANUP_AND_RETURN();
        }
        if (!allascii(hval)) {
            msg_warn("%s: non-ASCII \"%s\" header value in %s template "
                     "-- ignoring this template",
-                    *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                    cp, template_name);
-           CLEANUP_AND_RETURN(def_template);
+                    tp->origin, cp, tp->class);
+           CLEANUP_AND_RETURN();
        }
        if (strcasecmp("charset", cp) == 0) {
-           tp->charset = hval;
+           tp->mime_charset = hval;
        } else if (strcasecmp("from", cp) == 0) {
            tp->from = hval;
        } else if (strcasecmp("subject", cp) == 0) {
@@ -463,17 +309,15 @@ const BOUNCE_TEMPLATE *bounce_template_find(const char *template_name,
            if (tp->postmaster_subject == 0) {
                msg_warn("%s: inapplicable \"%s\" header label in %s template "
                         "-- ignoring this template",
-                        *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                        cp, template_name);
-               CLEANUP_AND_RETURN(def_template);
+                        tp->origin, cp, tp->class);
+               CLEANUP_AND_RETURN();
            }
            tp->postmaster_subject = hval;
        } else {
            msg_warn("%s: unknown \"%s\" header label in %s template "
                     "-- ignoring this template",
-                    *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                    cp, template_name);
-           CLEANUP_AND_RETURN(def_template);
+                    tp->origin, cp, tp->class);
+           CLEANUP_AND_RETURN();
        }
     }
 
@@ -485,9 +329,8 @@ const BOUNCE_TEMPLATE *bounce_template_find(const char *template_name,
     if (cp == 0) {
        msg_warn("%s: missing message text in %s template "
                 "-- ignoring this template",
-                *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                template_name);
-       CLEANUP_AND_RETURN(def_template);
+                tp->origin, tp->class);
+       CLEANUP_AND_RETURN();
     }
 
     /*
@@ -497,13 +340,12 @@ const BOUNCE_TEMPLATE *bounce_template_find(const char *template_name,
 #define NON_ASCII(p) (*(p) && !allascii((p)))
 
     if (NON_ASCII(cp) || NON_ASCII(tval)) {
-       if (strcasecmp(tp->charset, "us-ascii") == 0) {
+       if (strcasecmp(tp->mime_charset, "us-ascii") == 0) {
            msg_warn("%s: 8-bit message text in %s template",
-                    *var_bounce_tmpl ? var_bounce_tmpl : "[built-in]",
-                    template_name);
+                    tp->origin, tp->class);
            msg_warn("please specify a charset value other than us-ascii");
            msg_warn("-- ignoring this template for now");
-           CLEANUP_AND_RETURN(def_template);
+           CLEANUP_AND_RETURN();
        }
        tp->mime_encoding = MAIL_ATTR_ENC_8BIT;
     }
@@ -525,68 +367,115 @@ const BOUNCE_TEMPLATE *bounce_template_find(const char *template_name,
     }
     cpp[cpp_used] = 0;
     tp->message_text = (const char **) cpp;
-
-    return (tp);
 }
 
-/* print_template - dump one template */
+/* bounce_template_lookup - lookup $name value */
 
-static void print_template(VSTREAM *stream, const BOUNCE_TEMPLATE *tp)
+static const char *bounce_template_lookup(const char *key, int unused_mode,
+                                                 char *context)
 {
-    const char **cpp;
+    BOUNCE_TEMPLATE *tp = (BOUNCE_TEMPLATE *) context;
+    BOUNCE_TIME_PARAMETER *bp;
+    BOUNCE_TIME_DIVISOR *bd;
+    static VSTRING *buf;
+    int     result;
 
-    vstream_fprintf(stream, "%s_template = <<EOF\n", tp->class);
-    vstream_fprintf(stream, "Charset: %s\n", tp->charset);
-    vstream_fprintf(stream, "From: %s\n", tp->from);
-    vstream_fprintf(stream, "Subject: %s\n", tp->subject);
-    if (tp->postmaster_subject)
-       vstream_fprintf(stream, "Postmaster-Subject: %s\n",
-                       tp->postmaster_subject);
-    vstream_fprintf(stream, "\n");
-    for (cpp = tp->message_text; *cpp; cpp++)
-       vstream_fprintf(stream, "%s\n", *cpp);
-    vstream_fprintf(stream, "EOF\n");
-    vstream_fflush(stream);
+    /*
+     * Look for parameter names that can have a time unit suffix, and scale
+     * the time value according to the suffix.
+     */
+    for (bp = time_parameter; bp->param_name; bp++) {
+       if (strncmp(key, bp->param_name, bp->param_name_len) == 0
+           && key[bp->param_name_len] == '_') {
+           for (bd = time_divisors; bd->suffix; bd++) {
+               if (strcmp(key + bp->param_name_len + 1, bd->suffix) == 0) {
+                   result = bp->value[0] / bd->divisor;
+                   if (result > 999 && bd->divisor < 86400) {
+                       msg_warn("%s: excessive result \"%d\" in %s "
+                                "template conversion of parameter \"%s\"",
+                                tp->origin, result, tp->class, key);
+                       msg_warn("please increase time unit \"%s\" of \"%s\" "
+                             "in %s template", bd->suffix, key, tp->class);
+                   } else if (result == 0 && bp->value[0] && bd->divisor > 1) {
+                       msg_warn("%s: zero result in %s template "
+                                "conversion of parameter \"%s\"",
+                                tp->origin, tp->class, key);
+                       msg_warn("please reduce time unit \"%s\" of \"%s\" "
+                             "in %s template", bd->suffix, key, tp->class);
+                   }
+                   if (buf == 0)
+                       buf = vstring_alloc(10);
+                   vstring_sprintf(buf, "%d", result);
+                   return (STR(buf));
+               }
+           }
+           msg_fatal("%s: unrecognized suffix \"%s\" in parameter \"%s\"",
+                     tp->origin,
+                     key + bp->param_name_len + 1, key);
+       }
+    }
+    return (mail_conf_lookup_eval(key));
 }
 
-/* bounce_template_dump_all - dump bounce templates to stream */
+/* bounce_template_headers - send template headers */
 
-void    bounce_template_dump_all(VSTREAM *stream)
+void    bounce_template_headers(BOUNCE_XP_PRN_FN out_fn, VSTREAM *fp,
+                                       BOUNCE_TEMPLATE *tp,
+                                       const char *rcpt,
+                                       int postmaster_copy)
 {
-    print_template(VSTREAM_OUT, FAIL_TEMPLATE());
-    vstream_fprintf(stream, "\n");
-    print_template(VSTREAM_OUT, DELAY_TEMPLATE());
-    vstream_fprintf(stream, "\n");
-    print_template(VSTREAM_OUT, SUCCESS_TEMPLATE());
-    vstream_fprintf(stream, "\n");
-    print_template(VSTREAM_OUT, VERIFY_TEMPLATE());
+    if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER)
+       bounce_template_parse_buffer(tp);
+
+    out_fn(fp, "From: %s", tp->from);
+    out_fn(fp, "Subject: %s", tp->postmaster_subject && postmaster_copy ?
+          tp->postmaster_subject : tp->subject);
+    out_fn(fp, "To: %s", rcpt);
 }
 
-/* bounce_plain_out - output line as plain text */
+/* bounce_template_expand - expand template to stream */
 
-static int bounce_plain_out(VSTREAM *stream, const char *text)
+void    bounce_template_expand(BOUNCE_XP_PUT_FN out_fn, VSTREAM *fp,
+                                      BOUNCE_TEMPLATE *tp)
 {
-    vstream_fprintf(stream, "%s\n", text);
-    return (0);
+    VSTRING *buf = vstring_alloc(100);
+    const char **cpp;
+    int     stat;
+    const char *filter = "\t !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+
+    if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER)
+       bounce_template_parse_buffer(tp);
+
+    for (cpp = tp->message_text; *cpp; cpp++) {
+       stat = mac_expand(buf, *cpp, MAC_EXP_FLAG_NONE, filter,
+                         bounce_template_lookup, (char *) tp);
+       if (stat & MAC_PARSE_ERROR)
+           msg_fatal("%s: bad $name syntax in %s template: %s",
+                     tp->origin, tp->class, *cpp);
+       if (stat & MAC_PARSE_UNDEF)
+           msg_fatal("%s: undefined $name in %s template: %s",
+                     tp->origin, tp->class, *cpp);
+       out_fn(fp, STR(buf));
+    }
+    vstring_free(buf);
 }
 
-/* bounce_template_expand_all - dump expanded template text to stream */
+/* bounce_template_dump - dump template to stream */
 
-void    bounce_template_expand_all(VSTREAM *stream)
+void    bounce_template_dump(VSTREAM *fp, BOUNCE_TEMPLATE *tp)
 {
-    const BOUNCE_TEMPLATE *tp;
-
-    tp = FAIL_TEMPLATE();
-    vstream_fprintf(VSTREAM_OUT, "expanded_%s_text = <<EOF\n", tp->class);
-    bounce_template_expand(bounce_plain_out, VSTREAM_OUT, tp);
-    tp = DELAY_TEMPLATE();
-    vstream_fprintf(VSTREAM_OUT, "EOF\n\nexpanded_%s_text = <<EOF\n", tp->class);
-    bounce_template_expand(bounce_plain_out, VSTREAM_OUT, tp);
-    tp = SUCCESS_TEMPLATE();
-    vstream_fprintf(VSTREAM_OUT, "EOF\n\nexpanded_%s_text = <<EOF\n", tp->class);
-    bounce_template_expand(bounce_plain_out, VSTREAM_OUT, tp);
-    tp = VERIFY_TEMPLATE();
-    vstream_fprintf(VSTREAM_OUT, "EOF\n\nexpanded_%s_text = <<EOF\n", tp->class);
-    bounce_template_expand(bounce_plain_out, VSTREAM_OUT, tp);
-    vstream_fprintf(VSTREAM_OUT, "EOF\n");
+    const char **cpp;
+
+    if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER)
+       bounce_template_parse_buffer(tp);
+
+    vstream_fprintf(fp, "Charset: %s\n", tp->mime_charset);
+    vstream_fprintf(fp, "From: %s\n", tp->from);
+    vstream_fprintf(fp, "Subject: %s\n", tp->subject);
+    if (tp->postmaster_subject)
+       vstream_fprintf(fp, "Postmaster-Subject: %s\n",
+                       tp->postmaster_subject);
+    vstream_fprintf(fp, "\n");
+    for (cpp = tp->message_text; *cpp; cpp++)
+       vstream_fprintf(fp, "%s\n", *cpp);
 }
diff --git a/postfix/src/bounce/bounce_template.h b/postfix/src/bounce/bounce_template.h
new file mode 100644 (file)
index 0000000..fe6c655
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef _BOUNCE_TEMPLATE_H_INCLUDED_
+#define _BOUNCE_TEMPLATE_H_INCLUDED_
+
+/*++
+/* NAME
+/*     bounce_template 3h
+/* SUMMARY
+/*     bounce template support
+/* SYNOPSIS
+/*     #include <bounce_template.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <vstream.h>
+
+ /*
+  * Structure of a single bounce template. Each template is manipulated by
+  * itself, without any external markers and delimiters. Applications are not
+  * supposed to access BOUNCE_TEMPLATE attributes directly.
+  */
+typedef struct BOUNCE_TEMPLATE {
+    int     flags;
+    const char *class;                 /* for diagnostics (fixed) */
+    const char *origin;                        /* built-in or pathname */
+    const char *mime_charset;          /* character set (configurable) */
+    const char *mime_encoding;         /* 7bit or 8bit (derived) */
+    const char *from;                  /* originator (configurable) */
+    const char *subject;               /* general subject (configurable) */
+    const char *postmaster_subject;    /* postmaster subject (configurable) */
+    const char **message_text;         /* message text (configurable) */
+    const struct BOUNCE_TEMPLATE *prototype;   /* defaults */
+    char   *buffer;                    /* ripped text */
+} BOUNCE_TEMPLATE;
+
+#define BOUNCE_TMPL_FLAG_NEW_BUFFER    (1<<0)
+
+#define BOUNCE_TMPL_CLASS_FAILURE      "failure"
+#define BOUNCE_TMPL_CLASS_DELAY                "delay"
+#define BOUNCE_TMPL_CLASS_SUCCESS      "success"
+#define BOUNCE_TMPL_CLASS_VERIFY       "verify"
+
+#define IS_FAILURE_TEMPLATE(t) ((t)->class[0] == BOUNCE_TMPL_CLASS_FAILURE[0])
+#define IS_DELAY_TEMPLATE(t)   ((t)->class[0] == BOUNCE_TMPL_CLASS_DELAY[0])
+#define IS_SUCCESS_TEMPLATE(t) ((t)->class[0] == BOUNCE_TMPL_CLASS_SUCCESS[0])
+#define IS_VERIFY_TEMPLATE(t)  ((t)->class[0] == BOUNCE_TMPL_CLASS_verify[0])
+
+#define bounce_template_encoding(t)    ((t)->mime_encoding)
+#define bounce_template_charset(t)     ((t)->mime_charset)
+
+typedef int (*BOUNCE_XP_PRN_FN) (VSTREAM *, const char *, ...);
+typedef int (*BOUNCE_XP_PUT_FN) (VSTREAM *, const char *);
+
+extern BOUNCE_TEMPLATE *bounce_template_create(const BOUNCE_TEMPLATE *);
+extern void bounce_template_free(BOUNCE_TEMPLATE *);
+extern void bounce_template_load(BOUNCE_TEMPLATE *, const char *, const char *);
+extern void bounce_template_headers(BOUNCE_XP_PRN_FN, VSTREAM *, BOUNCE_TEMPLATE *, const char *, int);
+extern void bounce_template_expand(BOUNCE_XP_PUT_FN, VSTREAM *, BOUNCE_TEMPLATE *);
+extern void bounce_template_dump(VSTREAM *, BOUNCE_TEMPLATE *);
+
+#define POSTMASTER_COPY                1       /* postmaster copy */
+#define NO_POSTMASTER_COPY     0       /* not postmaster copy */
+
+ /*
+  * Structure of a bounce template collection. These templates are read and
+  * written in their external representation, with markers and delimiters.
+  */
+typedef struct {
+    BOUNCE_TEMPLATE *failure;
+    BOUNCE_TEMPLATE *delay;
+    BOUNCE_TEMPLATE *success;
+    BOUNCE_TEMPLATE *verify;
+} BOUNCE_TEMPLATES;
+
+BOUNCE_TEMPLATES *bounce_templates_create(void);
+void    bounce_templates_free(BOUNCE_TEMPLATES *);
+void    bounce_templates_load(VSTREAM *, BOUNCE_TEMPLATES *);
+void    bounce_templates_expand(VSTREAM *, BOUNCE_TEMPLATES *);
+void    bounce_templates_dump(VSTREAM *, BOUNCE_TEMPLATES *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/bounce/bounce_templates.c b/postfix/src/bounce/bounce_templates.c
new file mode 100644 (file)
index 0000000..7038e3f
--- /dev/null
@@ -0,0 +1,390 @@
+/*++
+/* NAME
+/*     bounce_templates 3
+/* SUMMARY
+/*     bounce template group support
+/* SYNOPSIS
+/*     #include <bounce_template.h>
+/*
+/*     BOUNCE_TEMPLATES *bounce_templates_create(void)
+/*
+/*     void    bounce_templates_free(templates)
+/*     BOUNCE_TEMPLATES *templates;
+/*
+/*     void    bounce_templates_load(stream, templates)
+/*     VSTREAM *stream;
+/*     BOUNCE_TEMPLATES *templates;
+/*
+/*     void    bounce_templates_expand(stream, templates)
+/*     VSTREAM *stream;
+/*     BOUNCE_TEMPLATES *templates;
+/*
+/*     void    bounce_templates_dump(stream, templates)
+/*     VSTREAM *stream;
+/*     BOUNCE_TEMPLATES *templates;
+/* DESCRIPTION
+/*     This module implements support for bounce template groups
+/*     (i.e. groups that contain one template of each type).
+/*
+/*     bounce_templates_create() creates a bounce template group,
+/*     with default settings.
+/*
+/*     bounce_templates_free() destroys a bounce template group.
+/*
+/*     bounce_templates_load() reads zero or more bounce templates
+/*     from the specified file.
+/*
+/*     bounce_templates_expand() expands $name macros and writes
+/*     the text portions of the specified bounce template group
+/*     to the specified stream.
+/*
+/*     bounce_templates_dump() writes the complete content of the
+/*     specified bounce template group to the specified stream.
+/*     The format is compatible with bounce_templates_load().
+/* DIAGNOSTICS
+/*     Fatal error: out of memory, undefined macro name in template.
+/* SEE ALSO
+/*     bounce_template(3) bounce template support
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <ctype.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+
+/* Global library. */
+
+#include <mail_addr.h>
+#include <mail_proto.h>
+
+/* Application-specific. */
+
+#include <bounce_template.h>
+
+ /*
+  * The fail template is for permanent failure.
+  */
+static const char *def_bounce_failure_body[];
+
+static const BOUNCE_TEMPLATE def_bounce_failure_template = {
+    0,
+    BOUNCE_TMPL_CLASS_FAILURE,
+    "[built-in]",
+    "us-ascii",
+    MAIL_ATTR_ENC_7BIT,
+    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
+    "Undelivered Mail Returned to Sender",
+    "Postmaster Copy: Undelivered Mail",
+    def_bounce_failure_body,
+    &def_bounce_failure_template,
+};
+
+static const char *def_bounce_failure_body[] = {
+    "This is the $mail_name program at host $myhostname.",
+    "",
+    "I'm sorry to have to inform you that your message could not",
+    "be delivered to one or more recipients. It's attached below.",
+    "",
+    "For further assistance, please send mail to <" MAIL_ADDR_POSTMASTER ">",
+    "",
+    "If you do so, please include this problem report. You can",
+    "delete your own text from the attached returned message.",
+    "",
+    "                   The $mail_name program",
+    0,
+};
+
+ /*
+  * The delay template is for delayed mail notifications.
+  */
+static const char *def_bounce_delay_body[];
+
+static const BOUNCE_TEMPLATE def_bounce_delay_template = {
+    0,
+    BOUNCE_TMPL_CLASS_DELAY,
+    "[built-in]",
+    "us-ascii",
+    MAIL_ATTR_ENC_7BIT,
+    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
+    "Delayed Mail (still being retried)",
+    "Postmaster Warning: Delayed Mail",
+    def_bounce_delay_body,
+    &def_bounce_delay_template
+};
+
+static const char *def_bounce_delay_body[] = {
+    "This is the $mail_name program at host $myhostname.",
+    "",
+    "####################################################################",
+    "# THIS IS A WARNING ONLY.  YOU DO NOT NEED TO RESEND YOUR MESSAGE. #",
+    "####################################################################",
+    "",
+    "Your message could not be delivered for $delay_warning_time_hours hour(s)."
+    ,
+    "It will be retried until it is $maximal_queue_lifetime_days day(s) old.",
+    "",
+    "For further assistance, please send mail to <" MAIL_ADDR_POSTMASTER ">",
+    "",
+    "If you do so, please include this problem report. You can",
+    "delete your own text from the attached returned message.",
+    "",
+    "                   The $mail_name program",
+    0,
+};
+
+ /*
+  * The success template is for "delivered", "expanded" and "relayed" success
+  * notifications.
+  */
+static const char *def_bounce_success_body[];
+
+static const BOUNCE_TEMPLATE def_bounce_success_template = {
+    0,
+    BOUNCE_TMPL_CLASS_SUCCESS,
+    "[built-in]",
+    "us-ascii",
+    MAIL_ATTR_ENC_7BIT,
+    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
+    "Successful Mail Delivery Report",
+    0,
+    def_bounce_success_body,
+    &def_bounce_success_template,
+};
+
+static const char *def_bounce_success_body[] = {
+    "This is the $mail_name program at host $myhostname.",
+    "",
+    "Your message was successfully delivered to the destination(s)",
+    "listed below. If the message was delivered to mailbox you will",
+    "receive no further notifications. Otherwise you may still receive",
+    "notifications of mail delivery errors from other systems.",
+    "",
+    "                   The $mail_name program",
+    0,
+};
+
+ /*
+  * The "verify" template is for verbose delivery (sendmail -v) and for
+  * address verification (sendmail -bv).
+  */
+static const char *def_bounce_verify_body[];
+
+static const BOUNCE_TEMPLATE def_bounce_verify_template = {
+    0,
+    BOUNCE_TMPL_CLASS_VERIFY,
+    "[built-in]",
+    "us-ascii",
+    MAIL_ATTR_ENC_7BIT,
+    MAIL_ADDR_MAIL_DAEMON " (Mail Delivery System)",
+    "Mail Delivery Status Report",
+    0,
+    def_bounce_verify_body,
+    &def_bounce_verify_template,
+};
+
+static const char *def_bounce_verify_body[] = {
+    "This is the $mail_name program at host $myhostname.",
+    "",
+    "Enclosed is the mail delivery report that you requested.",
+    "",
+    "                   The $mail_name program",
+    0,
+};
+
+ /*
+  * SLMs.
+  */
+#define STR(x) vstring_str(x)
+
+/* bounce_templates_create - create template group */
+
+BOUNCE_TEMPLATES *bounce_templates_create(void)
+{
+    BOUNCE_TEMPLATES *bs;
+
+    bs = (BOUNCE_TEMPLATES *) mymalloc(sizeof(*bs));
+    bs->failure = bounce_template_create(&def_bounce_failure_template);
+    bs->delay = bounce_template_create(&def_bounce_delay_template);
+    bs->success = bounce_template_create(&def_bounce_success_template);
+    bs->verify = bounce_template_create(&def_bounce_verify_template);
+    return (bs);
+}
+
+/* bounce_templates_free - destroy template group */
+
+void    bounce_templates_free(BOUNCE_TEMPLATES *bs)
+{
+    bounce_template_free(bs->failure);
+    bounce_template_free(bs->delay);
+    bounce_template_free(bs->success);
+    bounce_template_free(bs->verify);
+    myfree((char *) bs);
+}
+
+/* bounce_templates_load - load template or group from stream */
+
+void    bounce_templates_load(VSTREAM *fp, BOUNCE_TEMPLATES *ts)
+{
+    VSTRING *line_buf;
+    char   *member_name;
+    VSTRING *multi_line_buf = 0;
+    VSTRING *saved_member_name = 0;
+    VSTRING *saved_end_marker = 0;
+    char   *value;
+    int     lineno;
+    const char *err;
+    char   *cp;
+    int     len;                       /* Grr... */
+
+    /*
+     * XXX That's a lot of non-reusable code to parse a configuration file.
+     * Unfortunately, much of the "name = value" infrastructure is married to
+     * the dict(3) class which doesn't really help here.
+     */
+    line_buf = vstring_alloc(100);
+    lineno = 1;
+    while (vstring_get_nonl(line_buf, fp) > 0) {
+       lineno++;
+       cp = STR(line_buf) + strspn(STR(line_buf), " \t\n\v\f\r");
+       if (*cp == 0 || *cp == '#')
+           continue;
+       if ((err = split_nameval(STR(line_buf), &member_name, &value)) != 0)
+           msg_fatal("%s, line %d: %s: \"%s\"",
+                     VSTREAM_PATH(fp), lineno, err, STR(line_buf));
+       if (value[0] == '<' && value[1] == '<') {
+           value += 2;
+           while (ISSPACE(*value))
+               value++;
+           if (*value == 0)
+               msg_fatal("%s, line %d: missing end marker after <<",
+                         VSTREAM_PATH(fp), lineno);
+           if (!ISALNUM(*value))
+               msg_fatal("%s, line %d: malformed end marker after <<",
+                         VSTREAM_PATH(fp), lineno);
+           if (multi_line_buf == 0) {
+               saved_member_name = vstring_alloc(100);
+               saved_end_marker = vstring_alloc(100);
+               multi_line_buf = vstring_alloc(100);
+           } else
+               VSTRING_RESET(multi_line_buf);
+           vstring_strcpy(saved_member_name, member_name);
+           vstring_strcpy(saved_end_marker, value);
+           while (vstring_get_nonl(line_buf, fp) > 0) {
+               lineno++;
+               if (strcmp(STR(line_buf), STR(saved_end_marker)) == 0)
+                   break;
+               if (VSTRING_LEN(multi_line_buf) > 0)
+                   vstring_strcat(multi_line_buf, "\n");
+               vstring_strcat(multi_line_buf, STR(line_buf));
+           }
+           if (vstream_feof(fp))
+               msg_warn("%s, line %d: missing \"%s\" end marker",
+                         VSTREAM_PATH(fp), lineno, value);
+           member_name = STR(saved_member_name);
+           value = STR(multi_line_buf);
+       }
+#define MATCH_TMPL_NAME(tname, tname_len, mname) \
+    (strncmp(tname, mname, tname_len = strlen(tname)) == 0 \
+       && strcmp(mname + tname_len, "_template") == 0)
+
+       if (MATCH_TMPL_NAME(ts->failure->class, len, member_name))
+           bounce_template_load(ts->failure, VSTREAM_PATH(fp), value);
+       else if (MATCH_TMPL_NAME(ts->delay->class, len, member_name))
+           bounce_template_load(ts->delay, VSTREAM_PATH(fp), value);
+       else if (MATCH_TMPL_NAME(ts->success->class, len, member_name))
+           bounce_template_load(ts->success, VSTREAM_PATH(fp), value);
+       else if (MATCH_TMPL_NAME(ts->verify->class, len, member_name))
+           bounce_template_load(ts->verify, VSTREAM_PATH(fp), value);
+       else
+           msg_warn("%s, line %d: unknown template name: %s "
+                    "-- ignoring this template",
+                    VSTREAM_PATH(fp), lineno, member_name);
+    }
+    vstring_free(line_buf);
+    if (multi_line_buf) {
+       vstring_free(saved_member_name);
+       vstring_free(saved_end_marker);
+       vstring_free(multi_line_buf);
+    }
+}
+
+/* bounce_plain_out - output line as plain text */
+
+static int bounce_plain_out(VSTREAM *fp, const char *text)
+{
+    vstream_fprintf(fp, "%s\n", text);
+    return (0);
+}
+
+/* bounce_templates_expand - dump expanded template group text to stream */
+
+void    bounce_templates_expand(VSTREAM *fp, BOUNCE_TEMPLATES *ts)
+{
+    BOUNCE_TEMPLATE *tp;
+
+    tp = ts->failure;
+    vstream_fprintf(fp, "expanded_%s_text = <<EOF\n", tp->class);
+    bounce_template_expand(bounce_plain_out, fp, tp);
+    vstream_fprintf(fp, "EOF\n\n");
+
+    tp = ts->delay;
+    vstream_fprintf(fp, "expanded_%s_text = <<EOF\n", tp->class);
+    bounce_template_expand(bounce_plain_out, fp, tp);
+    vstream_fprintf(fp, "EOF\n\n");
+
+    tp = ts->success;
+    vstream_fprintf(fp, "expanded_%s_text = <<EOF\n", tp->class);
+    bounce_template_expand(bounce_plain_out, fp, tp);
+    vstream_fprintf(fp, "EOF\n\n");
+
+    tp = ts->verify;
+    vstream_fprintf(fp, "expanded_%s_text = <<EOF\n", tp->class);
+    bounce_template_expand(bounce_plain_out, fp, tp);
+    vstream_fprintf(fp, "EOF\n");
+}
+
+/* bounce_templates_dump - dump bounce template group to stream */
+
+void    bounce_templates_dump(VSTREAM *fp, BOUNCE_TEMPLATES *ts)
+{
+    BOUNCE_TEMPLATE *tp;
+
+    tp = ts->failure;
+    vstream_fprintf(fp, "%s_template = <<EOF\n", tp->class);
+    bounce_template_dump(fp, tp);
+    vstream_fprintf(fp, "EOF\n\n");
+
+    tp = ts->delay;
+    vstream_fprintf(fp, "%s_template = <<EOF\n", tp->class);
+    bounce_template_dump(fp, tp);
+    vstream_fprintf(fp, "EOF\n\n");
+
+    tp = ts->success;
+    vstream_fprintf(fp, "%s_template = <<EOF\n", tp->class);
+    bounce_template_dump(fp, tp);
+    vstream_fprintf(fp, "EOF\n\n");
+
+    tp = ts->verify;
+    vstream_fprintf(fp, "%s_template = <<EOF\n", tp->class);
+    bounce_template_dump(fp, tp);
+    vstream_fprintf(fp, "EOF\n");
+}
index c760f16188fe5756690bca039474bcfe6ea5995d..a1f9fd532885ef64c99651bbfae7863dc3067cef 100644 (file)
@@ -7,7 +7,7 @@
 /*     #include "bounce_service.h"
 /*
 /*     int     bounce_trace_service(flags, queue_name, queue_id, encoding,
-/*                                     sender, char *envid, int ret)
+/*                                     sender, char *envid, int ret, templates)
 /*     int     flags;
 /*     char    *queue_name;
 /*     char    *queue_id;
@@ -15,6 +15,7 @@
 /*     char    *sender;
 /*     char    *envid;
 /*     int     ret;
+/*     BOUNCE_TEMPLATES *templates;
 /* DESCRIPTION
 /*     This module implements the server side of the trace_flush()
 /*     (send delivery notice) request. The logfile
@@ -80,7 +81,8 @@
 int     bounce_trace_service(int flags, char *service, char *queue_name,
                                     char *queue_id, char *encoding,
                                     char *recipient, char *dsn_envid,
-                                    int unused_dsn_ret)
+                                    int unused_dsn_ret,
+                                    BOUNCE_TEMPLATES *ts)
 {
     BOUNCE_INFO *bounce_info;
     int     bounce_status = 1;
@@ -106,8 +108,7 @@ int     bounce_trace_service(int flags, char *service, char *queue_name,
     bounce_info = bounce_mail_init(service, queue_name, queue_id,
                                   encoding, dsn_envid,
                                   flags & NON_DSN_FLAGS ?
-                                  VERIFY_TEMPLATE() :
-                                  SUCCESS_TEMPLATE());
+                                  ts->verify : ts->success);
 
     /*
      * XXX With multi-recipient mail some queue file recipients may have
@@ -145,7 +146,8 @@ int     bounce_trace_service(int flags, char *service, char *queue_name,
                                         CLEANUP_FLAG_MASK_INTERNAL,
                                         NULL_TRACE_FLAGS)) != 0) {
        count = -1;
-       if (bounce_header(bounce, bounce_info, recipient) == 0
+       if (bounce_header(bounce, bounce_info, recipient,
+                         NO_POSTMASTER_COPY) == 0
            && bounce_boilerplate(bounce, bounce_info) == 0
            && (count = bounce_diagnostic_log(bounce, bounce_info,
                                              DSN_NOTIFY_OVERRIDE)) > 0
index 229965fd8731bfc9ac0ba76ebe99641fc9f737f7..f446dd6d5f61fd32e1a5fea061c9705852cce57b 100644 (file)
@@ -7,7 +7,7 @@
 /*     #include "bounce_service.h"
 /*
 /*     int     bounce_warn_service(flags, queue_name, queue_id, encoding,
-/*                                     sender, envid, dsn_ret)
+/*                                     sender, envid, dsn_ret, templates)
 /*     int     flags;
 /*     char    *queue_name;
 /*     char    *queue_id;
@@ -15,6 +15,7 @@
 /*     char    *sender;
 /*     char    *envid;
 /*     int     dsn_ret;
+/*     BOUNCE_TEMPLATES *ts;
 /* DESCRIPTION
 /*     This module implements the server side of the bounce_warn()
 /*     (send delay notice) request. The logfile
@@ -83,7 +84,7 @@
 int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
                                    char *queue_id, char *encoding,
                                    char *recipient, char *dsn_envid,
-                                   int dsn_ret)
+                                   int dsn_ret, BOUNCE_TEMPLATES *ts)
 {
     BOUNCE_INFO *bounce_info;
     int     bounce_status = 1;
@@ -117,7 +118,7 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
      * notify_classes restrictions.
      */
     bounce_info = bounce_mail_init(service, queue_name, queue_id,
-                                  encoding, dsn_envid, DELAY_TEMPLATE());
+                                  encoding, dsn_envid, ts->delay);
 
 #define NULL_SENDER            MAIL_ADDR_EMPTY /* special address */
 #define NULL_TRACE_FLAGS       0
@@ -172,7 +173,8 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
                 * message. Don't bother sending the boiler-plate text.
                 */
                count = -1;
-               if (!bounce_header(bounce, bounce_info, postmaster)
+               if (!bounce_header(bounce, bounce_info, postmaster,
+                                  POSTMASTER_COPY)
                    && (count = bounce_diagnostic_log(bounce, bounce_info,
                                                   DSN_NOTIFY_OVERRIDE)) > 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
@@ -204,7 +206,8 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
             * reason for the bounce, and a copy of the original message.
             */
            count = -1;
-           if (bounce_header(bounce, bounce_info, recipient) == 0
+           if (bounce_header(bounce, bounce_info, recipient,
+                             NO_POSTMASTER_COPY) == 0
                && bounce_boilerplate(bounce, bounce_info) == 0
                && (count = bounce_diagnostic_log(bounce, bounce_info,
                                                  DSN_NOTIFY_DELAY)) > 0
@@ -243,7 +246,8 @@ int     bounce_warn_service(int unused_flags, char *service, char *queue_name,
                                                 CLEANUP_FLAG_MASK_INTERNAL,
                                                 NULL_TRACE_FLAGS)) != 0) {
                count = -1;
-               if (bounce_header(bounce, bounce_info, postmaster) == 0
+               if (bounce_header(bounce, bounce_info, postmaster,
+                                 POSTMASTER_COPY) == 0
                    && (count = bounce_diagnostic_log(bounce, bounce_info,
                                                   DSN_NOTIFY_OVERRIDE)) > 0
                    && bounce_header_dsn(bounce, bounce_info) == 0
diff --git a/postfix/src/bounce/dict_ml.c b/postfix/src/bounce/dict_ml.c
deleted file mode 100644 (file)
index d7be3f1..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*++
-/* NAME
-/*     dict 3
-/* SUMMARY
-/*     dictionary manager, multi-line entry support
-/* SYNOPSIS
-/*     #include <dict_ml.h>
-/*
-/*     void    dict_ml_load_file(dict_name, path)
-/*     const char *dict_name;
-/*     const char *path;
-/*
-/*     void    dict_ml_load_fp(dict_name, fp)
-/*     const char *dict_name;
-/*     VSTREAM *fp;
-/* DESCRIPTION
-/*     This module implements input routines for dictionaries
-/*     with single-line and multi-line values.
-/* .IP \(bu
-/*     Single-line values are specified as "name = value".
-/*     Like dict_load_file() and dict_load_fp(), leading and
-/*     trailing whitespace is stripped from name and value.
-/* .IP \(bu
-/*     Multi-line values are specified as:
-/*
-/* .na
-/* .nf
-/* .in +4
-/*     name = <<EOF
-/*     text here...
-/*     EOF
-/* .in -4
-/* .ad
-/* .fi
-/*
-/*     Leading or trailing white space is not stripped from
-/*     multi-line values.
-/* .IP \(bu
-/*     The following input is ignored outside "<<" context: empty
-/*     lines, all whitespace lines, and lines whose first
-/*     non-whitespace character is "#".
-/* .PP
-/*     dict_ml_load_file() enters (name, value) pairs from the
-/*     specified file to the specified dictionary.
-/*
-/*     dict_ml_load_fp() reads (name, value) pairs from an open
-/*     stream. It has the same semantics as dict_ml_load_file().
-/* SEE ALSO
-/*     dict(3)
-/* DIAGNOSTICS
-/*     Fatal errors: out of memory, malformed macro name, missing
-/*     or mal-formed end marker.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System library. */
-
-#include <sys_defs.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <ctype.h>
-#include <string.h>
-
-/* Utility library. */
-
-#include <msg.h>
-#include <vstring.h>
-#include <vstream.h>
-#include <vstring_vstream.h>
-#include <iostuff.h>
-#include <stringops.h>
-#include <dict.h>
-#include <dict_ml.h>
-
-#define STR(x) vstring_str(x)
-
-/* dict_ml_load_file - load table from file */
-
-void    dict_ml_load_file(const char *dict_name, const char *path)
-{
-    VSTREAM *fp;
-    struct stat st;
-    time_t  before;
-    time_t  after;
-
-    /*
-     * Read the file again if it is hot. This may result in reading a partial
-     * parameter name when a file changes in the middle of a read.
-     */
-    for (before = time((time_t *) 0); /* see below */ ; before = after) {
-       if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0)
-           msg_fatal("open %s: %m", path);
-       dict_ml_load_fp(dict_name, fp);
-       if (fstat(vstream_fileno(fp), &st) < 0)
-           msg_fatal("fstat %s: %m", path);
-       if (vstream_ferror(fp) || vstream_fclose(fp))
-           msg_fatal("read %s: %m", path);
-       after = time((time_t *) 0);
-       if (st.st_mtime < before - 1 || st.st_mtime > after)
-           break;
-       if (msg_verbose)
-           msg_info("pausing to let %s cool down", path);
-       doze(300000);
-    }
-}
-
-/* dict_ml_load_fp - load table from stream */
-
-void    dict_ml_load_fp(const char *dict_name, VSTREAM *fp)
-{
-    VSTRING *line_buf;
-    char   *member_name;
-    VSTRING *multi_line_buf = 0;
-    VSTRING *saved_member_name = 0;
-    VSTRING *saved_end_marker = 0;
-    char   *value;
-    int     lineno;
-    const char *err;
-    char   *cp;
-
-    line_buf = vstring_alloc(100);
-    lineno = 1;
-    while (vstring_get_nonl(line_buf, fp) > 0) {
-       lineno++;
-       cp = STR(line_buf) + strspn(STR(line_buf), " \t\n\v\f\r");
-       if (*cp == 0 || *cp == '#')
-           continue;
-       if ((err = split_nameval(STR(line_buf), &member_name, &value)) != 0)
-           msg_fatal("%s, line %d: %s: \"%s\"",
-                     VSTREAM_PATH(fp), lineno, err, STR(line_buf));
-       if (value[0] == '<' && value[1] == '<') {
-           value += 2;
-           while (ISSPACE(*value))
-               value++;
-           if (*value == 0)
-               msg_fatal("%s, line %d: missing end marker after <<",
-                         VSTREAM_PATH(fp), lineno);
-           if (!ISALNUM(*value))
-               msg_fatal("%s, line %d: malformed end marker after <<",
-                         VSTREAM_PATH(fp), lineno);
-           if (multi_line_buf == 0) {
-               saved_member_name = vstring_alloc(100);
-               saved_end_marker = vstring_alloc(100);
-               multi_line_buf = vstring_alloc(100);
-           } else
-               VSTRING_RESET(multi_line_buf);
-           vstring_strcpy(saved_member_name, member_name);
-           vstring_strcpy(saved_end_marker, value);
-           while (vstring_get_nonl(line_buf, fp) > 0) {
-               lineno++;
-               if (strcmp(STR(line_buf), STR(saved_end_marker)) == 0)
-                   break;
-               if (VSTRING_LEN(multi_line_buf) > 0)
-                   vstring_strcat(multi_line_buf, "\n");
-               vstring_strcat(multi_line_buf, STR(line_buf));
-           }
-           if (vstream_feof(fp))
-               msg_fatal("%s, line %d: missing \"%s\" end marker",
-                         VSTREAM_PATH(fp), lineno, value);
-           member_name = STR(saved_member_name);
-           value = STR(multi_line_buf);
-       }
-       dict_update(dict_name, member_name, value);
-    }
-    vstring_free(line_buf);
-    if (multi_line_buf) {
-       vstring_free(saved_member_name);
-       vstring_free(saved_end_marker);
-       vstring_free(multi_line_buf);
-    }
-}
diff --git a/postfix/src/bounce/dict_ml.h b/postfix/src/bounce/dict_ml.h
deleted file mode 100644 (file)
index b7f47dc..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _DICT_ML_H_INCLUDED_
-#define _DICT_ML_H_INCLUDED_
-
-/*++
-/* NAME
-/*     dict_ml 3h
-/* SUMMARY
-/*     dictionary manager, multi-line entry support
-/* SYNOPSIS
-/*     #include <dict_ml.h>
-/* DESCRIPTION
-/* .nf
-
- /*
-  * Utility library.
-  */
-#include <vstream.h>
-#include <dict.h>
-
- /*
-  * External interface.
-  */
-extern void dict_ml_load_file(const char *, const char *);
-extern void dict_ml_load_fp(const char *, VSTREAM *);
-
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-#endif
diff --git a/postfix/src/bounce/template_test.ref b/postfix/src/bounce/template_test.ref
new file mode 100644 (file)
index 0000000..3fac4d4
--- /dev/null
@@ -0,0 +1,68 @@
+failure_template = <<EOF
+Charset: us-ascii
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Undelivered Mail Returned to Sender
+Postmaster-Subject: Postmaster Copy: Undelivered Mail
+
+This is the $mail_name program at host $myhostname.
+
+I'm sorry to have to inform you that your message could not
+be delivered to one or more recipients. It's attached below.
+
+For further assistance, please send mail to <postmaster>
+
+If you do so, please include this problem report. You can
+delete your own text from the attached returned message.
+
+                   The $mail_name program
+EOF
+
+delay_template = <<EOF
+Charset: us-ascii
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Delayed Mail (still being retried)
+Postmaster-Subject: Postmaster Warning: Delayed Mail
+
+This is the $mail_name program at host $myhostname.
+
+####################################################################
+# THIS IS A WARNING ONLY.  YOU DO NOT NEED TO RESEND YOUR MESSAGE. #
+####################################################################
+
+Your message could not be delivered for $delay_warning_time_hours hour(s).
+It will be retried until it is $maximal_queue_lifetime_days day(s) old.
+
+For further assistance, please send mail to <postmaster>
+
+If you do so, please include this problem report. You can
+delete your own text from the attached returned message.
+
+                   The $mail_name program
+EOF
+
+success_template = <<EOF
+Charset: us-ascii
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Successful Mail Delivery Report
+
+This is the $mail_name program at host $myhostname.
+
+Your message was successfully delivered to the destination(s)
+listed below. If the message was delivered to mailbox you will
+receive no further notifications. Otherwise you may still receive
+notifications of mail delivery errors from other systems.
+
+                   The $mail_name program
+EOF
+
+verify_template = <<EOF
+Charset: us-ascii
+From: MAILER-DAEMON (Mail Delivery System)
+Subject: Mail Delivery Status Report
+
+This is the $mail_name program at host $myhostname.
+
+Enclosed is the mail delivery report that you requested.
+
+                   The $mail_name program
+EOF
index ab32fe444b07b63f1d3d510f0e1c19bd59d23481..b1db34f3798c71b5f2ada9d811c0868c6d3aef7f 100644 (file)
@@ -19,6 +19,9 @@
 #ifdef RESOLVE_H_NEEDS_STDIO_H
 #include <stdio.h>
 #endif
+#ifdef RESOLVE_H_NEEDS_NAMESER8_COMPAT_H
+#include <nameser8_compat.h>
+#endif
 #include <resolv.h>
 
  /*
index 0485ca136f0a642c0f3edc1ee5677185ee8940b7..e78f0833d97d9cc683f788023867c9bf86e76193 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20051114"
+#define MAIL_RELEASE_DATE      "20051117"
 #define MAIL_VERSION_NUMBER    "2.3"
 
 #ifdef SNAPSHOT
index 42bad2ef6e10fd228fc28becc257b5991f18d077..ed3796d4d50eb3937ca197139f9c877f74d1754f 100644 (file)
 /* FILES
 /*     /etc/postfix/main.cf, Postfix configuration parameters
 /* SEE ALSO
-/*     bounce(5), bouce template file format
+/*     bounce(5), bounce template file format
 /*     postconf(5), configuration parameters
 /* README FILES
 /* .ad
index 182d8eb274d932e40eb247dee1b068e1223d33fe..153836e0da624ab4175919fce2063b38f864169e 100644 (file)
@@ -30,7 +30,7 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
        vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
        write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
-       allascii.c
+       allascii.c load_file.c
 OBJS   = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
        attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@@ -62,7 +62,7 @@ OBJS  = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
        vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
        write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
-       allascii.o
+       allascii.o load_file.o
 HDRS   = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
        dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
@@ -81,7 +81,7 @@ HDRS  = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        sigdelay.h sock_addr.h spawn_command.h split_at.h stat_as.h \
        stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \
        username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
-       vstring_vstream.h watchdog.h format_tv.h
+       vstring_vstream.h watchdog.h format_tv.h load_file.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c dup2_pass_on_exec.c
 DEFS   = -I. -D$(SYSTYPE)
@@ -1112,6 +1112,13 @@ inet_trigger.o: trigger.h
 line_wrap.o: line_wrap.c
 line_wrap.o: line_wrap.h
 line_wrap.o: sys_defs.h
+load_file.o: iostuff.h
+load_file.o: load_file.c
+load_file.o: load_file.h
+load_file.o: msg.h
+load_file.o: sys_defs.h
+load_file.o: vbuf.h
+load_file.o: vstream.h
 lowercase.o: lowercase.c
 lowercase.o: stringops.h
 lowercase.o: sys_defs.h
diff --git a/postfix/src/util/load_file.c b/postfix/src/util/load_file.c
new file mode 100644 (file)
index 0000000..59af345
--- /dev/null
@@ -0,0 +1,79 @@
+/*++
+/* NAME
+/*     load_file 3
+/* SUMMARY
+/*     load file with some prejudice
+/* SYNOPSIS
+/*     #include <load_file.h>
+/*
+/*     void    load_file(path, action, context)
+/*     const char *path;
+/*     void    (*action)(VSTREAM, void *);
+/*     void    *context;
+/* DESCRIPTION
+/*     This routine reads a file and reads it again when the
+/*     file changed recently.
+/*
+/*     Arguments:
+/* .IP path
+/*     The file to be opened, read-only.
+/* .IP action
+/*     The function that presumably reads the file.
+/* .IP context
+/*     Application-specific context for the action routine.
+/* DIAGNOSTICS
+/*     Fatal errors: out of memory, cannot open file.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <time.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstream.h>
+#include <iostuff.h>
+#include <load_file.h>
+
+/* load_file - load file with some prejudice */
+
+void    load_file(const char *path, LOAD_FILE_FN action, void *context)
+{
+    VSTREAM *fp;
+    struct stat st;
+    time_t  before;
+    time_t  after;
+
+    /*
+     * Read the file again if it is hot. This may result in reading a partial
+     * parameter name or missing end marker when a file changes in the middle
+     * of a read.
+     */
+    for (before = time((time_t *) 0); /* see below */ ; before = after) {
+       if ((fp = vstream_fopen(path, O_RDONLY, 0)) == 0)
+           msg_fatal("open %s: %m", path);
+       action(fp, context);
+       if (fstat(vstream_fileno(fp), &st) < 0)
+           msg_fatal("fstat %s: %m", path);
+       if (vstream_ferror(fp) || vstream_fclose(fp))
+           msg_fatal("read %s: %m", path);
+       after = time((time_t *) 0);
+       if (st.st_mtime < before - 1 || st.st_mtime > after)
+           break;
+       if (msg_verbose)
+           msg_info("pausing to let %s cool down", path);
+       doze(300000);
+    }
+}
diff --git a/postfix/src/util/load_file.h b/postfix/src/util/load_file.h
new file mode 100644 (file)
index 0000000..3e635f3
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef LOAD_FILE_H_INCLUDED_
+#define LOAD_FILE_H_INCLUDED_
+
+/*++
+/* NAME
+/*     load_file 3h
+/* SUMMARY
+/*     load file with some prejudice
+/* SYNOPSIS
+/*     #include <load_file.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * External interface.
+  */
+typedef void (*LOAD_FILE_FN)(VSTREAM *, void *);
+
+extern void load_file(const char *, LOAD_FILE_FN, void *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
index 6c52e02c69343036d79f2218a4f76f968b684500..17d7968cfe240ae7f7b23890f7fa38f5b8f98ae7 100644 (file)
@@ -50,7 +50,7 @@
 #endif
 #define GETTIMEOFDAY(t)        gettimeofday(t,(struct timezone *) 0)
 #define ROOT_PATH      "/bin:/usr/bin:/sbin:/usr/sbin"
-#if (defined(__NetBSD_Version__) && __NetBSD_Version__ > 200040000)
+#if (defined(__NetBSD_Version__) && __NetBSD_Version__ > 299000900)
 # define USE_STATVFS
 # define STATVFS_IN_SYS_STATVFS_H
 #else
 #define SOCKOPT_SIZE   socklen_t
 #endif
 
-#if __NetBSD_Version__ >= 200060000    /* 2.0F */
+#if __NetBSD_Version__ >= 299000900    /* 2.99.9 */
 #define HAS_CLOSEFROM
 #endif
 
 #define DEF_DB_TYPE    "hash"
 #define ALIAS_DB_MAP   "hash:/etc/aliases"
 #define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
+#define RESOLVE_H_NEEDS_NAMESER8_COMPAT_H
 #define ROOT_PATH      "/bin:/usr/bin:/sbin:/usr/sbin"
 #define USE_STATFS
 #define STATFS_IN_SYS_MOUNT_H