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 000000000..3f7c5f3e6
Binary files /dev/null and b/postfix/src/cleanup/test-queue-file16 differ
diff --git a/postfix/src/global/attr_override.h b/postfix/src/global/attr_override.h
index 7da63b5af..6b7828dee 100644
--- a/postfix/src/global/attr_override.h
+++ b/postfix/src/global/attr_override.h
@@ -16,8 +16,6 @@
*/
extern void attr_override(char *, const char *, const char *,...);
-typedef const char *CONST_CHAR_STAR;
-
typedef struct {
const char *name;
CONST_CHAR_STAR *target;
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index f93030bd1..d2c90f831 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20141118"
+#define MAIL_RELEASE_DATE "20141119"
#define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT
diff --git a/postfix/src/util/base64_code.c b/postfix/src/util/base64_code.c
index 797f3cbc1..c7d745ecb 100644
--- a/postfix/src/util/base64_code.c
+++ b/postfix/src/util/base64_code.c
@@ -201,55 +201,25 @@ VSTRING *base64_decode_opt(VSTRING *result, const char *in, ssize_t len,
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
-#define TESXT "this is a test!"
-
int main(int unused_argc, char **unused_argv)
{
VSTRING *b1 = vstring_alloc(1);
VSTRING *b2 = vstring_alloc(1);
- char *test = TESXT;
- char *test2 = TESXT TESXT;
+ char test[256];
+ int n;
-#define DECODE(b,x,l) { \
- if (base64_decode((b),(x),(l)) == 0) \
- msg_panic("bad base64: %s", (x)); \
- }
-#define VERIFY(b,t) { \
- if (strcmp((b), (t)) != 0) \
- msg_panic("bad test: %s", (b)); \
- }
-
- base64_encode(b1, test, strlen(test));
- DECODE(b2, STR(b1), LEN(b1));
- VERIFY(STR(b2), test);
-
- base64_encode(b1, test, strlen(test));
- base64_encode(b2, STR(b1), LEN(b1));
- base64_encode(b1, STR(b2), LEN(b2));
- DECODE(b2, STR(b1), LEN(b1));
- DECODE(b1, STR(b2), LEN(b2));
- DECODE(b2, STR(b1), LEN(b1));
- VERIFY(STR(b2), test);
-
- base64_encode(b1, test, strlen(test));
- base64_encode(b2, STR(b1), LEN(b1));
- base64_encode(b1, STR(b2), LEN(b2));
- base64_encode(b2, STR(b1), LEN(b1));
- base64_encode(b1, STR(b2), LEN(b2));
- DECODE(b2, STR(b1), LEN(b1));
- DECODE(b1, STR(b2), LEN(b2));
- DECODE(b2, STR(b1), LEN(b1));
- DECODE(b1, STR(b2), LEN(b2));
- DECODE(b2, STR(b1), LEN(b1));
- VERIFY(STR(b2), test);
-
- base64_encode(b1, test, strlen(test));
- base64_encode_opt(b1, test, strlen(test), BASE64_FLAG_APPEND);
- DECODE(b2, STR(b1), LEN(b1));
- VERIFY(STR(b2), test2);
-
- vstring_free(b1);
- vstring_free(b2);
+ for (n = 0; n < sizeof(test); n++)
+ test[n] = n;
+ base64_encode(b1, test, sizeof(test));
+ if (base64_decode(b2, STR(b1), LEN(b1)) == 0)
+ msg_panic("bad base64: %s", STR(b1));
+ if (LEN(b2) != sizeof(test))
+ msg_panic("bad decode length: %ld != %ld",
+ (long) LEN(b2), (long) sizeof(test));
+ for (n = 0; n < sizeof(test); n++)
+ if (STR(b2)[n] != test[n])
+ msg_panic("bad decode value %d != %d",
+ (unsigned char) STR(b2)[n], (unsigned char) test[n]);
return (0);
}
diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h
index bfd6f0549..266f5cce4 100644
--- a/postfix/src/util/sys_defs.h
+++ b/postfix/src/util/sys_defs.h
@@ -1693,6 +1693,14 @@ typedef int pid_t;
#define UINT32_SIZE 4
#define UINT16_SIZE 2
+ /*
+ * For the sake of clarity.
+ */
+#ifndef HAVE_CONST_CHAR_STAR
+typedef const char *CONST_CHAR_STAR;
+
+#endif
+
/*
* Safety. On some systems, ctype.h misbehaves with non-ASCII or negative
* characters. More importantly, Postfix uses the ISXXX() macros to ensure