diff --git a/postfix/HISTORY b/postfix/HISTORY index 82c867d87..1ec7f261d 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -6829,10 +6829,36 @@ Apologies for any names omitted. mail to be placed on the "hold" queue for manual inspection. Files: global/hold_message.[hc], cleanup/cleanup_message.c. +20020820 + + Bugfix: yesterday's HOLD pattern code did not update the + cleanup server's idea of the queue file name for error + recovery and for error reporting purposes, so that incomplete + or content rejected mail would not be deleted from the + queue, and so that the bouncer would not find the queue + file. + + Feature: new header/body_checks DISCARD pattern that causes + mail to be silently discarded. Files: global/cleanup_user.h, + cleanup/cleanup_message.c. + + Bugfix: the local delivery agent's mailbox duplicate delivery + eliminator was not updated when address extensions were + added to Postfix. The other local duplicate eliminators + may need revision as well. File: local/mailbox.c. + +20020821 + + Feature: HOLD and DISCARD actions in SMTPD access tables. + These requests are propagated to the cleanup daemon, + which required a bit of redesign of internal protocols. + Files: cleanup/cleanup.c pickup/pickup.c smtpd/smtpd.c + global/post_mail.c qmqpd/qmqpd.c local/forward.c. + Open problems: - Medium: should permit_mx_backup defer delivery if DNS - has some error of some kind? + Medium: should permit_mx_backup defer delivery if DNS has + some error of some kind? Low: all table lookups should consistently use internalized (unquoted) or externalized (quoted) forms as lookup keys. diff --git a/postfix/README_FILES/LDAP_README b/postfix/README_FILES/LDAP_README index 6f158d7b0..02c152b3c 100644 --- a/postfix/README_FILES/LDAP_README +++ b/postfix/README_FILES/LDAP_README @@ -15,9 +15,16 @@ BUILDING WITH LDAP SUPPORT Note: Postfix no longer supports the LDAP version 1 interface. -You need to have LDAP libraries and include files installed somewhere on -your system, and you need to configure the Postfix Makefiles -accordingly. +You need to have LDAP libraries and include files installed somewhere +on your system, and you need to configure the Postfix Makefiles +accordingly. + +For example, to build the OpenLDAP libraries for use with Postfix +(i.e. LDAP client code only), you could use the following command: + + % ./configure --without-kerberos --without-cyrus-sasl --without-tls \ + --without-threads --disable-slapd --disable-slurpd \ + --disable-debug --disable-shared If you're using the libraries from the UM distribution (http://www.umich.edu/~dirsvcs/ldap/ldap.html) or OpenLDAP diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 58ec18c3a..e8339cf50 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -12,8 +12,14 @@ snapshot release). Patches change the patchlevel and the release date. Snapshots change only the release date, unless they include the same bugfixes as a patch release. -Incompatible changes with Postfix snapshot 1.1.11-2002018 -========================================================= +Incompatible changes with Postfix snapshot 1.1.11-20020821 +========================================================== + +After switching Postfix versions you need to "postfix reload" +because internal protocols have changed. + +Incompatible changes with Postfix snapshot 1.1.11-20020818 +========================================================== The qmgr_site_hog_factor feature is gone (this would defer mail delivery for sites that occupy too much space in the active queue, diff --git a/postfix/conf/access b/postfix/conf/access index 0b1148ed0..20a13c44b 100644 --- a/postfix/conf/access +++ b/postfix/conf/access @@ -115,6 +115,17 @@ # # OK Accept the address etc. that matches the pattern. # +# HOLD Place the message on the hold queue, where it will +# sit until someone either deletes it or releases it +# for delivery. Mail that is placed on hold can be +# examined with the postcat(1) command, and can be +# destroyed or released with the postsuper(1) com- +# mand. +# +# DISCARD +# Claim successful delivery and silently discard the +# message. +# # all-numerical # An all-numerical result is treated as OK. This for- # mat is generated by address-based relay authoriza- diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf index 579916cfa..1aee92cc6 100644 --- a/postfix/conf/main.cf +++ b/postfix/conf/main.cf @@ -29,14 +29,13 @@ queue_directory = /var/spool/postfix # The command_directory parameter specifies the location of all -# postXXX commands. The default value is $program_directory. +# postXXX commands. # command_directory = /usr/sbin # The daemon_directory parameter specifies the location of all Postfix -# daemon programs (i.e. programs listed in the master.cf file). The -# default value is $program_directory. This directory must be owned -# by root. +# daemon programs (i.e. programs listed in the master.cf file). This +# directory must be owned by root. # daemon_directory = /usr/libexec/postfix @@ -417,11 +416,22 @@ mail_owner = postfix # When a pattern matches, what happens next depends on the associated # action that is specified in the right-hand side of the table: # -# REJECT the entire message is rejected. -# 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. +# REJECT [optional text...] +# Reject the entire message. The optional text is sent to the +# originator and is logged to the maillog file. +# IGNORE Silently discard the header line. +# WARN [optional text...] +# Log the message header and the optional text. This is useful +# for testing. When the pattern is OK, change the WARN into a +# REJECT or into a DISCARD. +# HOLD [optional text...] +# Place the message on the hold queue. Mail on hold can be +# inspected with the postcat command, and can be destroyed or +# taken off hold (i.e. delivered) with the postsuper command. +# The matched header is logged with the optional text. +# DISCARD [optional text...] +# Claim successful delivery and silently discard the message. +# The matched header is logged with the optional text. # FILTER transport:nexthop # after the message is queued, send the entire message through # a content filter. This requires different cleanup servers diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf index 936c60801..2bcdadb28 100644 --- a/postfix/conf/master.cf +++ b/postfix/conf/master.cf @@ -42,7 +42,7 @@ # # Command + args: the command to be executed. The command name is # relative to the Postfix program directory (pathname is controlled by -# the program_directory configuration variable). Adding one or more +# the daemon_directory configuration variable). Adding one or more # -v options turns on verbose logging for that service; adding a -D # option enables symbolic debugging (see the debugger_command variable # in the main.cf configuration file). See individual command man pages diff --git a/postfix/conf/sample-debug.cf b/postfix/conf/sample-debug.cf index 5f850ddc7..6ac659e46 100644 --- a/postfix/conf/sample-debug.cf +++ b/postfix/conf/sample-debug.cf @@ -29,4 +29,4 @@ debug_peer_list = # debugger_command = PATH=/usr/bin:/usr/X11R6/bin - xxgdb $program_directory/$process_name $process_id & sleep 5 + xxgdb $daemon_directory/$process_name $process_id & sleep 5 diff --git a/postfix/conf/sample-filter.cf b/postfix/conf/sample-filter.cf index 7ddfc3c27..f6e7388a3 100644 --- a/postfix/conf/sample-filter.cf +++ b/postfix/conf/sample-filter.cf @@ -11,11 +11,22 @@ # When a pattern matches, what happens next depends on the associated # action that is specified in the right-hand side of the table: # -# REJECT the entire message is rejected. -# 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. +# REJECT [optional text...] +# Reject the entire message. The optional text is sent to the +# originator and is logged to the maillog file. +# IGNORE Silently discard the header line. +# WARN [optional text...] +# Log the message header and the optional text. This is useful +# for testing. When the pattern is OK, change the WARN into a +# REJECT or into a DISCARD. +# HOLD [optional text...] +# Place the message on the hold queue. Mail on hold can be +# inspected with the postcat command, and can be destroyed or +# taken off hold (i.e. delivered) with the postsuper command. +# The matched header is logged with the optional text. +# DISCARD [optional text...] +# Claim successful delivery and silently discard the message. +# The matched header is logged with the optional text. # FILTER transport:nexthop # after the message is queued, the message is sent through # a content filter. This requires different cleanup servers @@ -40,11 +51,22 @@ header_checks = regexp:/etc/postfix/header_checks # depends on the associated action that is specified in the right-hand # side of the table: # -# REJECT the entire message is rejected. -# 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. +# REJECT [optional text...] +# Reject the entire message. The optional text is sent to the +# originator and is logged to the maillog file. +# IGNORE Silently discard the body line +# WARN [optional text...] +# Log the body line and the optional text. This is useful +# for testing. When the pattern is OK, change the WARN into a +# REJECT or into a DISCARD. +# HOLD [optional text...] +# Place the message on the hold queue. Mail on hold can be +# inspected with the postcat command, and can be destroyed or +# taken off hold (i.e. delivered) with the postsuper command. +# The matched body line is logged with the optional text. +# DISCARD [optional text...] +# Claim successful delivery and silently discard the message. +# The matched body line is logged with the optional text. # FILTER transport:nexthop # after the message is queued, the message is sent through # a content filter. This requires different cleanup servers diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf index 8f7e2ed45..420600211 100644 --- a/postfix/conf/sample-misc.cf +++ b/postfix/conf/sample-misc.cf @@ -317,10 +317,10 @@ parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains, # process_id_directory = pid -# The program_directory parameter specifies the location of Postfix +# The daemon_directory parameter specifies the location of Postfix # support programs and daemons. This directory must be owned by root. # -program_directory = /usr/libexec/postfix +daemon_directory = /usr/libexec/postfix # The queue_directory specifies the location of the Postfix queue. # This is also the root directory of Postfix daemons that run chrooted. diff --git a/postfix/conf/sample-pcre-body.cf b/postfix/conf/sample-pcre-body.cf index 6b23c9434..1d314a3be 100644 --- a/postfix/conf/sample-pcre-body.cf +++ b/postfix/conf/sample-pcre-body.cf @@ -1,4 +1,4 @@ -# +# # Sample pcre (PERL-compatible regular expression) map file for # mail body filtering. See pcre_table(5) for syntax description. # @@ -19,13 +19,26 @@ # info). # # The second field is the "replacement" string - the text -# returned by the match. +# returned by the match. # -# REJECT The entire message is rejected. -# 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. +# REJECT [optional text...] +# Reject the entire message. The optional text is sent to +# the originator and is logged to the maillog file. +# IGNORE Silently discard the body line. +# WARN [optional text...] +# Log the body line and the optional text. This is +# useful for testing. When the pattern is OK, change the +# WARN into a REJECT or into a DISCARD. +# HOLD [optional text...] +# Place the message on the hold queue. Mail on hold can +# be inspected with the postcat command, and can be +# destroyed or taken off hold (i.e. delivered) with the +# postsuper command. The matched body line is logged +# together with the optional text. +# DISCARD [optional text...] +# Claim successful delivery and silently discard the +# message. The matched body line is logged together +# with the optional text. # FILTER transport:nexthop # After the message is queued, send the entire # message through a content filter. This diff --git a/postfix/conf/sample-pcre-header.cf b/postfix/conf/sample-pcre-header.cf index 44bd75997..e69dda783 100644 --- a/postfix/conf/sample-pcre-header.cf +++ b/postfix/conf/sample-pcre-header.cf @@ -21,19 +21,32 @@ # The second field is the "replacement" string - the text # returned by the match. # -# REJECT The entire message is rejected. -# 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. -# FILTER transport:nexthop -# After the message is queued, send the entire -# message through a content filter. This -# requires different cleanup servers before -# and after the filter, with header/body -# checks turned off in the second cleanup -# server. More information about content filters -# is in the Postfix FILTER_README file. +# REJECT [optional text...] +# Reject the entire message. The optional text is sent to +# the originator and is logged to the maillog file. +# IGNORE Silently ignore the message header. +# WARN [optional text...] +# Log the message header and the optional text. This is +# useful for testing. When the pattern is OK, change the +# WARN into a REJECT or into a DISCARD. +# HOLD [optional text...] +# Place the message on the hold queue. Mail on hold can +# be inspected with the postcat command, and can be +# destroyed or taken off hold (i.e. delivered) with the +# postsuper command. The matched header is logged +# together with the optional text. +# DISCARD [optional text...] +# Claim successful delivery and silently discard the +# message. The matched header is logged together with +# the optional text. +# FILTER transport:nexthop +# After the message is queued, send the entire +# message through a content filter. This +# requires different cleanup servers before +# and after the filter, with header/body +# checks turned off in the second cleanup +# server. More information about content filters +# is in the Postfix FILTER_README file. # # Substitution of sub-strings from the matched expression is # possible using the conventional perl syntax. The macros in the diff --git a/postfix/conf/sample-regexp-body.cf b/postfix/conf/sample-regexp-body.cf index 577428e43..69f78d38a 100644 --- a/postfix/conf/sample-regexp-body.cf +++ b/postfix/conf/sample-regexp-body.cf @@ -17,18 +17,27 @@ # terminating processing of the ruleset. # # The result is one of the following: -# REJECT The entire message is rejected. -# 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. -# FILTER transport:nexthop -# After the message is queued, send the entire -# message through a content filter. This requires -# different cleanup servers before and after the -# filter, with header/body checks turned off in -# the second cleanup server. More information about -# content filters is in the Postfix FILTER_README file. +# REJECT [optional text...] +# Reject the entire message. The optional text is sent to the +# originator and is logged to the maillog file. +# IGNORE Silently ignore the body line. +# WARN [optional text...] +# Log the body line and the optional text. This is useful +# for testing. When the pattern is OK, change the WARN into a +# REJECT or into a DISCARD. +# HOLD [optional text...] +# Place the message on the hold queue. Mail on hold can be +# inspected with the postcat command, and can be destroyed or +# taken off hold (i.e. delivered) with the postsuper command. +# The matched body line is logged together with the optional text. +# DISCARD [optional text...] +# Claim successful delivery and silently discard the message. +# The matched body line is logged together with the optional text. +# FILTER transport:nexthop +# After the message is queued, send the entire message through +# a content filter. This requires different cleanup servers +# before and after the filter, with header/body checks turned +# off in the second cleanup server. # Skip over base 64 encoded blocks. This saves lots of CPU cycles. # Expressions by Liviu Daia. Amended by Victor Duchovni. diff --git a/postfix/conf/sample-regexp-header.cf b/postfix/conf/sample-regexp-header.cf index 23be2c363..9684f682b 100644 --- a/postfix/conf/sample-regexp-header.cf +++ b/postfix/conf/sample-regexp-header.cf @@ -18,18 +18,27 @@ # terminating processing of the ruleset. # # The result is one of the following: -# REJECT the entire message is rejected. -# 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. -# FILTER transport:nexthop -# After the message is queued, send the entire -# message through a content filter. This requires -# different cleanup servers before and after the -# filter, with header/body checks turned off in -# the second cleanup server. More information about -# content filters is in the Postfix FILTER_README file. +# REJECT [optional text...] +# Reject the entire message. The optional text is sent to the +# originator and is logged to the maillog file. +# IGNORE Silently discard the message header. +# WARN [optional text...] +# Log the message header and the optional text. This is useful +# for testing. When the pattern is OK, change the WARN into a +# REJECT or into a DISCARD. +# HOLD [optional text...] +# Place the message on the hold queue. Mail on hold can be +# inspected with the postcat command, and can be destroyed or +# taken off hold (i.e. delivered) with the postsuper command. +# The matched header is logged together with the optional text. +# DISCARD [optional text...] +# Claim successful delivery and silently discard the message. +# The matched header is logged together with the optional text. +# FILTER transport:nexthop +# After the message is queued, send the entire message through +# a content filter. This requires different cleanup servers +# before and after the filter, with header/body checks turned +# off in the second cleanup server. /^Subject: Make Money Fast/ REJECT /^To: friend@public.com/ REJECT diff --git a/postfix/html/access.5.html b/postfix/html/access.5.html index 2e1400596..487913402 100644 --- a/postfix/html/access.5.html +++ b/postfix/html/access.5.html @@ -116,6 +116,17 @@ ACCESS(5) ACCESS(5) OK Accept the address etc. that matches the pattern. + HOLD Place the message on the hold queue, where it will + sit until someone either deletes it or releases it + for delivery. Mail that is placed on hold can be + examined with the postcat(1) command, and can be + destroyed or released with the postsuper(1) com- + mand. + + DISCARD + Claim successful delivery and silently discard the + message. + all-numerical An all-numerical result is treated as OK. This for- mat is generated by address-based relay authoriza- diff --git a/postfix/html/uce.html b/postfix/html/uce.html index 5532378ec..1dd3b0025 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -127,21 +127,38 @@ matches a table, the action depends on the lookup result:
-
REJECT
Reject the message, and log the header. +
REJECT
-
REJECT text...
As above, and also send the text to -the originator. +
REJECT text...
+ +Reject the message, log the header and the optional text, +and send the optional text to the originator.
IGNORE
Delete the header from the message. -
HOLD
Place the message on the hold queue. Mail on -hold can be inspected with the postcat -command, and can be destroyed or taken off hold with the postsuper command. +
WARN
-
WARN
Log (but do not reject) the header with a warning. +
WARN text...
-
WARN text...
As above, and also log the text. +Log (but do not reject) the header with a warning, and log the +optional text. + +
HOLD
+ +
HOLD text...
+ +Place the message on the hold queue. Mail on hold can be +inspected with the postcat command, +and can be destroyed or taken off hold with the postsuper command. +The optional text is logged together with the matched text. + +
DISCARD
+ +
DISCARD text...
+ +Claim successful delivery and silently discard the message. +The optional text is logged together with the matched text.
FILTER transport:nexthop
After the message is queued, send the entire message through @@ -209,21 +226,38 @@ line matches a table, the action depends on the lookup result:
-
REJECT
Reject the message, and log the matched line. +
REJECT
-
REJECT text...
As above, and also send the text to -the originator. +
REJECT text...
+ +Reject the message, log the body line and the optional text, +and send the optional text to the originator. + +
WARN
+ +
WARN text...
+ +Log (but do not reject) the body line with a warning, and log the +optional text.
IGNORE
Delete the matched line from the message. -
HOLD
Place the message on the hold queue. Mail on -hold can be inspected with the postcat -command, and can be destroyed or taken off hold with the HOLD
+ +
HOLD text...
+ +Place the message on the hold queue. Mail on hold can be +inspected with the postcat command, +and can be destroyed or taken off hold with the postsuper command. +The optional text is logged together with the matched text. -
WARN
Log (but do not reject) the matched line with a warning. +
DISCARD
-
WARN text...
As above, and also log the text. +
DISCARD text...
+ +Claim successful delivery and silently discard the message. +The optional text is logged together with the matched text.
FILTER transport:nexthop
After the message is queued, send the entire message through @@ -331,12 +365,46 @@ href="basic.html#mynetworks"> $mynetworks.
maptype:mapname
Search the named access database for the client hostname, parent domains, client IP address, or networks obtained by stripping least -significant octets. Reject the request if the result is REJECT -or "[45]XX text". Permit the request if the result -is OK or RELAY or all-numerical. Otherwise, treat the -result as another list of UCE restrictions. The -access_map_reject_code parameter specifies the response code for -REJECT results (default: 554). +significant octets. + +

+ +

+ +
REJECT +
Reject the request. The access_map_reject_code parameter +specifies the response code (default: 554). + +

+ +

[45]XX text +
Reject the request. Send the numerical code and text to the SMTP client. + +

+ +

OK +
RELAY +
all-numerical +
Permit the request. + +

+ +

HOLD +
Place the message on the hold queue. Mail on hold can +be inspected with the postcat command, +and can be destroyed or taken off hold with the postsuper command. + +

+ +

DISCARD +
Claim successful delivery and silently discard the message. + +

+ +

Other
Treat the result as another list of UCE restrictions. + +

diff --git a/postfix/man/man5/access.5 b/postfix/man/man5/access.5 index 43846a08b..72b7d1e1e 100644 --- a/postfix/man/man5/access.5 +++ b/postfix/man/man5/access.5 @@ -115,6 +115,14 @@ Reject the address etc. that matches the pattern. A generic error response message is generated. .IP \fBOK\fR Accept the address etc. that matches the pattern. +.IP \fBHOLD\fR +Place the message on the \fBhold\fR queue, where it will sit +until someone either deletes it or releases it for delivery. +Mail that is placed on hold can be examined with the +\fBpostcat\fR(1) command, and can be destroyed or released with +the \fBpostsuper\fR(1) command. +.IP \fBDISCARD\fR +Claim successful delivery and silently discard the message. .IP \fIall-numerical\fR An all-numerical result is treated as OK. This format is generated by address-based relay authorization schemes. diff --git a/postfix/proto/access b/postfix/proto/access index cdb445966..b0564d06c 100644 --- a/postfix/proto/access +++ b/postfix/proto/access @@ -59,7 +59,7 @@ # Note: lookup of the null sender address is not possible with # some types of lookup table. By default, Postfix uses \fB<>\fR # as the lookup key for such addresses. The value is specified with -# the workaround is to specify \fBsmtpd_null_access_lookup_key\fR +# the workaround is to specify \fBsmtpd_null_access_lookup_key\fR # parameter in the Postfix \fBmain.cf\fR file. # ADDRESS EXTENSION # .fi @@ -102,6 +102,14 @@ # .IP \fIall-numerical\fR # An all-numerical result is treated as OK. This format is # generated by address-based relay authorization schemes. +# .IP \fBHOLD\fR +# Place the message on the \fBhold\fR queue, where it will sit +# until someone either deletes it or releases it for delivery. +# Mail that is placed on hold can be examined with the +# \fBpostcat\fR(1) command, and can be destroyed or released with +# the \fBpostsuper\fR(1) command. +# .IP \fBDISCARD\fR +# Claim successful delivery and silently discard the message. # .IP \fIrestriction...\fR # Apply the named UCE restriction(s) (\fBpermit\fR, \fBreject\fR, # \fBreject_unauth_destination\fR, and so on). diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index f176e222f..d607e46d6 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -145,7 +145,7 @@ static int bounce_append_proto(char *service_name, VSTREAM *client) * Read the and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, why, @@ -185,7 +185,7 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, int flush) * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, @@ -233,7 +233,7 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client, int flush) * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, @@ -293,7 +293,7 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &unused_flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, &unused_flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 7a7ab688d..b5fc13992 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -125,6 +125,7 @@ cleanup_api.o: ../../include/attr.h cleanup_api.o: ../../include/bounce.h cleanup_api.o: ../../include/mail_params.h cleanup_api.o: ../../include/mail_stream.h +cleanup_api.o: ../../include/hold_message.h cleanup_api.o: cleanup.h cleanup_api.o: ../../include/argv.h cleanup_api.o: ../../include/nvtable.h @@ -321,7 +322,6 @@ cleanup_message.o: ../../include/iostuff.h cleanup_message.o: ../../include/attr.h cleanup_message.o: ../../include/mime_state.h cleanup_message.o: ../../include/lex_822.h -cleanup_message.o: ../../include/hold_message.h cleanup_message.o: cleanup.h cleanup_message.o: ../../include/maps.h cleanup_message.o: ../../include/dict.h diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index a9bf352f2..b07b3319a 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -226,20 +226,11 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv) state = cleanup_open(); /* - * Send the queue id to the client. Read client processing options. If we - * can't read the client processing options we can pretty much forget - * about the whole operation. + * Send the queue id to the client. */ attr_print(src, ATTR_FLAG_NONE, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, state->queue_id, ATTR_TYPE_END); - if (attr_scan(src, ATTR_FLAG_STRICT, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, - ATTR_TYPE_END) != 1) { - state->errs |= CLEANUP_STAT_BAD; - flags = 0; - } - cleanup_control(state, flags); /* * XXX Rely on the front-end programs to enforce record size limits. @@ -263,7 +254,8 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv) * our status report. */ if (CLEANUP_OUT_OK(state) == 0 && type > 0) { - if ((state->errs & CLEANUP_STAT_CONT) == 0) + if ((state->errs & CLEANUP_STAT_CONT) == 0 + && (state->flags & CLEANUP_FLAG_DISCARD) == 0) msg_warn("%s: skipping further client input", state->queue_id); while (type != REC_TYPE_END && (type = rec_get(src, buf, 0)) > 0) diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index c795b350f..94ca492bb 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -133,7 +133,8 @@ extern void PRINTFLIKE(3, 4) cleanup_out_format(CLEANUP_STATE *, int, const char #define CLEANUP_OUT_BUF(s, t, b) \ cleanup_out((s), (t), vstring_str((b)), VSTRING_LEN((b))) -#define CLEANUP_OUT_OK(s) (((s)->errs & (s)->err_mask) == 0) +#define CLEANUP_OUT_OK(s) \ + (!((s)->errs & (s)->err_mask) && !((s)->flags & CLEANUP_FLAG_DISCARD)) /* * cleanup_envelope.c diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index 9b6e39b60..2644aa8dd 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -35,8 +35,9 @@ /* queue_id result structure member. /* /* cleanup_control() processes per-message flags specified by the caller. -/* These flags control the handling of data errors, and must be set -/* before processing the first message record. +/* These flags control the storage of mail and the handling of errors. +/* It is an error to any change error handling flags in the middle of +/* a message. /* .IP CLEANUP_FLAG_BOUNCE /* The cleanup server is responsible for returning undeliverable /* mail (too many hops, message too large) to the sender. @@ -98,6 +99,7 @@ #include #include #include +#include /* Application-specific. */ @@ -168,6 +170,8 @@ void cleanup_control(CLEANUP_STATE *state, int flags) * definition. */ if ((state->flags = flags) & CLEANUP_FLAG_BOUNCE) { + if (state->err_mask && state->err_mask != CLEANUP_STAT_MASK_INCOMPLETE) + msg_fatal("can't set CLEANUP_FLAG_BOUNCE after initializations"); state->err_mask = CLEANUP_STAT_MASK_INCOMPLETE; } else { state->err_mask = ~CLEANUP_STAT_MASK_EXTRACT_RCPT; @@ -203,11 +207,28 @@ int cleanup_flush(CLEANUP_STATE *state) * If there are no errors, be very picky about queue file write errors * because we are about to tell the sender that it can throw away its * copy of the message. + * + * Optionally, place the message on hold, but only if the message was + * received successfully. This involves renaming the queue file before + * "finishing" it (or else the queue manager would open it for delivery) + * and updating our own idea of the queue file name for error recovery + * and for error reporting purposes. */ - if (state->errs == 0) { + if (state->errs == 0 && (state->flags & CLEANUP_FLAG_DISCARD) == 0) { + if ((state->flags & CLEANUP_FLAG_HOLD) != 0) { + hold_message(state->temp1, state->queue_name, state->queue_id); + junk = cleanup_path; + cleanup_path = mystrdup(vstring_str(state->temp1)); + myfree(junk); + vstream_control(state->handle->stream, + VSTREAM_CTL_PATH, cleanup_path, + VSTREAM_CTL_END); + } state->errs = mail_stream_finish(state->handle, (VSTRING *) 0); } else { mail_stream_cleanup(state->handle); + if ((state->flags & CLEANUP_FLAG_DISCARD) != 0) + state->errs = 0; } state->handle = 0; state->dst = 0; @@ -254,8 +275,10 @@ int cleanup_flush(CLEANUP_STATE *state) } if (REMOVE(cleanup_path)) msg_warn("remove %s: %m", cleanup_path); + } else if ((state->flags & CLEANUP_FLAG_DISCARD) != 0) { + if (REMOVE(cleanup_path)) + msg_warn("remove %s: %m", cleanup_path); } - /* * Make sure that our queue file will not be deleted by the error handler * AFTER we have taken responsibility for delivery. Better to deliver diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index 00858cc91..96dedfe4f 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -217,6 +217,13 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, return; } nvtable_update(state->attr, attr_name, attr_value); + } else if (type == REC_TYPE_FLGS) { + + /* + * For safety's sake, allow setting flags only. Even this sucks when + * people set the CLEANUP_FLAG_BOUNCE flag too late in the game. + */ + cleanup_control(state, state->flags | atol(buf)); } else { cleanup_out(state, type, buf, len); } diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index faa2ab66a..ad68ee05f 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -80,7 +80,6 @@ #include #include #include -#include /* Application-specific. */ @@ -291,10 +290,11 @@ static int cleanup_act(CLEANUP_STATE *state, char *context, const char *buf, return (CLEANUP_ACT_KEEP); } if (STREQUAL(value, "WARN", command_len)) { - msg_info("%s: warning: %s %.200s; from=<%s> to=<%s>: %s", + msg_info("%s: warning: %s %.200s; from=<%s> to=<%s>%s%s", state->queue_id, context, buf, state->sender, state->recip ? state->recip : "unknown", - *optional_text ? optional_text : "content matched"); + *optional_text ? ": " : "", + *optional_text ? optional_text : ""); return (CLEANUP_ACT_KEEP); } if (STREQUAL(value, "FILTER", command_len)) { @@ -307,6 +307,24 @@ static int cleanup_act(CLEANUP_STATE *state, char *context, const char *buf, } return (CLEANUP_ACT_KEEP); } + if (STREQUAL(value, "DISCARD", command_len)) { + msg_info("%s: discard: %s %.200s; from=<%s> to=<%s>%s%s", + state->queue_id, context, buf, state->sender, + state->recip ? state->recip : "unknown", + *optional_text ? ": " : "", + *optional_text ? optional_text : ""); + state->flags |= CLEANUP_FLAG_DISCARD; + return (CLEANUP_ACT_KEEP); + } + if (STREQUAL(value, "HOLD", command_len)) { + msg_info("%s: hold: %s %.200s; from=<%s> to=<%s>%s%s", + state->queue_id, context, buf, state->sender, + state->recip ? state->recip : "unknown", + *optional_text ? ": " : "", + *optional_text ? optional_text : ""); + state->flags |= CLEANUP_FLAG_HOLD; + return (CLEANUP_ACT_KEEP); + } if (*optional_text) msg_warn("unexpected text after command in %s map: %s", map_class, value); @@ -314,10 +332,6 @@ static int cleanup_act(CLEANUP_STATE *state, char *context, const char *buf, if (STREQUAL(value, "IGNORE", command_len)) return (CLEANUP_ACT_DROP); - if (STREQUAL(value, "HOLD", command_len)) { - hold_message(state->queue_name, state->queue_id); - return (CLEANUP_ACT_KEEP); - } if (STREQUAL(value, "OK", command_len)) return (CLEANUP_ACT_KEEP); diff --git a/postfix/src/global/abounce.c b/postfix/src/global/abounce.c index 3bb158889..44ff81d65 100644 --- a/postfix/src/global/abounce.c +++ b/postfix/src/global/abounce.c @@ -211,7 +211,7 @@ static void abounce_request_verp(const char *class, const char *service, if (attr_print(ap->fp, ATTR_FLAG_NONE, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, @@ -273,7 +273,7 @@ static void abounce_request(const char *class, const char *service, if (attr_print(ap->fp, ATTR_FLAG_NONE, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, command, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, diff --git a/postfix/src/global/bounce.c b/postfix/src/global/bounce.c index 14b74f84b..bcd4b91fb 100644 --- a/postfix/src/global/bounce.c +++ b/postfix/src/global/bounce.c @@ -182,7 +182,7 @@ int vbounce_append(int flags, const char *id, const char *recipient, if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ? var_defer_service : var_bounce_service, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why), @@ -216,7 +216,7 @@ int bounce_flush(int flags, const char *queue, const char *id, return (-1); if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, @@ -271,7 +271,7 @@ int vbounce_one(int flags, const char *queue, const char *id, vstring_vsprintf(why, fmt, ap); if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_ONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, diff --git a/postfix/src/global/cleanup_user.h b/postfix/src/global/cleanup_user.h index c60565d62..86471854a 100644 --- a/postfix/src/global/cleanup_user.h +++ b/postfix/src/global/cleanup_user.h @@ -16,7 +16,9 @@ */ #define CLEANUP_FLAG_NONE 0 /* No special features */ #define CLEANUP_FLAG_BOUNCE (1<<0) /* Bounce bad messages */ -#define CLEANUP_FLAG_FILTER (2<<0) /* Enable content filter */ +#define CLEANUP_FLAG_FILTER (1<<1) /* Enable content filter */ +#define CLEANUP_FLAG_HOLD (1<<2) /* Place message on hold */ +#define CLEANUP_FLAG_DISCARD (1<<3) /* Discard message */ /* * Diagnostics. diff --git a/postfix/src/global/defer.c b/postfix/src/global/defer.c index 862f3a6fd..8c6544aeb 100644 --- a/postfix/src/global/defer.c +++ b/postfix/src/global/defer.c @@ -151,7 +151,7 @@ int vdefer_append(int flags, const char *id, const char *recipient, vstring_vsprintf(why, fmt, ap); if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why), @@ -185,7 +185,7 @@ int defer_flush(int flags, const char *queue, const char *id, { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, @@ -205,7 +205,7 @@ int defer_warn(int flags, const char *queue, const char *id, { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_BFLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index d2492292f..300665df4 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -94,7 +94,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, int stat; attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, request->flags, + ATTR_TYPE_NUM, MAIL_ATTR_DFLAGS, request->flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, request->queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, request->queue_id, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, request->data_offset, diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c index 75dd3c61b..bb44526bc 100644 --- a/postfix/src/global/deliver_request.c +++ b/postfix/src/global/deliver_request.c @@ -196,7 +196,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) * the conversation when they send bad information. */ if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request->flags, + ATTR_TYPE_NUM, MAIL_ATTR_DFLAGS, &request->flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &request->data_offset, diff --git a/postfix/src/global/hold_message.c b/postfix/src/global/hold_message.c index 241a021b2..d360a3b63 100644 --- a/postfix/src/global/hold_message.c +++ b/postfix/src/global/hold_message.c @@ -6,13 +6,22 @@ /* SYNOPSIS /* #include /* -/* void hold_message(queue_name, queue_id) +/* void hold_message(path_buf, queue_name, queue_id) +/* VSTRING *path_buf; /* const char *queue_name; /* const char *queue_id; /* DESCRIPTION /* The \fBhold_message\fR() routine moves the specified /* queue file to the \fBhold\fR queue, where it will sit /* until someone either destroys it or releases it. +/* +/* Arguments: +/* .IP path_buf +/* A null pointer, or storage for the new pathname. +/* .IP queue_name +/* Queue name with the message that needs to be placed on hold. +/* .IP queue_id +/* Queue file name with the message that needs to be placed on hold. /* LICENSE /* .ad /* .fi @@ -47,10 +56,11 @@ /* hold_message - move message to hold queue */ -void hold_message(const char *queue_name, const char *queue_id) +void hold_message(VSTRING *path_buf, const char *queue_name, + const char *queue_id) { VSTRING *old_path = vstring_alloc(100); - VSTRING *new_path = vstring_alloc(100); + VSTRING *new_path = 0; uid_t saved_uid; gid_t saved_gid; @@ -62,18 +72,26 @@ void hold_message(const char *queue_name, const char *queue_id) set_eugid(var_owner_uid, var_owner_gid); } + /* + * Your buffer or mine? + */ + if (path_buf == 0) + new_path = path_buf = vstring_alloc(100); + /* * Grr. Don't do stupid things when this function is called multiple * times. sane_rename() would emit a bogus warning about spurious NFS * problems. */ (void) mail_queue_path(old_path, queue_name, queue_id); - (void) mail_queue_path(new_path, MAIL_QUEUE_HOLD, queue_id); + (void) mail_queue_path(path_buf, MAIL_QUEUE_HOLD, queue_id); if (access(STR(old_path), F_OK) == 0) { - if (rename(STR(old_path), STR(new_path)) == 0 - || access(STR(new_path), F_OK) == 0) - msg_info("%s: placed on hold", queue_id); - else + if (rename(STR(old_path), STR(path_buf)) == 0 + || (access(STR(old_path), F_OK) < 0 + && access(STR(path_buf), F_OK) == 0)) { + if (msg_verbose) + msg_info("%s: placed on hold", queue_id); + } else msg_warn("%s: could not place message on hold: %m", queue_id); } @@ -87,5 +105,6 @@ void hold_message(const char *queue_name, const char *queue_id) * Cleanup. */ vstring_free(old_path); - vstring_free(new_path); + if (new_path) + vstring_free(new_path); } diff --git a/postfix/src/global/hold_message.h b/postfix/src/global/hold_message.h index 0092c8ca0..0b30a0154 100644 --- a/postfix/src/global/hold_message.h +++ b/postfix/src/global/hold_message.h @@ -14,7 +14,7 @@ /* * External interface. */ -extern void hold_message(const char *, const char *); +extern void hold_message(VSTRING *, const char *, const char *); /* LICENSE /* .ad diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index eeb44f325..71f78bd20 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -811,7 +811,7 @@ extern bool var_smtpd_sasl_enable; extern char *var_smtpd_sasl_opts; #define VAR_SMTPD_SASL_REALM "smtpd_sasl_local_domain" -#define DEF_SMTPD_SASL_REALM "$myhostname" +#define DEF_SMTPD_SASL_REALM "" extern char *var_smtpd_sasl_realm; #define VAR_SMTPD_SND_AUTH_MAPS "smtpd_sender_login_maps" diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index bb4e5caef..92b9e67b7 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -80,7 +80,9 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_NREQ "nrequest" #define MAIL_ATTR_STATUS "status" -#define MAIL_ATTR_FLAGS "flags" +#define MAIL_ATTR_BFLAGS "bounce_flags" +#define MAIL_ATTR_DFLAGS "delivery_flags" +#define MAIL_ATTR_RFLAGS "resolve_flags" #define MAIL_ATTR_QUEUE "queue_name" #define MAIL_ATTR_QUEUEID "queue_id" #define MAIL_ATTR_SENDER "sender" diff --git a/postfix/src/global/mail_run.c b/postfix/src/global/mail_run.c index 4b469b6cc..45b786a9d 100644 --- a/postfix/src/global/mail_run.c +++ b/postfix/src/global/mail_run.c @@ -41,7 +41,6 @@ /* command. mail_run_background() returns the process id in case /* of success. /* CONFIGURATION PARAMETERS -/* program_directory: directory with Postfix executables; /* fork_attempts: number of attempts to fork() a process; /* fork_delay: delay in seconds between fork() attempts. /* LICENSE diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index a3f5d3564..3bbc2d47f 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20020819" +#define MAIL_RELEASE_DATE "20020821" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/post_mail.c b/postfix/src/global/post_mail.c index 02e3faf0e..5ae9e571f 100644 --- a/postfix/src/global/post_mail.c +++ b/postfix/src/global/post_mail.c @@ -141,16 +141,14 @@ static void post_mail_init(VSTREAM *stream, const char *sender, */ if (attr_scan(stream, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, - ATTR_TYPE_END) != 1 - || attr_print(stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, - ATTR_TYPE_END) != 0) + ATTR_TYPE_END) != 1) msg_fatal("unable to contact the %s service", var_cleanup_service); /* * Generate a minimal envelope section. The cleanup service will add a * size record. */ + rec_fprintf(stream, REC_TYPE_FLGS, "%d", flags); rec_fprintf(stream, REC_TYPE_TIME, "%ld", (long) now); rec_fprintf(stream, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ORIGIN, MAIL_ATTR_ORG_LOCAL); diff --git a/postfix/src/global/rec_type.h b/postfix/src/global/rec_type.h index 00d4b4697..82392eabf 100644 --- a/postfix/src/global/rec_type.h +++ b/postfix/src/global/rec_type.h @@ -36,6 +36,7 @@ #define REC_TYPE_ORCP 'O' /* original recipient, optional */ #define REC_TYPE_WARN 'W' /* warning message time */ #define REC_TYPE_ATTR 'A' /* named attribute for extensions */ +#define REC_TYPE_FLGS 'f' /* set processing flags */ #define REC_TYPE_MESG 'M' /* start message records */ @@ -62,7 +63,7 @@ * allow for the presence of A records in the extracted segment, because it * can be requested to re-process already queued mail with `postsuper -r'. */ -#define REC_TYPE_ENVELOPE "MCTFILSDROWVA" +#define REC_TYPE_ENVELOPE "MCTFILSDROWVAf" #define REC_TYPE_CONTENT "XLN" #define REC_TYPE_EXTRACT "EDROPreAFI" diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index c8e6ccca9..bd9a93144 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -168,7 +168,7 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply) ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, reply->nexthop, ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &reply->flags, + ATTR_TYPE_NUM, MAIL_ATTR_RFLAGS, &reply->flags, ATTR_TYPE_END) != 4) { if (msg_verbose || (errno != EPIPE && errno != ENOENT)) msg_warn("%s: bad read: %m", myname); diff --git a/postfix/src/local/forward.c b/postfix/src/local/forward.c index a15cc5592..f865e10c5 100644 --- a/postfix/src/local/forward.c +++ b/postfix/src/local/forward.c @@ -139,14 +139,12 @@ static FORWARD_INFO *forward_open(char *sender) info->cleanup = cleanup; info->queue_id = mystrdup(vstring_str(buffer)); info->posting_time = time((time_t *) 0); - attr_print(cleanup, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_BOUNCE, - ATTR_TYPE_END); /* * Send initial message envelope information. For bounces, set the * designated sender: mailing list owner, posting user, whatever. */ + rec_fprintf(cleanup, REC_TYPE_FLGS, "%d", CLEANUP_FLAG_BOUNCE); rec_fprintf(cleanup, REC_TYPE_TIME, "%ld", (long) info->posting_time); rec_fputs(cleanup, REC_TYPE_FROM, sender); diff --git a/postfix/src/local/mailbox.c b/postfix/src/local/mailbox.c index 45d24d8d2..49ac57b25 100644 --- a/postfix/src/local/mailbox.c +++ b/postfix/src/local/mailbox.c @@ -252,7 +252,7 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) * * Don't come here more than once, whether or not the recipient exists. */ - if (been_here(state.dup_filter, "mailbox %s", state.msg_attr.user)) + if (been_here(state.dup_filter, "mailbox %s", state.msg_attr.local)) return (YES); /* diff --git a/postfix/src/nqmgr/qmgr_deliver.c b/postfix/src/nqmgr/qmgr_deliver.c index d8de110c9..93c8e7c98 100644 --- a/postfix/src/nqmgr/qmgr_deliver.c +++ b/postfix/src/nqmgr/qmgr_deliver.c @@ -160,7 +160,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) nexthop = (cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 : entry->queue->name; attr_print(stream, ATTR_FLAG_MORE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_DFLAGS, flags, 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, diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 9b3dba8d3..8eceb81be 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -191,6 +191,8 @@ static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, info->rcpt = mystrdup(vstring_str(buf)); if (type == REC_TYPE_TIME) continue; + if (type == REC_TYPE_FLGS) + continue; if (type == REC_TYPE_ATTR) { if ((error_text = split_nameval(vstring_str(buf), &attr_name, &attr_value)) != 0) { @@ -267,6 +269,15 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, info->id, (int) (now - info->st.st_mtime) / DAY_SECONDS); } + /* + * Send our processing options. In case of trouble, request that the + * cleanup service bounces its copy of the message. because the original + * input file is not readable by the bounce service. + */ +#define PICKUP_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER) + + rec_fprintf(cleanup, REC_TYPE_FLGS, "%d", PICKUP_CLEANUP_FLAGS); + /* * Make sure the message has a posting-time record. */ @@ -389,23 +400,17 @@ static int pickup_file(PICKUP_INFO *info) /* * Contact the cleanup service and read the queue ID that it has - * allocated. In case of trouble, request that the cleanup service - * bounces its copy of the message. because the original input file is - * not readable by the bounce service. + * allocated. * * The actual message copying code is in a separate routine, so that it is * easier to implement the many possible error exits without forgetting * to close files, or to release memory. */ -#define PICKUP_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER) cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); if (attr_scan(cleanup, ATTR_FLAG_STRICT, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf, - ATTR_TYPE_END) != 1 - || attr_print(cleanup, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, PICKUP_CLEANUP_FLAGS, - ATTR_TYPE_END) != 0) { + ATTR_TYPE_END) != 1) { status = KEEP_MESSAGE_FILE; } else { info->id = mystrdup(vstring_str(buf)); diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 6832aa9bd..3c67a7a62 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -297,6 +297,9 @@ int main(int argc, char **argv) * * If something goes wrong, slurp up the input before responding to the * client, otherwise the client will give up after detecting SIGPIPE. + * + * XXX Need to add REC_TYPE_ATTR filtering code before we can talk directly + * to the cleanup daemon. */ vstream_control(VSTREAM_IN, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END); buf = vstring_alloc(100); @@ -315,13 +318,17 @@ int main(int argc, char **argv) } if (rec_type == REC_TYPE_ERROR) msg_fatal("uid=%ld: malformed input", (long) uid); - if (rec_type == REC_TYPE_TIME) - rec_fprintf(dst->stream, REC_TYPE_TIME, "%ld", - (long) time((time_t *) 0)); if (strchr(*expected, rec_type) == 0) msg_fatal("uid=%ld: unexpected record type: %d", (long) uid, rec_type); if (rec_type == **expected) expected++; + if (rec_type == REC_TYPE_TIME) { + rec_fprintf(dst->stream, REC_TYPE_TIME, "%ld", + (long) time((time_t *) 0)); + continue; + } + if (rec_type == REC_TYPE_FLGS) + continue; if (REC_PUT_BUF(dst->stream, rec_type, buf) < 0) { while ((rec_type = rec_get(VSTREAM_IN, buf, var_line_limit)) > 0 && rec_type != REC_TYPE_END) diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c index 64b170c26..bf0828109 100644 --- a/postfix/src/qmgr/qmgr_deliver.c +++ b/postfix/src/qmgr/qmgr_deliver.c @@ -155,7 +155,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) nexthop = (cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 : entry->queue->name; attr_print(stream, ATTR_FLAG_MORE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_DFLAGS, flags, 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, diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index dbcfcb4f0..b83a40403 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -182,10 +182,7 @@ static void qmqpd_open_file(QMQPD_STATE *state) * Connect to the cleanup server. Log client name/address with queue ID. */ state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); - if (state->dest == 0 - || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER, - ATTR_TYPE_END) != 0) + if (state->dest == 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); state->cleanup = state->dest->stream; @@ -197,6 +194,7 @@ static void qmqpd_open_file(QMQPD_STATE *state) * bloody likely, but present for the sake of consistency with all other * Postfix points of entrance). */ + rec_fprintf(state->cleanup, REC_TYPE_FLGS, "%d", CLEANUP_FLAG_FILTER); rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld", (long) state->time); if (*var_filter_xport) rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport); diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 53b9c94a6..4682d1305 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -230,11 +230,9 @@ /* .IP \fBmail_owner\fR /* The owner of the mail queue and of most Postfix processes. /* .IP \fBcommand_directory\fR -/* Directory with Postfix support commands (default: -/* \fB$program_directory\fR). +/* Directory with Postfix support commands. /* .IP \fBdaemon_directory\fR -/* Directory with Postfix daemon programs (default: -/* \fB$program_directory\fR). +/* Directory with Postfix daemon programs. /* .IP \fBqueue_directory\fR /* Top-level directory of the Postfix queue. This is also the root /* directory of Postfix daemons that run chrooted. diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 32fbaeb2b..9a4b28b08 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -198,6 +198,9 @@ smtpd_check.o: ../../include/mail_addr_find.h smtpd_check.o: ../../include/match_parent_style.h smtpd_check.o: ../../include/strip_addr.h smtpd_check.o: ../../include/virtual8.h +smtpd_check.o: ../../include/cleanup_user.h +smtpd_check.o: ../../include/record.h +smtpd_check.o: ../../include/rec_type.h smtpd_check.o: smtpd.h smtpd_check.o: ../../include/mail_stream.h smtpd_check.o: smtpd_sasl_glue.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 91e7b6dee..ef81c30a8 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -103,8 +103,7 @@ /* .IP \fBalways_bcc\fR /* Address to send a copy of each message that enters the system. /* .IP \fBcommand_directory\fR -/* Location of Postfix support commands (default: -/* \fB$program_directory\fR). +/* Location of Postfix support commands. /* .IP \fBdebug_peer_level\fR /* Increment in verbose logging level when a remote host matches a /* pattern in the \fBdebug_peer_list\fR parameter. @@ -539,12 +538,11 @@ static void mail_open_stream(SMTPD_STATE *state) if (SMTPD_STAND_ALONE(state) == 0) { state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); - if (state->dest == 0 - || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER, - ATTR_TYPE_END) != 0) + if (state->dest == 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); + rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", + CLEANUP_FLAG_FILTER); } /* diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 0c94c4cca..2a3a38919 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -293,6 +293,9 @@ #include #include #include +#include +#include +#include /* Application-specific. */ @@ -614,6 +617,29 @@ void smtpd_check_init(void) #endif } +/* log_whatsup - log as much context as we have */ + +static void log_whatsup(SMTPD_STATE *state, const char *whatsup, + const char *text) +{ + if (state->recipient && state->sender) { + msg_info("%s: %s from %s: %s; from=<%s> to=<%s>", + whatsup, state->where, state->namaddr, text, + state->sender, state->recipient); + } else if (state->recipient) { + msg_info("%s: %s from %s: %s; to=<%s>", + whatsup, state->where, state->namaddr, text, + state->recipient); + } else if (state->sender) { + msg_info("%s: %s from %s: %s; from=<%s>", + whatsup, state->where, state->namaddr, text, + state->sender); + } else { + msg_info("%s: %s from %s: %s", + whatsup, state->where, state->namaddr, text); + } +} + /* smtpd_check_reject - do the boring things that must be done */ static int smtpd_check_reject(SMTPD_STATE *state, int error_class, @@ -682,22 +708,8 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class, * postmaster notices, this may be the only trace left that service was * rejected. Print the request, client name/address, and response. */ - if (state->recipient && state->sender) { - msg_info("%s: %s from %s: %s; from=<%s> to=<%s>", - whatsup, state->where, state->namaddr, STR(error_text), - state->sender, state->recipient); - } else if (state->recipient) { - msg_info("%s: %s from %s: %s; to=<%s>", - whatsup, state->where, state->namaddr, STR(error_text), - state->recipient); - } else if (state->sender) { - msg_info("%s: %s from %s: %s; from=<%s>", - whatsup, state->where, state->namaddr, STR(error_text), - state->sender); - } else { - msg_info("%s: %s from %s: %s", - whatsup, state->where, state->namaddr, STR(error_text)); - } + log_whatsup(state, whatsup, STR(error_text)); + return (warn_if_reject ? 0 : SMTPD_CHECK_REJECT); } @@ -1496,6 +1508,28 @@ static int check_table_result(SMTPD_STATE *state, const char *table, "%d <%s>: %s rejected: Access denied", var_access_map_code, reply_name, reply_class)); + /* + * HOLD means deliver later. + */ + if (strcasecmp(value, "HOLD") == 0) { + vstring_sprintf(error_text, "<%s>: %s triggers HOLD action", + reply_name, reply_class); + log_whatsup(state, "hold", STR(error_text)); + rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", + CLEANUP_FLAG_HOLD); + } + + /* + * DISCARD means silently discard and claim successful delivery. + */ + if (strcasecmp(value, "DISCARD") == 0) { + vstring_sprintf(error_text, "<%s>: %s triggers DISCARD action", + reply_name, reply_class); + log_whatsup(state, "discard", STR(error_text)); + rec_fprintf(state->dest->stream, REC_TYPE_FLGS, "%d", + CLEANUP_FLAG_DISCARD); + } + /* * All-numeric result probably means OK - some out-of-band authentication * mechanism uses this as time stamp. diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index b53d56563..a3af883fc 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -291,7 +291,7 @@ int resolve_proto(VSTREAM *stream) ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, STR(channel), ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, STR(nexthop), ATTR_TYPE_STR, MAIL_ATTR_RECIP, STR(nextrcpt), - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_NUM, MAIL_ATTR_RFLAGS, flags, ATTR_TYPE_END); if (vstream_fflush(stream) != 0) { diff --git a/postfix/src/util/dict_ldap.c b/postfix/src/util/dict_ldap.c index eab1c20f3..fa370107a 100644 --- a/postfix/src/util/dict_ldap.c +++ b/postfix/src/util/dict_ldap.c @@ -94,13 +94,6 @@ #ifdef HAS_LDAP - /* - * Older APIs have weird memory freeing behavior. - */ -#if !defined(LDAP_API_VERSION) || (LDAP_API_VERSION < 2000) -#error "Your LDAP version is too old" -#endif - #include #include #include @@ -110,6 +103,13 @@ #include #include + /* + * Older APIs have weird memory freeing behavior. + */ +#if !defined(LDAP_API_VERSION) || (LDAP_API_VERSION < 2000) +#error "Your LDAP version is too old" +#endif + /* Handle differences between LDAP SDK's constant definitions */ #ifndef LDAP_CONST #define LDAP_CONST const @@ -187,22 +187,14 @@ static int dict_ldap_get_errno(LDAP * ld) { int rc; -#if (LDAP_API_VERSION >= 2000) if (ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &rc) != LDAP_OPT_SUCCESS) rc = LDAP_OTHER; -#else - rc = dict_ldap->ld->ld_errno; -#endif return rc; } static int dict_ldap_set_errno(LDAP * ld, int rc) { -#if (LDAP_API_VERSION >= 2000) (void) ldap_set_option(ld, LDAP_OPT_ERROR_NUMBER, &rc); -#else - ld->ld_errno = rc; -#endif return rc; } @@ -320,13 +312,9 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap) * Configure alias dereferencing for this connection. Thanks to Mike * Mattice for this, and to Hery Rakotoarisoa for the v3 update. */ -#if (LDAP_API_VERSION >= 2000) if (ldap_set_option(dict_ldap->ld, LDAP_OPT_DEREF, &(dict_ldap->dereference)) != LDAP_OPT_SUCCESS) msg_warn("%s: Unable to set dereference option.", myname); -#else - dict_ldap->ld->ld_deref = dict_ldap->dereference; -#endif #if defined(LDAP_OPT_DEBUG_LEVEL) && defined(LBER_OPT_LOG_PRINT_FN) if (dict_ldap->debuglevel > 0 &&