This is a code cleanup release. The main change is more graceful handling of message content with abnormally long lines or with abnormally long logical message headers. The purpose of the change is to avoid inter-operability problems, and to avoid breaking MIME encapsulation so that attachments no longer "disappear". The new code avoids problems with SMTP servers that will not receive mail with lines longer than the 1000 characters that are allowed by the SMTP standard. The new code is more graceful in the handling of abnormally long message headers. It will no longer switch from "message header" to "message body" mode in the middle of an abnormally long message header line. Prereq: "1.1.5" diff -cr ../postfix-1.1.5/src/global/mail_version.h ./src/global/mail_version.h *** ../postfix-1.1.5/src/global/mail_version.h Mon Mar 11 21:10:12 2002 --- ./src/global/mail_version.h Tue Mar 26 15:17:54 2002 *************** *** 22,30 **** */ #define VAR_MAIL_VERSION "mail_version" #ifdef SNAPSHOT ! #define DEF_MAIL_VERSION "1.1.5-$mail_release_date" #else ! #define DEF_MAIL_VERSION "1.1.5" #endif extern char *var_mail_version; --- 22,30 ---- */ #define VAR_MAIL_VERSION "mail_version" #ifdef SNAPSHOT ! #define DEF_MAIL_VERSION "1.1.6-$mail_release_date" #else ! #define DEF_MAIL_VERSION "1.1.6" #endif extern char *var_mail_version; *************** *** 32,38 **** * Release date. */ #define VAR_MAIL_RELEASE "mail_release_date" ! #define DEF_MAIL_RELEASE "20020311" extern char *var_mail_release; /* LICENSE --- 32,38 ---- * Release date. */ #define VAR_MAIL_RELEASE "mail_release_date" ! #define DEF_MAIL_RELEASE "20020326" extern char *var_mail_release; /* LICENSE diff -cr ../postfix-1.1.5/HISTORY ./HISTORY *** ../postfix-1.1.5/HISTORY Mon Mar 11 20:51:39 2002 --- ./HISTORY Tue Mar 26 15:39:02 2002 *************** *** 6125,6131 **** --- 6125,6197 ---- Duchovny, Morgan Stanley. Files: util/dict.h util/dict.c util/dict_db.c util/dict_dbm.c global/mkmap.c local/alias.c. + 20020313 + + Bugfix: mailq could show addresses with unusual characters + twice. Problem reported by Victor Duchovny, Morgan Stanley. + File: showq/showq.c. + + Bugfix: null recipients weren't properly recorded in + bounce/defer logfiles. Such recipient addresses are not + accepted in SMTP mail, but they could appear within locally + submitted mail. File: bounce/bounce_append_service.c. + + 20020318 + + Workaround: Berkeley DB can't handle null key lookups, + which happen with HELO names ending in ".". Victor Duchovni, + Morgan Stanley. File: smtpd/smtpd_check.c. + + Logging: log a hint when mail is deferred because the + soft_bounce parameter is set. People sometimes forget to + turn it off. File: global/bounce.c. + + 20020319 + + Cleanup: add a msg_warn() call when fork() fails in + pipe_command(), to make problems easier to investigate. + Chris Wedgwood. File: global/pipe_command.c. + + 20020324 + + Cleanup: more graceful handling of long physical message + header lines upon input. Physical header lines can now + extend up to $header_size_limit characters. When a logical + message header is too long, the excess text is discarded + and Postfix no longer switches to body mode, to avoid + breaking MIME encapsulation. Based on code by Victor + Duchovni, Morgan Stanley. Files: cleanup/cleanup_out.c, + cleanup/cleanup_message.c. + + Cleanup: more graceful handling of long physical message + header or body lines upon output by the SMTP client. The + SMTP client output line length is controlled by a new + parameter smtp_line_length_limit (default: 990; specify 0 + to disable the limit). Long lines are folded by inserting + , to avoid breaking MIME encapsulation. + Based on code by Victor Duchovni, Morgan Stanley. File: + smtp/smtp_proto.c. + + 20020325 + + Cleanup: allow additional text after a WARN command in a + header/body_checks pattern file, so that one can change + REJECT+text into WARN+text and vice versa. Based on code + by Fredrik Thulin, Stockholm University. + + Cleanup: log a warning when an unknown command is found in + a header/body_checks pattern file, or when additional text + is found after a command that does not expect additional + text. Based on code by Fredrik Thulin, Stockholm University. + + Bugfix: sendmail should not recognize "." as the end of + input when the current read operation started in the middle + of a line. Victor Duchovni, Morgan Stanley. File: + sendmail/sendmail.c. + Open problems: + + Low: sendmail does not store null command-line recipients. Low: don't do user@domain and @domain lookups in local_recipient_maps queries. diff -cr ../postfix-1.1.5/README_FILES/FILTER_README ./README_FILES/FILTER_README *** ../postfix-1.1.5/README_FILES/FILTER_README Tue Jan 22 09:07:57 2002 --- ./README_FILES/FILTER_README Tue Mar 26 16:40:31 2002 *************** *** 51,57 **** exit $? The idea is to first capture the message to file and then run the ! content through run a third-party content filter program. If the mail cannot be captured to file, mail delivery is deferred by terminating with exit status 75 (EX_TEMPFAIL). If the content filter program finds a problem, the mail is bounced by terminating --- 51,57 ---- exit $? The idea is to first capture the message to file and then run the ! content through a third-party content filter program. If the mail cannot be captured to file, mail delivery is deferred by terminating with exit status 75 (EX_TEMPFAIL). If the content filter program finds a problem, the mail is bounced by terminating diff -cr ../postfix-1.1.5/RELEASE_NOTES ./RELEASE_NOTES *** ../postfix-1.1.5/RELEASE_NOTES Fri Feb 1 13:55:45 2002 --- ./RELEASE_NOTES Tue Mar 26 16:11:22 2002 *************** *** 12,17 **** --- 12,42 ---- date. Snapshots change only the release date, unless they include the same bugfix as a patch release. + Incompatible changes with Postfix version 1.1.6 (released 20020326) + =================================================================== + + The Postfix SMTP client now breaks message header or body lines + that are longer than $smtp_line_length_limit characters (default: + 990). Earlier Postfix versions broke lines at $line_length_limit + characters (default: 2048). Postfix versions before 20010611 did + not break long lines at all. Reportedly, some mail servers refuse + to receive mail with lines that exceed the 1000 character limit + that is specified by the SMTP standard. + + The Postfix SMTP client now breaks long message header or body + lines by inserting . Earlier Postfix versions + broke long lines by inserting only. This broke MIME + encapsulation, causing MIME attachments to "disappear" with Postfix + versions after 20010611. + + Postfix now discards text when a logical message header exceeds + $header_size_limit characters (default: 102400). Earlier Postfix + versions would place excess text, and all following text, in the + message body. The same thing was done when a physical header line + exceeded $line_length_limit characters (default: 2048). Both + behaviors broke MIME encapsulation, causing MIME attachments to + "disappear" with all previous Postfix versions. + Incompatible changes with Postfix version 1.1.3 (released 20020201) =================================================================== *************** *** 20,26 **** some Berkeley DB implementations. This behavior is controlled with the smtpd_null_access_lookup_key configuration parameter. ! On SCO #.2 UNIX, the input rate flow control is now turned off by default, because of limitations in the SCO UNIX kernel. Incompatible changes with Postfix version 1.1.2 (released 20020125) --- 45,51 ---- some Berkeley DB implementations. This behavior is controlled with the smtpd_null_access_lookup_key configuration parameter. ! On SCO 3.2 UNIX, the input rate flow control is now turned off by default, because of limitations in the SCO UNIX kernel. Incompatible changes with Postfix version 1.1.2 (released 20020125) diff -cr ../postfix-1.1.5/conf/main.cf ./conf/main.cf *** ../postfix-1.1.5/conf/main.cf Sun Mar 3 11:58:06 2002 --- ./conf/main.cf Mon Mar 25 15:09:24 2002 *************** *** 417,422 **** --- 417,423 ---- # REJECT text.... The text is sent to the originator. # IGNORE the header line is silently discarded. # WARN the header is logged (not rejected) with a warning message. + # WARN text... as above, and the text is logged, too. # # These patterns do not apply to MIME headers in the message body. # diff -cr ../postfix-1.1.5/conf/sample-filter.cf ./conf/sample-filter.cf *** ../postfix-1.1.5/conf/sample-filter.cf Tue Nov 27 12:55:57 2001 --- ./conf/sample-filter.cf Mon Mar 25 11:12:21 2002 *************** *** 15,20 **** --- 15,21 ---- # REJECT text.... The text is sent to the originator. # IGNORE the header line is silently discarded. # WARN the header is logged (not rejected) with a warning message. + # WARN text... as above, and the text is logged, too. # # These patterns do not apply to MIME headers in the message body. # *************** *** 34,38 **** --- 35,40 ---- # REJECT text.... The text is sent to the originator. # IGNORE the body line is silently discarded. # WARN the body line is logged (not rejected) with a warning message. + # WARN text... as above, and the text is logged, too. # body_checks = regexp:/etc/postfix/body_checks diff -cr ../postfix-1.1.5/conf/sample-pcre-body.cf ./conf/sample-pcre-body.cf *** ../postfix-1.1.5/conf/sample-pcre-body.cf Mon Dec 10 11:04:07 2001 --- ./conf/sample-pcre-body.cf Mon Mar 25 11:12:35 2002 *************** *** 25,30 **** --- 25,31 ---- # REJECT text.... The text is sent to the originator. # IGNORE The line is silently discarded. # WARN The line is logged (not rejected) with a warning. + # WARN text.... As above, and the text is logged, too. # # Substitution of sub-strings from the matched expression is # possible using the conventional perl syntax. The macros in the diff -cr ../postfix-1.1.5/conf/sample-pcre-header.cf ./conf/sample-pcre-header.cf *** ../postfix-1.1.5/conf/sample-pcre-header.cf Mon Dec 10 11:10:58 2001 --- ./conf/sample-pcre-header.cf Mon Mar 25 11:12:52 2002 *************** *** 25,30 **** --- 25,31 ---- # REJECT text.... The text is sent to the originator. # IGNORE The header line is silently discarded. # WARN The header is logged (not rejected) with a warning. + # WARN text.... As above, and the text is logged, too. # # Substitution of sub-strings from the matched expression is # possible using the conventional perl syntax. The macros in the diff -cr ../postfix-1.1.5/conf/sample-regexp-body.cf ./conf/sample-regexp-body.cf *** ../postfix-1.1.5/conf/sample-regexp-body.cf Wed Dec 12 17:38:19 2001 --- ./conf/sample-regexp-body.cf Mon Mar 25 11:13:11 2002 *************** *** 21,23 **** --- 21,24 ---- # REJECT text.... The text is sent to the originator. # IGNORE The header line is silently discarded. # WARN The header is logged (not rejected) with a warning. + # WARN text.... As above, and the text is logged, too. diff -cr ../postfix-1.1.5/conf/sample-regexp-header.cf ./conf/sample-regexp-header.cf *** ../postfix-1.1.5/conf/sample-regexp-header.cf Mon Dec 10 20:24:07 2001 --- ./conf/sample-regexp-header.cf Mon Mar 25 11:13:30 2002 *************** *** 22,27 **** --- 22,28 ---- # REJECT text.... The text is sent to the originator. # IGNORE the header line is silently discarded. # WARN the header is logged (not rejected) with a warning. + # WARN text... As above, and the text is logged, too. /^Subject: Make Money Fast/ REJECT /^To: friend@public.com/ REJECT diff -cr ../postfix-1.1.5/conf/sample-smtp.cf ./conf/sample-smtp.cf *** ../postfix-1.1.5/conf/sample-smtp.cf Mon Dec 10 20:04:51 2001 --- ./conf/sample-smtp.cf Mon Mar 25 11:20:51 2002 *************** *** 65,77 **** # #smtp_bind_address=111.222.333.444 ! # The smtp_break_lines parameter controls whether the SMTP client ! # will break lines longer than $line_length_limit characters. # ! # By default, line breaking is turned on, because some fragile SMTP ! # server implementations cannot receive mail with long lines. # ! #smtp_break_lines = yes # The smtp_skip_4xx_greeting parameter controls what happens when # an SMTP server greets us with a 4XX status code (go away, try --- 65,78 ---- # #smtp_bind_address=111.222.333.444 ! # The smtp_line_length_limit parameter controls the length of ! # message header and body lines that Postfix will send via SMTP. ! # Lines that are longer are broken by inserting . # ! # By default, the line length is limited to 990 characters, because ! # some server implementations cannot receive mail with long lines. # ! #smtp_line_length_limit = 990 # The smtp_skip_4xx_greeting parameter controls what happens when # an SMTP server greets us with a 4XX status code (go away, try diff -cr ../postfix-1.1.5/html/nqmgr.8.html ./html/nqmgr.8.html *** ../postfix-1.1.5/html/nqmgr.8.html Fri Aug 3 19:43:33 2001 --- ./html/nqmgr.8.html Tue Mar 26 16:49:23 2002 *************** *** 1,5 ****
- 
  NQMGR(8)                                                 NQMGR(8)
  
  NAME
--- 1,4 ----
***************
*** 224,230 ****
                transport can have.
  
  Timing controls
!        min_backoff
                Minimal  time  in seconds between delivery attempts
                of a deferred message.
  
--- 223,229 ----
                transport can have.
  
  Timing controls
!        minimal_backoff_time
                Minimal  time  in seconds between delivery attempts
                of a deferred message.
  
***************
*** 232,238 ****
                destination  is  kept  in the short-term, in-memory
                destination status cache.
  
!        max_backoff
                Maximal time in seconds between  delivery  attempts
                of a deferred message.
  
--- 231,237 ----
                destination  is  kept  in the short-term, in-memory
                destination status cache.
  
!        maximal_backoff_time
                Maximal time in seconds between  delivery  attempts
                of a deferred message.
  
***************
*** 338,343 ****
         Modra 6
         155 00, Prague, Czech Republic
  
!                                                                 1
! 
  
--- 337,341 ---- Modra 6 155 00, Prague, Czech Republic ! NQMGR(8) diff -cr ../postfix-1.1.5/html/qmgr.8.html ./html/qmgr.8.html *** ../postfix-1.1.5/html/qmgr.8.html Fri Aug 3 19:43:33 2001 --- ./html/qmgr.8.html Tue Mar 26 16:49:22 2002 *************** *** 1,5 ****
- 
  QMGR(8)                                                   QMGR(8)
  
  NAME
--- 1,4 ----
***************
*** 193,199 ****
                term, in-memory destination cache.
  
  Timing controls
!        min_backoff
                Minimal time in seconds between  delivery  attempts
                of a deferred message.
  
--- 192,198 ----
                term, in-memory destination cache.
  
  Timing controls
!        minimal_backoff_time
                Minimal time in seconds between  delivery  attempts
                of a deferred message.
  
***************
*** 201,207 ****
                destination is kept in  the  short-term,  in-memory
                destination status cache.
  
!        max_backoff
                Maximal  time  in seconds between delivery attempts
                of a deferred message.
  
--- 200,206 ----
                destination is kept in  the  short-term,  in-memory
                destination status cache.
  
!        maximal_backoff_time
                Maximal  time  in seconds between delivery attempts
                of a deferred message.
  
***************
*** 287,292 ****
         P.O. Box 704
         Yorktown Heights, NY 10598, USA
  
!                                                                 1
! 
  
--- 286,290 ---- P.O. Box 704 Yorktown Heights, NY 10598, USA ! QMGR(8) diff -cr ../postfix-1.1.5/html/showq.8.html ./html/showq.8.html *** ../postfix-1.1.5/html/showq.8.html Tue Jan 15 09:42:35 2002 --- ./html/showq.8.html Tue Mar 26 16:49:22 2002 *************** *** 1,5 ****
- 
  SHOWQ(8)                                                 SHOWQ(8)
  
  NAME
--- 1,4 ----
***************
*** 51,56 ****
         P.O. Box 704
         Yorktown Heights, NY 10598, USA
  
!                                                                 1
! 
  
--- 50,54 ---- P.O. Box 704 Yorktown Heights, NY 10598, USA ! SHOWQ(8) diff -cr ../postfix-1.1.5/html/smtp.8.html ./html/smtp.8.html *** ../postfix-1.1.5/html/smtp.8.html Mon Mar 11 19:55:43 2002 --- ./html/smtp.8.html Mon Mar 25 10:49:08 2002 *************** *** 120,129 **** Numerical source network address to bind to when making a connection. ! smtp_break_lines ! Break lines > $line_length_limit into multiple ! shorter lines. Some SMTP servers misbehave on long ! lines. smtp_skip_4xx_greeting Skip servers that greet us with a 4xx status code. --- 120,129 ---- Numerical source network address to bind to when making a connection. ! smtp_line_length_limit ! Length limit for SMTP message content lines. Zero ! means no limit. Some SMTP servers misbehave on ! long lines. smtp_skip_4xx_greeting Skip servers that greet us with a 4xx status code. diff -cr ../postfix-1.1.5/html/uce.html ./html/uce.html *** ../postfix-1.1.5/html/uce.html Fri Jan 18 07:54:32 2002 --- ./html/uce.html Mon Mar 25 11:08:54 2002 *************** *** 48,53 **** --- 48,57 ----

+

  • Body filtering + +

    +

  • Client hostname/address restrictions *************** *** 93,100 ****

    Header filtering

    ! The header_checks parameter restricts what ! is allowed in message headers.

    --- 97,105 ----

    Header filtering

    ! The header_checks parameter restricts what is allowed in ! message headers. Patterns are applied to entire logical message ! headers, even when a header spans multiple lines of text.

    *************** *** 124,129 **** --- 129,136 ----

    WARN
    Log (but do not reject) the header with a warning. +
    WARN text...
    As above, and also log the text. +

    *************** *** 148,153 **** --- 155,224 ----

    Example (header_checks):
    /^to: *friend@public\.com$/ REJECT + +

    + + + +

    Body filtering

    + + The body_checks parameter restricts what text is + is allowed in message body lines (including MIME headers + within the message body). + +

    + + Note: the message body is matched one line at a time. + There is no multi-line concept as with message headers. + +

    + +

    + +
    Default: + +
    Allow anything in message body lines. + +

    + +

    Syntax: + +
    Specify a list of zero or more lookup tables. Whenever a body + line matches a table, the action depends on the lookup result: + +

    + +

    + +
    REJECT
    Reject the message, and log the matched line. + +
    REJECT text...
    As above, and also send the text to + the originator. + +
    IGNORE
    Delete the matched line from the message. + +
    WARN
    Log (but do not reject) the matched line with a warning. + +
    WARN text...
    As above, and also log the text. + +
    + +

    + + At present, specifying a pattern with OK serves no useful + purpose. A rule ending in OK affects only the line being matched. + The next line may still result in a REJECT match, causing the + mail still to be rejected. + +

    + +

    + +

    Examples (main.cf): + +
    body_checks = regexp:/etc/postfix/body_checks + +
    body_checks = pcre:/etc/postfix/body_checks

    diff -cr ../postfix-1.1.5/man/man8/nqmgr.8 ./man/man8/nqmgr.8 *** ../postfix-1.1.5/man/man8/nqmgr.8 Fri Aug 3 19:43:27 2001 --- ./man/man8/nqmgr.8 Tue Mar 26 16:49:21 2002 *************** *** 208,220 **** .SH "Timing controls" .ad .fi ! .IP \fBmin_backoff\fR Minimal time in seconds between delivery attempts of a deferred message. .sp This parameter also limits the time an unreachable destination is kept in the short-term, in-memory destination status cache. ! .IP \fBmax_backoff\fR Maximal time in seconds between delivery attempts of a deferred message. .IP \fBmaximal_queue_lifetime\fR --- 208,220 ---- .SH "Timing controls" .ad .fi ! .IP \fBminimal_backoff_time\fR Minimal time in seconds between delivery attempts of a deferred message. .sp This parameter also limits the time an unreachable destination is kept in the short-term, in-memory destination status cache. ! .IP \fBmaximal_backoff_time\fR Maximal time in seconds between delivery attempts of a deferred message. .IP \fBmaximal_queue_lifetime\fR diff -cr ../postfix-1.1.5/man/man8/qmgr.8 ./man/man8/qmgr.8 *** ../postfix-1.1.5/man/man8/qmgr.8 Fri Aug 3 19:43:27 2001 --- ./man/man8/qmgr.8 Tue Mar 26 16:49:21 2002 *************** *** 189,201 **** .SH "Timing controls" .ad .fi ! .IP \fBmin_backoff\fR Minimal time in seconds between delivery attempts of a deferred message. .sp This parameter also limits the time an unreachable destination is kept in the short-term, in-memory destination status cache. ! .IP \fBmax_backoff\fR Maximal time in seconds between delivery attempts of a deferred message. .IP \fBmaximal_queue_lifetime\fR --- 189,201 ---- .SH "Timing controls" .ad .fi ! .IP \fBminimal_backoff_time\fR Minimal time in seconds between delivery attempts of a deferred message. .sp This parameter also limits the time an unreachable destination is kept in the short-term, in-memory destination status cache. ! .IP \fBmaximal_backoff_time\fR Maximal time in seconds between delivery attempts of a deferred message. .IP \fBmaximal_queue_lifetime\fR diff -cr ../postfix-1.1.5/man/man8/smtp.8 ./man/man8/smtp.8 *** ../postfix-1.1.5/man/man8/smtp.8 Mon Mar 11 19:55:42 2002 --- ./man/man8/smtp.8 Mon Mar 25 10:49:08 2002 *************** *** 113,120 **** Never send EHLO at the start of a connection. .IP \fBsmtp_bind_address\fR Numerical source network address to bind to when making a connection. ! .IP \fBsmtp_break_lines\fR ! Break lines > \fB$line_length_limit\fR into multiple shorter lines. Some SMTP servers misbehave on long lines. .IP \fBsmtp_skip_4xx_greeting\fR Skip servers that greet us with a 4xx status code. --- 113,120 ---- Never send EHLO at the start of a connection. .IP \fBsmtp_bind_address\fR Numerical source network address to bind to when making a connection. ! .IP \fBsmtp_line_length_limit\fR ! Length limit for SMTP message content lines. Zero means no limit. Some SMTP servers misbehave on long lines. .IP \fBsmtp_skip_4xx_greeting\fR Skip servers that greet us with a 4xx status code. diff -cr ../postfix-1.1.5/src/bounce/bounce_append_service.c ./src/bounce/bounce_append_service.c *** ../postfix-1.1.5/src/bounce/bounce_append_service.c Sun Dec 3 18:57:33 2000 --- ./src/bounce/bounce_append_service.c Tue Mar 26 15:52:18 2002 *************** *** 91,96 **** --- 91,102 ---- * file format because we do not need anything more complicated. As a * benefit, we can still recover some data when the file is a little * garbled. + * + * XXX addresses in defer logfiles are in printable quoted form, while + * addresses in message envelope records are in raw unquoted form. This + * may change once we replace the present ad-hoc bounce/defer logfile + * format by one that is transparent for control etc. characters. See + * also: showq/showq.c. */ if ((orig_length = vstream_fseek(log, 0L, SEEK_END)) < 0) msg_fatal("seek file %s %s: %m", service, queue_id); *************** *** 98,103 **** --- 104,111 ---- if (*recipient) vstream_fprintf(log, "<%s>: ", printable(vstring_str(quote_822_local(in_buf, recipient)), '?')); + else + vstream_fprintf(log, "<>: "); vstream_fputs(printable(why, '?'), log); vstream_fputs("\n\n", log); diff -cr ../postfix-1.1.5/src/cleanup/Makefile.in ./src/cleanup/Makefile.in *** ../postfix-1.1.5/src/cleanup/Makefile.in Fri Jan 25 09:10:49 2002 --- ./src/cleanup/Makefile.in Sun Mar 24 14:47:01 2002 *************** *** 265,270 **** --- 265,271 ---- cleanup_out.o: ../../include/record.h cleanup_out.o: ../../include/rec_type.h cleanup_out.o: ../../include/cleanup_user.h + cleanup_out.o: ../../include/mail_params.h cleanup_out.o: cleanup.h cleanup_out.o: ../../include/argv.h cleanup_out.o: ../../include/maps.h diff -cr ../postfix-1.1.5/src/cleanup/cleanup.h ./src/cleanup/cleanup.h *** ../postfix-1.1.5/src/cleanup/cleanup.h Tue Oct 30 19:39:06 2001 --- ./src/cleanup/cleanup.h Sun Mar 24 14:48:10 2002 *************** *** 47,52 **** --- 47,53 ---- int err_mask; /* allowed badness */ VSTRING *header_buf; /* multi-record header */ int headers_seen; /* which headers were seen */ + int long_header; /* multi-record physical header line */ int hop_count; /* count of received: headers */ ARGV *recipients; /* recipients from regular headers */ ARGV *resent_recip; /* recipients from resent headers */ diff -cr ../postfix-1.1.5/src/cleanup/cleanup_message.c ./src/cleanup/cleanup_message.c *** ../postfix-1.1.5/src/cleanup/cleanup_message.c Tue Nov 27 08:25:17 2001 --- ./src/cleanup/cleanup_message.c Mon Mar 25 15:37:17 2002 *************** *** 254,284 **** cleanup_fold_header(state); } ! /* cleanup_check_reject - parse and match header/body REJECT line */ ! static int cleanup_check_reject(CLEANUP_STATE *state, const char *value) { ! const char *reason = value + strcspn(value, " \t"); ! /* ! * See if they spelled REJECT right. ! * ! * XXX The reason should be set only if we have a more severe error than ! * anything that was found before. This calls for a cleanup_set_error() ! * routine that takes an error code and an optional text. ! */ ! if (strncasecmp(value, "REJECT", reason - value) == 0) { ! if (state->reason == 0) { ! while (*reason && ISSPACE(*reason)) ! reason++; ! state->reason = mystrdup(*reason ? reason : cleanup_strerror(CLEANUP_STAT_CONT)); - } state->errs |= CLEANUP_STAT_CONT; ! return (1); ! } else { ! return (0); ! } } /* cleanup_header - process one complete header line */ --- 254,305 ---- cleanup_fold_header(state); } ! /* cleanup_act - act upon a header/body match */ ! static int cleanup_act(CLEANUP_STATE *state, char *context, char *buf, ! const char *value, const char *map_class) { ! const char *optional_text = value + strcspn(value, " \t"); ! int command_len = optional_text - value; ! while (*optional_text && ISSPACE(*optional_text)) ! optional_text++; ! ! #define STREQUAL(x,y,l) (strncasecmp((x), (y), (l)) == 0 && (y)[l] == 0) ! #define CLEANUP_ACT_KEEP 1 ! #define CLEANUP_ACT_DROP 0 ! ! if (STREQUAL(value, "REJECT", command_len)) { ! if (state->reason == 0) ! state->reason = mystrdup(*optional_text ? optional_text : cleanup_strerror(CLEANUP_STAT_CONT)); state->errs |= CLEANUP_STAT_CONT; ! msg_info("%s: reject: %s %.200s; from=<%s> to=<%s>: %s", ! state->queue_id, context, buf, state->sender, ! state->recip ? state->recip : "unknown", ! state->reason); ! return (CLEANUP_ACT_KEEP); ! } ! if (STREQUAL(value, "WARN", command_len)) { ! msg_info("%s: warning: %s %.200s; from=<%s> to=<%s>: %s", ! state->queue_id, context, buf, state->sender, ! state->recip ? state->recip : "unknown", ! *optional_text ? optional_text : ! cleanup_strerror(CLEANUP_STAT_CONT)); ! return (CLEANUP_ACT_KEEP); ! } ! if (*optional_text) ! msg_warn("unexpected text after command in %s map: %s", ! map_class, value); ! ! if (STREQUAL(value, "IGNORE", command_len)) ! return (CLEANUP_ACT_DROP); ! ! if (STREQUAL(value, "OK", command_len)) ! return (CLEANUP_ACT_KEEP); ! ! msg_warn("unknown command in %s map: %s", map_class, value); ! return (CLEANUP_ACT_KEEP); } /* cleanup_header - process one complete header line */ *************** *** 296,313 **** const char *value; if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) { ! if (cleanup_check_reject(state, value) != 0) { ! msg_info("%s: reject: header %.200s; from=<%s> to=<%s>: %s", ! state->queue_id, header, state->sender, ! state->recip ? state->recip : "unknown", ! state->reason); ! } else if (strcasecmp(value, "IGNORE") == 0) { return; - } else if (strcasecmp(value, "WARN") == 0) { - msg_info("%s: warning: header %.200s; from=<%s> to=<%s>", - state->queue_id, header, state->sender, - state->recip ? state->recip : "unknown"); - } } } --- 317,325 ---- const char *value; if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) { ! if (cleanup_act(state, "header", header, value, VAR_HEADER_CHECKS) ! == CLEANUP_ACT_DROP) return; } } *************** *** 506,528 **** /* * First, deal with header information that we have accumulated from ! * previous input records. A whole record that starts with whitespace is ! * a continuation of previous data. * ! * XXX Silently switch to body processing when some message header requires ! * an unreasonable amount of storage, or when a message header record ! * does not fit in a REC_TYPE_NORM type record. */ if (VSTRING_LEN(state->header_buf) > 0) { ! if ((VSTRING_LEN(state->header_buf) >= var_header_limit ! || type == REC_TYPE_CONT)) { ! state->errs |= CLEANUP_STAT_HOVFL; ! } else if (type == REC_TYPE_NORM && ISSPACE(*buf)) { ! VSTRING_ADDCH(state->header_buf, '\n'); ! vstring_strcat(state->header_buf, buf); ! return; ! } else { ! /* Body record or end of message segment. */ ; } /* --- 518,553 ---- /* * First, deal with header information that we have accumulated from ! * previous input records. * ! * If a physical header line exceeds the capacity of a Postfix queue file ! * record, reconstruct the long line from multiple records (up to the ! * header size limit), and break the long line up into multiple Postfix ! * records upon output to the queue file. Discard text that does not fit ! * in a header buffer, so as to avoid breaking MIME formatting. ! * ! * It is left up to delivery agents to glue long lines back together and to ! * enforce an appropriate output line length limit. */ if (VSTRING_LEN(state->header_buf) > 0) { ! if (type != REC_TYPE_XTRA) { ! if (state->long_header) { ! if (VSTRING_LEN(state->header_buf) < var_header_limit) ! vstring_strcat(state->header_buf, buf); ! else ! state->errs |= CLEANUP_STAT_HOVFL; ! state->long_header = (type == REC_TYPE_CONT); ! return; ! } ! if (ISSPACE(*buf)) { ! if (VSTRING_LEN(state->header_buf) < var_header_limit) { ! VSTRING_ADDCH(state->header_buf, '\n'); ! vstring_strcat(state->header_buf, buf); ! } else ! state->errs |= CLEANUP_STAT_HOVFL; ! state->long_header = (type == REC_TYPE_CONT); ! return; ! } } /* *************** *** 535,548 **** } /* ! * Switch to body processing if this is not a header or if the saved ! * header would require an unreasonable amount of storage. Generate ! * missing headers. Add one blank line when the message headers are ! * immediately followed by a non-empty message body. ! */ ! if (((state->errs & CLEANUP_STAT_HOVFL) ! || type != REC_TYPE_NORM ! || !is_header(buf))) { cleanup_missing_headers(state); if (type != REC_TYPE_XTRA && *buf) /* output blank line */ cleanup_out_string(state, REC_TYPE_NORM, ""); --- 560,570 ---- } /* ! * Switch to body processing if this is not a header. Generate missing ! * headers. Add one blank line when the message headers are immediately ! * followed by a non-empty message body. ! */ ! if (type == REC_TYPE_XTRA || !is_header(buf)) { cleanup_missing_headers(state); if (type != REC_TYPE_XTRA && *buf) /* output blank line */ cleanup_out_string(state, REC_TYPE_NORM, ""); *************** *** 555,560 **** --- 577,583 ---- */ else { vstring_strcpy(state->header_buf, buf); + state->long_header = (type == REC_TYPE_CONT); } } *************** *** 580,597 **** const char *value; if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) { ! if (cleanup_check_reject(state, value) != 0) { ! msg_info("%s: reject: body %.200s; from=<%s> to=<%s>: %s", ! state->queue_id, buf, state->sender, ! state->recip ? state->recip : "unknown", ! state->reason); ! } else if (strcasecmp(value, "IGNORE") == 0) { return; - } else if (strcasecmp(value, "WARN") == 0) { - msg_info("%s: warning: body %.200s; from=<%s> to=<%s>", - state->queue_id, buf, state->sender, - state->recip ? state->recip : "unknown"); - } } } cleanup_out(state, type, buf, len); --- 603,611 ---- const char *value; if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) { ! if (cleanup_act(state, "body", buf, value, VAR_BODY_CHECKS) ! == CLEANUP_ACT_DROP) return; } } cleanup_out(state, type, buf, len); diff -cr ../postfix-1.1.5/src/cleanup/cleanup_out.c ./src/cleanup/cleanup_out.c *** ../postfix-1.1.5/src/cleanup/cleanup_out.c Sat Jan 29 19:23:45 2000 --- ./src/cleanup/cleanup_out.c Tue Mar 26 14:40:49 2002 *************** *** 77,82 **** --- 77,83 ---- #include #include #include + #include /* Application-specific. */ *************** *** 86,101 **** void cleanup_out(CLEANUP_STATE *state, int type, char *string, int len) { ! if (CLEANUP_OUT_OK(state)) { ! if (rec_put(state->dst, type, string, len) < 0) { ! if (errno == EFBIG) { ! msg_warn("%s: queue file size limit exceeded", ! state->queue_id); ! state->errs |= CLEANUP_STAT_SIZE; ! } else { ! msg_warn("%s: write queue file: %m", state->queue_id); ! state->errs |= CLEANUP_STAT_WRITE; ! } } } } --- 87,128 ---- void cleanup_out(CLEANUP_STATE *state, int type, char *string, int len) { ! int err = 0; ! ! /* ! * Long message header lines have to be read and written as multiple ! * records. Other header/body content, and envelope data, is copied one ! * record at a time. Be sure to not skip a zero-length request. ! * ! * XXX We don't know if we're writing a message header or not, but that is ! * not a problem. A REC_TYPE_NORM or REC_TYPE_CONT record can always be ! * chopped up into an equivalent set of REC_TYPE_CONT plus REC_TYPE_NORM ! * records. ! */ ! if (CLEANUP_OUT_OK(state) == 0) ! return; ! ! #define TEXT_RECORD(t) ((t) == REC_TYPE_NORM || (t) == REC_TYPE_CONT) ! ! do { ! if (len > var_line_limit && TEXT_RECORD(type)) { ! err = rec_put(state->dst, REC_TYPE_CONT, string, var_line_limit); ! string += var_line_limit; ! len -= var_line_limit; ! } else { ! err = rec_put(state->dst, type, string, len); ! break; ! } ! } while (len > 0 && err >= 0); ! ! if (err < 0) { ! if (errno == EFBIG) { ! msg_warn("%s: queue file size limit exceeded", ! state->queue_id); ! state->errs |= CLEANUP_STAT_SIZE; ! } else { ! msg_warn("%s: write queue file: %m", state->queue_id); ! state->errs |= CLEANUP_STAT_WRITE; } } } diff -cr ../postfix-1.1.5/src/cleanup/cleanup_state.c ./src/cleanup/cleanup_state.c *** ../postfix-1.1.5/src/cleanup/cleanup_state.c Thu Oct 18 18:23:19 2001 --- ./src/cleanup/cleanup_state.c Sun Mar 24 14:49:15 2002 *************** *** 72,77 **** --- 72,78 ---- state->err_mask = 0; state->header_buf = vstring_alloc(100); state->headers_seen = 0; + state->long_header = 0; state->hop_count = 0; state->recipients = argv_alloc(2); state->resent_recip = argv_alloc(2); diff -cr ../postfix-1.1.5/src/global/bounce.c ./src/global/bounce.c *** ../postfix-1.1.5/src/global/bounce.c Mon Oct 15 09:46:58 2001 --- ./src/global/bounce.c Tue Mar 26 15:48:52 2002 *************** *** 150,158 **** ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why), ATTR_TYPE_END) == 0) { ! msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s)", id, recipient, relay, delay, var_soft_bounce ? "deferred" : ! "bounced", vstring_str(why)); status = (var_soft_bounce ? -1 : 0); } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { status = defer_append(flags, id, recipient, "bounce", delay, --- 150,159 ---- ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why), ATTR_TYPE_END) == 0) { ! msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s%s)", id, recipient, relay, delay, var_soft_bounce ? "deferred" : ! "bounced", var_soft_bounce ? "SOFT BOUNCE - " : "", ! vstring_str(why)); status = (var_soft_bounce ? -1 : 0); } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { status = defer_append(flags, id, recipient, "bounce", delay, diff -cr ../postfix-1.1.5/src/global/mail_params.h ./src/global/mail_params.h *** ../postfix-1.1.5/src/global/mail_params.h Fri Feb 1 08:59:51 2002 --- ./src/global/mail_params.h Mon Mar 25 08:22:11 2002 *************** *** 738,746 **** #define DEF_SMTP_RAND_ADDR 1 extern bool var_smtp_rand_addr; ! #define VAR_SMTP_BREAK_LINES "smtp_break_lines" ! #define DEF_SMTP_BREAK_LINES 1 ! extern bool var_smtp_break_lines; #define VAR_SMTP_PIX_THRESH "smtp_pix_workaround_threshold_time" #define DEF_SMTP_PIX_THRESH "500s" --- 738,746 ---- #define DEF_SMTP_RAND_ADDR 1 extern bool var_smtp_rand_addr; ! #define VAR_SMTP_LINE_LIMIT "smtp_line_length_limit" ! #define DEF_SMTP_LINE_LIMIT 990 ! extern int var_smtp_line_limit; #define VAR_SMTP_PIX_THRESH "smtp_pix_workaround_threshold_time" #define DEF_SMTP_PIX_THRESH "500s" diff -cr ../postfix-1.1.5/src/global/pipe_command.c ./src/global/pipe_command.c *** ../postfix-1.1.5/src/global/pipe_command.c Mon Nov 26 20:02:17 2001 --- ./src/global/pipe_command.c Tue Mar 19 12:51:08 2002 *************** *** 368,373 **** --- 368,374 ---- * system a chance to recover, and try again later. */ case -1: + msg_warn("fork: %m"); vstring_sprintf(why, "Delivery failed: %m"); return (PIPE_STAT_DEFER); diff -cr ../postfix-1.1.5/src/global/record.c ./src/global/record.c *** ../postfix-1.1.5/src/global/record.c Wed Mar 28 16:28:20 2001 --- ./src/global/record.c Sun Mar 24 16:49:23 2002 *************** *** 113,118 **** --- 113,121 ---- int rec_put_type(VSTREAM *stream, int type, long offset) { + if (type < 0 || type > 255) + msg_panic("rec_put_type: bad record type %d", type); + if (msg_verbose > 2) msg_info("rec_put_type: %d at %ld", type, offset); *************** *** 130,135 **** --- 133,141 ---- { int len_rest; int len_byte; + + if (type < 0 || type > 255) + msg_panic("rec_put: bad record type %d", type); if (msg_verbose > 2) msg_info("rec_put: type %c len %d data %.10s", type, len, data); diff -cr ../postfix-1.1.5/src/nqmgr/qmgr.c ./src/nqmgr/qmgr.c *** ../postfix-1.1.5/src/nqmgr/qmgr.c Wed Aug 1 17:00:53 2001 --- ./src/nqmgr/qmgr.c Tue Mar 26 16:49:07 2002 *************** *** 184,196 **** /* .SH "Timing controls" /* .ad /* .fi ! /* .IP \fBmin_backoff\fR /* Minimal time in seconds between delivery attempts /* of a deferred message. /* .sp /* This parameter also limits the time an unreachable destination /* is kept in the short-term, in-memory destination status cache. ! /* .IP \fBmax_backoff\fR /* Maximal time in seconds between delivery attempts /* of a deferred message. /* .IP \fBmaximal_queue_lifetime\fR --- 184,196 ---- /* .SH "Timing controls" /* .ad /* .fi ! /* .IP \fBminimal_backoff_time\fR /* Minimal time in seconds between delivery attempts /* of a deferred message. /* .sp /* This parameter also limits the time an unreachable destination /* is kept in the short-term, in-memory destination status cache. ! /* .IP \fBmaximal_backoff_time\fR /* Maximal time in seconds between delivery attempts /* of a deferred message. /* .IP \fBmaximal_queue_lifetime\fR diff -cr ../postfix-1.1.5/src/qmgr/qmgr.c ./src/qmgr/qmgr.c *** ../postfix-1.1.5/src/qmgr/qmgr.c Wed Aug 1 16:44:42 2001 --- ./src/qmgr/qmgr.c Tue Mar 26 16:49:13 2002 *************** *** 165,177 **** /* .SH "Timing controls" /* .ad /* .fi ! /* .IP \fBmin_backoff\fR /* Minimal time in seconds between delivery attempts /* of a deferred message. /* .sp /* This parameter also limits the time an unreachable destination /* is kept in the short-term, in-memory destination status cache. ! /* .IP \fBmax_backoff\fR /* Maximal time in seconds between delivery attempts /* of a deferred message. /* .IP \fBmaximal_queue_lifetime\fR --- 165,177 ---- /* .SH "Timing controls" /* .ad /* .fi ! /* .IP \fBminimal_backoff_time\fR /* Minimal time in seconds between delivery attempts /* of a deferred message. /* .sp /* This parameter also limits the time an unreachable destination /* is kept in the short-term, in-memory destination status cache. ! /* .IP \fBmaximal_backoff_time\fR /* Maximal time in seconds between delivery attempts /* of a deferred message. /* .IP \fBmaximal_queue_lifetime\fR diff -cr ../postfix-1.1.5/src/sendmail/sendmail.c ./src/sendmail/sendmail.c *** ../postfix-1.1.5/src/sendmail/sendmail.c Fri Mar 8 14:12:33 2002 --- ./src/sendmail/sendmail.c Mon Mar 25 14:51:40 2002 *************** *** 367,372 **** --- 367,373 ---- uid_t uid = getuid(); int status; int naddr; + int prev_type; /* * Initialize. *************** *** 457,464 **** rec_fprintf(dst, REC_TYPE_MESG, REC_TYPE_MESG_FORMAT, 0L); skip_from_ = 1; strip_cr = STRIP_CR_DUNNO; ! while ((type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit)) ! != REC_TYPE_EOF) { if (strip_cr == STRIP_CR_DUNNO && type == REC_TYPE_NORM) { if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r') strip_cr = STRIP_CR_DO; --- 458,465 ---- rec_fprintf(dst, REC_TYPE_MESG, REC_TYPE_MESG_FORMAT, 0L); skip_from_ = 1; strip_cr = STRIP_CR_DUNNO; ! for (prev_type = 0; (type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit)) ! != REC_TYPE_EOF; prev_type = type) { if (strip_cr == STRIP_CR_DUNNO && type == REC_TYPE_NORM) { if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r') strip_cr = STRIP_CR_DO; *************** *** 476,482 **** if (strip_cr == STRIP_CR_DO && type == REC_TYPE_NORM) if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r') vstring_truncate(buf, VSTRING_LEN(buf) - 1); ! if ((flags & SM_FLAG_AEOF) && VSTRING_LEN(buf) == 1 && *STR(buf) == '.') break; if (REC_PUT_BUF(dst, type, buf) < 0) msg_fatal_status(EX_TEMPFAIL, --- 477,484 ---- if (strip_cr == STRIP_CR_DO && type == REC_TYPE_NORM) if (VSTRING_LEN(buf) > 0 && vstring_end(buf)[-1] == '\r') vstring_truncate(buf, VSTRING_LEN(buf) - 1); ! if ((flags & SM_FLAG_AEOF) && prev_type != REC_TYPE_CONT ! && VSTRING_LEN(buf) == 1 && *STR(buf) == '.') break; if (REC_PUT_BUF(dst, type, buf) < 0) msg_fatal_status(EX_TEMPFAIL, diff -cr ../postfix-1.1.5/src/showq/showq.c ./src/showq/showq.c *** ../postfix-1.1.5/src/showq/showq.c Sat Jan 12 18:42:12 2002 --- ./src/showq/showq.c Tue Mar 26 15:52:55 2002 *************** *** 80,85 **** --- 80,87 ---- #include #include #include + #include + #include #include /* Single-threaded server skeleton. */ *************** *** 89,94 **** --- 91,97 ---- /* Application-specific. */ int var_dup_filter_limit; + char *var_empty_addr; #define STRING_FORMAT "%-10s %8s %-20s %s\n" #define DATA_FORMAT "%-10s%c%8ld %20.20s %s\n" *************** *** 96,105 **** --- 99,113 ---- static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *); + #define STR(x) vstring_str(x) + + /* showq_report - report status of sender and recipients */ + static void showq_report(VSTREAM *client, char *queue, char *id, VSTREAM *qfile, long size) { VSTRING *buf = vstring_alloc(100); + VSTRING *printable_quoted_addr = vstring_alloc(100); int rec_type; time_t arrival_time = 0; char *start; *************** *** 109,114 **** --- 117,129 ---- char status = (strcmp(queue, MAIL_QUEUE_ACTIVE) == 0 ? '*' : ' '); long offset; + /* + * XXX addresses in defer logfiles are in printable quoted form, while + * addresses in message envelope records are in raw unquoted form. This + * may change once we replace the present ad-hoc bounce/defer logfile + * format by one that is transparent for control etc. characters. See + * also: bounce/bounce_append_service.c. + */ while (!vstream_ferror(client) && (rec_type = rec_get(qfile, buf, 0)) > 0) { start = vstring_str(buf); switch (rec_type) { *************** *** 121,138 **** break; case REC_TYPE_FROM: if (*start == 0) ! start = "(MAILER-DAEMON)"; vstream_fprintf(client, DATA_FORMAT, id, status, msg_size > 0 ? msg_size : size, arrival_time > 0 ? asctime(localtime(&arrival_time)) : "??", ! printable(start, '?')); break; case REC_TYPE_RCPT: if (*start == 0) /* can't happen? */ ! start = "(MAILER-DAEMON)"; ! if (dup_filter == 0 || htable_locate(dup_filter, start) == 0) vstream_fprintf(client, STRING_FORMAT, ! "", "", "", printable(start, '?')); break; case REC_TYPE_MESG: if ((offset = atol(start)) > 0 --- 136,158 ---- break; case REC_TYPE_FROM: if (*start == 0) ! start = var_empty_addr; ! quote_822_local(printable_quoted_addr, start); ! printable(STR(printable_quoted_addr), '?'); vstream_fprintf(client, DATA_FORMAT, id, status, msg_size > 0 ? msg_size : size, arrival_time > 0 ? asctime(localtime(&arrival_time)) : "??", ! STR(printable_quoted_addr)); break; case REC_TYPE_RCPT: if (*start == 0) /* can't happen? */ ! start = var_empty_addr; ! quote_822_local(printable_quoted_addr, start); ! printable(STR(printable_quoted_addr), '?'); ! if (dup_filter == 0 ! || htable_locate(dup_filter, STR(printable_quoted_addr)) == 0) vstream_fprintf(client, STRING_FORMAT, ! "", "", "", STR(printable_quoted_addr)); break; case REC_TYPE_MESG: if ((offset = atol(start)) > 0 *************** *** 163,168 **** --- 183,189 ---- } } vstring_free(buf); + vstring_free(printable_quoted_addr); if (dup_filter) htable_free(dup_filter, (void (*) (char *)) 0); } *************** *** 307,314 **** --- 328,340 ---- VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0, 0, }; + CONFIG_STR_TABLE str_table[] = { + VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0, + 0, + }; single_server_main(argc, argv, showq_service, MAIL_SERVER_INT_TABLE, int_table, + MAIL_SERVER_STR_TABLE, str_table, 0); } diff -cr ../postfix-1.1.5/src/smtp/smtp.c ./src/smtp/smtp.c *** ../postfix-1.1.5/src/smtp/smtp.c Tue Mar 5 20:04:30 2002 --- ./src/smtp/smtp.c Mon Mar 25 08:22:29 2002 *************** *** 97,104 **** /* Never send EHLO at the start of a connection. /* .IP \fBsmtp_bind_address\fR /* Numerical source network address to bind to when making a connection. ! /* .IP \fBsmtp_break_lines\fR ! /* Break lines > \fB$line_length_limit\fR into multiple shorter lines. /* Some SMTP servers misbehave on long lines. /* .IP \fBsmtp_skip_4xx_greeting\fR /* Skip servers that greet us with a 4xx status code. --- 97,104 ---- /* Never send EHLO at the start of a connection. /* .IP \fBsmtp_bind_address\fR /* Numerical source network address to bind to when making a connection. ! /* .IP \fBsmtp_line_length_limit\fR ! /* Length limit for SMTP message content lines. Zero means no limit. /* Some SMTP servers misbehave on long lines. /* .IP \fBsmtp_skip_4xx_greeting\fR /* Skip servers that greet us with a 4xx status code. *************** *** 259,267 **** bool var_smtp_sasl_enable; char *var_smtp_bind_addr; bool var_smtp_rand_addr; - bool var_smtp_break_lines; int var_smtp_pix_thresh; int var_smtp_pix_delay; /* * Global variables. smtp_errno is set by the address lookup routines and by --- 259,267 ---- bool var_smtp_sasl_enable; char *var_smtp_bind_addr; bool var_smtp_rand_addr; int var_smtp_pix_thresh; int var_smtp_pix_delay; + int var_smtp_line_limit; /* * Global variables. smtp_errno is set by the address lookup routines and by *************** *** 429,434 **** --- 429,435 ---- 0, }; static CONFIG_INT_TABLE int_table[] = { + VAR_SMTP_LINE_LIMIT, DEF_SMTP_LINE_LIMIT, &var_smtp_line_limit, 0, 0, 0, }; static CONFIG_BOOL_TABLE bool_table[] = { *************** *** 440,446 **** VAR_SMTP_NEVER_EHLO, DEF_SMTP_NEVER_EHLO, &var_smtp_never_ehlo, VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable, VAR_SMTP_RAND_ADDR, DEF_SMTP_RAND_ADDR, &var_smtp_rand_addr, - VAR_SMTP_BREAK_LINES, DEF_SMTP_BREAK_LINES, &var_smtp_break_lines, 0, }; --- 441,446 ---- diff -cr ../postfix-1.1.5/src/smtp/smtp_proto.c ./src/smtp/smtp_proto.c *** ../postfix-1.1.5/src/smtp/smtp_proto.c Wed Dec 26 16:21:04 2001 --- ./src/smtp/smtp_proto.c Tue Mar 26 15:55:59 2002 *************** *** 296,301 **** --- 296,304 ---- int sndbuffree; SOCKOPT_SIZE optlen = sizeof(sndbufsize); int mail_from_rejected; + int space_left = var_smtp_line_limit; + int data_left; + char *data_start; /* * Macros for readability. *************** *** 665,680 **** if (prev_type != REC_TYPE_CONT) if (vstring_str(state->scratch)[0] == '.') smtp_fputc('.', session->stream); ! if (var_smtp_break_lines) ! rec_type = REC_TYPE_NORM; ! if (rec_type == REC_TYPE_CONT) ! smtp_fwrite(vstring_str(state->scratch), ! VSTRING_LEN(state->scratch), ! session->stream); ! else ! smtp_fputs(vstring_str(state->scratch), ! VSTRING_LEN(state->scratch), ! session->stream); prev_type = rec_type; } --- 668,705 ---- if (prev_type != REC_TYPE_CONT) if (vstring_str(state->scratch)[0] == '.') smtp_fputc('.', session->stream); ! ! /* ! * Deal with an impedance mismatch between Postfix queue ! * files (record length <= $message_line_length_limit) and ! * SMTP (DATA record length <= $smtp_line_length_limit). The ! * code below does a little too much work when the SMTP line ! * length limit is disabled, but it avoids code duplication, ! * and thus, it avoids testing and maintenance problems. ! */ ! data_left = VSTRING_LEN(state->scratch); ! data_start = vstring_str(state->scratch); ! do { ! if (var_smtp_line_limit > 0 && data_left >= space_left) { ! smtp_fputs(data_start, space_left, session->stream); ! data_start += space_left; ! data_left -= space_left; ! space_left = var_smtp_line_limit; ! if (data_left > 0 || rec_type == REC_TYPE_CONT) { ! smtp_fputc(' ', session->stream); ! space_left -= 1; ! } ! } else { ! if (rec_type == REC_TYPE_CONT) { ! smtp_fwrite(data_start, data_left, session->stream); ! space_left -= data_left; ! } else { ! smtp_fputs(data_start, data_left, session->stream); ! space_left = var_smtp_line_limit; ! } ! break; ! } ! } while (data_left > 0); prev_type = rec_type; } diff -cr ../postfix-1.1.5/src/smtpd/smtpd.c ./src/smtpd/smtpd.c *** ../postfix-1.1.5/src/smtpd/smtpd.c Fri Mar 8 09:41:09 2002 --- ./src/smtpd/smtpd.c Tue Mar 26 16:14:41 2002 *************** *** 1398,1404 **** continue; } if (cmdp->flags & SMTPD_CMD_FLAG_HEADER) { ! msg_warn("%s sent mail content instead of SMTP command: %.100s", state->namaddr, vstring_str(state->buffer)); smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye."); break; --- 1398,1404 ---- continue; } if (cmdp->flags & SMTPD_CMD_FLAG_HEADER) { ! msg_warn("%s sent message header instead of SMTP command: %.100s", state->namaddr, vstring_str(state->buffer)); smtpd_chat_reply(state, "221 Error: I can break rules, too. Goodbye."); break; diff -cr ../postfix-1.1.5/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c *** ../postfix-1.1.5/src/smtpd/smtpd_check.c Tue Jan 22 09:52:15 2002 --- ./src/smtpd/smtpd_check.c Mon Mar 18 15:10:27 2002 *************** *** 1594,1605 **** /* * Try the name and its parent domains. Including top-level domains. */ #define CHK_DOMAIN_RETURN(x,y) { *found = y; myfree(low_domain); return(x); } if ((dict = dict_handle(table)) == 0) msg_panic("%s: dictionary not found: %s", myname, table); ! for (name = low_domain; /* void */ ; name = next) { if (flags == 0 || (flags & dict->flags) != 0) { if ((value = dict_get(dict, name)) != 0) CHK_DOMAIN_RETURN(check_table_result(state, table, value, --- 1594,1609 ---- /* * Try the name and its parent domains. Including top-level domains. + * + * Helo names can end in ".". The test below avoids lookups of the empty + * key, because Berkeley DB cannot deal with it. [Victor Duchovni, Morgan + * Stanley]. */ #define CHK_DOMAIN_RETURN(x,y) { *found = y; myfree(low_domain); return(x); } if ((dict = dict_handle(table)) == 0) msg_panic("%s: dictionary not found: %s", myname, table); ! for (name = low_domain; *name != 0; name = next) { if (flags == 0 || (flags & dict->flags) != 0) { if ((value = dict_get(dict, name)) != 0) CHK_DOMAIN_RETURN(check_table_result(state, table, value,