From 92625903ff36aa01b51a12d8fc4cd1405e75777d Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Wed, 19 Nov 2014 00:00:00 -0500 Subject: [PATCH] postfix-2.12-20141119 --- postfix/HISTORY | 21 +++ postfix/WISHLIST | 2 + postfix/conf/header_checks | 203 ++++++++++++--------- postfix/html/header_checks.5.html | 162 ++++++++-------- postfix/man/man5/header_checks.5 | 17 ++ postfix/proto/header_checks | 17 ++ postfix/src/cleanup/Makefile.in | 71 +++++-- postfix/src/cleanup/cleanup.h | 2 +- postfix/src/cleanup/cleanup_extracted.c | 15 ++ postfix/src/cleanup/cleanup_message.c | 13 ++ postfix/src/cleanup/cleanup_milter.c | 133 +++++++++----- postfix/src/cleanup/cleanup_milter.in16a | 10 + postfix/src/cleanup/cleanup_milter.in16b | 12 ++ postfix/src/cleanup/cleanup_milter.ref16a1 | 3 + postfix/src/cleanup/cleanup_milter.ref16a2 | 37 ++++ postfix/src/cleanup/cleanup_milter.ref16b1 | 1 + postfix/src/cleanup/cleanup_milter.ref16b2 | 42 +++++ postfix/src/cleanup/cleanup_milter.reg16a | 2 + postfix/src/cleanup/cleanup_state.c | 6 +- postfix/src/cleanup/test-queue-file16 | Bin 0 -> 654 bytes postfix/src/global/attr_override.h | 2 - postfix/src/global/mail_version.h | 2 +- postfix/src/util/base64_code.c | 58 ++---- postfix/src/util/sys_defs.h | 8 + 24 files changed, 563 insertions(+), 276 deletions(-) create mode 100644 postfix/src/cleanup/cleanup_milter.in16a create mode 100644 postfix/src/cleanup/cleanup_milter.in16b create mode 100644 postfix/src/cleanup/cleanup_milter.ref16a1 create mode 100644 postfix/src/cleanup/cleanup_milter.ref16a2 create mode 100644 postfix/src/cleanup/cleanup_milter.ref16b1 create mode 100644 postfix/src/cleanup/cleanup_milter.ref16b2 create mode 100644 postfix/src/cleanup/cleanup_milter.reg16a create mode 100644 postfix/src/cleanup/test-queue-file16 diff --git a/postfix/HISTORY b/postfix/HISTORY index 95c8b763c..60f891e0d 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -20778,3 +20778,24 @@ Apologies for any names omitted. Cleanup: use more meaningful name for global variable so that it isn't shadowed by a local variable. Based on complaints from the BEAM static analyzer. smtpstone/smtp-sink.c. + +20141119 + + Cleanup: base64 test driver. File: base64_code.c. + + Cleanup: make the CONST_CHAR_STAR typedef project-wide. + Files: global/attr_override.h, util/sys_defs.h. + + Feature: BCC action in header/body_checks and milter_header_checks. + Files: proto/header_checks, cleanup/cleanup.h, + cleanup/cleanup_extracted.c, cleanup/cleanup_message.c, + cleanup/cleanup_milter.c, cleanup/cleanup_milter.in16a, + cleanup/cleanup_milter.ref16a1, cleanup/cleanup_milter.ref16a2, + cleanup/cleanup_milter.reg16a, cleanup/cleanup_state.c, + cleanup/test-queue-file16, global/attr_override.h, + global/cleanup_strflags.c, global/cleanup_user.h, + util/sys_defs.h. + + Cleanup: don't write back-to-back queue file pointer records + when the "add recipient" action was a NOOP (e.g., because + the recipient was a duplicate). File: cleanup/cleanup_milter.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 454ae0399..9c8988a9d 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -8,6 +8,8 @@ Wish list: Things to do after the stable release: + Make the access map BCC action consistent with header_checks. + Find a way to show non-default OPT, DEBUG etc. settings at the top of the makedefs.out file. diff --git a/postfix/conf/header_checks b/postfix/conf/header_checks index b68e148f8..cf1e36021 100644 --- a/postfix/conf/header_checks +++ b/postfix/conf/header_checks @@ -175,13 +175,34 @@ # Action names are case insensitive. They are shown in upper # case for consistency with other Postfix documentation. # +# BCC user@domain +# Add the specified address as a BCC recipient. The +# address must have a local part and domain part. The +# number of BCC addresses that can be added is lim- +# ited only by the amount of available storage space. +# +# Note 1: the BCC address is added as if it was spec- +# ified with NOTIFY=NONE. The sender will not be +# notified when the BCC address is undeliverable, as +# long as all down-stream software implements RFC +# 3461. +# +# Note 2: this ignores duplicate addresses (with the +# same delivery status notification options). +# +# This feature is available in Postfix 2.12 and +# later. +# +# This feature is not supported with smtp header/body +# checks. +# # DISCARD optional text... -# Claim successful delivery and silently discard the -# message. Log the optional text if specified, oth- +# Claim successful delivery and silently discard the +# message. Log the optional text if specified, oth- # erwise log a generic message. # -# Note: this action disables further header or -# body_checks inspection of the current message and +# Note: this action disables further header or +# body_checks inspection of the current message and # affects all recipients. To discard only one recip- # ient without discarding the entire message, use the # transport(5) table to direct mail to the discard(8) @@ -192,43 +213,43 @@ # This feature is not supported with smtp header/body # checks. # -# DUNNO Pretend that the input line did not match any pat- -# tern, and inspect the next input line. This action +# DUNNO Pretend that the input line did not match any pat- +# tern, and inspect the next input line. This action # can be used to shorten the table search. # -# For backwards compatibility reasons, Postfix also -# accepts OK but it is (and always has been) treated +# For backwards compatibility reasons, Postfix also +# accepts OK but it is (and always has been) treated # as DUNNO. # # This feature is available in Postfix 2.1 and later. # # FILTER transport:destination -# After the message is queued, send the entire mes- +# After the message is queued, send the entire mes- # sage through the specified external content filter. -# The transport name specifies the first field of a -# mail delivery agent definition in master.cf; the -# syntax of the next-hop destination is described in +# The transport name specifies the first field of a +# mail delivery agent definition in master.cf; the +# syntax of the next-hop destination is described in # the manual page of the corresponding delivery -# agent. More information about external content +# agent. More information about external content # filters is in the Postfix FILTER_README file. # -# Note 1: do not use $number regular expression sub- -# stitutions for transport or destination unless you +# Note 1: do not use $number regular expression sub- +# stitutions for transport or destination unless you # know that the information has a trusted origin. # -# Note 2: this action overrides the main.cf con- -# tent_filter setting, and affects all recipients of -# the message. In the case that multiple FILTER +# Note 2: this action overrides the main.cf con- +# tent_filter setting, and affects all recipients of +# the message. In the case that multiple FILTER # actions fire, only the last one is executed. # -# Note 3: the purpose of the FILTER command is to -# override message routing. To override the recipi- -# ent's transport but not the next-hop destination, -# specify an empty filter destination (Postfix 2.7 +# Note 3: the purpose of the FILTER command is to +# override message routing. To override the recipi- +# ent's transport but not the next-hop destination, +# specify an empty filter destination (Postfix 2.7 # and later), or specify a transport:destination that -# delivers through a different Postfix instance -# (Postfix 2.6 and earlier). Other options are using -# the recipient-dependent transport_maps or the sen- +# delivers through a different Postfix instance +# (Postfix 2.6 and earlier). Other options are using +# the recipient-dependent transport_maps or the sen- # der-dependent sender_dependent_default_transport- # _maps features. # @@ -238,23 +259,23 @@ # checks. # # HOLD optional text... -# Arrange for the message to be placed on the hold -# queue, and inspect the next input line. The mes- -# sage remains on hold until someone either deletes -# it or releases it for delivery. Log the optional +# Arrange for the message to be placed on the hold +# queue, and inspect the next input line. The mes- +# sage remains on hold until someone either deletes +# it or releases it for delivery. Log the optional # text if specified, otherwise log a generic message. # -# Mail that is placed on hold can be examined with -# the postcat(1) command, and can be destroyed or +# Mail that is placed on hold can be examined with +# the postcat(1) command, and can be destroyed or # released with the postsuper(1) command. # -# Note: use "postsuper -r" to release mail that was -# kept on hold for a significant fraction of $maxi- +# Note: use "postsuper -r" to release mail that was +# kept on hold for a significant fraction of $maxi- # mal_queue_lifetime or $bounce_queue_lifetime, or -# longer. Use "postsuper -H" only for mail that will +# longer. Use "postsuper -H" only for mail that will # not expire within a few delivery attempts. # -# Note: this action affects all recipients of the +# Note: this action affects all recipients of the # message. # # This feature is available in Postfix 2.0 and later. @@ -267,30 +288,30 @@ # # INFO optional text... # Log an "info:" record with the optional text... (or -# log a generic text), and inspect the next input -# line. This action is useful for routine logging or +# log a generic text), and inspect the next input +# line. This action is useful for routine logging or # for debugging. # # This feature is available in Postfix 2.8 and later. # # PREPEND text... -# Prepend one line with the specified text, and +# Prepend one line with the specified text, and # inspect the next input line. # # Notes: # -# o The prepended text is output on a separate +# o The prepended text is output on a separate # line, immediately before the input that # triggered the PREPEND action. # # o The prepended text is not considered part of -# the input stream: it is not subject to +# the input stream: it is not subject to # header/body checks or address rewriting, and # it does not affect the way that Postfix adds # missing message headers. # # o When prepending text before a message header -# line, the prepended text must begin with a +# line, the prepended text must begin with a # valid message header label. # # o This action cannot be used to prepend multi- @@ -302,14 +323,14 @@ # ter_header_checks. # # REDIRECT user@domain -# Write a message redirection request to the queue -# file, and inspect the next input line. After the +# Write a message redirection request to the queue +# file, and inspect the next input line. After the # message is queued, it will be sent to the specified # address instead of the intended recipient(s). # -# Note: this action overrides the FILTER action, and -# affects all recipients of the message. If multiple -# REDIRECT actions fire, only the last one is exe- +# Note: this action overrides the FILTER action, and +# affects all recipients of the message. If multiple +# REDIRECT actions fire, only the last one is exe- # cuted. # # This feature is available in Postfix 2.1 and later. @@ -318,33 +339,33 @@ # checks. # # REPLACE text... -# Replace the current line with the specified text, +# Replace the current line with the specified text, # and inspect the next input line. # # This feature is available in Postfix 2.2 and later. -# The description below applies to Postfix 2.2.2 and +# The description below applies to Postfix 2.2.2 and # later. # # Notes: # -# o When replacing a message header line, the -# replacement text must begin with a valid +# o When replacing a message header line, the +# replacement text must begin with a valid # header label. # -# o The replaced text remains part of the input -# stream. Unlike the result from the PREPEND -# action, a replaced message header may be -# subject to address rewriting and may affect -# the way that Postfix adds missing message +# o The replaced text remains part of the input +# stream. Unlike the result from the PREPEND +# action, a replaced message header may be +# subject to address rewriting and may affect +# the way that Postfix adds missing message # headers. # # REJECT optional text... -# Reject the entire message. Reply with optional +# Reject the entire message. Reply with optional # text... when the optional text is specified, other- # wise reply with a generic error message. # -# Note: this action disables further header or -# body_checks inspection of the current message and +# Note: this action disables further header or +# body_checks inspection of the current message and # affects all recipients. # # Postfix version 2.3 and later support enhanced sta- @@ -356,38 +377,38 @@ # checks. # # WARN optional text... -# Log a "warning:" record with the optional text... +# Log a "warning:" record with the optional text... # (or log a generic text), and inspect the next input -# line. This action is useful for debugging and for -# testing a pattern before applying more drastic +# line. This action is useful for debugging and for +# testing a pattern before applying more drastic # actions. # # BUGS # Empty lines never match, because some map types mis-behave -# when given a zero-length search string. This limitation -# may be removed for regular expression tables in a future +# when given a zero-length search string. This limitation +# may be removed for regular expression tables in a future # release. # -# Many people overlook the main limitations of header and +# Many people overlook the main limitations of header and # body_checks rules. # -# o These rules operate on one logical message header +# o These rules operate on one logical message header # or one body line at a time. A decision made for one # line is not carried over to the next line. # -# o If text in the message body is encoded (RFC 2045) +# o If text in the message body is encoded (RFC 2045) # then the rules need to be specified for the encoded # form. # -# o Likewise, when message headers are encoded (RFC -# 2047) then the rules need to be specified for the +# o Likewise, when message headers are encoded (RFC +# 2047) then the rules need to be specified for the # encoded form. # -# Message headers added by the cleanup(8) daemon itself are +# Message headers added by the cleanup(8) daemon itself are # excluded from inspection. Examples of such message headers # are From:, To:, Message-ID:, Date:. # -# Message headers deleted by the cleanup(8) daemon will be +# Message headers deleted by the cleanup(8) daemon will be # examined before they are deleted. Examples are: Bcc:, Con- # tent-Length:, Return-Path:. # @@ -395,11 +416,11 @@ # body_checks # Lookup tables with content filter rules for message # body lines. These filters see one physical line at -# a time, in chunks of at most $line_length_limit +# a time, in chunks of at most $line_length_limit # bytes. # # body_checks_size_limit -# The amount of content per message body segment +# The amount of content per message body segment # (attachment) that is subjected to $body_checks fil- # tering. # @@ -409,35 +430,35 @@ # # nested_header_checks (default: $header_checks) # Lookup tables with content filter rules for message -# header lines: respectively, these are applied to -# the initial message headers (not including MIME -# headers), to the MIME headers anywhere in the mes- -# sage, and to the initial headers of attached mes- +# header lines: respectively, these are applied to +# the initial message headers (not including MIME +# headers), to the MIME headers anywhere in the mes- +# sage, and to the initial headers of attached mes- # sages. # -# Note: these filters see one logical message header -# at a time, even when a message header spans multi- -# ple lines. Message headers that are longer than +# Note: these filters see one logical message header +# at a time, even when a message header spans multi- +# ple lines. Message headers that are longer than # $header_size_limit characters are truncated. # # disable_mime_input_processing -# While receiving mail, give no special treatment to -# MIME related message headers; all text after the +# While receiving mail, give no special treatment to +# MIME related message headers; all text after the # initial message headers is considered to be part of -# the message body. This means that header_checks is -# applied to all the initial message headers, and +# the message body. This means that header_checks is +# applied to all the initial message headers, and # that body_checks is applied to the remainder of the # message. # -# Note: when used in this manner, body_checks will -# process a multi-line message header one line at a +# Note: when used in this manner, body_checks will +# process a multi-line message header one line at a # time. # # EXAMPLES -# Header pattern to block attachments with bad file name -# extensions. For convenience, the PCRE /x flag is speci- -# fied, so that there is no need to collapse the pattern -# into a single line of text. The purpose of the +# Header pattern to block attachments with bad file name +# extensions. For convenience, the PCRE /x flag is speci- +# fied, so that there is no need to collapse the pattern +# into a single line of text. The purpose of the # [[:xdigit:]] sub-expressions is to recognize Windows CLSID # strings. # @@ -476,7 +497,7 @@ # RFC 2047, message header encoding for non-ASCII text # # README FILES -# Use "postconf readme_directory" or "postconf html_direc- +# Use "postconf readme_directory" or "postconf html_direc- # tory" to locate this information. # DATABASE_README, Postfix lookup table overview # CONTENT_INSPECTION_README, Postfix content inspection overview @@ -484,7 +505,7 @@ # BACKSCATTER_README, blocking returned forged mail # # LICENSE -# The Secure Mailer license must be distributed with this +# The Secure Mailer license must be distributed with this # software. # # AUTHOR(S) diff --git a/postfix/html/header_checks.5.html b/postfix/html/header_checks.5.html index ce7272a64..891829c48 100644 --- a/postfix/html/header_checks.5.html +++ b/postfix/html/header_checks.5.html @@ -164,13 +164,31 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) Action names are case insensitive. They are shown in upper case for consistency with other Postfix documentation. + BCC user@domain + Add the specified address as a BCC recipient. The address must + have a local part and domain part. The number of BCC addresses + that can be added is limited only by the amount of available + storage space. + + Note 1: the BCC address is added as if it was specified with + NOTIFY=NONE. The sender will not be notified when the BCC + address is undeliverable, as long as all down-stream software + implements RFC 3461. + + Note 2: this ignores duplicate addresses (with the same delivery + status notification options). + + This feature is available in Postfix 2.12 and later. + + This feature is not supported with smtp header/body checks. + DISCARD optional text... Claim successful delivery and silently discard the message. Log the optional text if specified, otherwise log a generic message. Note: this action disables further header or body_checks inspec- tion of the current message and affects all recipients. To dis- - card only one recipient without discarding the entire message, + card only one recipient without discarding the entire message, use the transport(5) table to direct mail to the discard(8) ser- vice. @@ -178,8 +196,8 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) This feature is not supported with smtp header/body checks. - DUNNO Pretend that the input line did not match any pattern, and - inspect the next input line. This action can be used to shorten + DUNNO Pretend that the input line did not match any pattern, and + inspect the next input line. This action can be used to shorten the table search. For backwards compatibility reasons, Postfix also accepts OK but @@ -189,29 +207,29 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) FILTER transport:destination After the message is queued, send the entire message through the - specified external content filter. The transport name specifies - the first field of a mail delivery agent definition in mas- - ter.cf; the syntax of the next-hop destination is described in - the manual page of the corresponding delivery agent. More - information about external content filters is in the Postfix + specified external content filter. The transport name specifies + the first field of a mail delivery agent definition in mas- + ter.cf; the syntax of the next-hop destination is described in + the manual page of the corresponding delivery agent. More + information about external content filters is in the Postfix FILTER_README file. - Note 1: do not use $number regular expression substitutions for - transport or destination unless you know that the information + Note 1: do not use $number regular expression substitutions for + transport or destination unless you know that the information has a trusted origin. - Note 2: this action overrides the main.cf content_filter set- - ting, and affects all recipients of the message. In the case - that multiple FILTER actions fire, only the last one is exe- + Note 2: this action overrides the main.cf content_filter set- + ting, and affects all recipients of the message. In the case + that multiple FILTER actions fire, only the last one is exe- cuted. Note 3: the purpose of the FILTER command is to override message - routing. To override the recipient's transport but not the + routing. To override the recipient's transport but not the next-hop destination, specify an empty filter destination (Post- - fix 2.7 and later), or specify a transport:destination that - delivers through a different Postfix instance (Postfix 2.6 and + fix 2.7 and later), or specify a transport:destination that + delivers through a different Postfix instance (Postfix 2.6 and earlier). Other options are using the recipient-dependent trans- - port_maps or the sender-dependent sender_dependent_default- + port_maps or the sender-dependent sender_dependent_default- _transport_maps features. This feature is available in Postfix 2.0 and later. @@ -219,18 +237,18 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) This feature is not supported with smtp header/body checks. HOLD optional text... - Arrange for the message to be placed on the hold queue, and - inspect the next input line. The message remains on hold until - someone either deletes it or releases it for delivery. Log the + Arrange for the message to be placed on the hold queue, and + inspect the next input line. The message remains on hold until + someone either deletes it or releases it for delivery. Log the optional text if specified, otherwise log a generic message. - Mail that is placed on hold can be examined with the postcat(1) - command, and can be destroyed or released with the postsuper(1) + Mail that is placed on hold can be examined with the postcat(1) + command, and can be destroyed or released with the postsuper(1) command. - Note: use "postsuper -r" to release mail that was kept on hold - for a significant fraction of $maximal_queue_lifetime or - $bounce_queue_lifetime, or longer. Use "postsuper -H" only for + Note: use "postsuper -r" to release mail that was kept on hold + for a significant fraction of $maximal_queue_lifetime or + $bounce_queue_lifetime, or longer. Use "postsuper -H" only for mail that will not expire within a few delivery attempts. Note: this action affects all recipients of the message. @@ -239,32 +257,32 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) This feature is not supported with smtp header/body checks. - IGNORE Delete the current line from the input, and inspect the next + IGNORE Delete the current line from the input, and inspect the next input line. INFO optional text... - Log an "info:" record with the optional text... (or log a - generic text), and inspect the next input line. This action is + Log an "info:" record with the optional text... (or log a + generic text), and inspect the next input line. This action is useful for routine logging or for debugging. This feature is available in Postfix 2.8 and later. PREPEND text... - Prepend one line with the specified text, and inspect the next + Prepend one line with the specified text, and inspect the next input line. Notes: - o The prepended text is output on a separate line, immedi- + o The prepended text is output on a separate line, immedi- ately before the input that triggered the PREPEND action. - o The prepended text is not considered part of the input - stream: it is not subject to header/body checks or - address rewriting, and it does not affect the way that + o The prepended text is not considered part of the input + stream: it is not subject to header/body checks or + address rewriting, and it does not affect the way that Postfix adds missing message headers. - o When prepending text before a message header line, the - prepended text must begin with a valid message header + o When prepending text before a message header line, the + prepended text must begin with a valid message header label. o This action cannot be used to prepend multi-line text. @@ -274,13 +292,13 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) This feature is not supported with milter_header_checks. REDIRECT user@domain - Write a message redirection request to the queue file, and - inspect the next input line. After the message is queued, it - will be sent to the specified address instead of the intended + Write a message redirection request to the queue file, and + inspect the next input line. After the message is queued, it + will be sent to the specified address instead of the intended recipient(s). - Note: this action overrides the FILTER action, and affects all - recipients of the message. If multiple REDIRECT actions fire, + Note: this action overrides the FILTER action, and affects all + recipients of the message. If multiple REDIRECT actions fire, only the last one is executed. This feature is available in Postfix 2.1 and later. @@ -288,7 +306,7 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) This feature is not supported with smtp header/body checks. REPLACE text... - Replace the current line with the specified text, and inspect + Replace the current line with the specified text, and inspect the next input line. This feature is available in Postfix 2.2 and later. The descrip- @@ -296,65 +314,65 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) Notes: - o When replacing a message header line, the replacement + o When replacing a message header line, the replacement text must begin with a valid header label. - o The replaced text remains part of the input stream. - Unlike the result from the PREPEND action, a replaced - message header may be subject to address rewriting and - may affect the way that Postfix adds missing message + o The replaced text remains part of the input stream. + Unlike the result from the PREPEND action, a replaced + message header may be subject to address rewriting and + may affect the way that Postfix adds missing message headers. REJECT optional text... - Reject the entire message. Reply with optional text... when the + Reject the entire message. Reply with optional text... when the optional text is specified, otherwise reply with a generic error message. Note: this action disables further header or body_checks inspec- tion of the current message and affects all recipients. - Postfix version 2.3 and later support enhanced status codes. - When no code is specified at the beginning of optional text..., + Postfix version 2.3 and later support enhanced status codes. + When no code is specified at the beginning of optional text..., Postfix inserts a default enhanced status code of "5.7.1". This feature is not supported with smtp header/body checks. WARN optional text... - Log a "warning:" record with the optional text... (or log a - generic text), and inspect the next input line. This action is - useful for debugging and for testing a pattern before applying + Log a "warning:" record with the optional text... (or log a + generic text), and inspect the next input line. This action is + useful for debugging and for testing a pattern before applying more drastic actions. BUGS Empty lines never match, because some map types mis-behave when given a - zero-length search string. This limitation may be removed for regular + zero-length search string. This limitation may be removed for regular expression tables in a future release. - Many people overlook the main limitations of header and body_checks + Many people overlook the main limitations of header and body_checks rules. - o These rules operate on one logical message header or one body + o These rules operate on one logical message header or one body line at a time. A decision made for one line is not carried over to the next line. o If text in the message body is encoded (RFC 2045) then the rules need to be specified for the encoded form. - o Likewise, when message headers are encoded (RFC 2047) then the + o Likewise, when message headers are encoded (RFC 2047) then the rules need to be specified for the encoded form. Message headers added by the cleanup(8) daemon itself are excluded from - inspection. Examples of such message headers are From:, To:, Message- + inspection. Examples of such message headers are From:, To:, Message- ID:, Date:. - Message headers deleted by the cleanup(8) daemon will be examined - before they are deleted. Examples are: Bcc:, Content-Length:, Return- + Message headers deleted by the cleanup(8) daemon will be examined + before they are deleted. Examples are: Bcc:, Content-Length:, Return- Path:. CONFIGURATION PARAMETERS body_checks - Lookup tables with content filter rules for message body lines. - These filters see one physical line at a time, in chunks of at + Lookup tables with content filter rules for message body lines. + These filters see one physical line at a time, in chunks of at most $line_length_limit bytes. body_checks_size_limit @@ -366,31 +384,31 @@ HEADER_CHECKS(5) HEADER_CHECKS(5) mime_header_checks (default: $header_checks) nested_header_checks (default: $header_checks) - Lookup tables with content filter rules for message header - lines: respectively, these are applied to the initial message - headers (not including MIME headers), to the MIME headers any- - where in the message, and to the initial headers of attached + Lookup tables with content filter rules for message header + lines: respectively, these are applied to the initial message + headers (not including MIME headers), to the MIME headers any- + where in the message, and to the initial headers of attached messages. - Note: these filters see one logical message header at a time, + Note: these filters see one logical message header at a time, even when a message header spans multiple lines. Message headers - that are longer than $header_size_limit characters are trun- + that are longer than $header_size_limit characters are trun- cated. disable_mime_input_processing - While receiving mail, give no special treatment to MIME related - message headers; all text after the initial message headers is - considered to be part of the message body. This means that + While receiving mail, give no special treatment to MIME related + message headers; all text after the initial message headers is + considered to be part of the message body. This means that header_checks is applied to all the initial message headers, and that body_checks is applied to the remainder of the message. - Note: when used in this manner, body_checks will process a + Note: when used in this manner, body_checks will process a multi-line message header one line at a time. EXAMPLES Header pattern to block attachments with bad file name extensions. For convenience, the PCRE /x flag is specified, so that there is no need to - collapse the pattern into a single line of text. The purpose of the + collapse the pattern into a single line of text. The purpose of the [[:xdigit:]] sub-expressions is to recognize Windows CLSID strings. /etc/postfix/main.cf: diff --git a/postfix/man/man5/header_checks.5 b/postfix/man/man5/header_checks.5 index f5419fbf0..d6ae3eb25 100644 --- a/postfix/man/man5/header_checks.5 +++ b/postfix/man/man5/header_checks.5 @@ -184,6 +184,23 @@ available for negated patterns. .fi Action names are case insensitive. They are shown in upper case for consistency with other Postfix documentation. +.IP "\fBBCC \fIuser@domain\fR" +Add the specified address as a BCC recipient. The address +must have a local part and domain part. The number of BCC +addresses that can be added is limited only by the amount +of available storage space. + +Note 1: the BCC address is added as if it was specified with +NOTIFY=NONE. The sender will not be notified when the BCC +address is undeliverable, as long as all down-stream software +implements RFC 3461. + +Note 2: this ignores duplicate addresses (with the same +delivery status notification options). +.sp +This feature is available in Postfix 2.12 and later. +.sp +This feature is not supported with smtp header/body checks. .IP "\fBDISCARD \fIoptional text...\fR" Claim successful delivery and silently discard the message. Log the optional text if specified, otherwise log a generic diff --git a/postfix/proto/header_checks b/postfix/proto/header_checks index c4c5b628e..531ea2b41 100644 --- a/postfix/proto/header_checks +++ b/postfix/proto/header_checks @@ -162,6 +162,23 @@ # .fi # Action names are case insensitive. They are shown in upper case # for consistency with other Postfix documentation. +# .IP "\fBBCC \fIuser@domain\fR" +# Add the specified address as a BCC recipient. The address +# must have a local part and domain part. The number of BCC +# addresses that can be added is limited only by the amount +# of available storage space. +# +# Note 1: the BCC address is added as if it was specified with +# NOTIFY=NONE. The sender will not be notified when the BCC +# address is undeliverable, as long as all down-stream software +# implements RFC 3461. +# +# Note 2: this ignores duplicate addresses (with the same +# delivery status notification options). +# .sp +# This feature is available in Postfix 2.12 and later. +# .sp +# This feature is not supported with smtp header/body checks. # \" .IP "\fBDELAY \fItime\fR" # \" Place the message into the deferred queue, and delay the # \" initial delivery attempt by \fItime\fR. The time value may diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index c6c5e74b4..6c9dfcc68 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -84,7 +84,8 @@ milter_tests: cleanup_milter_test bug_tests \ cleanup_milter_test14g \ cleanup_milter_test15a cleanup_milter_test15b cleanup_milter_test15c \ cleanup_milter_test15d cleanup_milter_test15e cleanup_milter_test15f \ - cleanup_milter_test15g cleanup_milter_test15h cleanup_milter_test15i + cleanup_milter_test15g cleanup_milter_test15h cleanup_milter_test15i \ + cleanup_milter_test16a cleanup_milter_test16b root_tests: @@ -355,7 +356,8 @@ cleanup_milter_test13d: cleanup_milter test-queue-file13d cleanup_milter.in13d \ rm -f test-queue-file13d.tmp cleanup_milter.tmp cleanup_milter_test14a: cleanup_milter test-queue-file14 cleanup_milter.in14a \ - cleanup_milter.ref14a1 ../postcat/postcat cleanup_milter.ref14a2 + cleanup_milter.ref14a1 ../postcat/postcat cleanup_milter.ref14a2 \ + cleanup_milter.reg14a cp test-queue-file14 test-queue-file14a.tmp chmod u+w test-queue-file14a.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -365,7 +367,8 @@ cleanup_milter_test14a: cleanup_milter test-queue-file14 cleanup_milter.in14a \ rm -f test-queue-file14a.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test14b: cleanup_milter test-queue-file14 cleanup_milter.in14b \ - cleanup_milter.ref14b1 ../postcat/postcat cleanup_milter.ref14b2 + cleanup_milter.ref14b1 ../postcat/postcat cleanup_milter.ref14b2 \ + cleanup_milter.reg14b cp test-queue-file14 test-queue-file14b.tmp chmod u+w test-queue-file14b.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -375,7 +378,8 @@ cleanup_milter_test14b: cleanup_milter test-queue-file14 cleanup_milter.in14b \ rm -f test-queue-file14b.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test14c: cleanup_milter test-queue-file14 cleanup_milter.in14c \ - cleanup_milter.ref14c1 ../postcat/postcat cleanup_milter.ref14c2 + cleanup_milter.ref14c1 ../postcat/postcat cleanup_milter.ref14c2 \ + cleanup_milter.reg14c cp test-queue-file14 test-queue-file14c.tmp chmod u+w test-queue-file14c.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -385,7 +389,8 @@ cleanup_milter_test14c: cleanup_milter test-queue-file14 cleanup_milter.in14c \ rm -f test-queue-file14c.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test14d: cleanup_milter test-queue-file14 cleanup_milter.in14d \ - cleanup_milter.ref14d1 ../postcat/postcat cleanup_milter.ref14d2 + cleanup_milter.ref14d1 ../postcat/postcat cleanup_milter.ref14d2 \ + cleanup_milter.reg14d cp test-queue-file14 test-queue-file14d.tmp chmod u+w test-queue-file14d.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -395,7 +400,8 @@ cleanup_milter_test14d: cleanup_milter test-queue-file14 cleanup_milter.in14d \ rm -f test-queue-file14d.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test14e: cleanup_milter test-queue-file14 cleanup_milter.in14e \ - cleanup_milter.ref14e1 ../postcat/postcat cleanup_milter.ref14e2 + cleanup_milter.ref14e1 ../postcat/postcat cleanup_milter.ref14e2 \ + cleanup_milter.reg14e cp test-queue-file14 test-queue-file14e.tmp chmod u+w test-queue-file14e.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -405,7 +411,8 @@ cleanup_milter_test14e: cleanup_milter test-queue-file14 cleanup_milter.in14e \ rm -f test-queue-file14e.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test14f: cleanup_milter test-queue-file14 cleanup_milter.in14f \ - cleanup_milter.ref14f1 ../postcat/postcat cleanup_milter.ref14f2 + cleanup_milter.ref14f1 ../postcat/postcat cleanup_milter.ref14f2 \ + cleanup_milter.reg14f cp test-queue-file14 test-queue-file14f.tmp chmod u+w test-queue-file14f.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -415,7 +422,8 @@ cleanup_milter_test14f: cleanup_milter test-queue-file14 cleanup_milter.in14f \ rm -f test-queue-file14f.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test14g: cleanup_milter test-queue-file14 cleanup_milter.in14g \ - cleanup_milter.ref14g1 ../postcat/postcat cleanup_milter.ref14g2 + cleanup_milter.ref14g1 ../postcat/postcat cleanup_milter.ref14g2 \ + cleanup_milter.reg14g cp test-queue-file14 test-queue-file14g.tmp chmod u+w test-queue-file14g.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -425,7 +433,8 @@ cleanup_milter_test14g: cleanup_milter test-queue-file14 cleanup_milter.in14g \ rm -f test-queue-file14g.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15a: cleanup_milter test-queue-file15 cleanup_milter.in15a \ - cleanup_milter.ref15a1 ../postcat/postcat cleanup_milter.ref15a2 + cleanup_milter.ref15a1 ../postcat/postcat cleanup_milter.ref15a2 \ + cleanup_milter.reg15a cp test-queue-file15 test-queue-file15a.tmp chmod u+w test-queue-file15a.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -435,7 +444,8 @@ cleanup_milter_test15a: cleanup_milter test-queue-file15 cleanup_milter.in15a \ rm -f test-queue-file15a.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15b: cleanup_milter test-queue-file15 cleanup_milter.in15b \ - cleanup_milter.ref15b1 ../postcat/postcat cleanup_milter.ref15b2 + cleanup_milter.ref15b1 ../postcat/postcat cleanup_milter.ref15b2 \ + cleanup_milter.reg15b cp test-queue-file15 test-queue-file15b.tmp chmod u+w test-queue-file15b.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -445,7 +455,8 @@ cleanup_milter_test15b: cleanup_milter test-queue-file15 cleanup_milter.in15b \ rm -f test-queue-file15b.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15c: cleanup_milter test-queue-file15 cleanup_milter.in15c \ - cleanup_milter.ref15c1 ../postcat/postcat cleanup_milter.ref15c2 + cleanup_milter.ref15c1 ../postcat/postcat cleanup_milter.ref15c2 \ + cleanup_milter.reg15c cp test-queue-file15 test-queue-file15c.tmp chmod u+w test-queue-file15c.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -455,7 +466,8 @@ cleanup_milter_test15c: cleanup_milter test-queue-file15 cleanup_milter.in15c \ rm -f test-queue-file15c.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15d: cleanup_milter test-queue-file15 cleanup_milter.in15d \ - cleanup_milter.ref15d1 ../postcat/postcat cleanup_milter.ref15d2 + cleanup_milter.ref15d1 ../postcat/postcat cleanup_milter.ref15d2 \ + cleanup_milter.reg15d cp test-queue-file15 test-queue-file15d.tmp chmod u+w test-queue-file15d.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -465,7 +477,8 @@ cleanup_milter_test15d: cleanup_milter test-queue-file15 cleanup_milter.in15d \ rm -f test-queue-file15d.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15e: cleanup_milter test-queue-file15 cleanup_milter.in15e \ - cleanup_milter.ref15e1 ../postcat/postcat cleanup_milter.ref15e2 + cleanup_milter.ref15e1 ../postcat/postcat cleanup_milter.ref15e2 \ + cleanup_milter.reg15e cp test-queue-file15 test-queue-file15e.tmp chmod u+w test-queue-file15e.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -475,7 +488,8 @@ cleanup_milter_test15e: cleanup_milter test-queue-file15 cleanup_milter.in15e \ rm -f test-queue-file15e.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15f: cleanup_milter test-queue-file15 cleanup_milter.in15f \ - cleanup_milter.ref15f1 ../postcat/postcat cleanup_milter.ref15f2 + cleanup_milter.ref15f1 ../postcat/postcat cleanup_milter.ref15f2 \ + cleanup_milter.reg15f cp test-queue-file15 test-queue-file15f.tmp chmod u+w test-queue-file15f.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -485,7 +499,8 @@ cleanup_milter_test15f: cleanup_milter test-queue-file15 cleanup_milter.in15f \ rm -f test-queue-file15f.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15g: cleanup_milter test-queue-file15 cleanup_milter.in15g \ - cleanup_milter.ref15g1 ../postcat/postcat cleanup_milter.ref15g2 + cleanup_milter.ref15g1 ../postcat/postcat cleanup_milter.ref15g2 \ + cleanup_milter.reg15g cp test-queue-file15 test-queue-file15g.tmp chmod u+w test-queue-file15g.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -495,7 +510,8 @@ cleanup_milter_test15g: cleanup_milter test-queue-file15 cleanup_milter.in15g \ rm -f test-queue-file15g.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15h: cleanup_milter test-queue-file15 cleanup_milter.in15h \ - cleanup_milter.ref15h1 ../postcat/postcat cleanup_milter.ref15h2 + cleanup_milter.ref15h1 ../postcat/postcat cleanup_milter.ref15h2 \ + cleanup_milter.reg15h cp test-queue-file15 test-queue-file15h.tmp chmod u+w test-queue-file15h.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -505,7 +521,8 @@ cleanup_milter_test15h: cleanup_milter test-queue-file15 cleanup_milter.in15h \ rm -f test-queue-file15h.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 cleanup_milter_test15i: cleanup_milter test-queue-file15 cleanup_milter.in15i \ - cleanup_milter.ref15i1 ../postcat/postcat cleanup_milter.ref15i2 + cleanup_milter.ref15i1 ../postcat/postcat cleanup_milter.ref15i2 \ + cleanup_milter.reg15i cp test-queue-file15 test-queue-file15i.tmp chmod u+w test-queue-file15i.tmp $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 @@ -514,6 +531,26 @@ cleanup_milter_test15i: cleanup_milter test-queue-file15 cleanup_milter.in15i \ diff cleanup_milter.ref15i2 cleanup_milter.tmp2 rm -f test-queue-file15i.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 +cleanup_milter_test16a: cleanup_milter test-queue-file16 cleanup_milter.in16a \ + cleanup_milter.ref16a1 ../postcat/postcat cleanup_milter.ref16a2 + cp test-queue-file16 test-queue-file16a.tmp + chmod u+w test-queue-file16a.tmp + $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref16a1 cleanup_milter.tmp1 + $(SHLIB_ENV) ../postcat/postcat -ov test-queue-file16a.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref16a2 cleanup_milter.tmp2 + rm -f test-queue-file16a.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + +cleanup_milter_test16b: cleanup_milter test-queue-file16 cleanup_milter.in16b \ + cleanup_milter.ref16b1 ../postcat/postcat cleanup_milter.ref16b2 + cp test-queue-file16 test-queue-file16b.tmp + chmod u+w test-queue-file16b.tmp + $(SHLIB_ENV) ./cleanup_milter cleanup_milter.tmp1 + diff cleanup_milter.ref16b1 cleanup_milter.tmp1 + $(SHLIB_ENV) ../postcat/postcat -ov test-queue-file16b.tmp 2>/dev/null >cleanup_milter.tmp2 + diff cleanup_milter.ref16b2 cleanup_milter.tmp2 + rm -f test-queue-file16b.tmp cleanup_milter.tmp1 cleanup_milter.tmp2 + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index a18c3cdaa..9bd7f1b87 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -62,6 +62,7 @@ typedef struct CLEANUP_STATE { char *return_receipt; /* return-receipt address */ char *errors_to; /* errors-to address */ ARGV *auto_hdrs; /* MTA's own header(s) */ + ARGV *hbc_rcpt; /* header/body checks BCC addresses */ int flags; /* processing options, status flags */ int qmgr_opts; /* qmgr processing options */ int errs; /* any badness experienced */ @@ -115,7 +116,6 @@ typedef struct CLEANUP_STATE { VSTRING *milter_err_text; /* milter call-back reply */ HBC_CHECKS *milter_hbc_checks; /* Milter header checks */ VSTRING *milter_hbc_reply; /* Milter header checks reply */ - VSTRING *milter_orcpt_buf; /* add_rcpt_par() orcpt */ /* * Support for Milter body replacement requests. diff --git a/postfix/src/cleanup/cleanup_extracted.c b/postfix/src/cleanup/cleanup_extracted.c index 81bca0858..e6c21227f 100644 --- a/postfix/src/cleanup/cleanup_extracted.c +++ b/postfix/src/cleanup/cleanup_extracted.c @@ -306,6 +306,21 @@ void cleanup_extracted_finish(CLEANUP_STATE *state) && state->recip != 0 && *var_always_bcc) cleanup_addr_bcc(state, var_always_bcc); + /* + * Flush non-Milter header/body_checks BCC recipients. Clear hbc_rcpt + * so that it can be used for other purposes. + */ + if (state->hbc_rcpt) { + if (CLEANUP_OUT_OK(state) && state->recip != 0) { + char **cpp; + + for (cpp = state->hbc_rcpt->argv; *cpp; cpp++) + cleanup_addr_bcc(state, *cpp); + } + argv_free(state->hbc_rcpt); + state->hbc_rcpt = 0; + } + /* * Terminate the extracted segment. */ diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index a233b0220..aefd2ff57 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -425,6 +425,19 @@ static const char *cleanup_act(CLEANUP_STATE *state, char *context, } return (buf); } + if (STREQUAL(value, "BCC", command_len)) { + if (strchr(optional_text, '@') == 0) { + msg_warn("bad BCC address \"%s\" in %s map -- " + "need user@domain", + optional_text, map_class); + } else { + if (state->hbc_rcpt == 0) + state->hbc_rcpt = argv_alloc(1); + argv_add(state->hbc_rcpt, optional_text, (char *) 0); + cleanup_act_log(state, "bcc", context, buf, optional_text); + } + return (buf); + } /* Allow and ignore optional text after the action. */ if (STREQUAL(value, "IGNORE", command_len)) diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index 2894fa011..d3d8fde53 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -216,6 +216,7 @@ /*#define msg_verbose 2*/ static void cleanup_milter_set_error(CLEANUP_STATE *, int); +static const char *cleanup_add_rcpt_par(void *, const char *, const char *); #define STR(x) vstring_str(x) #define LEN(x) VSTRING_LEN(x) @@ -301,6 +302,18 @@ static char *cleanup_milter_hbc_extend(void *context, const char *command, if ((state->flags & CLEANUP_FLAG_FILTER_ALL) == 0) return ((char *) buf); + if (STREQUAL(command, "BCC", cmd_len)) { + if (strchr(optional_text, '@') == 0) { + msg_warn("bad BCC address \"%s\" in %s map -- " + "need user@domain", + optional_text, VAR_MILT_HEAD_CHECKS); + } else { + cleanup_milter_hbc_log(context, "bcc", where, buf, optional_text); + /* Caller checks state error flags. */ + (void) cleanup_add_rcpt_par(state, optional_text, ""); + } + return ((char *) buf); + } if (STREQUAL(command, "REJECT", cmd_len)) { const CLEANUP_STAT_DETAIL *detail; @@ -616,14 +629,22 @@ static const char *cleanup_add_header(void *context, const char *name, /* * Return early when Milter header checks request that this header record - * be dropped. + * be dropped, or that the message is discarded. Note: CLEANUP_OUT_OK() + * tests CLEANUP_FLAG_DISCARD. We don't want to report the latter as an + * error. */ buf = vstring_alloc(100); vstring_sprintf(buf, "%s:%s%s", name, space, value); - if (state->milter_hbc_checks - && cleanup_milter_header_checks(state, buf) == 0) { - vstring_free(buf); - return (0); + if (state->milter_hbc_checks) { + if (cleanup_milter_header_checks(state, buf) == 0 + || (state->flags & CLEANUP_FLAG_DISCARD)) { + vstring_free(buf); + return (0); + } + if (CLEANUP_OUT_OK(state) == 0) { + vstring_free(buf); + return (cleanup_milter_error(state, 0)); + } } /* @@ -1394,7 +1415,7 @@ static const char *cleanup_chg_from(void *context, const char *ext_from, static const char *cleanup_add_rcpt_par(void *context, const char *ext_rcpt, const char *esmtp_args) { - const char *myname = "cleanup_add_rcpt"; + const char *myname = "cleanup_add_rcpt_par"; CLEANUP_STATE *state = (CLEANUP_STATE *) context; off_t new_rcpt_offset; off_t reverse_ptr_offset; @@ -1402,6 +1423,7 @@ static const char *cleanup_add_rcpt_par(void *context, const char *ext_rcpt, TOK822 *tree; TOK822 *tp; VSTRING *int_rcpt_buf; + VSTRING *orcpt_buf = 0; ARGV *esmtp_argv; int dsn_notify = 0; const char *dsn_orcpt_info = 0; @@ -1410,39 +1432,8 @@ static const char *cleanup_add_rcpt_par(void *context, const char *ext_rcpt, const char *arg; const char *arg_val; - if (esmtp_args[0]) { - esmtp_argv = argv_split(esmtp_args, " "); - for (i = 0; i < esmtp_argv->argc; ++i) { - arg = esmtp_argv->argv[i]; - if (strncasecmp(arg, "NOTIFY=", 7) == 0) { /* RFC 3461 */ - if (dsn_notify || (dsn_notify = dsn_notify_mask(arg + 7)) == 0) - msg_warn("%s: Bad NOTIFY parameter from MILTER: \"%.100s\"", - state->queue_id, arg); - } else if (strncasecmp(arg, "ORCPT=", 6) == 0) { /* RFC 3461 */ - if (state->milter_orcpt_buf == 0) - state->milter_orcpt_buf = vstring_alloc(100); - if (dsn_orcpt_info - || (type_len = strcspn(arg_val = arg + 6, ";")) == 0 - || (arg_val)[type_len] != ';' - || xtext_unquote_append( - vstring_sprintf(state->milter_orcpt_buf, - "%.*s;", (int) type_len, - arg_val), - arg_val + type_len + 1) == 0) { - msg_warn("%s: Bad ORCPT parameter from MILTER: \"%.100s\"", - state->queue_id, arg); - } else { - dsn_orcpt_info = STR(state->milter_orcpt_buf); - } - } else { - msg_warn("%s: ignoring ESMTP argument from MILTER: \"%.100s\"", - state->queue_id, arg); - } - } - argv_free(esmtp_argv); - } if (msg_verbose) - msg_info("%s: \"%s\"", myname, ext_rcpt); + msg_info("%s: \"%s\" \"%s\"", myname, ext_rcpt, esmtp_args); /* * To simplify implementation, the cleanup server writes a dummy @@ -1471,6 +1462,43 @@ static const char *cleanup_add_rcpt_par(void *context, const char *ext_rcpt, return (cleanup_milter_error(state, errno)); } + /* + * Parse ESMTP parameters. XXX UTF8SMTP don't assume ORCPT is xtext. + */ + if (esmtp_args[0]) { + esmtp_argv = argv_split(esmtp_args, " "); + for (i = 0; i < esmtp_argv->argc; ++i) { + arg = esmtp_argv->argv[i]; + if (strncasecmp(arg, "NOTIFY=", 7) == 0) { /* RFC 3461 */ + if (dsn_notify || (dsn_notify = dsn_notify_mask(arg + 7)) == 0) + msg_warn("%s: Bad NOTIFY parameter from Milter or " + "header/body_checks: \"%.100s\"", + state->queue_id, arg); + } else if (strncasecmp(arg, "ORCPT=", 6) == 0) { /* RFC 3461 */ + if (orcpt_buf == 0) + orcpt_buf = vstring_alloc(100); + if (dsn_orcpt_info + || (type_len = strcspn(arg_val = arg + 6, ";")) == 0 + || (arg_val)[type_len] != ';' + || xtext_unquote_append(vstring_sprintf(orcpt_buf, + "%.*s;", (int) type_len, + arg_val), + arg_val + type_len + 1) == 0) { + msg_warn("%s: Bad ORCPT parameter from Milter or " + "header/body_checks: \"%.100s\"", + state->queue_id, arg); + } else { + dsn_orcpt_info = STR(orcpt_buf); + } + } else { + msg_warn("%s: ignoring ESMTP argument from Milter or " + "header/body_checks: \"%.100s\"", + state->queue_id, arg); + } + } + argv_free(esmtp_argv); + } + /* * Transform recipient from external form to internal form. This also * removes the enclosing <>, if present. @@ -1485,21 +1513,35 @@ static const char *cleanup_add_rcpt_par(void *context, const char *ext_rcpt, tok822_internalize(int_rcpt_buf, tp->head, TOK822_STR_DEFL); addr_count += 1; } else { - msg_warn("%s: Milter request to add multi-recipient: \"%s\"", + msg_warn("%s: Milter or header/body_checks request to " + "add multi-recipient: \"%s\"", state->queue_id, ext_rcpt); break; } } } tok822_free_tree(tree); - cleanup_addr_bcc_dsn(state, STR(int_rcpt_buf), dsn_orcpt_info, - dsn_notify ? dsn_notify : DEF_DSN_NOTIFY); - vstring_free(int_rcpt_buf); - if (addr_count == 0) { + if (addr_count != 0) + cleanup_addr_bcc_dsn(state, STR(int_rcpt_buf), dsn_orcpt_info, + dsn_notify ? dsn_notify : DEF_DSN_NOTIFY); + else msg_warn("%s: ignoring attempt from Milter to add null recipient", state->queue_id); + vstring_free(int_rcpt_buf); + if (orcpt_buf) + vstring_free(orcpt_buf); + + /* + * Don't update the queue file when we did not write a recipient record + * (malformed or duplicate BCC recipient). + */ + if (vstream_ftell(state->dst) == new_rcpt_offset) return (CLEANUP_OUT_OK(state) ? 0 : cleanup_milter_error(state, 0)); - } + + /* + * Follow the recipient with a "reverse" pointer to the old recipient + * append target. + */ if ((reverse_ptr_offset = vstream_ftell(state->dst)) < 0) { msg_warn("%s: vstream_ftell file %s: %m", myname, cleanup_path); return (cleanup_milter_error(state, errno)); @@ -2431,7 +2473,6 @@ int main(int unused_argc, char **argv) msg_info("ignoring: %s %s %s", argv->argv[0], argv->argc > 1 ? argv->argv[1] : "", argv->argc > 2 ? argv->argv[2] : ""); - continue; } else if (strcmp(argv->argv[0], "add_header") == 0) { if (argv->argc < 2) { msg_warn("bad add_header argument count: %d", argv->argc); @@ -2533,6 +2574,8 @@ int main(int unused_argc, char **argv) msg_info("errs = %s", cleanup_strerror(state->errs)); } cleanup_state_free(state); + if (*var_milt_head_checks) + myfree(var_milt_head_checks); return (0); } diff --git a/postfix/src/cleanup/cleanup_milter.in16a b/postfix/src/cleanup/cleanup_milter.in16a new file mode 100644 index 000000000..3b7da4456 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.in16a @@ -0,0 +1,10 @@ +#verbose on +open test-queue-file16a.tmp + +# Test the BCC action in milter_header_checks. + +header_checks regexp:cleanup_milter.reg16a +add_header X-SPAM-FLAG NO +add_header X-SPAM-FLAG YES + +close diff --git a/postfix/src/cleanup/cleanup_milter.in16b b/postfix/src/cleanup/cleanup_milter.in16b new file mode 100644 index 000000000..57f6e2467 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.in16b @@ -0,0 +1,12 @@ +#verbose on +open test-queue-file16b.tmp + +# Test the add_rcpt_par action + +add_rcpt_par foo@example.com notify=never +add_rcpt_par foo@example.com notify=never +add_rcpt bar@example.com +add_rcpt_par bar@example.com orcpt=rfc822;orig-bar@example.com +add_rcpt_par bar@example.com notify=delay + +close diff --git a/postfix/src/cleanup/cleanup_milter.ref16a1 b/postfix/src/cleanup/cleanup_milter.ref16a1 new file mode 100644 index 000000000..a1d30b0f1 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref16a1 @@ -0,0 +1,3 @@ +./cleanup_milter: NOQUEUE: milter-header-bcc: header X-SPAM-FLAG: NO from client_name[client_addr]; from= to=: bar@example.com +./cleanup_milter: NOQUEUE: milter-header-bcc: header X-SPAM-FLAG: YES from client_name[client_addr]; from= to=: foo@example.com +./cleanup_milter: flags = enable_header_body_filter enable_milters diff --git a/postfix/src/cleanup/cleanup_milter.ref16a2 b/postfix/src/cleanup/cleanup_milter.ref16a2 new file mode 100644 index 000000000..3b0edd27c --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref16a2 @@ -0,0 +1,37 @@ +*** ENVELOPE RECORDS test-queue-file16a.tmp *** + 0 message_size: 343 215 1 0 343 0 + 97 message_arrival_time: Tue Nov 18 16:43:29 2014 + 116 create_time: Tue Nov 18 16:43:29 2014 + 140 named_attribute: rewrite_context=local + 163 sender_fullname: Wietse Venema + 178 sender: user@example.com + 196 pointer_record: 654 + 654 original_recipient: bar@example.com + 671 recipient: bar@example.com + 688 pointer_record: 739 + 739 original_recipient: foo@example.com + 756 recipient: foo@example.com + 773 pointer_record: 213 + 213 *** MESSAGE CONTENTS test-queue-file16a.tmp *** + 215 regular_text: Received: by host.example.com (Postfix, from userid 1001) + 274 regular_text: id 663E22172797; Tue, 18 Nov 2014 16:43:29 -0500 (EST) + 331 regular_text: To: user@example.com + 353 regular_text: Subject: test + 368 padding: 0 + 371 regular_text: Message-Id: <20141118214329.663E22172797@host.example.com> + 431 regular_text: Date: Tue, 18 Nov 2014 16:43:29 -0500 (EST) + 476 regular_text: From: user@example.com (Wietse Venema) + 516 pointer_record: 705 + 705 regular_text: X-SPAM-FLAG: NO + 722 pointer_record: 790 + 790 regular_text: X-SPAM-FLAG: YES + 808 pointer_record: 533 + 533 regular_text: + 535 regular_text: test + 541 pointer_record: 0 + 558 *** HEADER EXTRACTED test-queue-file16a.tmp *** + 560 pointer_record: 0 + 577 named_attribute: dsn_orig_rcpt=rfc822;user@example.com + 616 original_recipient: user@example.com + 634 recipient: user@example.com + 652 *** MESSAGE FILE END test-queue-file16a.tmp *** diff --git a/postfix/src/cleanup/cleanup_milter.ref16b1 b/postfix/src/cleanup/cleanup_milter.ref16b1 new file mode 100644 index 000000000..eab5a83d6 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref16b1 @@ -0,0 +1 @@ +./cleanup_milter: flags = enable_header_body_filter enable_milters diff --git a/postfix/src/cleanup/cleanup_milter.ref16b2 b/postfix/src/cleanup/cleanup_milter.ref16b2 new file mode 100644 index 000000000..2ae8719e5 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.ref16b2 @@ -0,0 +1,42 @@ +*** ENVELOPE RECORDS test-queue-file16b.tmp *** + 0 message_size: 343 215 1 0 343 0 + 97 message_arrival_time: Tue Nov 18 16:43:29 2014 + 116 create_time: Tue Nov 18 16:43:29 2014 + 140 named_attribute: rewrite_context=local + 163 sender_fullname: Wietse Venema + 178 sender: user@example.com + 196 pointer_record: 654 + 654 named_attribute: notify_flags=1 + 670 original_recipient: foo@example.com + 687 recipient: foo@example.com + 704 pointer_record: 721 + 721 original_recipient: bar@example.com + 738 recipient: bar@example.com + 755 pointer_record: 772 + 772 named_attribute: dsn_orig_rcpt=rfc822;orig-bar@example.com + 815 original_recipient: bar@example.com + 832 recipient: bar@example.com + 849 pointer_record: 866 + 866 named_attribute: notify_flags=8 + 882 original_recipient: bar@example.com + 899 recipient: bar@example.com + 916 pointer_record: 213 + 213 *** MESSAGE CONTENTS test-queue-file16b.tmp *** + 215 regular_text: Received: by host.example.com (Postfix, from userid 1001) + 274 regular_text: id 663E22172797; Tue, 18 Nov 2014 16:43:29 -0500 (EST) + 331 regular_text: To: user@example.com + 353 regular_text: Subject: test + 368 padding: 0 + 371 regular_text: Message-Id: <20141118214329.663E22172797@host.example.com> + 431 regular_text: Date: Tue, 18 Nov 2014 16:43:29 -0500 (EST) + 476 regular_text: From: user@example.com (Wietse Venema) + 516 pointer_record: 0 + 533 regular_text: + 535 regular_text: test + 541 pointer_record: 0 + 558 *** HEADER EXTRACTED test-queue-file16b.tmp *** + 560 pointer_record: 0 + 577 named_attribute: dsn_orig_rcpt=rfc822;user@example.com + 616 original_recipient: user@example.com + 634 recipient: user@example.com + 652 *** MESSAGE FILE END test-queue-file16b.tmp *** diff --git a/postfix/src/cleanup/cleanup_milter.reg16a b/postfix/src/cleanup/cleanup_milter.reg16a new file mode 100644 index 000000000..674aa5d70 --- /dev/null +++ b/postfix/src/cleanup/cleanup_milter.reg16a @@ -0,0 +1,2 @@ +/YES/ bcc foo@example.com +/NO/ bcc bar@example.com diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index e061921ff..b0bae0495 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -79,6 +79,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src) state->return_receipt = 0; state->errors_to = 0; state->auto_hdrs = argv_alloc(1); + state->hbc_rcpt = 0; state->flags = 0; state->qmgr_opts = 0; state->errs = 0; @@ -102,7 +103,6 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src) state->append_meta_pt_target = -1; state->milter_hbc_checks = 0; state->milter_hbc_reply = 0; - state->milter_orcpt_buf = 0; state->rcpt_count = 0; state->reason = 0; state->smtp_reply = 0; @@ -154,6 +154,8 @@ void cleanup_state_free(CLEANUP_STATE *state) if (state->errors_to) myfree(state->errors_to); argv_free(state->auto_hdrs); + if (state->hbc_rcpt) + argv_free(state->hbc_rcpt); if (state->queue_name) myfree(state->queue_name); if (state->queue_id) @@ -163,8 +165,6 @@ void cleanup_state_free(CLEANUP_STATE *state) myfree(state->reason); if (state->smtp_reply) myfree(state->smtp_reply); - if (state->milter_orcpt_buf) - vstring_free(state->milter_orcpt_buf); nvtable_free(state->attr); if (state->mime_state) mime_state_free(state->mime_state); diff --git a/postfix/src/cleanup/test-queue-file16 b/postfix/src/cleanup/test-queue-file16 new file mode 100644 index 0000000000000000000000000000000000000000..3f7c5f3e61beb1d2a6e0148b77e1c3b049fac16b GIT binary patch literal 654 zcma)(%}>HW5XCX^;(@4%dY+30B9NVJX=xDyQAj+n8fes8Q_7$MI1>sf z+S1&G**AR3M7J^>P