]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.4-20070116
authorWietse Venema <wietse@porcupine.org>
Tue, 16 Jan 2007 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:32:48 +0000 (06:32 +0000)
48 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/MILTER_README
postfix/RELEASE_NOTES
postfix/html/MILTER_README.html
postfix/proto/MILTER_README.html
postfix/src/cleanup/Makefile.in
postfix/src/cleanup/cleanup.h
postfix/src/cleanup/cleanup_api.c
postfix/src/cleanup/cleanup_body_region.c [new file with mode: 0644]
postfix/src/cleanup/cleanup_envelope.c
postfix/src/cleanup/cleanup_extracted.c
postfix/src/cleanup/cleanup_message.c
postfix/src/cleanup/cleanup_milter.c
postfix/src/cleanup/cleanup_milter.in10a [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.in10b [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.in10c [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.in10d [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.in10e [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref10a [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref10b [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref10c [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref10d [new file with mode: 0644]
postfix/src/cleanup/cleanup_milter.ref10e [new file with mode: 0644]
postfix/src/cleanup/cleanup_state.c
postfix/src/cleanup/loremipsum [new file with mode: 0644]
postfix/src/cleanup/loremipsum2 [new file with mode: 0644]
postfix/src/cleanup/test-queue-file10 [new file with mode: 0644]
postfix/src/global/Makefile.in
postfix/src/global/mail_version.h
postfix/src/global/mime_garb3.ref
postfix/src/global/mime_garb4.in [new file with mode: 0644]
postfix/src/global/mime_garb4.ref [new file with mode: 0644]
postfix/src/global/mime_state.c
postfix/src/global/rec_type.h
postfix/src/global/record.c
postfix/src/global/record.h
postfix/src/milter/milter.c
postfix/src/milter/milter.h
postfix/src/milter/milter8.c
postfix/src/milter/test-milter.c
postfix/src/oqmgr/qmgr.h
postfix/src/oqmgr/qmgr_deliver.c
postfix/src/oqmgr/qmgr_message.c
postfix/src/qmgr/qmgr.h
postfix/src/qmgr/qmgr_deliver.c
postfix/src/qmgr/qmgr_message.c
postfix/src/smtpd/smtpd_exp.ref

index 2970847d7760b60f6eb2c8ca717308306eb5a960..c45e2f9ce87cf797090d259bae5534d8a19b65d0 100644 (file)
@@ -28,6 +28,7 @@
 -TBOUNCE_TIME_PARAMETER
 -TCFG_PARSER
 -TCIDR_MATCH
+-TCLEANUP_BODY_REGION
 -TCLEANUP_STATE
 -TCLEANUP_STAT_DETAIL
 -TCLIENT_LIST
index f72f6cc80ae5ed61e91f9c1cf877ebecef1148ef..0e6d4be2afe8a628b1280863740aa6aa6e803fd5 100644 (file)
@@ -13096,16 +13096,25 @@ Apologies for any names omitted.
 
 20070112
 
-       Bugfix (introduced 20011008): with nested access restrictions,
-       possible longjump into exited stack frame after configuration
-       error or table lookup error. Victor Duchovni.  Files:
-       smtpd/smtpd_check.c.
-
-       Horrible workaround: don't insert header/body blank line
-       separator in malformed attachments. This breaks digital
-       signatures. People concerned about MIME evasion can use a
-       MIME normalizer to corrupt their user's legitimate email.
-       File: global/mime_state.c.
+       Bugfix (introduced 20011008): after return from nested
+       access restriction, possible longjump into exited stack
+       frame upon configuration error or table lookup error. Victor
+       Duchovni.  Files: smtpd/smtpd_check.c.
+
+       Workaround: don't insert header/body blank line separator
+       in malformed attachments, to avoid breaking digital signatures.
+       Switch from header to body state, for robust MIME parsing.
+       People concerned about MIME evasion can use a MIME normalizer
+       to corrupt their user's legitimate email.  File:
+       global/mime_state.c.
+
+20070114
+
+       Feature: body replacement support for Milter applications.
+       Postfix 2.3 and older 2.4 versions will be able to deliver
+       body-replaced queue files, but will report the message size
+       as it was before the body was replaced.  Files: milter/milter8.c,
+       cleanup/cleanup_milter.c, cleanup/cleanup_body_region.c.
 
 Wish list:
 
index ca95394f61d28bc20d43cf87ece03a8eb0ed5f7c..ac96f8c88e3b40e925eee788cb47f38e57d782d8 100644 (file)
@@ -15,9 +15,10 @@ authenticity (examples: SenderID+SPF and Domain keys) or to digitally sign mail
 (example: Domain keys). Having yet another Postfix-specific version of all that
 software is a poor use of human and system resources.
 
-Postfix 2.3 implements all the requests of Sendmail version 8 Milter protocols
-up to version 4, except one: message body replacement. See, however, the
-workarounds and limitations sections at the end of this document.
+Postfix version 2.4 implements all the requests of Sendmail version 8 Milter
+protocols up to version 4, including message body replacement (body replacement
+is not available with Postfix version 2.3). See, however, the workarounds and
+limitations sections at the end of this document.
 
 This document provides information on the following topics:
 
@@ -513,7 +514,7 @@ the CONTENT_INSPECTION_README document for a discussion.
         application name: st_optionneg[134563840]: 0x3d does not fulfill action
         requirements 0x1e
 
-    The solution is (to wait for) a Postfix version that supports the missing
+    The solution is to use a Postfix version that supports the missing
     functionality.
 
   * Most Milter configuration options are global. Future Postfix versions may
index 84d03ca59091f6e087af7a287f8244420eb25cfa..0173df6bee14f8457e1908e4862a64f5b17a3abd 100644 (file)
@@ -17,6 +17,21 @@ Incompatibility with Postfix 2.2 and earlier
 If you upgrade from Postfix 2.2 or earlier, read RELEASE_NOTES-2.3
 before proceeding.
 
+Incompatible changes with Postfix snapshot 20070116
+===================================================
+
+A new field is added to the queue file "size" record that specifies
+the message content length.  Postfix 2.3 and older Postfix 2.4
+versions will ignore this field, and will report the message size
+as it was before the body was replaced.
+
+Major changes with Postfix snapshot 20070116
+============================================
+
+Support for Milter applications that replace the message body.
+Postfix now implements all the header/body modification requests
+that are available with Sendmail 8.13.
+
 Incompatible changes with Postfix snapshot 20061217
 ===================================================
 
index 2619bab66bced4d3a702ebc679e6d0417c918eea..1bbb5cce09fd4208c95c071010bac906fdb866e0 100644 (file)
@@ -35,8 +35,10 @@ href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>).
 Having yet another Postfix-specific version of all that software
 is a poor use of human and system resources. </p>
 
-<p> Postfix 2.3 implements all the requests of Sendmail version 8
-Milter protocols up to version 4, except one: message body replacement.
+<p> Postfix version 2.4 implements all the requests of Sendmail
+version 8 Milter protocols up to version 4, including message body
+replacement (body replacement is not available with Postfix version
+2.3).
 See, however, the <a href="#workarounds">workarounds</a> and <a
 href="#limitations">limitations</a> sections at the end of this
 document. </p>
@@ -793,8 +795,8 @@ operation will log a warning like this: </p>
 </pre>
 </blockquote>
 
-<p> The solution is (to wait for) a Postfix version that supports
-the missing functionality.
+<p> The solution is to use a Postfix version that supports the
+missing functionality. </p>
 
 <li> <p> Most Milter configuration options are global. Future Postfix
 versions may support per-Milter timeouts, per-Milter error handling,
index 3fcf83da22bea9ff32693531c89462c92a587386..853bb8ae3c55c81829d65bba153341f1c8ae3d17 100644 (file)
@@ -35,8 +35,10 @@ href="http://sourceforge.net/projects/dk-milter/">Domain keys</a>).
 Having yet another Postfix-specific version of all that software
 is a poor use of human and system resources. </p>
 
-<p> Postfix 2.3 implements all the requests of Sendmail version 8
-Milter protocols up to version 4, except one: message body replacement.
+<p> Postfix version 2.4 implements all the requests of Sendmail
+version 8 Milter protocols up to version 4, including message body
+replacement (body replacement is not available with Postfix version
+2.3).
 See, however, the <a href="#workarounds">workarounds</a> and <a
 href="#limitations">limitations</a> sections at the end of this
 document. </p>
@@ -793,8 +795,8 @@ operation will log a warning like this: </p>
 </pre>
 </blockquote>
 
-<p> The solution is (to wait for) a Postfix version that supports
-the missing functionality.
+<p> The solution is to use a Postfix version that supports the
+missing functionality. </p>
 
 <li> <p> Most Milter configuration options are global. Future Postfix
 versions may support per-Milter timeouts, per-Milter error handling,
index 2bf737122db22bb9047a762347236c24e84f4257..5630233249cc74821220328743d01bd26c38f3c3 100644 (file)
@@ -3,12 +3,14 @@ SRCS  = cleanup.c cleanup_out.c cleanup_envelope.c cleanup_message.c \
        cleanup_extracted.c cleanup_state.c cleanup_rewrite.c \
        cleanup_map11.c cleanup_map1n.c cleanup_masquerade.c \
        cleanup_out_recipient.c cleanup_init.c cleanup_api.c \
-       cleanup_addr.c cleanup_bounce.c cleanup_milter.c
+       cleanup_addr.c cleanup_bounce.c cleanup_milter.c \
+       cleanup_body_region.c
 OBJS   = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \
        cleanup_extracted.o cleanup_state.o cleanup_rewrite.o \
        cleanup_map11.o cleanup_map1n.o cleanup_masquerade.o \
        cleanup_out_recipient.o cleanup_init.o cleanup_api.o \
-       cleanup_addr.o cleanup_bounce.o cleanup_milter.o
+       cleanup_addr.o cleanup_bounce.o cleanup_milter.o \
+       cleanup_body_region.o
 HDRS   =
 TESTSRC        = 
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -59,15 +61,20 @@ cleanup_masquerade: cleanup_masquerade.o
        mv junk cleanup_masquerade.o
 
 CLEANUP_MILTER_OBJS = cleanup_state.o cleanup_out.o cleanup_addr.o \
-       cleanup_out_recipient.o 
+       cleanup_out_recipient.o cleanup_body_region.o
 cleanup_milter: cleanup_milter.o $(CLEANUP_MILTER_OBJS) $(LIBS)
        mv cleanup_milter.o junk
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(CLEANUP_MILTER_OBJS) $(LIBS) $(SYSLIBS)
        mv junk cleanup_milter.o
 
-tests: cleanup_masquerade_test cleanup_milter_test bug_tests \
+tests: cleanup_masquerade_test milter_tests
+
+milter_tests: cleanup_milter_test bug_tests \
        cleanup_milter_test2 cleanup_milter_test3 cleanup_milter_test4 \
-       cleanup_milter_test5 cleanup_milter_test6 cleanup_milter_test7
+       cleanup_milter_test5 cleanup_milter_test6 cleanup_milter_test7 \
+       cleanup_milter_test8 cleanup_milter_test9 cleanup_milter_test10a \
+       cleanup_milter_test10b cleanup_milter_test10c cleanup_milter_test10d \
+       cleanup_milter_test10e
 
 root_tests:
 
@@ -176,6 +183,7 @@ cleanup_milter_test6a: cleanup_milter test-queue-file6 cleanup_milter.in6a \
        ./cleanup_milter <cleanup_milter.in6a
        ../postcat/postcat -ov test-queue-file6.tmp 2>/dev/null >cleanup_milter.tmp
        diff cleanup_milter.ref6a cleanup_milter.tmp
+       rm -f test-queue-file6.tmp cleanup_milter.tmp
 
 cleanup_milter_test6b: cleanup_milter test-queue-file6 cleanup_milter.in6b \
        cleanup_milter.ref6b test-queue-file6 ../postcat/postcat
@@ -184,6 +192,7 @@ cleanup_milter_test6b: cleanup_milter test-queue-file6 cleanup_milter.in6b \
        ./cleanup_milter <cleanup_milter.in6b
        ../postcat/postcat -ov test-queue-file6.tmp 2>/dev/null >cleanup_milter.tmp
        diff cleanup_milter.ref6b cleanup_milter.tmp
+       rm -f test-queue-file6.tmp cleanup_milter.tmp
 
 cleanup_milter_test6c: cleanup_milter test-queue-file6 cleanup_milter.in6c \
        cleanup_milter.ref6c test-queue-file6 ../postcat/postcat
@@ -192,6 +201,7 @@ cleanup_milter_test6c: cleanup_milter test-queue-file6 cleanup_milter.in6c \
        ./cleanup_milter <cleanup_milter.in6c
        ../postcat/postcat -ov test-queue-file6.tmp 2>/dev/null >cleanup_milter.tmp
        diff cleanup_milter.ref6c cleanup_milter.tmp
+       rm -f test-queue-file6.tmp cleanup_milter.tmp
 
 cleanup_milter_test7: cleanup_milter test-queue-file7 cleanup_milter.in7 \
        cleanup_milter.ref7 test-queue-file7 ../postcat/postcat
@@ -200,6 +210,7 @@ cleanup_milter_test7: cleanup_milter test-queue-file7 cleanup_milter.in7 \
        ./cleanup_milter <cleanup_milter.in7
        ../postcat/postcat -ov test-queue-file7.tmp 2>/dev/null >cleanup_milter.tmp
        diff cleanup_milter.ref7 cleanup_milter.tmp
+       rm -f test-queue-file7.tmp cleanup_milter.tmp
 
 cleanup_milter_test8: cleanup_milter test-queue-file8 cleanup_milter.in8 \
        cleanup_milter.ref8 test-queue-file8 ../postcat/postcat
@@ -208,6 +219,7 @@ cleanup_milter_test8: cleanup_milter test-queue-file8 cleanup_milter.in8 \
        ./cleanup_milter <cleanup_milter.in8
        ../postcat/postcat -ov test-queue-file8.tmp 2>/dev/null >cleanup_milter.tmp
        diff cleanup_milter.ref8 cleanup_milter.tmp
+       rm -f test-queue-file8.tmp cleanup_milter.tmp
 
 cleanup_milter_test9: cleanup_milter test-queue-file9 cleanup_milter.in9 \
        cleanup_milter.ref9 test-queue-file9 ../postcat/postcat
@@ -216,6 +228,52 @@ cleanup_milter_test9: cleanup_milter test-queue-file9 cleanup_milter.in9 \
        ./cleanup_milter <cleanup_milter.in9
        ../postcat/postcat -ov test-queue-file9.tmp 2>/dev/null >cleanup_milter.tmp
        diff cleanup_milter.ref9 cleanup_milter.tmp
+       rm -f test-queue-file9.tmp cleanup_milter.tmp
+
+cleanup_milter_test10a: cleanup_milter test-queue-file10 cleanup_milter.in10a \
+       cleanup_milter.ref10a test-queue-file10 ../postcat/postcat
+       cp test-queue-file10 test-queue-file10.tmp
+       chmod u+w test-queue-file10.tmp
+       ./cleanup_milter <cleanup_milter.in10a
+       ../postcat/postcat -ov test-queue-file10.tmp 2>/dev/null >cleanup_milter.tmp
+       diff cleanup_milter.ref10a cleanup_milter.tmp
+       rm -f test-queue-file10.tmp cleanup_milter.tmp
+
+cleanup_milter_test10b: cleanup_milter test-queue-file10 cleanup_milter.in10b \
+       cleanup_milter.ref10b test-queue-file10 ../postcat/postcat
+       cp test-queue-file10 test-queue-file10.tmp
+       chmod u+w test-queue-file10.tmp
+       ./cleanup_milter <cleanup_milter.in10b
+       ../postcat/postcat -ov test-queue-file10.tmp 2>/dev/null >cleanup_milter.tmp
+       diff cleanup_milter.ref10b cleanup_milter.tmp
+       rm -f test-queue-file10.tmp cleanup_milter.tmp
+
+cleanup_milter_test10c: cleanup_milter test-queue-file10 cleanup_milter.in10c \
+       cleanup_milter.ref10c test-queue-file10 ../postcat/postcat
+       cp test-queue-file10 test-queue-file10.tmp
+       chmod u+w test-queue-file10.tmp
+       ./cleanup_milter <cleanup_milter.in10c
+       ../postcat/postcat -ov test-queue-file10.tmp 2>/dev/null >cleanup_milter.tmp
+       diff cleanup_milter.ref10c cleanup_milter.tmp
+       rm -f test-queue-file10.tmp cleanup_milter.tmp
+
+cleanup_milter_test10d: cleanup_milter test-queue-file10 cleanup_milter.in10c \
+       cleanup_milter.ref10d test-queue-file10 ../postcat/postcat
+       cp test-queue-file10 test-queue-file10.tmp
+       chmod u+w test-queue-file10.tmp
+       ./cleanup_milter <cleanup_milter.in10d
+       ../postcat/postcat -ov test-queue-file10.tmp 2>/dev/null >cleanup_milter.tmp
+       diff cleanup_milter.ref10d cleanup_milter.tmp
+       rm -f test-queue-file10.tmp cleanup_milter.tmp
+
+cleanup_milter_test10e: cleanup_milter test-queue-file10 cleanup_milter.in10c \
+       cleanup_milter.ref10e test-queue-file10 ../postcat/postcat
+       cp test-queue-file10 test-queue-file10.tmp
+       chmod u+w test-queue-file10.tmp
+       ./cleanup_milter <cleanup_milter.in10e
+       ../postcat/postcat -ov test-queue-file10.tmp 2>/dev/null >cleanup_milter.tmp
+       diff cleanup_milter.ref10e cleanup_milter.tmp
+       rm -f test-queue-file10.tmp cleanup_milter.tmp
 
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
@@ -322,6 +380,7 @@ cleanup_api.o: ../../include/msg.h
 cleanup_api.o: ../../include/msg_stats.h
 cleanup_api.o: ../../include/mymalloc.h
 cleanup_api.o: ../../include/nvtable.h
+cleanup_api.o: ../../include/rec_type.h
 cleanup_api.o: ../../include/recipient_list.h
 cleanup_api.o: ../../include/resolve_clnt.h
 cleanup_api.o: ../../include/string_list.h
@@ -332,6 +391,33 @@ cleanup_api.o: ../../include/vstream.h
 cleanup_api.o: ../../include/vstring.h
 cleanup_api.o: cleanup.h
 cleanup_api.o: cleanup_api.c
+cleanup_body_region.o: ../../include/argv.h
+cleanup_body_region.o: ../../include/been_here.h
+cleanup_body_region.o: ../../include/cleanup_user.h
+cleanup_body_region.o: ../../include/dict.h
+cleanup_body_region.o: ../../include/header_opts.h
+cleanup_body_region.o: ../../include/htable.h
+cleanup_body_region.o: ../../include/mail_conf.h
+cleanup_body_region.o: ../../include/mail_stream.h
+cleanup_body_region.o: ../../include/maps.h
+cleanup_body_region.o: ../../include/match_list.h
+cleanup_body_region.o: ../../include/match_ops.h
+cleanup_body_region.o: ../../include/milter.h
+cleanup_body_region.o: ../../include/mime_state.h
+cleanup_body_region.o: ../../include/msg.h
+cleanup_body_region.o: ../../include/mymalloc.h
+cleanup_body_region.o: ../../include/nvtable.h
+cleanup_body_region.o: ../../include/rec_type.h
+cleanup_body_region.o: ../../include/record.h
+cleanup_body_region.o: ../../include/resolve_clnt.h
+cleanup_body_region.o: ../../include/string_list.h
+cleanup_body_region.o: ../../include/sys_defs.h
+cleanup_body_region.o: ../../include/tok822.h
+cleanup_body_region.o: ../../include/vbuf.h
+cleanup_body_region.o: ../../include/vstream.h
+cleanup_body_region.o: ../../include/vstring.h
+cleanup_body_region.o: cleanup.h
+cleanup_body_region.o: cleanup_body_region.c
 cleanup_bounce.o: ../../include/argv.h
 cleanup_bounce.o: ../../include/attr.h
 cleanup_bounce.o: ../../include/been_here.h
@@ -447,6 +533,7 @@ cleanup_extracted.o: cleanup.h
 cleanup_extracted.o: cleanup_extracted.c
 cleanup_init.o: ../../include/argv.h
 cleanup_init.o: ../../include/been_here.h
+cleanup_init.o: ../../include/cleanup_user.h
 cleanup_init.o: ../../include/dict.h
 cleanup_init.o: ../../include/ext_prop.h
 cleanup_init.o: ../../include/flush_clnt.h
@@ -536,6 +623,7 @@ cleanup_map1n.o: cleanup.h
 cleanup_map1n.o: cleanup_map1n.c
 cleanup_masquerade.o: ../../include/argv.h
 cleanup_masquerade.o: ../../include/been_here.h
+cleanup_masquerade.o: ../../include/cleanup_user.h
 cleanup_masquerade.o: ../../include/dict.h
 cleanup_masquerade.o: ../../include/header_opts.h
 cleanup_masquerade.o: ../../include/htable.h
@@ -716,6 +804,7 @@ cleanup_out_recipient.o: cleanup_out_recipient.c
 cleanup_rewrite.o: ../../include/argv.h
 cleanup_rewrite.o: ../../include/attr.h
 cleanup_rewrite.o: ../../include/been_here.h
+cleanup_rewrite.o: ../../include/cleanup_user.h
 cleanup_rewrite.o: ../../include/dict.h
 cleanup_rewrite.o: ../../include/header_opts.h
 cleanup_rewrite.o: ../../include/htable.h
@@ -746,6 +835,7 @@ cleanup_rewrite.o: cleanup_rewrite.c
 cleanup_state.o: ../../include/argv.h
 cleanup_state.o: ../../include/attr.h
 cleanup_state.o: ../../include/been_here.h
+cleanup_state.o: ../../include/cleanup_user.h
 cleanup_state.o: ../../include/dict.h
 cleanup_state.o: ../../include/header_opts.h
 cleanup_state.o: ../../include/htable.h
index 2c7637ecb8cb1922d5d52ef1301ddf096bc32407..e31301f37c7e9a054db4570a299e54b6182ab0ec 100644 (file)
@@ -31,6 +31,7 @@
 #include <mail_conf.h>
 #include <mime_state.h>
 #include <string_list.h>
+#include <cleanup_user.h>
 
  /*
   * Milter library.
@@ -69,6 +70,7 @@ typedef struct CLEANUP_STATE {
     void    (*action) (struct CLEANUP_STATE *, int, const char *, ssize_t);
     off_t   data_offset;               /* start of message content */
     off_t   xtra_offset;               /* start of extra segment */
+    off_t   cont_length;               /* length including Milter edits */
     off_t   append_rcpt_pt_offset;     /* append recipient here */
     off_t   append_rcpt_pt_target;     /* target of above record */
     off_t   append_hdr_pt_offset;      /* append header here */
@@ -89,6 +91,10 @@ typedef struct CLEANUP_STATE {
 #ifdef DELAY_ACTION
     int     defer_delay;               /* deferred delivery */
 #endif
+
+    /*
+     * Miscellaneous Milter support.
+     */
     MILTERS *milters;                  /* mail filters */
     const char *client_name;           /* real or ersatz client */
     const char *reverse_name;          /* real or ersatz client */
@@ -97,6 +103,13 @@ typedef struct CLEANUP_STATE {
     const char *client_port;           /* real or ersatz client */
     VSTRING *milter_ext_from;          /* externalized sender */
     VSTRING *milter_ext_rcpt;          /* externalized recipient */
+
+    /*
+     * Support for Milter body replacement requests.
+     */
+    struct CLEANUP_BODY_REGION *body_regions;
+    struct CLEANUP_BODY_REGION *curr_body_region;
+    off_t   body_write_offs;           /* body write position */
 } CLEANUP_STATE;
 
  /*
@@ -281,6 +294,20 @@ extern void cleanup_milter_emul_data(CLEANUP_STATE *, MILTERS *);
     (((s)->flags & CLEANUP_FLAG_MILTER) != 0 \
        && (s)->errs == 0 && ((s)->flags & CLEANUP_FLAG_DISCARD) == 0)
 
+ /*
+  * cleanup_body_region.c
+  */
+typedef struct CLEANUP_BODY_REGION {
+    off_t   start;                     /* start of region */
+    off_t   len;                       /* length or zero (open-ended) */
+    struct CLEANUP_BODY_REGION *next;
+} CLEANUP_BODY_REGION;
+
+extern int cleanup_body_region_start(CLEANUP_STATE *);
+extern int cleanup_body_region_write(CLEANUP_STATE *, int, VSTRING *);
+extern int cleanup_body_region_finish(CLEANUP_STATE *);
+extern void cleanup_body_region_free(CLEANUP_STATE *);
+
 /* LICENSE
 /* .ad
 /* .fi
index 4769289b80c061c65972c81f935334cfa9fdc146..c06627436949e2b3dfce5d084d636e7450446741 100644 (file)
 #include <mail_params.h>
 #include <mail_stream.h>
 #include <mail_flow.h>
+#include <rec_type.h>
 
 /* Milter library. */
 
@@ -198,6 +199,7 @@ void    cleanup_control(CLEANUP_STATE *state, int flags)
 
 int     cleanup_flush(CLEANUP_STATE *state)
 {
+    const char *myname = "cleanup_flush";
     int     status;
     char   *junk;
     VSTRING *trace_junk;
@@ -234,6 +236,21 @@ int     cleanup_flush(CLEANUP_STATE *state)
        }
     }
 
+    /*
+     * Update the preliminary message size and count fields with the actual
+     * values.
+     * 
+     * XXX This ugly code was moved up here from a lower-level module.
+     */
+    if (vstream_fseek(state->dst, 0L, SEEK_SET) < 0)
+       msg_fatal("%s: vstream_fseek %s: %m", myname, cleanup_path);
+    cleanup_out_format(state, REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT,
+           (REC_TYPE_SIZE_CAST1) (state->xtra_offset - state->data_offset),
+                      (REC_TYPE_SIZE_CAST2) state->data_offset,
+                      (REC_TYPE_SIZE_CAST3) state->rcpt_count,
+                      (REC_TYPE_SIZE_CAST4) state->qmgr_opts,
+                      (REC_TYPE_SIZE_CAST5) state->cont_length);
+
     /*
      * If there was an error that requires us to generate a bounce message
      * (mail submitted with the Postfix sendmail command, mail forwarded by
diff --git a/postfix/src/cleanup/cleanup_body_region.c b/postfix/src/cleanup/cleanup_body_region.c
new file mode 100644 (file)
index 0000000..7ad47b0
--- /dev/null
@@ -0,0 +1,266 @@
+/*++
+/* NAME
+/*     cleanup_body_region 3
+/* SUMMARY
+/*     manage body content regions
+/* SYNOPSIS
+/*     #include "cleanup.h"
+/*
+/*     int     cleanup_body_region_start(state)
+/*     CLEANUP_STATE *state;
+/*
+/*     int     cleanup_body_region_write(state, type, buf)
+/*     CLEANUP_STATE *state;
+/*     int     type;
+/*     VSTRING *buf;
+/*
+/*     int     cleanup_body_region_finish(state)
+/*     CLEANUP_STATE *state;
+/*
+/*     void    cleanup_body_region_free(state)
+/*     CLEANUP_STATE *state;
+/* DESCRIPTION
+/*     This module maintains queue file regions with body content.
+/*     Regions are created on the fly, and can be reused multiple
+/*     times. This module must not be called until the queue file
+/*     is complete.
+/*
+/*     cleanup_body_region_start() performs initialization and
+/*     sets the queue file write pointer to the start of the
+/*     first body content segment.
+/*
+/*     cleanup_body_region_write() adds a queue file record to the
+/*     current queue file. When the current queue file region fills
+/*     up, some other region is reused or a new one is created.
+/*
+/*     cleanup_body_region_finish() makes some final adjustments
+/*     after the last body content record is written.
+/*
+/*     cleanup_body_region_free() frees up memory that was allocated
+/*     by cleanup_body_region_start() and cleanup_body_region_write().
+/*
+/*     Arguments:
+/* .IP state
+/*     Queue file and message processing state. This state is updated
+/*     as records are processed and as errors happen.
+/* .IP type
+/*     Record type.
+/* .IP buf
+/*     Record content.
+/* BUGS
+/*     Currently, queue file region management is intertwined with
+/*     body content management. Eventually the two should be
+/*     decoupled, so that space freed up after body editing may
+/*     be reused for header updates and vice versa.
+/* 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>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstream.h>
+#include <vstring.h>
+
+/* Global library. */
+
+#include <rec_type.h>
+#include <record.h>
+
+/* Application-specific. */
+
+#include <cleanup.h>
+
+#define LEN(s) VSTRING_LEN(s)
+
+/* cleanup_body_region_alloc - create body content region */
+
+static CLEANUP_BODY_REGION *cleanup_body_region_alloc(off_t start, off_t len)
+{
+    CLEANUP_BODY_REGION *rp;
+
+    rp = (CLEANUP_BODY_REGION *) mymalloc(sizeof(*rp));
+    rp->start = start;
+    rp->len = len;
+    rp->next = 0;
+
+    return (rp);
+}
+
+/* cleanup_body_region_free - destroy all body content regions */
+
+void    cleanup_body_region_free(CLEANUP_STATE *state)
+{
+    CLEANUP_BODY_REGION *rp;
+    CLEANUP_BODY_REGION *next;
+
+    for (rp = state->body_regions; rp != 0; rp = next) {
+       next = rp->next;
+       myfree((char *) rp);
+    }
+}
+
+/* cleanup_body_region_start - rewrite body buffer pool */
+
+int     cleanup_body_region_start(CLEANUP_STATE *state)
+{
+    const char *myname = "cleanup_body_region_write";
+
+    /*
+     * Calculate the payload size sans body.
+     */
+    state->cont_length = state->append_hdr_pt_target - state->data_offset;
+
+    /*
+     * Craft the first body region on the fly, from circumstantial evidence.
+     */
+    if (state->body_regions == 0)
+       state->body_regions =
+           cleanup_body_region_alloc(state->append_hdr_pt_target,
+                         state->xtra_offset - state->append_hdr_pt_target);
+
+    /*
+     * Select the first region and initialize the write position.
+     */
+    state->curr_body_region = state->body_regions;
+    state->body_write_offs = state->curr_body_region->start;
+
+    /*
+     * Move the file write pointer to the start of the current region.
+     */
+    if (vstream_fseek(state->dst, state->body_write_offs, SEEK_SET) < 0) {
+       msg_warn("%s: seek file %s: %m", myname, cleanup_path);
+       return (-1);
+    }
+    return (0);
+}
+
+/* cleanup_body_region_write - add record to body buffer pool */
+
+int     cleanup_body_region_write(CLEANUP_STATE *state, int rec_type,
+                                         VSTRING *buf)
+{
+    const char *myname = "cleanup_body_region_write";
+    CLEANUP_BODY_REGION *rp = state->curr_body_region;
+    off_t   used;
+    ssize_t rec_len;
+    off_t   start;
+
+    if (msg_verbose)
+       msg_info("%s: where %ld, buflen %ld region start %ld len %ld",
+                myname, (long) state->body_write_offs, (long) LEN(buf),
+                (long) rp->start, (long) rp->len);
+
+    /*
+     * Switch to the next body region if we filled up the current one (we
+     * always append to an open-ended region). Besides space to write the
+     * specified record, we need to leave space for a final pointer record
+     * that will link this body region to the next region or to the content
+     * terminator record.
+     */
+    REC_SPACE_NEED(LEN(buf), rec_len);
+    if (rp->len > 0 && (used = state->body_write_offs - rp->start,
+                       rec_len + REC_TYPE_PTR_SIZE > rp->len - used)) {
+
+       /*
+        * Allocate a new body region if we filled up the last one. A newly
+        * allocated region sits at the end of the queue file, and therefore
+        * it starts as open ended. We freeze the region size later.
+        * 
+        * Don't use fstat() to figure out where the queue file ends, in case
+        * file sizes have magic in them. Instead we seek to the end and then
+        * back to where we were. We're not switching body regions often, so
+        * this is not performance critical.
+        */
+       if (rp->next == 0) {
+           if ((start = vstream_fseek(state->dst, (off_t) 0, SEEK_END)) < 0) {
+               msg_warn("%s: seek file %s: %m", myname, cleanup_path);
+               return (-1);
+           }
+           if (vstream_fseek(state->dst, state->body_write_offs, SEEK_SET) < 0) {
+               msg_warn("%s: seek file %s: %m", myname, cleanup_path);
+               return (-1);
+           }
+           rp->next = cleanup_body_region_alloc(start, 0);
+       }
+
+       /*
+        * Update the payload size and select the new body region.
+        */
+       state->cont_length += state->body_write_offs - rp->start;
+       state->curr_body_region = rp = rp->next;
+
+       /*
+        * Connect the filled up body region to its successor. By design a
+        * region has always space for a final pointer record.
+        */
+       if (msg_verbose)
+           msg_info("%s: link %ld -> %ld", myname,
+                    (long) state->body_write_offs, (long) rp->start);
+       rec_fprintf(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
+                   (long) rp->start);
+       if (vstream_fseek(state->dst, rp->start, SEEK_SET) < 0) {
+           msg_warn("%s: seek file %s: %m", myname, cleanup_path);
+           return (-1);
+       }
+    }
+
+    /*
+     * Finally, output the queue file record.
+     */
+    CLEANUP_OUT_BUF(state, REC_TYPE_NORM, buf);
+    state->body_write_offs = vstream_ftell(state->dst);
+
+    return (0);
+}
+
+/* cleanup_body_region_finish - wrap up body buffer pool */
+
+int     cleanup_body_region_finish(CLEANUP_STATE *state)
+{
+    const char *myname = "cleanup_body_region_finish";
+    CLEANUP_BODY_REGION *rp;
+
+    /*
+     * Link the last body region to the content terminator record.
+     */
+    rec_fprintf(state->dst, REC_TYPE_PTR, REC_TYPE_PTR_FORMAT,
+               (long) state->xtra_offset);
+    state->body_write_offs = vstream_ftell(state->dst);
+
+    /*
+     * Update the payload size.
+     */
+    rp = state->curr_body_region;
+    state->cont_length += state->body_write_offs - rp->start;
+
+    /*
+     * Freeze the size of the last region if it is still open ended. The next
+     * Milter application may append more header records, therefore we must
+     * not assume that this region can grow further. Nor can we truncate the
+     * queue file to the end of this region, as this region may be followed
+     * by headers that were appended by an earlier Milter application.
+     * 
+     * XXX Eventually, split a partially-used region so that the remainder can
+     * be returned to a free pool and reused for header updates.
+     */
+    if (rp->len == 0)
+       rp->len = state->body_write_offs - rp->start;
+    if (msg_verbose)
+       msg_info("%s: freeze start %ld len %ld",
+                myname, (long) rp->start, (long) rp->len);
+
+    return (CLEANUP_OUT_OK(state) ? 0 : -1);
+}
index eb4171bdfe53a06ebe8d13392d4f3dc42f5009f6..ef4dbc7dc36302c23a15590260a7e1aee5a9fbf8 100644 (file)
@@ -89,10 +89,11 @@ void    cleanup_envelope(CLEANUP_STATE *state, int type,
      * first, for backwards compatibility reasons.
      */
     cleanup_out_format(state, REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT,
-                      (REC_TYPE_SIZE_CAST1) 0, /* content size */
+                      (REC_TYPE_SIZE_CAST1) 0, /* extra offs - content offs */
                       (REC_TYPE_SIZE_CAST2) 0, /* content offset */
                       (REC_TYPE_SIZE_CAST3) 0, /* recipient count */
-                      (REC_TYPE_SIZE_CAST4) 0);        /* qmgr options */
+                      (REC_TYPE_SIZE_CAST4) 0, /* qmgr options */
+                      (REC_TYPE_SIZE_CAST5) 0);        /* content length */
 
     /*
      * Pass control to the actual envelope processing routine.
index 60f0ab345e267dedeb2d97800cd4dda70decb596..5f02e25850ee9163a16238cfe0d7968747073e2b 100644 (file)
@@ -316,16 +316,4 @@ void    cleanup_extracted_finish(CLEANUP_STATE *state)
        }
        return;
     }
-
-    /*
-     * Update the preliminary message size and count fields with the actual
-     * values.
-     */
-    if (vstream_fseek(state->dst, 0L, SEEK_SET) < 0)
-       msg_fatal("%s: vstream_fseek %s: %m", myname, cleanup_path);
-    cleanup_out_format(state, REC_TYPE_SIZE, REC_TYPE_SIZE_FORMAT,
-           (REC_TYPE_SIZE_CAST1) (state->xtra_offset - state->data_offset),
-                      (REC_TYPE_SIZE_CAST2) state->data_offset,
-                      (REC_TYPE_SIZE_CAST3) state->rcpt_count,
-                      (REC_TYPE_SIZE_CAST4) state->qmgr_opts);
 }
index 5e71c8b8963975a81af2d8361101d504e5974d21..e777f455ac6f2560ee1b24408b1b8023e0e8d603 100644 (file)
@@ -831,6 +831,7 @@ static void cleanup_message_headerbody(CLEANUP_STATE *state, int type,
        state->mime_state = mime_state_free(state->mime_state);
        if ((state->xtra_offset = vstream_ftell(state->dst)) < 0)
            msg_fatal("%s: vstream_ftell %s: %m", myname, cleanup_path);
+       state->cont_length = state->xtra_offset - state->data_offset;
        state->action = cleanup_extracted;
     }
 
index da4fddb1fa2c22b1ba26c02fc9405bc7d27973fa..348b3b7906ac84de27dec140c66489f2172534d4 100644 (file)
@@ -1254,15 +1254,35 @@ static const char *cleanup_del_rcpt(void *context, char *ext_rcpt)
 
 /* cleanup_repl_body - replace message body */
 
-static const char *cleanup_repl_body(void *context, VSTRING *body)
+static const char *cleanup_repl_body(void *context, int cmd, VSTRING *buf)
 {
     const char *myname = "cleanup_repl_body";
+    CLEANUP_STATE *state = (CLEANUP_STATE *) context;
+    static VSTRING empty;
 
     /*
      * XXX Sendmail compatibility: milters don't see the first body line, so
      * don't expect they will send one.
      */
-    msg_panic("%s: message body replace operation is not implemented", myname);
+    switch (cmd) {
+    case MILTER_BODY_LINE:
+       if (cleanup_body_region_write(state, REC_TYPE_NORM, buf) < 0)
+           return (cleanup_milter_error(state, errno));
+       break;
+    case MILTER_BODY_START:
+       VSTRING_RESET(&empty);
+       if (cleanup_body_region_start(state) < 0
+           || cleanup_body_region_write(state, REC_TYPE_NORM, &empty) < 0)
+           return (cleanup_milter_error(state, errno));
+       break;
+    case MILTER_BODY_END:
+       if (cleanup_body_region_finish(state) < 0)
+           return (cleanup_milter_error(state, errno));
+       break;
+    default:
+       msg_panic("%s: bad command: %d", myname, cmd);
+    }
+    return (CLEANUP_OUT_OK(state) ? 0 : cleanup_milter_error(state, errno));
 }
 
 /* cleanup_milter_eval - expand macro */
@@ -1779,6 +1799,12 @@ static void open_queue_file(CLEANUP_STATE *state, const char *path)
                }
            }
        }
+       if (state->append_rcpt_pt_offset < 0)
+           msg_fatal("file %s: no append recipient pointer record",
+                     cleanup_path);
+       if (state->append_hdr_pt_offset < 0)
+           msg_fatal("file %s: no append header pointer record",
+                     cleanup_path);
        if (msg_verbose) {
            msg_info("append_rcpt_pt_offset %ld append_rcpt_pt_target %ld",
                     (long) state->append_rcpt_pt_offset,
@@ -1819,7 +1845,7 @@ int     main(int unused_argc, char **argv)
            vstream_printf("- ");
            vstream_fflush(VSTREAM_OUT);
        }
-       if (vstring_fgets_nonl(inbuf, VSTREAM_IN) <= 0)
+       if (vstring_fgets_nonl(inbuf, VSTREAM_IN) == 0)
            break;
 
        bufp = vstring_str(inbuf);
@@ -1903,6 +1929,25 @@ int     main(int unused_argc, char **argv)
            } else {
                cleanup_del_rcpt(state, argv->argv[1]);
            }
+       } else if (strcmp(argv->argv[0], "replbody") == 0) {
+           if (argv->argc != 2) {
+               msg_warn("bad replbody argument count: %d", argv->argc);
+           } else {
+               VSTREAM *fp;
+               VSTRING *buf;
+
+               if ((fp = vstream_fopen(argv->argv[1], O_RDONLY, 0)) == 0) {
+                   msg_warn("open %s file: %m", argv->argv[1]);
+               } else {
+                   buf = vstring_alloc(100);
+                   cleanup_repl_body(state, MILTER_BODY_START, buf);
+                   while (vstring_get_nonl(buf, fp) != VSTREAM_EOF)
+                       cleanup_repl_body(state, MILTER_BODY_LINE, buf);
+                   cleanup_repl_body(state, MILTER_BODY_END, buf);
+                   vstring_free(buf);
+                   vstream_fclose(fp);
+               }
+           }
        } else {
            msg_warn("bad command: %s", argv->argv[0]);
        }
diff --git a/postfix/src/cleanup/cleanup_milter.in10a b/postfix/src/cleanup/cleanup_milter.in10a
new file mode 100644 (file)
index 0000000..997b8a7
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Replace a short body by a longer one. The result is two body
+# regions: the original region with the head of the new text, and
+# one region at the end of the queue file with the remainder of the
+# new text.
+#
+open test-queue-file10.tmp
+
+replbody loremipsum
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in10b b/postfix/src/cleanup/cleanup_milter.in10b
new file mode 100644 (file)
index 0000000..ba3b07f
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Replace a short body by a longer one, and then replace the longer
+# body by itself. The result should be identical to what we had after
+# one replacement.
+#
+#verbose on
+open test-queue-file10.tmp
+
+replbody loremipsum
+replbody loremipsum
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in10c b/postfix/src/cleanup/cleanup_milter.in10c
new file mode 100644 (file)
index 0000000..79af0ce
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Replace a short body by a longer one, and then clobber that with
+# an even longer body. The result is three body regions: the original
+# region, the region that contained the tail of the first replacement,
+# and a region that contains the tail of the second replacement.
+#
+
+#verbose on
+open test-queue-file10.tmp
+
+replbody loremipsum
+replbody loremipsum2
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in10d b/postfix/src/cleanup/cleanup_milter.in10d
new file mode 100644 (file)
index 0000000..b7c515a
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# As test 10c, but then replace the longer body by the shorter one. The
+# result is three regions: the original region, the region with the
+# tail of the shorter replacement, and an unused region that contained
+# the tail of the larger region.
+#
+#verbose on
+open test-queue-file10.tmp
+
+replbody loremipsum
+replbody loremipsum2
+replbody loremipsum
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.in10e b/postfix/src/cleanup/cleanup_milter.in10e
new file mode 100644 (file)
index 0000000..763f79b
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Replace a short body by increasingly longer ones and do header
+# updates in between.
+#
+#verbose on
+open test-queue-file10.tmp
+
+add_header foo1 foobar
+replbody loremipsum
+add_header foo2 foobar
+replbody loremipsum2
+
+close
diff --git a/postfix/src/cleanup/cleanup_milter.ref10a b/postfix/src/cleanup/cleanup_milter.ref10a
new file mode 100644 (file)
index 0000000..38c5c84
--- /dev/null
@@ -0,0 +1,52 @@
+*** ENVELOPE RECORDS test-queue-file10.tmp ***
+        0 message_size:             329             181               1               0
+       65 message_arrival_time: Tue Jul 25 15:37:06 2006
+       82 create_time: Tue Jul 25 15:37:06 2006
+      106 named_attribute: rewrite_context=local
+      129 sender_fullname: Wietse Venema
+      144 sender: me@porcupine.org
+      162 pointer_record:               0
+      179 *** MESSAGE CONTENTS test-queue-file10.tmp ***
+      181 regular_text: Received: by bristle.watson.ibm.com (Postfix, from userid 0)
+      243 regular_text:        id 034B229013F; Tue, 25 Jul 2006 15:37:06 -0400 (EDT)
+      299 regular_text: From: me@porcupine.org
+      323 regular_text: To: you@porcupine.org
+      346 regular_text: Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
+      408 regular_text: Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
+      453 regular_text: Subject: hey!
+      468 pointer_record:               0
+      485 regular_text: 
+      487 pointer_record:             552
+      552 regular_text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+      617 regular_text: accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+      684 regular_text: quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+      752 regular_text: dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+      821 regular_text: aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+      890 regular_text: eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+      956 regular_text: est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+     1024 regular_text: velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+     1091 regular_text: et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+     1156 regular_text: veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+     1230 regular_text: nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+     1299 regular_text: reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+     1367 regular_text: consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+     1434 regular_text: pariatur?\r
+     1446 regular_text: \r
+     1449 regular_text: At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+     1514 regular_text: blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+     1579 regular_text: dolores et quas molestias excepturi sint occaecati cupiditate non\r
+     1647 regular_text: provident, similique sunt in culpa qui officia deserunt mollitia\r
+     1714 regular_text: animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+     1785 regular_text: est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+     1852 regular_text: est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+     1919 regular_text: placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+     1988 regular_text: repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+     2058 regular_text: rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+     2124 regular_text: sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+     2193 regular_text: sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+     2259 regular_text: consequatur aut perferendis doloribus asperiores repellat.\r
+     2320 pointer_record:             510
+      510 *** HEADER EXTRACTED test-queue-file10.tmp ***
+      512 original_recipient: you@porcupine.org
+      531 recipient: you@porcupine.org
+      550 *** MESSAGE FILE END test-queue-file10.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref10b b/postfix/src/cleanup/cleanup_milter.ref10b
new file mode 100644 (file)
index 0000000..38c5c84
--- /dev/null
@@ -0,0 +1,52 @@
+*** ENVELOPE RECORDS test-queue-file10.tmp ***
+        0 message_size:             329             181               1               0
+       65 message_arrival_time: Tue Jul 25 15:37:06 2006
+       82 create_time: Tue Jul 25 15:37:06 2006
+      106 named_attribute: rewrite_context=local
+      129 sender_fullname: Wietse Venema
+      144 sender: me@porcupine.org
+      162 pointer_record:               0
+      179 *** MESSAGE CONTENTS test-queue-file10.tmp ***
+      181 regular_text: Received: by bristle.watson.ibm.com (Postfix, from userid 0)
+      243 regular_text:        id 034B229013F; Tue, 25 Jul 2006 15:37:06 -0400 (EDT)
+      299 regular_text: From: me@porcupine.org
+      323 regular_text: To: you@porcupine.org
+      346 regular_text: Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
+      408 regular_text: Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
+      453 regular_text: Subject: hey!
+      468 pointer_record:               0
+      485 regular_text: 
+      487 pointer_record:             552
+      552 regular_text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+      617 regular_text: accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+      684 regular_text: quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+      752 regular_text: dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+      821 regular_text: aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+      890 regular_text: eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+      956 regular_text: est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+     1024 regular_text: velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+     1091 regular_text: et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+     1156 regular_text: veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+     1230 regular_text: nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+     1299 regular_text: reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+     1367 regular_text: consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+     1434 regular_text: pariatur?\r
+     1446 regular_text: \r
+     1449 regular_text: At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+     1514 regular_text: blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+     1579 regular_text: dolores et quas molestias excepturi sint occaecati cupiditate non\r
+     1647 regular_text: provident, similique sunt in culpa qui officia deserunt mollitia\r
+     1714 regular_text: animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+     1785 regular_text: est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+     1852 regular_text: est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+     1919 regular_text: placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+     1988 regular_text: repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+     2058 regular_text: rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+     2124 regular_text: sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+     2193 regular_text: sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+     2259 regular_text: consequatur aut perferendis doloribus asperiores repellat.\r
+     2320 pointer_record:             510
+      510 *** HEADER EXTRACTED test-queue-file10.tmp ***
+      512 original_recipient: you@porcupine.org
+      531 recipient: you@porcupine.org
+      550 *** MESSAGE FILE END test-queue-file10.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref10c b/postfix/src/cleanup/cleanup_milter.ref10c
new file mode 100644 (file)
index 0000000..78704f2
--- /dev/null
@@ -0,0 +1,82 @@
+*** ENVELOPE RECORDS test-queue-file10.tmp ***
+        0 message_size:             329             181               1               0
+       65 message_arrival_time: Tue Jul 25 15:37:06 2006
+       82 create_time: Tue Jul 25 15:37:06 2006
+      106 named_attribute: rewrite_context=local
+      129 sender_fullname: Wietse Venema
+      144 sender: me@porcupine.org
+      162 pointer_record:               0
+      179 *** MESSAGE CONTENTS test-queue-file10.tmp ***
+      181 regular_text: Received: by bristle.watson.ibm.com (Postfix, from userid 0)
+      243 regular_text:        id 034B229013F; Tue, 25 Jul 2006 15:37:06 -0400 (EDT)
+      299 regular_text: From: me@porcupine.org
+      323 regular_text: To: you@porcupine.org
+      346 regular_text: Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
+      408 regular_text: Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
+      453 regular_text: Subject: hey!
+      468 pointer_record:               0
+      485 regular_text: 
+      487 pointer_record:             552
+      552 regular_text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+      617 regular_text: accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+      684 regular_text: quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+      752 regular_text: dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+      821 regular_text: aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+      890 regular_text: eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+      956 regular_text: est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+     1024 regular_text: velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+     1091 regular_text: et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+     1156 regular_text: veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+     1230 regular_text: nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+     1299 regular_text: reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+     1367 regular_text: consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+     1434 regular_text: pariatur?\r
+     1446 regular_text: \r
+     1449 regular_text: At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+     1514 regular_text: blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+     1579 regular_text: dolores et quas molestias excepturi sint occaecati cupiditate non\r
+     1647 regular_text: provident, similique sunt in culpa qui officia deserunt mollitia\r
+     1714 regular_text: animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+     1785 regular_text: est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+     1852 regular_text: est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+     1919 regular_text: placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+     1988 regular_text: repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+     2058 regular_text: rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+     2124 regular_text: sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+     2193 regular_text: sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+     2259 regular_text: consequatur aut perferendis doloribus asperiores repellat.\r
+     2320 pointer_record:            2337
+     2337 regular_text: \r
+     2340 regular_text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+     2405 regular_text: accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+     2472 regular_text: quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+     2540 regular_text: dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+     2609 regular_text: aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+     2678 regular_text: eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+     2744 regular_text: est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+     2812 regular_text: velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+     2879 regular_text: et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+     2944 regular_text: veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+     3018 regular_text: nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+     3087 regular_text: reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+     3155 regular_text: consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+     3222 regular_text: pariatur?\r
+     3234 regular_text: \r
+     3237 regular_text: At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+     3302 regular_text: blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+     3367 regular_text: dolores et quas molestias excepturi sint occaecati cupiditate non\r
+     3435 regular_text: provident, similique sunt in culpa qui officia deserunt mollitia\r
+     3502 regular_text: animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+     3573 regular_text: est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+     3640 regular_text: est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+     3707 regular_text: placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+     3776 regular_text: repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+     3846 regular_text: rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+     3912 regular_text: sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+     3981 regular_text: sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+     4047 regular_text: consequatur aut perferendis doloribus asperiores repellat.\r
+     4108 pointer_record:             510
+      510 *** HEADER EXTRACTED test-queue-file10.tmp ***
+      512 original_recipient: you@porcupine.org
+      531 recipient: you@porcupine.org
+      550 *** MESSAGE FILE END test-queue-file10.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref10d b/postfix/src/cleanup/cleanup_milter.ref10d
new file mode 100644 (file)
index 0000000..38c5c84
--- /dev/null
@@ -0,0 +1,52 @@
+*** ENVELOPE RECORDS test-queue-file10.tmp ***
+        0 message_size:             329             181               1               0
+       65 message_arrival_time: Tue Jul 25 15:37:06 2006
+       82 create_time: Tue Jul 25 15:37:06 2006
+      106 named_attribute: rewrite_context=local
+      129 sender_fullname: Wietse Venema
+      144 sender: me@porcupine.org
+      162 pointer_record:               0
+      179 *** MESSAGE CONTENTS test-queue-file10.tmp ***
+      181 regular_text: Received: by bristle.watson.ibm.com (Postfix, from userid 0)
+      243 regular_text:        id 034B229013F; Tue, 25 Jul 2006 15:37:06 -0400 (EDT)
+      299 regular_text: From: me@porcupine.org
+      323 regular_text: To: you@porcupine.org
+      346 regular_text: Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
+      408 regular_text: Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
+      453 regular_text: Subject: hey!
+      468 pointer_record:               0
+      485 regular_text: 
+      487 pointer_record:             552
+      552 regular_text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+      617 regular_text: accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+      684 regular_text: quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+      752 regular_text: dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+      821 regular_text: aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+      890 regular_text: eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+      956 regular_text: est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+     1024 regular_text: velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+     1091 regular_text: et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+     1156 regular_text: veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+     1230 regular_text: nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+     1299 regular_text: reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+     1367 regular_text: consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+     1434 regular_text: pariatur?\r
+     1446 regular_text: \r
+     1449 regular_text: At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+     1514 regular_text: blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+     1579 regular_text: dolores et quas molestias excepturi sint occaecati cupiditate non\r
+     1647 regular_text: provident, similique sunt in culpa qui officia deserunt mollitia\r
+     1714 regular_text: animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+     1785 regular_text: est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+     1852 regular_text: est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+     1919 regular_text: placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+     1988 regular_text: repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+     2058 regular_text: rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+     2124 regular_text: sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+     2193 regular_text: sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+     2259 regular_text: consequatur aut perferendis doloribus asperiores repellat.\r
+     2320 pointer_record:             510
+      510 *** HEADER EXTRACTED test-queue-file10.tmp ***
+      512 original_recipient: you@porcupine.org
+      531 recipient: you@porcupine.org
+      550 *** MESSAGE FILE END test-queue-file10.tmp ***
diff --git a/postfix/src/cleanup/cleanup_milter.ref10e b/postfix/src/cleanup/cleanup_milter.ref10e
new file mode 100644 (file)
index 0000000..81b0502
--- /dev/null
@@ -0,0 +1,86 @@
+*** ENVELOPE RECORDS test-queue-file10.tmp ***
+        0 message_size:             329             181               1               0
+       65 message_arrival_time: Tue Jul 25 15:37:06 2006
+       82 create_time: Tue Jul 25 15:37:06 2006
+      106 named_attribute: rewrite_context=local
+      129 sender_fullname: Wietse Venema
+      144 sender: me@porcupine.org
+      162 pointer_record:               0
+      179 *** MESSAGE CONTENTS test-queue-file10.tmp ***
+      181 regular_text: Received: by bristle.watson.ibm.com (Postfix, from userid 0)
+      243 regular_text:        id 034B229013F; Tue, 25 Jul 2006 15:37:06 -0400 (EDT)
+      299 regular_text: From: me@porcupine.org
+      323 regular_text: To: you@porcupine.org
+      346 regular_text: Message-Id: <20060725192735.5EC2D29013F@hades.porcupine.org>
+      408 regular_text: Date: Tue, 25 Jul 2006 15:27:19 -0400 (EDT)
+      453 regular_text: Subject: hey!
+      468 pointer_record:             552
+      552 regular_text: foo1: foobar
+      566 pointer_record:            2368
+     2368 regular_text: foo2: foobar
+     2382 pointer_record:             485
+      485 regular_text: 
+      487 pointer_record:             583
+      583 regular_text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+      648 regular_text: accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+      715 regular_text: quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+      783 regular_text: dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+      852 regular_text: aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+      921 regular_text: eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+      987 regular_text: est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+     1055 regular_text: velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+     1122 regular_text: et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+     1187 regular_text: veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+     1261 regular_text: nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+     1330 regular_text: reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+     1398 regular_text: consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+     1465 regular_text: pariatur?\r
+     1477 regular_text: \r
+     1480 regular_text: At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+     1545 regular_text: blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+     1610 regular_text: dolores et quas molestias excepturi sint occaecati cupiditate non\r
+     1678 regular_text: provident, similique sunt in culpa qui officia deserunt mollitia\r
+     1745 regular_text: animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+     1816 regular_text: est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+     1883 regular_text: est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+     1950 regular_text: placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+     2019 regular_text: repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+     2089 regular_text: rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+     2155 regular_text: sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+     2224 regular_text: sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+     2290 regular_text: consequatur aut perferendis doloribus asperiores repellat.\r
+     2351 pointer_record:            2399
+     2399 regular_text: \r
+     2402 regular_text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+     2467 regular_text: accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+     2534 regular_text: quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+     2602 regular_text: dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+     2671 regular_text: aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+     2740 regular_text: eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+     2806 regular_text: est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+     2874 regular_text: velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+     2941 regular_text: et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+     3006 regular_text: veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+     3080 regular_text: nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+     3149 regular_text: reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+     3217 regular_text: consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+     3284 regular_text: pariatur?\r
+     3296 regular_text: \r
+     3299 regular_text: At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+     3364 regular_text: blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+     3429 regular_text: dolores et quas molestias excepturi sint occaecati cupiditate non\r
+     3497 regular_text: provident, similique sunt in culpa qui officia deserunt mollitia\r
+     3564 regular_text: animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+     3635 regular_text: est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+     3702 regular_text: est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+     3769 regular_text: placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+     3838 regular_text: repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+     3908 regular_text: rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+     3974 regular_text: sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+     4043 regular_text: sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+     4109 regular_text: consequatur aut perferendis doloribus asperiores repellat.\r
+     4170 pointer_record:             510
+      510 *** HEADER EXTRACTED test-queue-file10.tmp ***
+      512 original_recipient: you@porcupine.org
+      531 recipient: you@porcupine.org
+      550 *** MESSAGE FILE END test-queue-file10.tmp ***
index 9a35f107d81c48fca8247b6d1ba74ebe39152f73..e07bd2ace620301386fac0b187cc456a4998ba1d 100644 (file)
@@ -89,6 +89,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
     state->action = cleanup_envelope;
     state->data_offset = -1;
     state->xtra_offset = -1;
+    state->cont_length = 0;
     state->append_rcpt_pt_offset = -1;
     state->append_rcpt_pt_target = -1;
     state->append_hdr_pt_offset = -1;
@@ -115,6 +116,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src)
     state->client_port = 0;
     state->milter_ext_from = 0;
     state->milter_ext_rcpt = 0;
+    state->body_regions = state->curr_body_region = 0;
     return (state);
 }
 
@@ -165,5 +167,7 @@ void    cleanup_state_free(CLEANUP_STATE *state)
        vstring_free(state->milter_ext_from);
     if (state->milter_ext_rcpt)
        vstring_free(state->milter_ext_rcpt);
+    if (state->body_regions)
+       cleanup_body_region_free(state);
     myfree((char *) state);
 }
diff --git a/postfix/src/cleanup/loremipsum b/postfix/src/cleanup/loremipsum
new file mode 100644 (file)
index 0000000..774f86d
--- /dev/null
@@ -0,0 +1,28 @@
+Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+pariatur?\r
+\r
+At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+dolores et quas molestias excepturi sint occaecati cupiditate non\r
+provident, similique sunt in culpa qui officia deserunt mollitia\r
+animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+consequatur aut perferendis doloribus asperiores repellat.\r
diff --git a/postfix/src/cleanup/loremipsum2 b/postfix/src/cleanup/loremipsum2
new file mode 100644 (file)
index 0000000..93cfa67
--- /dev/null
@@ -0,0 +1,57 @@
+Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+pariatur?\r
+\r
+At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+dolores et quas molestias excepturi sint occaecati cupiditate non\r
+provident, similique sunt in culpa qui officia deserunt mollitia\r
+animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+consequatur aut perferendis doloribus asperiores repellat.\r
+\r
+Sed ut perspiciatis unde omnis iste natus error sit voluptatem\r
+accusantium doloremque laudantium, totam rem aperiam, eaque ipsa\r
+quae ab illo inventore veritatis et quasi architecto beatae vitae\r
+dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit\r
+aspernatur aut odit aut fugit, sed quia consequuntur magni dolores\r
+eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam\r
+est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci\r
+velit, sed quia non numquam eius modi tempora incidunt ut labore\r
+et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima\r
+veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam,\r
+nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure\r
+reprehenderit qui in ea voluptate velit esse quam nihil molestiae\r
+consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla\r
+pariatur?\r
+\r
+At vero eos et accusamus et iusto odio dignissimos ducimus qui\r
+blanditiis praesentium voluptatum deleniti atque corrupti quos\r
+dolores et quas molestias excepturi sint occaecati cupiditate non\r
+provident, similique sunt in culpa qui officia deserunt mollitia\r
+animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis\r
+est et expedita distinctio. Nam libero tempore, cum soluta nobis\r
+est eligendi optio cumque nihil impedit quo minus id quod maxime\r
+placeat facere possimus, omnis voluptas assumenda est, omnis dolor\r
+repellendus. Temporibus autem quibusdam et aut officiis debitis aut\r
+rerum necessitatibus saepe eveniet ut et voluptates repudiandae\r
+sint et molestiae non recusandae. Itaque earum rerum hic tenetur a\r
+sapiente delectus, ut aut reiciendis voluptatibus maiores alias\r
+consequatur aut perferendis doloribus asperiores repellat.\r
diff --git a/postfix/src/cleanup/test-queue-file10 b/postfix/src/cleanup/test-queue-file10
new file mode 100644 (file)
index 0000000..f5a7b01
Binary files /dev/null and b/postfix/src/cleanup/test-queue-file10 differ
index f3097f91a7305ede1111331d4fc95d89bd9821e9..49e288d8916bfbfd70c3317c594391f6456633b5 100644 (file)
@@ -273,7 +273,7 @@ tests: tok822_test mime_tests strip_addr_test tok822_limit_test \
        namadr_list_test mail_conf_time_test
 
 mime_tests: mime_test mime_nest mime_8bit mime_dom mime_trunc mime_cvt \
-       mime_cvt2 mime_cvt3 mime_garb1 mime_garb2 mime_garb3
+       mime_cvt2 mime_cvt3 mime_garb1 mime_garb2 mime_garb3 mime_garb4
 
 root_tests: rewrite_clnt_test resolve_clnt_test
 
@@ -337,6 +337,11 @@ mime_garb3: mime_state mime_garb3.in mime_garb3.ref
        diff  mime_garb3.ref mime_cvt.tmp
        rm -f mime_cvt.tmp
 
+mime_garb4: mime_state mime_garb4.in mime_garb4.ref
+       ./mime_state <mime_garb4.in >mime_cvt.tmp
+       diff  mime_garb4.ref mime_cvt.tmp
+       rm -f mime_cvt.tmp
+
 tok822_limit_test: tok822_parse tok822_limit.in tok822_limit.ref
        ./tok822_parse <tok822_limit.in >tok822_limit.tmp
        diff tok822_limit.ref tok822_limit.tmp
index 1bce4ac68df251824a78eae7622238c7e0086950..4dac78e6c30a8dc2aed6da7196cb74f1e0f8da3c 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      "20070113"
+#define MAIL_RELEASE_DATE      "20070116"
 #define MAIL_VERSION_NUMBER    "2.4"
 
 #ifdef SNAPSHOT
index 873ef91fa0d22cb7020b4fe46a9195c10bd80e40..ee8ef36b88c817215c63648b96bb1e4305e0e643 100644 (file)
@@ -9,7 +9,7 @@ MAIN 95 |Content-Type: Multipart/Mixed;
   boundary="Boundary-00=_mvhpFky0yqNhsa4"
 HEADER END
 mime_state: garbage in primary header
-BODY N -1      |
+BODY N       |
 BODY N 0       |junk in primary header
 BODY N 23      |
 BODY N 24      |--Boundary-00=_mvhpFky0yqNhsa4
diff --git a/postfix/src/global/mime_garb4.in b/postfix/src/global/mime_garb4.in
new file mode 100644 (file)
index 0000000..16dcfc6
--- /dev/null
@@ -0,0 +1,34 @@
+From: Some One <user@example.com>
+To: Some One <user@example.com>
+Subject: Test
+MIME-Version: 1.0
+Content-Type: Multipart/Mixed;
+  boundary="top-level-boundary"
+
+--top-level-boundary
+Content-Type: message/rfc822;
+  name="forwarded message"
+Content-Transfer-Encoding: quoted-printable
+Content-Disposition: inline
+
+To: user@example.com
+=46rom: Some One <user@example.com>
+Subject: Forwarded Test
+Content-Type: Multipart/Mixed;
+  boundary=3D"nested-level-boundary"
+
+--nested-level-boundary
+Content-Type: text/plain;
+Content-Transfer-Encoding: quoted-printable
+
+Blah
+
+--nested-level-boundary--
+
+--top-level-boundary
+Content-Type: text/plain;
+  charset="utf-8"
+Content-Transfer-Encoding: quoted-printable
+Content-Disposition: inline
+
+This is a test
diff --git a/postfix/src/global/mime_garb4.ref b/postfix/src/global/mime_garb4.ref
new file mode 100644 (file)
index 0000000..bd0e5cc
--- /dev/null
@@ -0,0 +1,50 @@
+MAIN 0 |From: Some One <user@example.com>
+MAIN 32        |To: Some One <user@example.com>
+MAIN 46        |Subject: Test
+MAIN 64        |MIME-Version: 1.0
+mime_state: header_token: Multipart / Mixed
+mime_state: header_token: boundary = top-level-boundary
+mime_state: PUSH boundary top-level-boundary
+MAIN 95        |Content-Type: Multipart/Mixed;
+  boundary="top-level-boundary"
+HEADER END
+BODY N 0       |
+BODY N 1       |--top-level-boundary
+mime_state: header_token: message / rfc822
+MULT 0 |Content-Type: message/rfc822;
+  name="forwarded message"
+mime_state: header_token: quoted-printable  
+MULT 44        |Content-Transfer-Encoding: quoted-printable
+MULT 72        |Content-Disposition: inline
+mime_state: warning: invalid message/* or multipart/* encoding domain: quoted-printable
+BODY N 0       |
+NEST 0 |To: user@example.com
+NEST 36        |=46rom: Some One <user@example.com>
+NEST 60        |Subject: Forwarded Test
+mime_state: header_token: Multipart / Mixed
+mime_state: header_token: boundary = 3D
+mime_state: PUSH boundary 3D
+NEST 91        |Content-Type: Multipart/Mixed;
+  boundary=3D"nested-level-boundary"
+BODY N 0       |
+BODY N 1       |--nested-level-boundary
+BODY N 25      |Content-Type: text/plain;
+BODY N 51      |Content-Transfer-Encoding: quoted-printable
+BODY N 95      |
+BODY N 96      |Blah
+BODY N 101     |
+BODY N 102     |--nested-level-boundary--
+BODY N 128     |
+mime_state: POP boundary 3D
+BODY N 129     |--top-level-boundary
+mime_state: header_token: text / plain
+MULT 0 |Content-Type: text/plain;
+  charset="utf-8"
+mime_state: header_token: quoted-printable  
+MULT 44        |Content-Transfer-Encoding: quoted-printable
+MULT 72        |Content-Disposition: inline
+BODY N 0       |
+BODY N 1       |This is a test
+BODY END
+mime_state: warning: improper message/* or multipart/* encoding domain
+mime_state: POP boundary top-level-boundary
index b81fc1f9072bd7a46ee0bedb96d84469c2ac271f..4b4bf69f99c2fd54c66cdc1b2c46a61007db1ede 100644 (file)
@@ -499,6 +499,7 @@ MIME_STATE *mime_state_alloc(int flags,
 
     /* Volatile members. */
     state->err_flags = 0;
+    state->body_offset = 0;                    /* XXX */
     SET_MIME_STATE(state, MIME_STATE_PRIMARY,
                   MIME_CTYPE_TEXT, MIME_STYPE_PLAIN,
                   MIME_ENC_7BIT, MIME_ENC_7BIT);
@@ -938,6 +939,15 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
         * messages. Otherwise, treat such headers as part of the "body". Set
         * the proper encoding information for the multipart prolog.
         * 
+        * XXX We parse headers inside message/* content even when the encoding
+        * is invalid (encoding != domain). With base64 we won't recognize
+        * any headers, and with quoted-printable we won't recognize MIME
+        * boundary strings, but the MIME processor will still resynchronize
+        * when it runs into the higher-level boundary string at the end of
+        * the message/* content. Although we will treat some headers as body
+        * text, we will still do a better job than if we were treating the
+        * entire message/* content as body text.
+        * 
         * XXX This changes state to MIME_STATE_NESTED and then outputs a body
         * line, so that the body offset is not properly reset.
         * 
@@ -973,13 +983,14 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
             * separator, nor does the Milter protocol pass it on to Milter
             * applications.
             * 
-            * XXX We don't insert a blank line separator with attachments, as
-            * this breaks digital signatures. Postfix shall not do a worse
-            * mail delivery job than crappy MTAs that can't even parse MIME.
-            * But we switch to the body state anyway.
+            * XXX We don't insert a blank line separator into attachments, to
+            * avoid breaking digital signatures. Postfix shall not do a
+            * worse mail delivery job than MTAs that can't even parse MIME.
+            * We switch to body state anyway, to avoid treating body text as
+            * header text, and mis-interpreting or truncating it. The code
+            * below for initial From_ lines is for educational purposes.
             * 
-            * People who worry about MIME evasion can use a MIME normalizer,
-            * and knowlingly corrupt legitimate email for their users.
+            * Sites concerned about MIME evasion can use a MIME normalizer.
             * Postfix has a different mission.
             */
            else {
@@ -989,9 +1000,25 @@ int     mime_state_update(MIME_STATE *state, int rec_type,
                       state->curr_state == MIME_STATE_PRIMARY ? "primary" :
                         state->curr_state == MIME_STATE_NESTED ? "nested" :
                             "other");
-               if (state->curr_state == MIME_STATE_PRIMARY)
+               switch (state->curr_state) {
+               case MIME_STATE_PRIMARY:
                    BODY_OUT(state, REC_TYPE_NORM, "", 0);
-               SET_CURR_STATE(state, MIME_STATE_BODY);
+                   SET_CURR_STATE(state, MIME_STATE_BODY);
+                   break;
+#if 0
+               case MIME_STATE_NESTED:
+                   if (state->body_offset <= 1
+                       && rec_type == REC_TYPE_NORM
+                       && len > 7
+                       && (strncmp(text + (*text == '>'), "From ", 5) == 0
+                           || strncmp(text, "=46rom ", 7) == 0))
+                       break;
+                   /* FALLTHROUGH */
+#endif
+               default:
+                   SET_CURR_STATE(state, MIME_STATE_BODY);
+                   break;
+               }
            }
        }
 
index bf158f934bf88c2f04b90aee1f32bb5fe704739b..cd0873f9e53dc91fdc85ab0c5032f13a76871168 100644 (file)
   * 
   * See also: REC_TYPE_PTR_FORMAT below.
   */
-#define REC_TYPE_SIZE_FORMAT   "%15ld %15ld %15ld %15ld"
-#define REC_TYPE_SIZE_CAST1    long
-#define REC_TYPE_SIZE_CAST2    long    /* Postfix 1.0, a.k.a. 20010228 */
-#define REC_TYPE_SIZE_CAST3    long    /* Postfix 1.0, a.k.a. 20010228 */
-#define REC_TYPE_SIZE_CAST4    long    /* Postfix 2.1 */
+#define REC_TYPE_SIZE_FORMAT   "%15ld %15ld %15ld %15ld %15ld"
+#define REC_TYPE_SIZE_CAST1    long    /* Vmailer extra offs - data offs */
+#define REC_TYPE_SIZE_CAST2    long    /* Postfix 1.0 data offset */
+#define REC_TYPE_SIZE_CAST3    long    /* Postfix 1.0 recipient count */
+#define REC_TYPE_SIZE_CAST4    long    /* Postfix 2.1 qmgr flags */
+#define REC_TYPE_SIZE_CAST5    long    /* Postfix 2.4 content length */
 
  /*
   * The warn record specifies when the next warning that the message was
index 3ef7ca7b5c287ae22eb98eb8c6b26d37aac0f044..12dbac4ba022ff16752aad4a94b11c1b771f8510 100644 (file)
 /*     int     rec_goto(stream, where)
 /*     VSTREAM *stream;
 /*     const char *where;
+/*
+/*     REC_SPACE_NEED(buflen, reclen)
+/*     ssize_t buflen;
+/*     ssize_t reclen;
 /* DESCRIPTION
 /*     This module reads and writes typed variable-length records.
 /*     Each record contains a 1-byte type code (0..255), a length
 /*     the file pointer to the specified location. A zero position
 /*     means do nothing. The result is REC_TYPE_ERROR in case of
 /*     failure.
+/*
+/*     REC_SPACE_NEED(buflen, reclen) converts the specified buffer
+/*     length into a record length. This macro modifies its second
+/*     argument.
 /* DIAGNOSTICS
 /*     Panics: interface violations. Fatal errors: insufficient memory.
 /*     Warnings: corrupted file.
index 6e75734a394234cd21d0a1bada00d2b71276d852..a5e8b8cedfd05d0794487e027903d49bdb35c1d8 100644 (file)
@@ -41,7 +41,7 @@ extern int rec_goto(VSTREAM *, const char *);
 
 #define REC_PUT_BUF(v, t, b) rec_put((v), (t), vstring_str(b), VSTRING_LEN(b))
 
-#define REC_FLAG_NONE  (0)
+#define REC_FLAG_NONE          (0)
 #define REC_FLAG_FOLLOW_PTR    (1<<0)          /* follow PTR records */
 #define REC_FLAG_SKIP_DTXT     (1<<1)          /* skip DTXT records */
 #define REC_FLAG_SEEK_END      (1<<2)          /* seek EOF after END record */
@@ -52,6 +52,13 @@ extern int rec_goto(VSTREAM *, const char *);
 #define rec_get(fp, buf, limit) \
        rec_get_raw((fp), (buf), (limit), REC_FLAG_DEFAULT)
 
+#define REC_SPACE_NEED(buflen, reclen) do { \
+           ssize_t _c, _l; \
+           for (_c = 1, _l = (buflen); _l != 0; _l >>= 7U, _c++) \
+               ; \
+           (reclen) = 1 + _c + (buflen); \
+       } while (0)
+
  /*
   * Stuff that needs <stdarg.h>
   */
index f006ffc71a595f36187282eb970bae35c9d20915..51f968d80bddee06ef0d35a62c41cae2a3117798 100644 (file)
@@ -280,7 +280,7 @@ void    milter_edit_callback(MILTERS *milters,
                        const char *(*del_header) (void *, ssize_t, char *),
                                   const char *(*add_rcpt) (void *, char *),
                                   const char *(*del_rcpt) (void *, char *),
-                              const char *(*repl_body) (void *, VSTRING *),
+                         const char *(*repl_body) (void *, int, VSTRING *),
                                     void *chg_context)
 {
     milters->add_header = add_header;
index 9e480193a8d62ddeb5b10d2cd566759b83e7db62..676322d4a4b9a6b52036676c0f329487c9fbac8c 100644 (file)
@@ -67,7 +67,7 @@ typedef struct MILTERS {
     const char *(*ins_header) (void *, ssize_t, char *, char *);
     const char *(*add_rcpt) (void *, char *);
     const char *(*del_rcpt) (void *, char *);
-    const char *(*repl_body) (void *, VSTRING *);
+    const char *(*repl_body) (void *, int, VSTRING *);
 } MILTERS;
 
 typedef const char *(*MILTER_MAC_LOOKUP_FN) (const char *, void *);
@@ -75,7 +75,7 @@ typedef const char *(*MILTER_ADD_HEADER_FN) (void *, char *, char *);
 typedef const char *(*MILTER_EDIT_HEADER_FN) (void *, ssize_t, char *, char *);
 typedef const char *(*MILTER_DEL_HEADER_FN) (void *, ssize_t, char *);
 typedef const char *(*MILTER_EDIT_RCPT_FN) (void *, char *);
-typedef const char *(*MILTER_EDIT_BODY_FN) (void *, VSTRING *);
+typedef const char *(*MILTER_EDIT_BODY_FN) (void *, int, VSTRING *);
 
 extern MILTERS *milter_create(const char *, int, int, int,
                                      const char *, const char *,
@@ -103,6 +103,13 @@ extern int milter_send(MILTERS *, VSTREAM *);
 extern MILTERS *milter_receive(VSTREAM *, int);
 extern void milter_free(MILTERS *);
 
+ /*
+  * Milter body edit commands.
+  */
+#define MILTER_BODY_START      1       /* start message body */
+#define MILTER_BODY_LINE       2       /* message body line */
+#define MILTER_BODY_END                3       /* end message body */
+
  /*
   * Sendmail 8 macro names. We support forms with and without the {}.
   */
index 96f637b49c5c6116735f03e771a294112115efbf..2ccd7e74913657f8dfbde4db78bc67c35417f1eb 100644 (file)
 
 /* Global library. */
 
+#include <mail_params.h>               /* var_line_limit */
 #include <mail_proto.h>
 #include <rec_type.h>
 #include <record.h>
@@ -866,9 +867,12 @@ static const char *milter8_event(MILTER8 *milter, int event,
     ssize_t data_size;
     const char *smfic_name;
     const char *smfir_name;
-    MILTERS *parent;
+    MILTERS *parent = milter->m.parent;
     UINT32_TYPE index;
-    const char *edit_resp;
+    const char *edit_resp = 0;
+    const char *retval = 0;
+    VSTRING *body_line_buf = 0;
+    int     done = 0;
 
 #define DONT_SKIP_REPLY        0
 
@@ -970,17 +974,30 @@ static const char *milter8_event(MILTER8 *milter, int event,
     /*
      * Receive the reply or replies.
      * 
+     * Intercept all loop exits so that we can do post body replacement
+     * processing.
+     * 
      * XXX Bound the loop iteration count.
      */
 #define IN_CONNECT_EVENT(e) ((e) == SMFIC_CONNECT || (e) == SMFIC_HELO)
 
-    for (;;) {
+    /*
+     * XXX Don't evaluate this macro's argument multiple times. Since we use
+     * "continue" the macro can't be enclosed in do .. while (0).
+     */
+#define MILTER8_EVENT_BREAK(s) { \
+       retval = (s); \
+       done = 1; \
+       continue; \
+    }
+
+    while (done == 0) {
        char   *cp;
        char   *rp;
        char    ch;
 
        if (milter8_read_resp(milter, event, &cmd, &data_size) != 0)
-           return (milter->def_reply);
+           MILTER8_EVENT_BREAK(milter->def_reply);
        if (msg_verbose)
            msg_info("reply: %s data %ld bytes",
                     (smfir_name = str_name_code(smfir_table, cmd)) != 0 ?
@@ -1001,7 +1018,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
        case SMFIR_CONTINUE:
            if (data_size != 0)
                break;
-           return (milter->def_reply);
+           MILTER8_EVENT_BREAK(milter->def_reply);
 
            /*
             * Decision: accept this message, or accept all further commands
@@ -1021,7 +1038,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
                /* No more events for this message. */
                milter->state = MILTER8_STAT_ACCEPT_MSG;
            }
-           return (milter->def_reply);
+           MILTER8_EVENT_BREAK(milter->def_reply);
 
            /*
             * Decision: accept and silently discard this message. According
@@ -1036,11 +1053,11 @@ static const char *milter8_event(MILTER8 *milter, int event,
                msg_warn("milter %s: DISCARD action is not allowed "
                         "for connect or helo", milter->m.name);
                milter8_conf_error(milter);
-               return (milter->def_reply);
+               MILTER8_EVENT_BREAK(milter->def_reply);
            } else {
                /* No more events for this message. */
                milter->state = MILTER8_STAT_ACCEPT_MSG;
-               return ("D");
+               MILTER8_EVENT_BREAK("D");
            }
 
            /*
@@ -1055,9 +1072,9 @@ static const char *milter8_event(MILTER8 *milter, int event,
                milter8_close_stream(milter);
 #endif
                milter->state = MILTER8_STAT_REJECT_CON;
-               return (milter8_def_reply(milter, "550 5.7.1 Command rejected"));
+               MILTER8_EVENT_BREAK(milter8_def_reply(milter, "550 5.7.1 Command rejected"));
            } else {
-               return ("550 5.7.1 Command rejected");
+               MILTER8_EVENT_BREAK("550 5.7.1 Command rejected");
            }
 
            /*
@@ -1072,10 +1089,10 @@ static const char *milter8_event(MILTER8 *milter, int event,
                milter8_close_stream(milter);
 #endif
                milter->state = MILTER8_STAT_REJECT_CON;
-               return (milter8_def_reply(milter,
+               MILTER8_EVENT_BREAK(milter8_def_reply(milter,
                        "451 4.7.1 Service unavailable - try again later"));
            } else {
-               return ("451 4.7.1 Service unavailable - try again later");
+               MILTER8_EVENT_BREAK("451 4.7.1 Service unavailable - try again later");
            }
 
            /*
@@ -1090,7 +1107,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
            milter8_close_stream(milter);
 #endif
            milter->state = MILTER8_STAT_REJECT_CON;
-           return (milter8_def_reply(milter, "S"));
+           MILTER8_EVENT_BREAK(milter8_def_reply(milter, "S"));
 #endif
 
            /*
@@ -1107,7 +1124,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
            if (milter8_read_data(milter, data_size,
                                  MILTER8_DATA_BUFFER, milter->buf,
                                  MILTER8_DATA_END) != 0)
-               return (milter->def_reply);
+               MILTER8_EVENT_BREAK(milter->def_reply);
            if ((STR(milter->buf)[0] != '4' && STR(milter->buf)[0] != '5')
                || !ISDIGIT(STR(milter->buf)[1])
                || !ISDIGIT(STR(milter->buf)[2])
@@ -1116,7 +1133,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
                msg_warn("milter %s: malformed reply: %s",
                         milter->m.name, STR(milter->buf));
                milter8_conf_error(milter);
-               return (milter->def_reply);
+               MILTER8_EVENT_BREAK(milter->def_reply);
            }
            if ((rp = cp = strchr(STR(milter->buf), '%')) != 0) {
                for (;;) {
@@ -1132,9 +1149,9 @@ static const char *milter8_event(MILTER8 *milter, int event,
                milter8_close_stream(milter);
 #endif
                milter->state = MILTER8_STAT_REJECT_CON;
-               return (milter8_def_reply(milter, STR(milter->buf)));
+               MILTER8_EVENT_BREAK(milter8_def_reply(milter, STR(milter->buf)));
            } else {
-               return (STR(milter->buf));
+               MILTER8_EVENT_BREAK(STR(milter->buf));
            }
 
            /*
@@ -1148,8 +1165,8 @@ static const char *milter8_event(MILTER8 *milter, int event,
            if (milter8_read_data(milter, data_size,
                                  MILTER8_DATA_BUFFER, milter->buf,
                                  MILTER8_DATA_END) != 0)
-               return (milter->def_reply);
-           return ("H");
+               MILTER8_EVENT_BREAK(milter->def_reply);
+           MILTER8_EVENT_BREAK("H");
 #endif
 
            /*
@@ -1170,8 +1187,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
                                          MILTER8_DATA_STRING, milter->buf,
                                          MILTER8_DATA_STRING, milter->body,
                                          MILTER8_DATA_END) != 0)
-                       return (milter->def_reply);
-                   parent = milter->m.parent;
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    /* XXX Sendmail 8 compatibility. */
                    if (index == 0)
                        index = 1;
@@ -1179,13 +1195,13 @@ static const char *milter8_event(MILTER8 *milter, int event,
                        msg_warn("milter %s: bad change header index: %ld",
                                 milter->m.name, (long) index);
                        milter8_conf_error(milter);
-                       return (milter->def_reply);
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    }
                    if (LEN(milter->buf) == 0) {
                        msg_warn("milter %s: null change header name",
                                 milter->m.name);
                        milter8_conf_error(milter);
-                       return (milter->def_reply);
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    }
                    if (STR(milter->body)[0])
                        edit_resp = parent->upd_header(parent->chg_context,
@@ -1197,7 +1213,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
                                                       (ssize_t) index,
                                                       STR(milter->buf));
                    if (edit_resp)
-                       return (edit_resp);
+                       MILTER8_EVENT_BREAK(edit_resp);
                    continue;
 #endif
 
@@ -1209,13 +1225,12 @@ static const char *milter8_event(MILTER8 *milter, int event,
                                          MILTER8_DATA_STRING, milter->buf,
                                          MILTER8_DATA_STRING, milter->body,
                                          MILTER8_DATA_END) != 0)
-                       return (milter->def_reply);
-                   parent = milter->m.parent;
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    edit_resp = parent->add_header(parent->chg_context,
                                                   STR(milter->buf),
                                                   STR(milter->body));
                    if (edit_resp)
-                       return (edit_resp);
+                       MILTER8_EVENT_BREAK(edit_resp);
                    continue;
 
                    /*
@@ -1231,20 +1246,19 @@ static const char *milter8_event(MILTER8 *milter, int event,
                                          MILTER8_DATA_STRING, milter->buf,
                                          MILTER8_DATA_STRING, milter->body,
                                          MILTER8_DATA_END) != 0)
-                       return (milter->def_reply);
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    if ((ssize_t) index + 1 < 1) {
                        msg_warn("milter %s: bad insert header index: %ld",
                                 milter->m.name, (long) index);
                        milter8_conf_error(milter);
-                       return (milter->def_reply);
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    }
-                   parent = milter->m.parent;
                    edit_resp = parent->ins_header(parent->chg_context,
                                                   (ssize_t) index + 1,
                                                   STR(milter->buf),
                                                   STR(milter->body));
                    if (edit_resp)
-                       return (edit_resp);
+                       MILTER8_EVENT_BREAK(edit_resp);
                    continue;
 #endif
 
@@ -1255,12 +1269,11 @@ static const char *milter8_event(MILTER8 *milter, int event,
                    if (milter8_read_data(milter, data_size,
                                          MILTER8_DATA_STRING, milter->buf,
                                          MILTER8_DATA_END) != 0)
-                       return (milter->def_reply);
-                   parent = milter->m.parent;
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    edit_resp = parent->add_rcpt(parent->chg_context,
                                                 STR(milter->buf));
                    if (edit_resp)
-                       return (edit_resp);
+                       MILTER8_EVENT_BREAK(edit_resp);
                    continue;
 
                    /*
@@ -1270,31 +1283,47 @@ static const char *milter8_event(MILTER8 *milter, int event,
                    if (milter8_read_data(milter, data_size,
                                          MILTER8_DATA_STRING, milter->buf,
                                          MILTER8_DATA_END) != 0)
-                       return (milter->def_reply);
-                   parent = milter->m.parent;
+                       MILTER8_EVENT_BREAK(milter->def_reply);
                    edit_resp = parent->del_rcpt(parent->chg_context,
                                                 STR(milter->buf));
                    if (edit_resp)
-                       return (edit_resp);
+                       MILTER8_EVENT_BREAK(edit_resp);
                    continue;
 
                    /*
                     * Modification request: replace the message body, and
                     * update the message size.
                     */
-#if 0
                case SMFIR_REPLBODY:
                    if (milter8_read_data(milter, data_size,
                                          MILTER8_DATA_BUFFER, milter->body,
                                          MILTER8_DATA_END) != 0)
-                       return (milter->def_reply);
-                   parent = milter->m.parent;
-                   edit_resp = parent->repl_body(parent->chg_context,
-                                                 milter->body);
-                   if (edit_resp)
-                       return (edit_resp);
+                       MILTER8_EVENT_BREAK(milter->def_reply);
+                   /* Start body replacement. */
+                   if (body_line_buf == 0) {
+                       body_line_buf = vstring_alloc(var_line_limit);
+                       edit_resp = parent->repl_body(parent->chg_context,
+                                                     MILTER_BODY_START,
+                                                     (VSTRING *) 0);
+                   }
+                   /* Extract lines from the on-the-wire CRLF format. */
+                   for (cp = STR(milter->body); edit_resp == 0
+                        && cp < vstring_end(milter->body); cp++) {
+                       ch = *(unsigned char *) cp;
+                       if (ch == '\n') {
+                           if (LEN(body_line_buf) > 0
+                               && vstring_end(body_line_buf)[-1] == '\r')
+                               vstring_truncate(body_line_buf,
+                                                LEN(body_line_buf) - 1);
+                           edit_resp = parent->repl_body(parent->chg_context,
+                                                         MILTER_BODY_LINE,
+                                                         body_line_buf);
+                           VSTRING_RESET(body_line_buf);
+                       } else {
+                           VSTRING_ADDCH(body_line_buf, ch);
+                       }
+                   }
                    continue;
-#endif
                }
            }
            msg_warn("milter %s: unexpected filter response %s after event %s",
@@ -1304,7 +1333,7 @@ static const char *milter8_event(MILTER8 *milter, int event,
                     (smfic_name = str_name_code(smfic_table, event)) != 0 ?
                     smfic_name : "(unknown MTA event)");
            milter8_comm_error(milter);
-           return (milter->def_reply);
+           MILTER8_EVENT_BREAK(milter->def_reply);
        }
 
        /*
@@ -1315,8 +1344,40 @@ static const char *milter8_event(MILTER8 *milter, int event,
        milter->m.name, (smfir_name = str_name_code(smfir_table, cmd)) != 0 ?
                 smfir_name : "unknown", (long) data_len);
        milter8_comm_error(milter);
-       return (milter->def_reply);
+       MILTER8_EVENT_BREAK(milter->def_reply);
+    }
+
+    /*
+     * Finish message body replacement.
+     */
+    if (body_line_buf != 0) {
+       if (edit_resp == 0) {
+           /* In case the last body replacement line didn't end in CRLF. */
+           if (LEN(body_line_buf) > 0)
+               edit_resp = parent->repl_body(parent->chg_context,
+                                             MILTER_BODY_LINE,
+                                             body_line_buf);
+           if (edit_resp == 0)
+               edit_resp = parent->repl_body(parent->chg_context,
+                                             MILTER_BODY_END,
+                                             (VSTRING *) 0);
+       }
+       vstring_free(body_line_buf);
+
+       /*
+        * Override a non-reject/discard result value after body replacement
+        * failure.
+        * 
+        * XXX Some cleanup clients ask the cleanup server to bounce mail for
+        * them. In that case we must override a hard reject retval result
+        * after queue file update failure. This is not a big problem; the
+        * odds are small that a Milter application sends a hard reject after
+        * replacing the message body.
+        */
+       if (edit_resp && (retval == 0 || strchr("DS4", retval[0]) == 0))
+           retval = edit_resp;
     }
+    return (retval);
 }
 
 /* milter8_connect - connect to filter */
@@ -1332,7 +1393,7 @@ static void milter8_connect(MILTER8 *milter)
     int     fd;
     const UINT32_TYPE my_actions = (SMFIF_ADDHDRS | SMFIF_ADDRCPT
                                    | SMFIF_DELRCPT | SMFIF_CHGHDRS
-    /* Not yet: | SMFIF_CHGBODY */
+                                   | SMFIF_CHGBODY
 #ifdef SMFIF_QUARANTINE
                                    | SMFIF_QUARANTINE
 #endif
@@ -1651,6 +1712,7 @@ static const char *milter8_helo_event(MILTER *m, const char *helo_name,
        return (milter->def_reply);
     case MILTER8_STAT_ENVELOPE:
     case MILTER8_STAT_ACCEPT_MSG:
+       /* With HELO after MAIL, smtpd(8) calls milter8_abort() next. */
        if (msg_verbose)
            msg_info("%s: milter %s: helo %s",
                     myname, milter->m.name, helo_name);
index ad76eb8001161f2ae31be85f95f1966818316c08..ba7289f66030b9f4b55dfc9a93babea2e54383da 100644 (file)
@@ -1,34 +1,52 @@
- /*
-  * Simple test mail filter program.
-  * 
-  * Options:
-  * 
-  * -a accept|tempfail|reject|discard|ddd x.y.z text
-  * 
-  * Specifies a non-default reply. The default is to always continue.
-  * 
-  * -d Enable libmilter debugging.
-  * 
-  * -c connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown|close|abort
-  * 
-  * When to send the non-default reply. The default is "connect".
-  * 
-  * -i "index header-label header-value"
-  * 
-  * Insert header at specified position.
-  * 
-  * -p inet:port@host|unix:/path/name
-  * 
-  * The mail filter listen endpoint.
-  * 
-  * -r "index header-label header-value"
-  * 
-  * Replace header at specified position.
-  * 
-  * -C count
-  * 
-  * Terminate after count connections.
-  */
+/*++
+/* NAME
+/*     test-milter 1
+/* SUMMARY
+/*     Simple test mail filter program.
+/* SYNOPSIS
+/* .fi
+/*     \fBtest-milter\fR [\fIoptions\fR] -p \fBinet:\fIport\fB@\fIhost\fR
+/*
+/*     \fBtest-milter\fR [\fIoptions\fR] -p \fBunix:\fIpathname\fR
+/* DESCRIPTION
+/*     \fBtest-milter\fR is a Milter (mail filter) application that
+/*     exercises selected features.
+/*
+/*     Note: this is an unsupported test program. No attempt is made
+/*     to maintain compatibility between successive versions.
+/*
+/*     Arguments (multiple alternatives are separated by "\fB|\fR"):
+/* .IP "\fB-a accept|tempfail|reject|discard|\fIddd x.y.z text\fR"
+/*     Specifies a non-default reply. The default is to continue
+/*     (i.e. \fBtempfail\fR).
+/* .IP "\fB-d\fI level\fR"
+/*     Enable libmilter debugging at the specified level.
+/* .IP "\fB-c connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown|close|abort\fR"
+/*     When to send the non-default reply specified with \fB-a\fR.
+/*     The default protocol stage is \fBconnect\fR.
+/* .IP "\fB-C\fI count\fR"
+/*     Terminate after \fIcount\fR connections.
+/* .IP "\fB-i \"\fIindex header-label header-value\"\fR"
+/*     Insert header at specified position.
+/* .IP "\fB-p inet:\fIport\fB@\fIhost\fB|unix:\fIpathname\fR"
+/*     The mail filter listen endpoint.
+/* .IP "\fB-r "index header-label header-value"
+/*     Replace the message header at the specified position.
+/* .IP "\fB-R pathname
+/*     Replace the message body by the content of the specified file.
+/* .IP "\fB-v\fR"
+/*     Make the program more verbose.
+/* 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
+/*--*/
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -110,12 +128,17 @@ static char *chg_val;
 
 #endif
 
+#ifdef SMFIR_REPLBODY
+static char *body_file;
+
+#endif
+
 static int test_reply(SMFICTX *ctx, int code)
 {
     (void) fflush(stdout);             /* In case output redirected. */
 
     if (code == SMFIR_REPLYCODE) {
-       if (smfi_setreply(ctx, reply_code, reply_dsn, reply_message) != MI_SUCCESS)
+       if (smfi_setreply(ctx, reply_code, reply_dsn, reply_message) == MI_FAILURE)
            fprintf(stderr, "smfi_setreply failed\n");
        return (reply_code[0] == '4' ? SMFIS_TEMPFAIL : SMFIS_REJECT);
     } else {
@@ -227,6 +250,34 @@ static sfsistat test_eom(SMFICTX *ctx)
 #ifdef SMFIR_CHGHEADER
     if (chg_hdr && smfi_chgheader(ctx, chg_hdr, chg_idx, chg_val) == MI_FAILURE)
        fprintf(stderr, "smfi_chgheader failed");
+#endif
+#ifdef SMFIR_REPLBODY
+    if (body_file) {
+       char    buf[BUFSIZ + 2];
+       FILE   *fp;
+       size_t  len;
+       int     count;
+
+       if ((fp = fopen(body_file, "r")) == 0) {
+           perror(body_file);
+       } else {
+           printf("replace body with content of %s\n", body_file);
+           for (count = 0; fgets(buf, BUFSIZ, fp) != 0; count++) {
+               len = strcspn(buf, "\n");
+               buf[len+0] = '\r';
+               buf[len+1] = '\n';
+               if (smfi_replacebody(ctx, buf, len + 2) == MI_FAILURE) {
+                   fprintf(stderr, "body replace failure\n");
+                   exit(1);
+               }
+               if (verbose)
+                   printf("%.*s\n", (int) len, buf);
+           }
+           if (count == 0)
+               perror("fgets");
+           (void) fclose(fp);
+       }
+    }
 #endif
     return (test_reply(ctx, test_eom_reply));
 }
@@ -271,7 +322,7 @@ static struct smfiDesc smfilter =
 {
     "test-milter",
     SMFI_VERSION,
-    SMFIF_ADDRCPT | SMFIF_DELRCPT | SMFIF_ADDHDRS | SMFIF_CHGHDRS,
+    SMFIF_ADDRCPT | SMFIF_DELRCPT | SMFIF_ADDHDRS | SMFIF_CHGHDRS | SMFIF_CHGBODY,
     test_connect,
     test_helo,
     test_mail,
@@ -314,7 +365,7 @@ int     main(int argc, char **argv)
     int     ch;
     int     code;
 
-    while ((ch = getopt(argc, argv, "a:c:d:i:p:r:vC:")) > 0) {
+    while ((ch = getopt(argc, argv, "a:c:C:d:i:p:r:R:v")) > 0) {
        switch (ch) {
        case 'a':
            action = optarg;
@@ -364,6 +415,15 @@ int     main(int argc, char **argv)
        case 'C':
            conn_count = atoi(optarg);
            break;
+#ifdef SMFIR_REPLBODY
+       case 'R':
+           if (body_file) {
+               fprintf(stderr, "too many -R options\n");
+               exit(1);
+           }
+           body_file = optarg;
+#endif
+           break;
        default:
            fprintf(stderr,
                    "usage: %s [-dv] \n"
@@ -373,6 +433,7 @@ int     main(int argc, char **argv)
                    "\t-p port                  milter application\n"
                    "\t[-r 'index label value'] replace header\n"
                    "\t[-C conn_count]          when to exit\n",
+                   "\t[-R body_text]           replace body\n",
                    argv[0]);
            exit(1);
        }
index 73744c5d8fe0a9434c058256f558b0fa71551a49..20f8c3a1861b269d1761caf643dc59a83a910f59 100644 (file)
@@ -230,7 +230,8 @@ struct QMGR_MESSAGE {
     char   *filter_xport;              /* filtering transport */
     char   *inspect_xport;             /* inspecting transport */
     char   *redirect_addr;             /* info@spammer.tld */
-    long    data_size;                 /* message content size */
+    long    data_size;                 /* data segment size */
+    long    cont_length;               /* message content length */
     long    rcpt_offset;               /* more recipients here */
     char   *client_name;               /* client hostname */
     char   *client_addr;               /* client address */
index 8d3b682ab1c2ce6b0e34de7c2d54fd6ecf8528d7..7e06b5dc5b8dae99178d79ffe80cbc33106f270b 100644 (file)
@@ -158,7 +158,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
               ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
               ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset,
-              ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->data_size,
+              ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->cont_length,
               ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, entry->queue->nexthop,
               ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding,
               ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
index 8e56e56e406fab7c77dd1eca6aee28d28a2e6a05..a646daef94558f1c4ccc2aa398518b81469af38b 100644 (file)
@@ -172,6 +172,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->inspect_xport = 0;
     message->redirect_addr = 0;
     message->data_size = 0;
+    message->cont_length = 0;
     message->warn_offset = 0;
     message->warn_time = 0;
     message->rcpt_offset = 0;
@@ -506,9 +507,10 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
            continue;
        if (rec_type == REC_TYPE_SIZE) {
            if (message->data_offset == 0) {
-               if ((count = sscanf(start, "%ld %ld %d %d",
+               if ((count = sscanf(start, "%ld %ld %d %d %ld",
                                 &message->data_size, &message->data_offset,
-                                   &nrcpt, &message->rflags)) >= 3) {
+                                   &nrcpt, &message->rflags,
+                                   &message->cont_length)) >= 3) {
                    /* Postfix >= 1.0 (a.k.a. 20010228). */
                    if (message->data_offset <= 0 || message->data_size <= 0) {
                        msg_warn("%s: invalid size record: %.100s",
@@ -533,6 +535,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    break;
                }
            }
+           /* Postfix < 2.4 compatibility. */
+           if (message->cont_length == 0) {
+               message->cont_length = message->data_size;
+           } else if (message->cont_length < 0) {
+               msg_warn("%s: invalid size record: %.100s",
+                        message->queue_id, start);
+               rec_type = REC_TYPE_ERROR;
+               break;
+           }
            continue;
        }
        if (rec_type == REC_TYPE_TIME) {
@@ -567,7 +578,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
            if (message->sender == 0) {
                message->sender = mystrdup(start);
                opened(message->queue_id, message->sender,
-                      message->data_size, nrcpt,
+                      message->cont_length, nrcpt,
                       "queue %s", message->queue_name);
            }
            continue;
index 5582ef81a18dc511ce50760f91debebb3996fdee..f4b35460217fff7a084c59b0ab7c328febc4a85e 100644 (file)
@@ -139,7 +139,8 @@ struct QMGR_TRANSPORT {
     int     rcpt_per_stack;            /* extra slots reserved for jobs put
                                         * on the job stack */
     int     rcpt_unused;               /* available in-core recipient slots */
-    int     refill_limit;              /* recipient batch size for message refill */
+    int     refill_limit;              /* recipient batch size for message
+                                        * refill */
     int     refill_delay;              /* delay before message refill */
     int     slot_cost;                 /* cost of new preemption slot (# of
                                         * selected entries) */
@@ -259,7 +260,8 @@ struct QMGR_MESSAGE {
     struct timeval active_time;                /* time of entry into active queue */
     time_t  queued_time;               /* sanitized time when moved to the
                                         * active queue */
-    time_t  refill_time;               /* sanitized time of last message refill */
+    time_t  refill_time;               /* sanitized time of last message
+                                        * refill */
     long    warn_offset;               /* warning bounce flag offset */
     time_t  warn_time;                 /* time next warning to be sent */
     long    data_offset;               /* data seek offset */
@@ -273,7 +275,8 @@ struct QMGR_MESSAGE {
     char   *filter_xport;              /* filtering transport */
     char   *inspect_xport;             /* inspecting transport */
     char   *redirect_addr;             /* info@spammer.tld */
-    long    data_size;                 /* message content size */
+    long    data_size;                 /* data segment size */
+    long    cont_length;               /* message content length */
     long    rcpt_offset;               /* more recipients here */
     char   *client_name;               /* client hostname */
     char   *client_addr;               /* client address */
index c0589e16dff401c2132cba2c591b91ac93d9ee96..2785e59a95c959767777853842c63a11a6900dfe 100644 (file)
@@ -163,7 +163,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
               ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
               ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
               ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset,
-              ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->data_size,
+              ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->cont_length,
               ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, entry->queue->nexthop,
               ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding,
               ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender,
index ae0dd174d740d2347149934e9cb0e27bf7f9390c..9be26ec1cc0af837f47d9f951967e1c3bc683bd0 100644 (file)
@@ -183,6 +183,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
     message->inspect_xport = 0;
     message->redirect_addr = 0;
     message->data_size = 0;
+    message->cont_length = 0;
     message->warn_offset = 0;
     message->warn_time = 0;
     message->rcpt_offset = 0;
@@ -547,9 +548,10 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
            continue;
        if (rec_type == REC_TYPE_SIZE) {
            if (message->data_offset == 0) {
-               if ((count = sscanf(start, "%ld %ld %d %d",
+               if ((count = sscanf(start, "%ld %ld %d %d %ld",
                                 &message->data_size, &message->data_offset,
-                          &message->rcpt_unread, &message->rflags)) >= 3) {
+                                   &message->rcpt_unread, &message->rflags,
+                                   &message->cont_length)) >= 3) {
                    /* Postfix >= 1.0 (a.k.a. 20010228). */
                    if (message->data_offset <= 0 || message->data_size <= 0) {
                        msg_warn("%s: invalid size record: %.100s",
@@ -574,6 +576,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                    break;
                }
            }
+           /* Postfix < 2.4 compatibility. */
+           if (message->cont_length == 0) {
+               message->cont_length = message->data_size;
+           } else if (message->cont_length < 0) {
+               msg_warn("%s: invalid size record: %.100s",
+                        message->queue_id, start);
+               rec_type = REC_TYPE_ERROR;
+               break;
+           }
            continue;
        }
        if (rec_type == REC_TYPE_TIME) {
@@ -608,7 +619,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
            if (message->sender == 0) {
                message->sender = mystrdup(start);
                opened(message->queue_id, message->sender,
-                      message->data_size, message->rcpt_unread,
+                      message->cont_length, message->rcpt_unread,
                       "queue %s", message->queue_name);
            }
            continue;
index 75b6c84f388a341aa4aed66fa4127b2fbda82565..c04381ba8b5089f5cae821741474f725115fb4a4 100644 (file)
@@ -107,8 +107,8 @@ OK
 >>> mail sname@sdomain
 OK
 >>> rcpt rname@rdomain
-./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
-554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@example.tld
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.189.2]: 554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain; from=<sname@sdomain> to=<rname@rdomain> proto=SMTP helo=<example.tld>
+554 5.7.1 Service unavailable; Helo command [example.tld] blocked using abuse.rfc-ignorant.org; Not supporting abuse@domain
 >>> #
 >>> # Check MX access
 >>> #