From: Wietse Venema Date: Wed, 16 Apr 2003 05:00:00 +0000 (-0500) Subject: postfix-2.0.8-20030416 X-Git-Tag: v2.1-RC1-20040331~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=310a8503ae3ff13a6d64f934f2444fb45585130b;p=thirdparty%2Fpostfix.git postfix-2.0.8-20030416 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index cd42b54bb..e1dd7986d 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -150,6 +150,7 @@ -TSMTP_RESP -TSMTP_SESSION -TSMTP_STATE +-TSM_STATE -TSOCKADDR_SIZE -TSPAWN_ATTR -TSTRING_LIST diff --git a/postfix/HISTORY b/postfix/HISTORY index 6f0545601..08dc03abf 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -7967,11 +7967,40 @@ Apologies for any names omitted. client sockets. This puts less strain on local system resources. -10030415 +20030415 Cleanup: the file system clock drift detection code now runs only for incoming mail. File: global/mail_stream.c. +20030416 + + Bugfix: missing output flush when message content did not + end in newline while converting 8-bit to 7-bit mail. File: + smtp/smtp_proto.c. + + Cleanup: auto-bcc recipients are now added in one place + (the cleanup server) instead of by individual front-end + servers (pickup, smtpd, qmqpd). This makes it easier to + add auto-bcc features that trigger on sender or recipient + addresses. + + Cleanup: "sendmail -t" (recipients from headers) is now + implemented by the sendmail command instead of by the + cleanup server. This means that the extract_recipient_limit + configuration parameter is no longer needed. Files: + sendmail/sendmail.c, cleanup/cleanup_message.c, + cleanup/cleanup_extracted.c. + + Compatibility: "sendmail -t" (recipients from headers) now + accepts command-line recipients instead of complaining. + The extracted header recipients are added to the command-line + recipients. + + Feature: sender/recipient_bcc_maps. These are indexed by + sender/recipient address and are examined when mail enters + from outside of Postfix. Files: cleanup/cleanup_addr.c. + cleanup/cleanup_envelope.c cleanup/cleanup_extracted.c. + Open problems: Low: smtp-source may block when sending large test messages. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 55fab1989..2ea6bc9f4 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -22,7 +22,20 @@ snapshot release). Patches change the patchlevel and the release date. Snapshots change only the release date, unless they include the same bugfixes as a patch release. -Incompatible changes with Postfix snapshot 2.0.8-20040414 +Incompatible changes with Postfix snapshot 2.0.8-2004XXXX +========================================================= + +"sendmail -t" no longer complains when recipients are given on the +command line. Instead, it now adds recipients from headers to the +command-line recipients. + +Major changes with Postfix snapshot 2.0.8-2004XXXX +================================================== + +sender_bcc_maps and recipient_bcc_maps, after a reorganization +of how auto-bcc recipients are added. + +Incompatible changes with Postfix snapshot 2.0.8-20040415 ========================================================= Too many people mess up their net/mask patterns, causing open @@ -31,7 +44,7 @@ net/mask pattern with a non-zero host portion (for example, 168.100.189.2/28), and suggest to specify the proper net/mask pattern instead (for example, 168.100.189.0/28). -Major changes with Postfix snapshot 2.0.8-20040414 +Major changes with Postfix snapshot 2.0.8-20040415 ================================================== PostgreSQL table lookups. Specify "pgsql:/file/name" where "/file/name" diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf index 0dca7c8e9..1ec322d20 100644 --- a/postfix/conf/sample-misc.cf +++ b/postfix/conf/sample-misc.cf @@ -406,6 +406,19 @@ recipient_delimiter = #propagate_unmatched_extensions = canonical, virtual, alias, forward, include #propagate_unmatched_extensions = canonical, virtual +# The recipient_bcc_maps parameter specifies optional lookup tables +# with automatic BCC recipients per recipient address. Each table +# entry should contain exactly one recipient address. The BCC address +# is added when mail enters from outside of Postfix. +# +# By default, this feature is disabled. +# +# Specify the types and names of databases to use. After change, +# run "postmap /etc/postfix/relocated", then "postfix reload". +# +#recipient_bcc_maps = hash:/etc/postfix/recipient_bcc +recipient_bcc_maps = + # The relayhost parameter specifies the default host to send mail to # when no entry is matched in the optional transport(5) table. When # no relayhost is given, mail is routed directly to the destination. @@ -453,6 +466,19 @@ relocated_maps = # resolve_dequoted_address = no +# The sender_bcc_maps parameter specifies optional lookup tables with +# automatic BCC recipients per sender address. Each table entry +# should contain exactly one recipient address. The BCC address is +# added when mail enters from outside of Postfix. +# +# By default, this feature is disabled. +# +# Specify the types and names of databases to use. After change, +# run "postmap /etc/postfix/relocated", then "postfix reload". +# +#sender_bcc_maps = hash:/etc/postfix/sender_bcc +sender_bcc_maps = + # The syslog_facility parameter controls where Postfix logging is # sent by the syslog daemon. Specify a logging facility as defined # in syslog.conf(5). The default logging facility is "mail". diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index 287181429..d6a5eecda 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -143,6 +143,16 @@ CLEANUP(8) CLEANUP(8) Address to send a copy of each message that enters the system. + sender_bcc_maps + Automatic BCC recipient lookup table, indexed by + sender address. The BCC address is added when the + message enters the system. + + recipient_bcc_maps + Automatic BCC recipient lookup table, indexed by + recipient address. The BCC address is added when + the message enters the system. + hopcount_limit Limit the number of Received: message headers. @@ -204,17 +214,13 @@ CLEANUP(8) CLEANUP(8) when the message arrival rate exceeds the message delivery rate. - extract_recipient_limit - Limit the amount of recipients extracted from mes- - sage headers. - virtual_alias_expansion_limit - Limit the number of actual recipients produced by - virtual alias expansion from each original recipi- + Limit the number of actual recipients produced by + virtual alias expansion from each original recipi- ent. virtual_alias_recursion_limit - Limit the recursion depth of virtual alias expan- + Limit the recursion depth of virtual alias expan- sion. SEE ALSO @@ -229,7 +235,7 @@ CLEANUP(8) CLEANUP(8) /etc/postfix/virtual*, virtual mapping table 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/pickup.8.html b/postfix/html/pickup.8.html index ba6056e8e..d30fa6544 100644 --- a/postfix/html/pickup.8.html +++ b/postfix/html/pickup.8.html @@ -52,10 +52,6 @@ PICKUP(8) PICKUP(8) transport table. Miscellaneous - always_bcc - Address to send a copy of each message that enters - the system. - queue_directory Top-level directory of the Postfix queue. @@ -66,7 +62,7 @@ PICKUP(8) PICKUP(8) syslogd(8) system logging 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/qmqpd.8.html b/postfix/html/qmqpd.8.html index 9c99eb526..19d36f7ff 100644 --- a/postfix/html/qmqpd.8.html +++ b/postfix/html/qmqpd.8.html @@ -44,19 +44,15 @@ QMQPD(8) QMQPD(8) command after a configuration change. Miscellaneous - always_bcc - Address to send a copy of each message that enters - the system. - debug_peer_level - Increment in verbose logging level when a remote + Increment in verbose logging level when a remote host matches a pattern in the debug_peer_list parameter. debug_peer_list - List of domain or network patterns. When a remote - host matches a pattern, increase the verbose log- - ging level by the amount specified in the + List of domain or network patterns. When a remote + host matches a pattern, increase the verbose log- + ging level by the amount specified in the debug_peer_level parameter. hopcount_limit @@ -67,32 +63,32 @@ QMQPD(8) QMQPD(8) what clients are allowed to use the service. qmqpd_timeout - Limit the time to send a server response and to + Limit the time to send a server response and to receive a client request. soft_bounce - Change hard (D) reject responses into soft (Z) - reject responses. This can be useful for testing + Change hard (D) reject responses into soft (Z) + reject responses. This can be useful for testing purposes. Content inspection controls content_filter - The name of a mail delivery transport that filters + The name of a mail delivery transport that filters mail and that either bounces mail or re-injects the - result back into Postfix. This parameter uses the - same syntax as the right-hand side of a Postfix + result back into Postfix. This parameter uses the + same syntax as the right-hand side of a Postfix transport table. Resource controls line_length_limit - Limit the amount of memory in bytes used for the - handling of partial input lines, and the length of - sender and recipient addresses that are received + Limit the amount of memory in bytes used for the + handling of partial input lines, and the length of + sender and recipient addresses that are received from client. message_size_limit Limit the total size in bytes of a message, includ- - ing on-disk storage for sender and recipient + ing on-disk storage for sender and recipient address information. Tarpitting @@ -107,7 +103,7 @@ QMQPD(8) QMQPD(8) syslogd(8) system logging 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/sendmail.1.html b/postfix/html/sendmail.1.html index 35a140fa8..a5804b223 100644 --- a/postfix/html/sendmail.1.html +++ b/postfix/html/sendmail.1.html @@ -209,9 +209,9 @@ SENDMAIL(1) SENDMAIL(1) This command is not implemented. Use the slower sendmail -q command instead. - -t Extract recipients from message headers. This - requires that no recipients be specified on the - command line. + -t Extract recipients from message headers. These are + added to any recipients specified on the command + line. -v Send an email report of all delivery attempts (mail delivery always happens in the background). When diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index c481f9155..4aca9e81b 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -115,32 +115,28 @@ SMTPD(8) SMTPD(8) restriction. Miscellaneous - always_bcc - Address to send a copy of each message that enters - the system. - authorized_verp_clients Hostnames, domain names and/or addresses of clients that are authorized to use the XVERP extension. debug_peer_level - Increment in verbose logging level when a remote + Increment in verbose logging level when a remote host matches a pattern in the debug_peer_list parameter. debug_peer_list - List of domain or network patterns. When a remote - host matches a pattern, increase the verbose log- - ging level by the amount specified in the + List of domain or network patterns. When a remote + host matches a pattern, increase the verbose log- + ging level by the amount specified in the debug_peer_level parameter. default_verp_delimiters The default VERP delimiter characters that are used - when the XVERP command is specified without + when the XVERP command is specified without explicit delimiters. error_notice_recipient - Recipient of protocol/policy/resource/software + Recipient of protocol/policy/resource/software error notices. hopcount_limit @@ -149,18 +145,18 @@ SMTPD(8) SMTPD(8) notify_classes List of error classes. Of special interest are: - policy When a client violates any policy, mail a + policy When a client violates any policy, mail a transcript of the entire SMTP session to the postmaster. protocol - When a client violates the SMTP protocol or + When a client violates the SMTP protocol or issues an unimplemented command, mail a transcript of the entire SMTP session to the postmaster. smtpd_banner - Text that follows the 220 status code in the SMTP + Text that follows the 220 status code in the SMTP greeting banner. smtpd_expansion_filter @@ -168,57 +164,57 @@ SMTPD(8) SMTPD(8) expansion of rbl template responses and other text. smtpd_recipient_limit - Restrict the number of recipients that the SMTP + Restrict the number of recipients that the SMTP server accepts per message delivery. smtpd_timeout - Limit the time to send a server response and to + Limit the time to send a server response and to receive a client request. soft_bounce - Change hard (5xx) reject responses into soft (4xx) - reject responses. This can be useful for testing + Change hard (5xx) reject responses into soft (4xx) + reject responses. This can be useful for testing purposes. verp_delimiter_filter - The characters that Postfix accepts as VERP delim- + The characters that Postfix accepts as VERP delim- iter characters. Known versus unknown recipients show_user_unknown_table_name - Whether or not to reveal the table name in the - "User unknown" responses. The extra detail makes - trouble shooting easier but also reveals informa- + Whether or not to reveal the table name in the + "User unknown" responses. The extra detail makes + trouble shooting easier but also reveals informa- tion that is nobody elses business. unknown_local_recipient_reject_code The response code when a client specifies a recipi- - ent whose domain matches $mydestination or + ent whose domain matches $mydestination or $inet_interfaces, while $local_recipient_maps is - non-empty and does not list the recipient address + non-empty and does not list the recipient address or address local-part. unknown_relay_recipient_reject_code The response code when a client specifies a recipi- ent whose domain matches $relay_domains, while - $relay_recipient_maps is non-empty and does not + $relay_recipient_maps is non-empty and does not list the recipient address. unknown_virtual_alias_reject_code The response code when a client specifies a recipi- - ent whose domain matches $virtual_alias_domains, - while the recipient is not listed in $vir- + ent whose domain matches $virtual_alias_domains, + while the recipient is not listed in $vir- tual_alias_maps. unknown_virtual_mailbox_reject_code The response code when a client specifies a recipi- - ent whose domain matches $virtual_mailbox_domains, + ent whose domain matches $virtual_mailbox_domains, while the recipient is not listed in $virtual_mail- box_maps. Resource controls line_length_limit - Limit the amount of memory in bytes used for the + Limit the amount of memory in bytes used for the handling of partial input lines. message_size_limit @@ -226,8 +222,8 @@ SMTPD(8) SMTPD(8) ing on-disk storage for envelope information. queue_minfree - Minimal amount of free space in bytes in the queue - file system for the SMTP server to accept any mail + Minimal amount of free space in bytes in the queue + file system for the SMTP server to accept any mail at all. smtpd_history_flush_threshold @@ -242,23 +238,23 @@ SMTPD(8) SMTPD(8) smtpd_soft_error_limit When an SMTP client has made this number of errors, - wait error_count seconds before responding to any + wait error_count seconds before responding to any client request. smtpd_hard_error_limit - Disconnect after a client has made this number of + Disconnect after a client has made this number of errors. smtpd_junk_command_limit Limit the number of times a client can issue a junk - command such as NOOP, VRFY, ETRN or RSET in one - SMTP session before it is penalized with tarpit + command such as NOOP, VRFY, ETRN or RSET in one + SMTP session before it is penalized with tarpit delays. UCE control restrictions parent_domain_matches_subdomains - List of Postfix features that use domain.tld pat- - terns to match sub.domain.tld (as opposed to + List of Postfix features that use domain.tld pat- + terns to match sub.domain.tld (as opposed to requiring .domain.tld patterns). smtpd_client_restrictions @@ -266,19 +262,19 @@ SMTPD(8) SMTPD(8) tem. smtpd_helo_required - Require that clients introduce themselves at the + Require that clients introduce themselves at the beginning of an SMTP session. smtpd_helo_restrictions - Restrict what client hostnames are allowed in HELO + Restrict what client hostnames are allowed in HELO and EHLO commands. smtpd_sender_restrictions - Restrict what sender addresses are allowed in MAIL + Restrict what sender addresses are allowed in MAIL FROM commands. smtpd_recipient_restrictions - Restrict what recipient addresses are allowed in + Restrict what recipient addresses are allowed in RCPT TO commands. smtpd_etrn_restrictions @@ -286,77 +282,77 @@ SMTPD(8) SMTPD(8) mands, and what clients may issue ETRN commands. smtpd_data_restrictions - Restrictions on the DATA command. Currently, the - only restriction that makes sense here is + Restrictions on the DATA command. Currently, the + only restriction that makes sense here is reject_unauth_pipelining. allow_untrusted_routing - Allow untrusted clients to specify addresses with - sender-specified routing. Enabling this opens up - nasty relay loopholes involving trusted backup MX + Allow untrusted clients to specify addresses with + sender-specified routing. Enabling this opens up + nasty relay loopholes involving trusted backup MX hosts. smtpd_restriction_classes - Declares the name of zero or more parameters that - contain a list of UCE restrictions. The names of - these parameters can then be used instead of the + Declares the name of zero or more parameters that + contain a list of UCE restrictions. The names of + these parameters can then be used instead of the restriction lists that they represent. smtpd_null_access_lookup_key - The lookup key to be used in SMTPD access tables - instead of the null sender address. A null sender + The lookup key to be used in SMTPD access tables + instead of the null sender address. A null sender address cannot be looked up. maps_rbl_domains (deprecated) - List of DNS domains that publish the addresses of + List of DNS domains that publish the addresses of blacklisted hosts. This is used with the deprecated reject_maps_rbl restriction. permit_mx_backup_networks - Only domains whose primary MX hosts match the - listed networks are eligible for the per- + Only domains whose primary MX hosts match the + listed networks are eligible for the per- mit_mx_backup feature. relay_domains - Restrict what domains this mail system will relay - mail to. The domains are routed to the delivery + Restrict what domains this mail system will relay + mail to. The domains are routed to the delivery agent specified with the relay_transport setting. UCE control responses access_map_reject_code - Response code when a client violates an access + Response code when a client violates an access database restriction. default_rbl_reply Default template reply when a request is RBL black- - listed. This template is used by the reject_rbl_* - and reject_rhsbl_* restrictions. See also: + listed. This template is used by the reject_rbl_* + and reject_rhsbl_* restrictions. See also: rbl_reply_maps and smtpd_expansion_filter. defer_code - Response code when a client request is rejected by + Response code when a client request is rejected by the defer restriction. invalid_hostname_reject_code - Response code when a client violates the + Response code when a client violates the reject_invalid_hostname restriction. maps_rbl_reject_code Response code when a request is RBL blacklisted. multi_recipient_bounce_reject_code - Response code when a multi-recipient bounce is + Response code when a multi-recipient bounce is blocked. rbl_reply_maps - Table with template responses for RBL blacklisted - requests, indexed by RBL domain name. These tem- + Table with template responses for RBL blacklisted + requests, indexed by RBL domain name. These tem- plates are used by the reject_rbl_* and - reject_rhsbl_* restrictions. See also: + reject_rhsbl_* restrictions. See also: default_rbl_reply and smtpd_expansion_filter. reject_code - Response code when the client matches a reject + Response code when the client matches a reject restriction. relay_domains_reject_code @@ -364,7 +360,7 @@ SMTPD(8) SMTPD(8) mail relay policy. unknown_address_reject_code - Response code when a client violates the + Response code when a client violates the reject_unknown_address restriction. unknown_client_reject_code @@ -373,15 +369,15 @@ SMTPD(8) SMTPD(8) tion. unknown_hostname_reject_code - Response code when a client violates the + Response code when a client violates the reject_unknown_hostname restriction. unverified_sender_reject_code - Response code when a sender address is known to be + Response code when a sender address is known to be undeliverable. unverified_recipient_reject_code - Response code when a recipient address is known to + Response code when a recipient address is known to be undeliverable. SEE ALSO @@ -391,7 +387,7 @@ SMTPD(8) SMTPD(8) syslogd(8) system logging 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/man/man1/sendmail.1 b/postfix/man/man1/sendmail.1 index 6e7f76e6b..e7453eb8d 100644 --- a/postfix/man/man1/sendmail.1 +++ b/postfix/man/man1/sendmail.1 @@ -175,8 +175,8 @@ service. This command is not implemented. Use the slower \fBsendmail -q\fR command instead. .IP \fB-t\fR -Extract recipients from message headers. This requires that no -recipients be specified on the command line. +Extract recipients from message headers. These are added to any +recipients specified on the command line. .IP \fB-v\fR Send an email report of all delivery attempts (mail delivery always happens in the background). When multiple \fB-v\fR diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index fe4360d18..fdadfa4a8 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -130,6 +130,12 @@ from poorly written software. .fi .IP \fBalways_bcc\fR Address to send a copy of each message that enters the system. +.IP \fBsender_bcc_maps\fR +Automatic BCC recipient lookup table, indexed by sender address. +The BCC address is added when the message enters the system. +.IP \fBrecipient_bcc_maps\fR +Automatic BCC recipient lookup table, indexed by recipient address. +The BCC address is added when the message enters the system. .IP \fBhopcount_limit\fR Limit the number of \fBReceived:\fR message headers. .IP \fBundisclosed_recipients_header\fR @@ -172,8 +178,6 @@ Limits the amount of memory in bytes used to process a message header. .IP \fBin_flow_delay\fR Amount of time to pause before accepting a message, when the message arrival rate exceeds the message delivery rate. -.IP \fBextract_recipient_limit\fR -Limit the amount of recipients extracted from message headers. .IP \fBvirtual_alias_expansion_limit\fR Limit the number of actual recipients produced by virtual alias expansion from each original recipient. diff --git a/postfix/man/man8/pickup.8 b/postfix/man/man8/pickup.8 index 199e03055..92c98ae40 100644 --- a/postfix/man/man8/pickup.8 +++ b/postfix/man/man8/pickup.8 @@ -64,8 +64,6 @@ a Postfix transport table. .SH Miscellaneous .ad .fi -.IP \fBalways_bcc\fR -Address to send a copy of each message that enters the system. .IP \fBqueue_directory\fR Top-level directory of the Postfix queue. .SH SEE ALSO diff --git a/postfix/man/man8/qmqpd.8 b/postfix/man/man8/qmqpd.8 index b608249fa..e6308c794 100644 --- a/postfix/man/man8/qmqpd.8 +++ b/postfix/man/man8/qmqpd.8 @@ -56,8 +56,6 @@ a configuration change. .SH Miscellaneous .ad .fi -.IP \fBalways_bcc\fR -Address to send a copy of each message that enters the system. .IP \fBdebug_peer_level\fR Increment in verbose logging level when a remote host matches a pattern in the \fBdebug_peer_list\fR parameter. diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 1b7d59fa3..8646cd8bb 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -114,8 +114,6 @@ anti-spoofing restriction. .SH Miscellaneous .ad .fi -.IP \fBalways_bcc\fR -Address to send a copy of each message that enters the system. .IP \fBauthorized_verp_clients\fR Hostnames, domain names and/or addresses of clients that are authorized to use the XVERP extension. diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 3a5110c1d..d3d8832db 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -2,11 +2,13 @@ SHELL = /bin/sh SRCS = cleanup.c cleanup_out.c cleanup_envelope.c cleanup_message.c \ cleanup_extracted.c cleanup_state.c cleanup_rewrite.c \ cleanup_map11.c cleanup_map1n.c cleanup_masquerade.c \ - cleanup_out_recipient.c cleanup_init.c cleanup_api.c + cleanup_out_recipient.c cleanup_init.c cleanup_api.c \ + cleanup_addr.c OBJS = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \ cleanup_extracted.o cleanup_state.o cleanup_rewrite.o \ cleanup_map11.o cleanup_map1n.o cleanup_masquerade.o \ - cleanup_out_recipient.o cleanup_init.o cleanup_api.o + cleanup_out_recipient.o cleanup_init.o cleanup_api.o \ + cleanup_addr.o HDRS = TESTSRC = WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ @@ -113,6 +115,36 @@ cleanup.o: ../../include/header_opts.h cleanup.o: ../../include/string_list.h cleanup.o: ../../include/match_list.h cleanup.o: ../../include/match_ops.h +cleanup_addr.o: cleanup_addr.c +cleanup_addr.o: ../../include/sys_defs.h +cleanup_addr.o: ../../include/msg.h +cleanup_addr.o: ../../include/vstring.h +cleanup_addr.o: ../../include/vbuf.h +cleanup_addr.o: ../../include/vstream.h +cleanup_addr.o: ../../include/mymalloc.h +cleanup_addr.o: ../../include/stringops.h +cleanup_addr.o: ../../include/rec_type.h +cleanup_addr.o: ../../include/cleanup_user.h +cleanup_addr.o: ../../include/mail_params.h +cleanup_addr.o: ../../include/ext_prop.h +cleanup_addr.o: ../../include/mail_addr.h +cleanup_addr.o: ../../include/canon_addr.h +cleanup_addr.o: cleanup.h +cleanup_addr.o: ../../include/argv.h +cleanup_addr.o: ../../include/nvtable.h +cleanup_addr.o: ../../include/htable.h +cleanup_addr.o: ../../include/maps.h +cleanup_addr.o: ../../include/dict.h +cleanup_addr.o: ../../include/tok822.h +cleanup_addr.o: ../../include/resolve_clnt.h +cleanup_addr.o: ../../include/been_here.h +cleanup_addr.o: ../../include/mail_stream.h +cleanup_addr.o: ../../include/mail_conf.h +cleanup_addr.o: ../../include/mime_state.h +cleanup_addr.o: ../../include/header_opts.h +cleanup_addr.o: ../../include/string_list.h +cleanup_addr.o: ../../include/match_list.h +cleanup_addr.o: ../../include/match_ops.h cleanup_api.o: cleanup_api.c cleanup_api.o: ../../include/sys_defs.h cleanup_api.o: ../../include/msg.h @@ -273,6 +305,7 @@ cleanup_map1n.o: ../../include/vstring.h cleanup_map1n.o: ../../include/vbuf.h cleanup_map1n.o: ../../include/dict.h cleanup_map1n.o: ../../include/vstream.h +cleanup_map1n.o: ../../include/mail_params.h cleanup_map1n.o: ../../include/mail_addr_map.h cleanup_map1n.o: ../../include/maps.h cleanup_map1n.o: ../../include/cleanup_user.h @@ -440,7 +473,6 @@ cleanup_state.o: ../../include/sys_defs.h cleanup_state.o: ../../include/mymalloc.h cleanup_state.o: ../../include/vstring.h cleanup_state.o: ../../include/vbuf.h -cleanup_state.o: ../../include/argv.h cleanup_state.o: ../../include/htable.h cleanup_state.o: ../../include/been_here.h cleanup_state.o: ../../include/mail_params.h @@ -448,6 +480,7 @@ cleanup_state.o: ../../include/mime_state.h cleanup_state.o: ../../include/header_opts.h cleanup_state.o: cleanup.h cleanup_state.o: ../../include/vstream.h +cleanup_state.o: ../../include/argv.h cleanup_state.o: ../../include/nvtable.h cleanup_state.o: ../../include/maps.h cleanup_state.o: ../../include/dict.h diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 9ec0896fe..2b19a902e 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -116,6 +116,12 @@ /* .fi /* .IP \fBalways_bcc\fR /* Address to send a copy of each message that enters the system. +/* .IP \fBsender_bcc_maps\fR +/* Automatic BCC recipient lookup table, indexed by sender address. +/* The BCC address is added when the message enters the system. +/* .IP \fBrecipient_bcc_maps\fR +/* Automatic BCC recipient lookup table, indexed by recipient address. +/* The BCC address is added when the message enters the system. /* .IP \fBhopcount_limit\fR /* Limit the number of \fBReceived:\fR message headers. /* .IP \fBundisclosed_recipients_header\fR @@ -158,8 +164,6 @@ /* .IP \fBin_flow_delay\fR /* Amount of time to pause before accepting a message, when the /* message arrival rate exceeds the message delivery rate. -/* .IP \fBextract_recipient_limit\fR -/* Limit the amount of recipients extracted from message headers. /* .IP \fBvirtual_alias_expansion_limit\fR /* Limit the number of actual recipients produced by virtual alias /* expansion from each original recipient. diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index 8c6ee5345..c1a1c2fab 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -52,12 +52,10 @@ typedef struct CLEANUP_STATE { int err_mask; /* allowed badness */ int headers_seen; /* which headers were seen */ int hop_count; /* count of received: headers */ - ARGV *recipients; /* recipients from regular headers */ - ARGV *resent_recip; /* recipients from resent headers */ char *resent; /* any resent- header seen */ BH_TABLE *dups; /* recipient dup filter */ long warn_time; /* cleanup_envelope.c */ - void (*action) (struct CLEANUP_STATE *, int, char *, int); + void (*action) (struct CLEANUP_STATE *, int, const char *, int); off_t mesg_offset; /* start of message segment */ off_t data_offset; /* start of message content */ off_t xtra_offset; /* start of extra segment */ @@ -85,6 +83,8 @@ extern MAPS *cleanup_virt_alias_maps; extern ARGV *cleanup_masq_domains; extern STRING_LIST *cleanup_masq_exceptions; extern int cleanup_masq_flags; +extern MAPS *cleanup_send_bcc_maps; +extern MAPS *cleanup_rcpt_bcc_maps; /* * Address masquerading fine control. @@ -143,17 +143,17 @@ extern void PRINTFLIKE(3, 4) cleanup_out_format(CLEANUP_STATE *, int, const char /* * cleanup_envelope.c */ -extern void cleanup_envelope(CLEANUP_STATE *, int, char *, int); +extern void cleanup_envelope(CLEANUP_STATE *, int, const char *, int); /* * cleanup_message.c */ -extern void cleanup_message(CLEANUP_STATE *, int, char *, int); +extern void cleanup_message(CLEANUP_STATE *, int, const char *, int); /* * cleanup_extracted.c */ -extern void cleanup_extracted(CLEANUP_STATE *, int, char *, int); +extern void cleanup_extracted(CLEANUP_STATE *, int, const char *, int); /* * cleanup_rewrite.c @@ -182,10 +182,17 @@ extern void cleanup_masquerade_internal(VSTRING *, ARGV *); extern void cleanup_masquerade_tree(TOK822 *, ARGV *); /* - * Cleanup_recipient.c + * cleanup_recipient.c */ extern void cleanup_out_recipient(CLEANUP_STATE *, const char *, const char *); + /* + * cleanup_addr.c. + */ +extern void cleanup_addr_sender(CLEANUP_STATE *, const char *); +extern void cleanup_addr_recipient(CLEANUP_STATE *, const char *); +extern void cleanup_addr_bcc(CLEANUP_STATE *, const char *); + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/cleanup/cleanup_addr.c b/postfix/src/cleanup/cleanup_addr.c new file mode 100644 index 000000000..b52a27a18 --- /dev/null +++ b/postfix/src/cleanup/cleanup_addr.c @@ -0,0 +1,165 @@ +/*++ +/* NAME +/* cleanup_addr 3 +/* SUMMARY +/* process envelope addresses +/* SYNOPSIS +/* #include +/* +/* void cleanup_addr_sender(state, addr) +/* CLEANUP_STATE *state; +/* const char *addr; +/* +/* void cleanup_addr_recipient(state, addr) +/* CLEANUP_STATE *state; +/* const char *addr; +/* +/* void cleanup_addr_bcc(state, addr) +/* CLEANUP_STATE *state; +/* const char *addr; +/* DESCRIPTION +/* This module processes envelope address records and writes the result +/* to the queue file. Processing includes address rewriting and +/* sender/recipient auto bcc address generation. +/* +/* cleanup_addr_sender() process sender envelope information and updates +/* state->sender. +/* +/* cleanup_addr_recipient() processes recipient envelope information +/* and updates state->recip. +/* +/* cleanup_addr_bcc() processes recipient envelope information. This +/* is a separate function to avoid invoking cleanup_addr_recipient() +/* recursively. +/* +/* Arguments: +/* .IP state +/* Queue file and message processing state. This state is updated +/* as records are processed and as errors happen. +/* .IP buf +/* Record content. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include + +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif + +/* Utility library. */ + +#include +#include +#include +#include +#include + +/* Global library. */ + +#include +#include +#include +#include +#include +#include + +/* Application-specific. */ + +#include "cleanup.h" + +#define STR vstring_str + +/* cleanup_addr_sender - process envelope sender record */ + +void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) +{ + VSTRING *clean_addr = vstring_alloc(100); + const char *bcc; + + cleanup_rewrite_internal(clean_addr, buf); + if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@", + sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) { + canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON); + if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0) + vstring_strcpy(clean_addr, ""); + } + if (cleanup_send_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_comm_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) + cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); + CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr); + if (state->sender == 0) + state->sender = mystrdup(STR(clean_addr)); + if ((state->flags & CLEANUP_FLAG_BCC_OK) + && *STR(clean_addr) + && cleanup_send_bcc_maps + && (bcc = maps_find(cleanup_send_bcc_maps, STR(clean_addr), 0)) != 0) + cleanup_addr_bcc(state, bcc); + vstring_free(clean_addr); +} + +/* cleanup_addr_recipient - process envelope recipient */ + +void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) +{ + VSTRING *clean_addr = vstring_alloc(100); + const char *bcc; + + cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr); + if (cleanup_rcpt_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_comm_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) + cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); + cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr)); + if (state->recip == 0) + state->recip = mystrdup(STR(clean_addr)); + if ((state->flags & CLEANUP_FLAG_BCC_OK) + && *STR(clean_addr) + && cleanup_rcpt_bcc_maps + && (bcc = maps_find(cleanup_rcpt_bcc_maps, STR(clean_addr), 0)) != 0) + cleanup_addr_bcc(state, bcc); + vstring_free(clean_addr); +} + +/* cleanup_addr_bcc - process automatic BCC recipient */ + +void cleanup_addr_bcc(CLEANUP_STATE *state, const char *bcc) +{ + VSTRING *clean_addr = vstring_alloc(100); + + cleanup_rewrite_internal(clean_addr, bcc); + if (cleanup_rcpt_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_comm_canon_maps) + cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, + cleanup_ext_prop_mask & EXT_PROP_CANONICAL); + if (cleanup_masq_domains + && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) + cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); + cleanup_out_recipient(state, STR(clean_addr), STR(clean_addr)); + vstring_free(clean_addr); +} diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index bb06cb1b6..c0f749cd3 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -40,13 +40,12 @@ /* .IP CLEANUP_FLAG_BOUNCE /* The cleanup server is responsible for returning undeliverable /* mail (too many hops, message too large) to the sender. +/* .IP CLEANUP_FLAG_BCC_OK +/* It is OK to add automatic BCC recipient addresses. /* .IP CLEANUP_FLAG_FILTER /* Enable header/body filtering. This should be enabled only with mail /* that enters Postfix, not with locally forwarded mail or with bounce /* messages. -/* .IP CLEANUP_FLAG_EXTRACT -/* Extract recipients from message headers when no recipients are -/* provided in the message envelope records. /* .PP /* CLEANUP_RECORD() is a macro that processes one message record, /* that copies the result to the queue file, and that maintains a @@ -171,7 +170,7 @@ void cleanup_control(CLEANUP_STATE *state, int flags) if ((state->flags = flags) & CLEANUP_FLAG_BOUNCE) { state->err_mask = CLEANUP_STAT_MASK_INCOMPLETE; } else { - state->err_mask = ~CLEANUP_STAT_MASK_EXTRACT_RCPT; + state->err_mask = ~0; } } @@ -183,13 +182,6 @@ int cleanup_flush(CLEANUP_STATE *state) int status; char *encoding; - /* - * Ignore recipient extraction alarms if (a) we did (not need to) extract - * recipients, or (b) we did not examine all queue file records. - */ - if (state->recip != 0 || CLEANUP_OUT_OK(state) == 0) - state->errs &= ~CLEANUP_STAT_MASK_EXTRACT_RCPT; - /* * Raise these errors only if we examined all queue file records. */ diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index 77734a8b0..226a673d6 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -9,8 +9,7 @@ /* void cleanup_envelope(state, type, buf, len) /* CLEANUP_STATE *state; /* int type; -/* char *buf; -/* int len; +/* const char *buf; /* int len; /* DESCRIPTION /* This module processes envelope records and writes the result @@ -77,11 +76,12 @@ #define STR vstring_str -static void cleanup_envelope_process(CLEANUP_STATE *, int, char *, int); +static void cleanup_envelope_process(CLEANUP_STATE *, int, const char *, int); /* cleanup_envelope - initialize message envelope */ -void cleanup_envelope(CLEANUP_STATE *state, int type, char *str, int len) +void cleanup_envelope(CLEANUP_STATE *state, int type, + const char *str, int len) { /* @@ -104,13 +104,18 @@ void cleanup_envelope(CLEANUP_STATE *state, int type, char *str, int len) /* cleanup_envelope_process - process one envelope record */ -static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, int len) +static void cleanup_envelope_process(CLEANUP_STATE *state, int type, + const char *buf, int len) { char *attr_name; char *attr_value; const char *error_text; int extra_flags; + /* + * On the transition from envelope segment to content segment, do some + * sanity checks and add some records. + */ if (type == REC_TYPE_MESG) { if (state->sender == 0 || state->time == 0) { msg_warn("%s: missing sender or time envelope record", @@ -158,31 +163,13 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, } else if (type == REC_TYPE_FULL) { state->fullname = mystrdup(buf); } else if (type == REC_TYPE_FROM) { - VSTRING *clean_addr = vstring_alloc(100); - - cleanup_rewrite_internal(clean_addr, buf); - if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@", - sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) { - canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON); - if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0) - vstring_strcpy(clean_addr, ""); + if (state->sender != 0) { + msg_warn("%s: too many envelope sender records", state->queue_id); + state->errs |= CLEANUP_STAT_BAD; + return; } - if (cleanup_send_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_comm_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_masq_domains - && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) - cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); - CLEANUP_OUT_BUF(state, type, clean_addr); - if (state->sender == 0) - state->sender = mystrdup(STR(clean_addr)); - vstring_free(clean_addr); + cleanup_addr_sender(state, buf); } else if (type == REC_TYPE_RCPT) { - VSTRING *clean_addr = vstring_alloc(100); - if (state->sender == 0) { /* protect showq */ msg_warn("%s: envelope recipient precedes sender", state->queue_id); @@ -191,20 +178,7 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, } if (state->orig_rcpt == 0) state->orig_rcpt = mystrdup(buf); - cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr); - if (cleanup_rcpt_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_comm_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_masq_domains - && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) - cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); - cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr)); - if (state->recip == 0) - state->recip = mystrdup(STR(clean_addr)); - vstring_free(clean_addr); + cleanup_addr_recipient(state, buf); myfree(state->orig_rcpt); state->orig_rcpt = 0; } else if (type == REC_TYPE_WARN) { @@ -225,6 +199,8 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, return; } } else if (type == REC_TYPE_ATTR) { + char *sbuf; + if (state->attr->used >= var_qattr_count_limit) { msg_warn("%s: queue file attribute count exceeds safety limit: %d", state->queue_id, var_qattr_count_limit); @@ -232,13 +208,16 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, return; } cleanup_out(state, type, buf, len); - if ((error_text = split_nameval(buf, &attr_name, &attr_value)) != 0) { + sbuf = mystrdup(buf); + if ((error_text = split_nameval(sbuf, &attr_name, &attr_value)) != 0) { msg_warn("%s: malformed attribute: %s: %.100s", state->queue_id, error_text, buf); state->errs |= CLEANUP_STAT_BAD; + myfree(sbuf); return; } nvtable_update(state->attr, attr_name, attr_value); + myfree(sbuf); } else if (type == REC_TYPE_ORCP) { state->orig_rcpt = mystrdup(buf); } else { diff --git a/postfix/src/cleanup/cleanup_extracted.c b/postfix/src/cleanup/cleanup_extracted.c index 50b3d12ed..faad668a1 100644 --- a/postfix/src/cleanup/cleanup_extracted.c +++ b/postfix/src/cleanup/cleanup_extracted.c @@ -9,7 +9,7 @@ /* void cleanup_extracted(state, type, buf, len) /* CLEANUP_STATE *state; /* int type; -/* char *buf; +/* const char *buf; /* int len; /* DESCRIPTION /* This module processes message records with information extracted @@ -68,11 +68,12 @@ #define STR(x) vstring_str(x) -static void cleanup_extracted_process(CLEANUP_STATE *, int, char *, int); +static void cleanup_extracted_process(CLEANUP_STATE *, int, const char *, int); /* cleanup_extracted - initialize extracted segment */ -void cleanup_extracted(CLEANUP_STATE *state, int type, char *buf, int len) +void cleanup_extracted(CLEANUP_STATE *state, int type, + const char *buf, int len) { const char *encoding; @@ -128,12 +129,10 @@ void cleanup_extracted(CLEANUP_STATE *state, int type, char *buf, int len) /* cleanup_extracted_process - process extracted segment */ -static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, int len) +static void cleanup_extracted_process(CLEANUP_STATE *state, int type, + const char *buf, int len) { char *myname = "cleanup_extracted_process"; - VSTRING *clean_addr; - ARGV *rcpt; - char **cpp; /* * Weird condition for consistency with cleanup_envelope.c @@ -148,23 +147,9 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, } } if (type == REC_TYPE_RCPT) { - clean_addr = vstring_alloc(100); if (state->orig_rcpt == 0) state->orig_rcpt = mystrdup(buf); - cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr); - if (cleanup_rcpt_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_comm_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_masq_domains - && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) - cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); - cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr)); - if (state->recip == 0) - state->recip = mystrdup(STR(clean_addr)); - vstring_free(clean_addr); + cleanup_addr_recipient(state, buf); myfree(state->orig_rcpt); state->orig_rcpt = 0; return; @@ -177,52 +162,11 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, } /* - * Optionally account for missing recipient envelope records. - * - * Don't extract recipients when some header was too long. We have - * incomplete information. - * - * XXX Code duplication from cleanup_envelope.c. This should be in one - * place. + * On the way out, add the optional automatic BCC recipient. */ - if (state->recip == 0 && (state->errs & CLEANUP_STAT_HOVFL) == 0) { - rcpt = (state->resent[0] ? state->resent_recip : state->recipients); - if (rcpt->argc >= var_extra_rcpt_limit) { - state->errs |= CLEANUP_STAT_ROVFL; - } else { - clean_addr = vstring_alloc(100); - if (*var_always_bcc && rcpt->argv[0]) { - cleanup_rewrite_internal(clean_addr, var_always_bcc); - if (cleanup_rcpt_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - if (cleanup_comm_canon_maps) - cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps, - cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - argv_add(rcpt, STR(clean_addr), (char *) 0); - } - argv_terminate(rcpt); - - /* - * Recipients extracted from message headers already have - * undergone recipient address rewriting (see cleanup_message.c), - * but still may need address masquerading. - */ - for (cpp = rcpt->argv; CLEANUP_OUT_OK(state) && *cpp; cpp++) { - if (cleanup_masq_domains - && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) { - vstring_strcpy(clean_addr, *cpp); - cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); - cleanup_out_recipient(state, STR(clean_addr), - STR(clean_addr)); /* XXX */ - } else - cleanup_out_recipient(state, *cpp, *cpp); /* XXX */ - } - if (rcpt->argv[0]) - state->recip = mystrdup(rcpt->argv[0]); - vstring_free(clean_addr); - } - } + if ((state->flags & CLEANUP_FLAG_BCC_OK) + && state->recip != 0 && *var_always_bcc) + cleanup_addr_bcc(state, var_always_bcc); /* * Terminate the extracted segment. diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c index 5c8a57658..dcd1dfbf0 100644 --- a/postfix/src/cleanup/cleanup_init.c +++ b/postfix/src/cleanup/cleanup_init.c @@ -106,18 +106,18 @@ char *var_empty_addr; /* destination of bounced bounces */ int var_delay_warn_time; /* delay that triggers warning */ char *var_prop_extension; /* propagate unmatched extension */ char *var_always_bcc; /* big brother */ -int var_extra_rcpt_limit; /* recipient extract limit */ char *var_rcpt_witheld; /* recipients not disclosed */ char *var_masq_classes; /* what to masquerade */ int var_qattr_count_limit; /* named attribute limit */ int var_virt_recur_limit; /* maximum virtual alias recursion */ int var_virt_expan_limit; /* maximum virtual alias expansion */ int var_body_check_len; /* when to stop body scan */ +char *var_send_bcc_maps; /* sender auto-bcc maps */ +char *var_rcpt_bcc_maps; /* recipient auto-bcc maps */ CONFIG_INT_TABLE cleanup_int_table[] = { VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0, VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0, - VAR_EXTRA_RCPT_LIMIT, DEF_EXTRA_RCPT_LIMIT, &var_extra_rcpt_limit, 0, 0, VAR_QATTR_COUNT_LIMIT, DEF_QATTR_COUNT_LIMIT, &var_qattr_count_limit, 1, 0, VAR_VIRT_RECUR_LIMIT, DEF_VIRT_RECUR_LIMIT, &var_virt_recur_limit, 1, 0, VAR_VIRT_EXPAN_LIMIT, DEF_VIRT_EXPAN_LIMIT, &var_virt_expan_limit, 1, 0, @@ -146,6 +146,8 @@ CONFIG_STR_TABLE cleanup_str_table[] = { VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0, VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 1, 0, VAR_MASQ_CLASSES, DEF_MASQ_CLASSES, &var_masq_classes, 0, 0, + VAR_SEND_BCC_MAPS, DEF_SEND_BCC_MAPS, &var_send_bcc_maps, 0, 0, + VAR_RCPT_BCC_MAPS, DEF_RCPT_BCC_MAPS, &var_rcpt_bcc_maps, 0, 0, 0, }; @@ -163,6 +165,8 @@ MAPS *cleanup_virt_alias_maps; ARGV *cleanup_masq_domains; STRING_LIST *cleanup_masq_exceptions; int cleanup_masq_flags; +MAPS *cleanup_send_bcc_maps; +MAPS *cleanup_rcpt_bcc_maps; /* * Address extension propagation restrictions. @@ -224,6 +228,14 @@ void cleanup_pre_jail(char *unused_name, char **unused_argv) if (*var_masq_classes) cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table, var_masq_classes); + if (*var_send_bcc_maps) + cleanup_send_bcc_maps = + maps_create(VAR_SEND_BCC_MAPS, var_send_bcc_maps, + DICT_FLAG_LOCK); + if (*var_rcpt_bcc_maps) + cleanup_rcpt_bcc_maps = + maps_create(VAR_RCPT_BCC_MAPS, var_rcpt_bcc_maps, + DICT_FLAG_LOCK); } /* cleanup_post_jail - initialize after entering the chroot jail */ diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 28ac89b10..72a562703 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -9,7 +9,7 @@ /* void cleanup_message(state, type, buf, len) /* CLEANUP_STATE *state; /* int type; -/* char *buf; +/* const char *buf; /* int len; /* DESCRIPTION /* This module processes message content records and copies the @@ -213,7 +213,6 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts, TOK822 *tree; TOK822 **addr_list; TOK822 **tpp; - ARGV *rcpt; if (msg_verbose) msg_info("rewrite_recip: %s", hdr_opts->name); @@ -236,18 +235,6 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts, cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps, cleanup_ext_prop_mask & EXT_PROP_CANONICAL); - /* - * Extract envelope recipients after recipient address rewriting but - * before address masquerading. - */ - if (state->recip == 0 && (hdr_opts->flags & HDR_OPT_EXTRACT) != 0) { - rcpt = (hdr_opts->flags & HDR_OPT_RR) ? - state->resent_recip : state->recipients; - if (rcpt->argc < var_extra_rcpt_limit) { - tok822_internalize(state->temp1, tpp[0]->head, TOK822_STR_DEFL); - argv_add(rcpt, vstring_str(state->temp1), (char *) 0); - } - } if (cleanup_masq_domains && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT)) cleanup_masquerade_tree(*tpp, cleanup_masq_domains); @@ -269,7 +256,7 @@ static void cleanup_act_log(CLEANUP_STATE *state, const char *attr; if ((attr = nvtable_find(state->attr, MAIL_ATTR_ORIGIN)) == 0) - attr="unknown"; + attr = "unknown"; vstring_sprintf(state->temp1, "%s: %s: %s %.200s from %s;", state->queue_id, action, class, content, attr); if (state->sender) @@ -595,13 +582,6 @@ static void cleanup_header_done_callback(void *context) if ((state->headers_seen & VISIBLE_RCPT) == 0) cleanup_out_format(state, REC_TYPE_NORM, "%s", var_rcpt_witheld); - - /* - * Header buffer overflow is an unrecoverable error only if we extract - * recipients from the main message headers. - */ - if (state->mime_errs & MIME_ERR_TRUNC_HEADER) - state->errs |= CLEANUP_STAT_HOVFL; } /* cleanup_body_callback - output one body record */ @@ -635,7 +615,7 @@ static void cleanup_body_callback(void *context, int type, /* cleanup_message_headerbody - process message content, header and body */ static void cleanup_message_headerbody(CLEANUP_STATE *state, int type, - char *buf, int len) + const char *buf, int len) { char *myname = "cleanup_message_headerbody"; @@ -696,7 +676,7 @@ static void cleanup_mime_error_callback(void *context, int err_code, /* cleanup_message - initialize message content segment */ -void cleanup_message(CLEANUP_STATE *state, int type, char *buf, int len) +void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, int len) { char *myname = "cleanup_message"; int mime_options; @@ -717,7 +697,7 @@ void cleanup_message(CLEANUP_STATE *state, int type, char *buf, int len) * special processing of Content-Type: headers, and thus, causes all text * after the primary headers to be treated as the message body. */ - mime_options = MIME_OPT_REPORT_TRUNC_HEADER; + mime_options = 0; if (var_disable_mime_input) { mime_options |= MIME_OPT_DISABLE_MIME; } else { diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index 2f17fd050..f10d50c3d 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -37,7 +37,6 @@ #include #include -#include #include /* Global library. */ @@ -76,8 +75,6 @@ CLEANUP_STATE *cleanup_state_alloc(void) state->err_mask = 0; state->headers_seen = 0; state->hop_count = 0; - state->recipients = argv_alloc(2); - state->resent_recip = argv_alloc(2); state->resent = ""; state->dups = been_here_init(var_dup_filter_limit, BH_FLAG_FOLD); state->warn_time = 0; @@ -118,8 +115,6 @@ void cleanup_state_free(CLEANUP_STATE *state) myfree(state->return_receipt); if (state->errors_to) myfree(state->errors_to); - argv_free(state->recipients); - argv_free(state->resent_recip); if (state->queue_name) myfree(state->queue_name); if (state->queue_id) diff --git a/postfix/src/global/cleanup_strerror.c b/postfix/src/global/cleanup_strerror.c index 144b74e72..489093ed9 100644 --- a/postfix/src/global/cleanup_strerror.c +++ b/postfix/src/global/cleanup_strerror.c @@ -49,8 +49,6 @@ struct cleanup_stat_map { static struct cleanup_stat_map cleanup_stat_map[] = { CLEANUP_STAT_BAD, "Internal protocol error", - CLEANUP_STAT_HOVFL, "Message header too long", - CLEANUP_STAT_ROVFL, "Too many extracted recipients", CLEANUP_STAT_RCPT, "No recipients specified", CLEANUP_STAT_HOPS, "Too many hops", CLEANUP_STAT_SIZE, "Message file too big", diff --git a/postfix/src/global/cleanup_user.h b/postfix/src/global/cleanup_user.h index 44a4a506a..ce4af5851 100644 --- a/postfix/src/global/cleanup_user.h +++ b/postfix/src/global/cleanup_user.h @@ -19,6 +19,7 @@ #define CLEANUP_FLAG_FILTER (1<<1) /* Enable content filter */ #define CLEANUP_FLAG_HOLD (1<<2) /* Place message on hold */ #define CLEANUP_FLAG_DISCARD (1<<3) /* Discard message silently */ +#define CLEANUP_FLAG_BCC_OK (1<<4) /* Ok to add auto-BCC addresses */ /* * These are set on the fly while processing SMTP envelopes or message @@ -38,10 +39,7 @@ #define CLEANUP_STAT_SIZE (1<<2) /* Message file too big */ #define CLEANUP_STAT_CONT (1<<3) /* Message content rejected */ #define CLEANUP_STAT_HOPS (1<<4) /* Too many hops */ -#define CLEANUP_STAT_SYN (1<<5) /* Bad address syntax */ #define CLEANUP_STAT_RCPT (1<<6) /* No recipients found */ -#define CLEANUP_STAT_HOVFL (1<<7) /* Header overflow */ -#define CLEANUP_STAT_ROVFL (1<<8) /* Recipient overflow */ /* * These are set when we can't bounce even if we were asked to. @@ -55,12 +53,6 @@ #define CLEANUP_STAT_MASK_INCOMPLETE \ (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE) - /* - * These are relevant for extracting recipients from headers. - */ -#define CLEANUP_STAT_MASK_EXTRACT_RCPT \ - (CLEANUP_STAT_HOVFL | CLEANUP_STAT_ROVFL | CLEANUP_STAT_RCPT) - extern const char *cleanup_strerror(unsigned); /* LICENSE diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index e4cb9ce1b..67cc4ea05 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -324,6 +324,14 @@ extern char *var_send_canon_maps; #define DEF_RCPT_CANON_MAPS "" extern char *var_rcpt_canon_maps; +#define VAR_SEND_BCC_MAPS "sender_bcc_maps" +#define DEF_SEND_BCC_MAPS "" +extern char *var_send_bcc_maps; + +#define VAR_RCPT_BCC_MAPS "recipient_bcc_maps" +#define DEF_RCPT_BCC_MAPS "" +extern char *var_rcpt_bcc_maps; + #define VAR_TRANSPORT_MAPS "transport_maps" #define DEF_TRANSPORT_MAPS "" extern char *var_transport_maps; @@ -1015,10 +1023,6 @@ extern int var_header_limit; #define DEF_TOKEN_LIMIT 10240 extern int var_token_limit; -#define VAR_EXTRA_RCPT_LIMIT "extract_recipient_limit" -#define DEF_EXTRA_RCPT_LIMIT 10240 -extern int var_extra_rcpt_limit; - #define VAR_VIRT_RECUR_LIMIT "virtual_alias_recursion_limit" #define DEF_VIRT_RECUR_LIMIT 1000 extern int var_virt_recur_limit; diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f6665ddc1..cff3dd02c 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20030415" +#define MAIL_RELEASE_DATE "20030416" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "2.0.8-" MAIL_RELEASE_DATE diff --git a/postfix/src/local/maildir.c b/postfix/src/local/maildir.c index dca519394..e2d20cb42 100644 --- a/postfix/src/local/maildir.c +++ b/postfix/src/local/maildir.c @@ -216,6 +216,11 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path) defer_append : bounce_append) (BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr), "maildir delivery failed: %s", vstring_str(why)); + if (errno == EACCES) { + msg_warn("maildir access problem for UID/GID=%lu/%lu: %s", + (long) usr_attr.uid, (long) usr_attr.gid, vstring_str(why)); + msg_warn("perhaps you need to create the maildirs in advance"); + } } else { deliver_status = sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr), diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index fd586072f..6d51cec84 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -48,8 +48,6 @@ /* .SH Miscellaneous /* .ad /* .fi -/* .IP \fBalways_bcc\fR -/* Address to send a copy of each message that enters the system. /* .IP \fBqueue_directory\fR /* Top-level directory of the Postfix queue. /* SEE ALSO @@ -111,7 +109,6 @@ /* Application-specific. */ -char *var_always_bcc; char *var_filter_xport; /* @@ -299,9 +296,6 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, * Copy the message envelope segment. Allow only those records that we * expect to see in the envelope section. The envelope segment must * contain an envelope sender address. - * - * If the segment contains a recipient address, include the optional - * always_bcc recipient. */ if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_ENVELOPE)) != 0) return (status); @@ -313,11 +307,6 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, msg_info("%s: uid=%d from=<%s>", info->id, (int) info->st.st_uid, info->sender); - if (info->rcpt) { - if (*var_always_bcc) - rec_fputs(cleanup, REC_TYPE_RCPT, var_always_bcc); - } - /* * Message content segment. Send a dummy message length. Prepend a * Received: header to the message contents. For tracing purposes, @@ -408,7 +397,8 @@ static int pickup_file(PICKUP_INFO *info) * easier to implement the many possible error exits without forgetting * to close files, or to release memory. */ -#define PICKUP_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER) +#define PICKUP_CLEANUP_FLAGS \ + (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK) cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); if (attr_scan(cleanup, ATTR_FLAG_STRICT, @@ -512,7 +502,6 @@ static void drop_privileges(char *unused_name, char **unused_argv) int main(int argc, char **argv) { static CONFIG_STR_TABLE str_table[] = { - VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0, VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, 0, }; diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 4fe2cc8bd..28cbbcd68 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -42,8 +42,6 @@ /* .SH Miscellaneous /* .ad /* .fi -/* .IP \fBalways_bcc\fR -/* Address to send a copy of each message that enters the system. /* .IP \fBdebug_peer_level\fR /* Increment in verbose logging level when a remote host matches a /* pattern in the \fBdebug_peer_list\fR parameter. @@ -155,7 +153,6 @@ */ int var_qmqpd_timeout; int var_qmqpd_err_sleep; -char *var_always_bcc; char *var_filter_xport; char *var_qmqpd_clients; @@ -182,10 +179,12 @@ static void qmqpd_open_file(QMQPD_STATE *state) /* * Connect to the cleanup server. Log client name/address with queue ID. */ +#define QMQPD_CLEANUP_FLAGS (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK) + state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, QMQPD_CLEANUP_FLAGS, ATTR_TYPE_END) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); @@ -295,14 +294,6 @@ static void qmqpd_copy_recipients(QMQPD_STATE *state) if (state->recipient == 0) state->recipient = mystrndup(STR(state->buf), LEN(state->buf)); } - - /* - * Append the optional recipient who is copied on all mail. - */ - if (state->err == CLEANUP_STAT_OK - && *var_always_bcc - && rec_fputs(state->cleanup, REC_TYPE_RCPT, var_always_bcc) < 0) - state->err = CLEANUP_STAT_WRITE; } /* qmqpd_next_line - get line from buffer, return last char, newline, or -1 */ @@ -690,7 +681,6 @@ int main(int argc, char **argv) 0, }; static CONFIG_STR_TABLE str_table[] = { - VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0, VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, VAR_QMQPD_CLIENTS, DEF_QMQPD_CLIENTS, &var_qmqpd_clients, 0, 0, 0, diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 00785b831..38e604c16 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -169,8 +169,8 @@ /* This command is not implemented. Use the slower \fBsendmail -q\fR /* command instead. /* .IP \fB-t\fR -/* Extract recipients from message headers. This requires that no -/* recipients be specified on the command line. +/* Extract recipients from message headers. These are added to any +/* recipients specified on the command line. /* .IP \fB-v\fR /* Send an email report of all delivery attempts (mail delivery /* always happens in the background). When multiple \fB-v\fR @@ -304,6 +304,7 @@ #include #include #include +#include /* Global library. */ @@ -323,6 +324,8 @@ #include #include #include +#include +#include /* Application-specific. */ @@ -340,6 +343,7 @@ * Flag parade. Flags 8-15 are reserved for delivery request trace flags. */ #define SM_FLAG_AEOF (1<<0) /* archaic EOF */ +#define SM_FLAG_XRCPT (1<<1) /* extract recipients from headers */ #define SM_FLAG_DEFAULT (SM_FLAG_AEOF) @@ -348,11 +352,87 @@ */ char *verp_delims; + /* + * Context for extracting recipients. + */ +typedef struct SM_STATE { + VSTREAM *dst; /* output stream */ + ARGV *recipients; /* recipients from regular headers */ + ARGV *resent_recip; /* recipients from resent headers */ + int resent; /* resent flag */ + const char *saved_sender; /* for error messages */ + uid_t uid; /* for error messages */ + VSTRING *temp; /* scratch buffer */ +} SM_STATE; + /* * Silly little macros (SLMs). */ #define STR vstring_str +/* output_text - output partial or complete text line */ + +static void output_text(void *context, int rec_type, const char *buf, int len, + off_t unused_offset) +{ + SM_STATE *state = (SM_STATE *) context; + + if (rec_put(state->dst, rec_type, buf, len) < 0) + msg_fatal_status(EX_TEMPFAIL, + "%s(%ld): error writing queue file: %m", + state->saved_sender, (long) state->uid); +} + +/* output_header - output one message header */ + +static void output_header(void *context, int header_class, + HEADER_OPTS *header_info, + VSTRING *buf, off_t offset) +{ + SM_STATE *state = (SM_STATE *) context; + TOK822 *tree; + TOK822 **addr_list; + TOK822 **tpp; + ARGV *rcpt; + char *start; + char *line; + char *next_line; + + /* + * Pipe the unmodified message header through the header line folding + * routine. + */ + for (line = start = STR(buf); line; line = next_line) { + next_line = split_at(line, '\n'); + output_text(context, REC_TYPE_NORM, line, next_line ? + next_line - line - 1 : strlen(line), offset); + } + + /* + * Parse the header line, and save copies of recipient addresses in the + * appropriate place. + */ + if (header_class == MIME_HDR_PRIMARY + && header_info->flags & HDR_OPT_RECIP + && header_info->flags & HDR_OPT_EXTRACT + && (state->resent == 0 || (header_info->flags & HDR_OPT_RR))) { + if (header_info->flags & HDR_OPT_RR) { + rcpt = state->resent_recip; + if (state->resent == 0) + state->resent = 1; + } else + rcpt = state->recipients; + tree = tok822_parse(vstring_str(buf) + strlen(header_info->name) + 1); + addr_list = tok822_grep(tree, TOK822_ADDR); + for (tpp = addr_list; *tpp; tpp++) { + tok822_internalize(state->temp, tpp[0]->head, TOK822_STR_DEFL); + argv_add(rcpt, vstring_str(state->temp), (char *) 0); + } + myfree((char *) addr_list); + tok822_free_tree(tree); + } +} + /* enqueue - post one message */ static void enqueue(const int flags, const char *encoding, const char *sender, @@ -376,6 +456,9 @@ static void enqueue(const int flags, const char *encoding, const char *sender, int status; int naddr; int prev_type; + MIME_STATE *mime_state = 0; + SM_STATE state; + int mime_errs; /* * Initialize. @@ -482,6 +565,31 @@ static void enqueue(const int flags, const char *encoding, const char *sender, } } } else { + + /* + * Initialize the MIME processor and set up the callback context. + */ + if (flags & SM_FLAG_XRCPT) { + state.dst = dst; + state.recipients = argv_alloc(2); + state.resent_recip = argv_alloc(2); + state.resent = 0; + state.saved_sender = saved_sender; + state.uid = uid; + state.temp = vstring_alloc(10); + mime_state = mime_state_alloc(MIME_OPT_DISABLE_MIME + | MIME_OPT_REPORT_TRUNC_HEADER, + output_header, + (MIME_STATE_ANY_END) 0, + output_text, + (MIME_STATE_ANY_END) 0, + (MIME_STATE_ERR_PRINT) 0, + (void *) &state); + } + + /* + * Process header/body lines. + */ skip_from_ = 1; strip_cr = STRIP_CR_DUNNO; for (prev_type = 0; (type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit)) @@ -506,18 +614,52 @@ static void enqueue(const int flags, const char *encoding, const char *sender, if ((flags & SM_FLAG_AEOF) && prev_type != REC_TYPE_CONT && VSTRING_LEN(buf) == 1 && *STR(buf) == '.') break; - if (REC_PUT_BUF(dst, type, buf) < 0) - msg_fatal_status(EX_TEMPFAIL, - "%s(%ld): error writing queue file: %m", - saved_sender, (long) uid); + if (mime_state) { + mime_errs = mime_state_update(mime_state, type, STR(buf), + VSTRING_LEN(buf)); + if (mime_errs) + msg_fatal_status(EX_DATAERR, + "%s(%ld): unable to extract recipients: %s", + saved_sender, (long) uid, + mime_state_error(mime_errs)); + } else { + if (REC_PUT_BUF(dst, type, buf) < 0) + msg_fatal_status(EX_TEMPFAIL, + "%s(%ld): error writing queue file: %m", + saved_sender, (long) uid); + } } } /* - * Append an empty section for information extracted from message - * headers. Header parsing is done by the cleanup service. + * Finish up MIME processing. + */ + if (mime_state) { + mime_errs = mime_state_update(mime_state, REC_TYPE_EOF, "", 0); + if (mime_errs) + msg_fatal_status(EX_DATAERR, + "%s(%ld): unable to extract recipients: %s", + saved_sender, (long) uid, + mime_state_error(mime_errs)); + mime_state = mime_state_free(mime_state); + } + + /* + * Append recipient addresses that were extracted from message headers. */ rec_fputs(dst, REC_TYPE_XTRA, ""); + if (flags & SM_FLAG_XRCPT) { + for (cpp = state.resent ? state.resent_recip->argv : + state.recipients->argv; *cpp; cpp++) { + if (rec_put(dst, REC_TYPE_RCPT, *cpp, strlen(*cpp)) < 0) + msg_fatal_status(EX_TEMPFAIL, + "%s(%ld): error writing queue file: %m", + saved_sender, (long) uid); + } + argv_free(state.recipients); + argv_free(state.resent_recip); + vstring_free(state.temp); + } /* * Identify the end of the queue file. @@ -563,7 +705,6 @@ int main(int argc, char **argv) static char *full_name = 0; /* sendmail -F */ struct stat st; char *slash; - int extract_recipients = 0; /* sendmail -t, almost */ char *sender = 0; /* sendmail -f */ int c; int fd; @@ -797,7 +938,7 @@ int main(int argc, char **argv) } break; case 't': - extract_recipients = 1; + flags |= SM_FLAG_XRCPT; break; case 'v': msg_verbose++; @@ -810,16 +951,12 @@ int main(int argc, char **argv) /* * Look for conflicting options and arguments. */ - if (extract_recipients && mode != SM_MODE_ENQUEUE) + if ((flags & SM_FLAG_XRCPT) && mode != SM_MODE_ENQUEUE) msg_fatal_status(EX_USAGE, "-t can be used only in delivery mode"); if (site_to_flush && mode != SM_MODE_ENQUEUE) msg_fatal_status(EX_USAGE, "-qR can be used only in delivery mode"); - if (extract_recipients && argv[OPTIND]) - msg_fatal_status(EX_USAGE, - "cannot handle command-line recipients with -t"); - /* * The -v option plays double duty. One requests verbose delivery, more * than one requests verbose logging. diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c index e5bc30e2d..9235fe502 100644 --- a/postfix/src/smtp/smtp_addr.c +++ b/postfix/src/smtp/smtp_addr.c @@ -347,6 +347,14 @@ DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself) * preferred than myself. When no MX resource records exist, look up the * addresses listed for this name. * + * According to RFC 974: "It is possible that the list of MXs in the + * response to the query will be empty. This is a special case. If the + * list is empty, mailers should treat it as if it contained one RR, an + * MX RR with a preference value of 0, and a host name of REMOTE. (I.e., + * REMOTE is its only MX). In addition, the mailer should do no further + * processing on the list, but should attempt to deliver the message to + * REMOTE." + * * Normally it is OK if an MX host cannot be found in the DNS; we'll just * use a backup one, and silently ignore the better MX host. However, if * the best backup that we can find in the DNS is the local machine, then diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 0ad53abeb..543d78b2a 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -648,7 +648,7 @@ int smtp_xfer(SMTP_STATE *state) request->queue_id, rcpt->orig_addr, rcpt->address, session->namaddr, request->arrival_time, "%s", - translit(resp->str, "\n", " ")) == 0) { + translit(resp->str, "\n", " ")) == 0) { if (request->flags & DEL_REQ_FLAG_SUCCESS) deliver_completed(state->src, rcpt->offset); rcpt->offset = 0; /* in case deferred */ @@ -820,7 +820,8 @@ int smtp_xfer(SMTP_STATE *state) vstring_str(state->scratch), VSTRING_LEN(state->scratch)); if (mime_errs) { - smtp_mesg_fail(state, 554, "MIME 7-bit conversion failed: %s", + smtp_mesg_fail(state, 554, + "MIME 7-bit conversion failed: %s", mime_state_error(mime_errs)); RETURN(0); } @@ -828,7 +829,16 @@ int smtp_xfer(SMTP_STATE *state) prev_type = rec_type; } - if (prev_type == REC_TYPE_CONT) /* missing newline at end */ + if (state->mime_state) { + mime_errs = + mime_state_update(state->mime_state, rec_type, "", 0); + if (mime_errs) { + smtp_mesg_fail(state, 554, + "MIME 7-bit conversion failed: %s", + mime_state_error(mime_errs)); + RETURN(0); + } + } else if (prev_type == REC_TYPE_CONT) /* missing newline */ smtp_fputs("", 0, session->stream); if ((state->features & SMTP_FEATURE_MAYBEPIX) != 0 && request->arrival_time < vstream_ftime(session->stream) @@ -853,6 +863,5 @@ int smtp_xfer(SMTP_STATE *state) send_state = next_state; send_rcpt = next_rcpt; } - RETURN(0); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 7cf3ed70b..96147559d 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -100,8 +100,6 @@ /* .SH Miscellaneous /* .ad /* .fi -/* .IP \fBalways_bcc\fR -/* Address to send a copy of each message that enters the system. /* .IP \fBauthorized_verp_clients\fR /* Hostnames, domain names and/or addresses of clients that are /* authorized to use the XVERP extension. @@ -411,7 +409,6 @@ int var_reject_code; int var_defer_code; int var_smtpd_err_sleep; int var_non_fqdn_code; -char *var_always_bcc; char *var_error_rcpt; int var_smtpd_delay_reject; char *var_rest_classes; @@ -600,12 +597,14 @@ static void mail_open_stream(SMTPD_STATE *state) * If running from the master or from inetd, connect to the cleanup * service. */ +#define SMTPD_CLEANUP_FLAGS (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK) + if (SMTPD_STAND_ALONE(state) == 0) { state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, SMTPD_CLEANUP_FLAGS, ATTR_TYPE_END) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PUBLIC, var_cleanup_service); @@ -1028,8 +1027,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) * segment, and prepend our own Received: header. If there is only one * recipient, list the recipient address. */ - if (*var_always_bcc) - rec_fputs(state->cleanup, REC_TYPE_RCPT, var_always_bcc); rec_fputs(state->cleanup, REC_TYPE_MESG, ""); rec_fprintf(state->cleanup, REC_TYPE_NORM, "Received: from %s (%s [%s])", @@ -1694,7 +1691,6 @@ int main(int argc, char **argv) VAR_DATA_CHECKS, DEF_DATA_CHECKS, &var_data_checks, 0, 0, VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, 0, 0, VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps, 0, 0, - VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0, VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 0, 0, VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0, diff --git a/postfix/src/virtual/maildir.c b/postfix/src/virtual/maildir.c index b84c1fa74..c51a4e7c5 100644 --- a/postfix/src/virtual/maildir.c +++ b/postfix/src/virtual/maildir.c @@ -215,7 +215,11 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr) bounce_append : defer_append) (BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr), "maildir delivery failed: %s", vstring_str(why)); - + if (errno == EACCES) { + msg_warn("maildir access problem for UID/GID=%lu/%lu: %s", + (long) usr_attr.uid, (long) usr_attr.gid, vstring_str(why)); + msg_warn("perhaps you need to create the maildirs in advance"); + } } else { deliver_status = sent(BOUNCE_FLAGS(state.request), SENT_ATTR(state.msg_attr),